goscript 0.0.58 → 0.0.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +40 -33
  2. package/compiler/analysis.go +115 -19
  3. package/compiler/assignment.go +163 -217
  4. package/compiler/compiler.go +35 -31
  5. package/compiler/composite-lit.go +233 -196
  6. package/compiler/constraint.go +88 -0
  7. package/compiler/decl.go +82 -24
  8. package/compiler/expr-call-async.go +20 -34
  9. package/compiler/expr-call-builtins.go +19 -0
  10. package/compiler/expr-call-helpers.go +0 -28
  11. package/compiler/expr-call-make.go +93 -343
  12. package/compiler/expr-call-type-conversion.go +221 -249
  13. package/compiler/expr-call.go +70 -69
  14. package/compiler/expr-selector.go +21 -24
  15. package/compiler/expr.go +3 -60
  16. package/compiler/protobuf.go +180 -36
  17. package/compiler/spec-value.go +132 -24
  18. package/compiler/spec.go +14 -55
  19. package/compiler/stmt-assign.go +338 -356
  20. package/compiler/stmt-range.go +4 -24
  21. package/compiler/stmt.go +92 -203
  22. package/compiler/type-utils.go +185 -0
  23. package/compiler/type.go +26 -80
  24. package/dist/gs/builtin/slice.d.ts +1 -1
  25. package/dist/gs/builtin/slice.js +3 -0
  26. package/dist/gs/builtin/slice.js.map +1 -1
  27. package/dist/gs/builtin/type.js +8 -2
  28. package/dist/gs/builtin/type.js.map +1 -1
  29. package/dist/gs/fmt/fmt.js +113 -16
  30. package/dist/gs/fmt/fmt.js.map +1 -1
  31. package/dist/gs/runtime/runtime.d.ts +1 -1
  32. package/dist/gs/runtime/runtime.js +1 -1
  33. package/dist/gs/slices/slices.d.ts +23 -0
  34. package/dist/gs/slices/slices.js +61 -0
  35. package/dist/gs/slices/slices.js.map +1 -1
  36. package/go.mod +8 -8
  37. package/go.sum +14 -14
  38. package/gs/builtin/slice.ts +5 -2
  39. package/gs/builtin/type.ts +13 -6
  40. package/gs/fmt/fmt.test.ts +176 -0
  41. package/gs/fmt/fmt.ts +109 -18
  42. package/gs/runtime/runtime.ts +1 -1
  43. package/gs/slices/slices.ts +68 -0
  44. package/package.json +3 -3
package/gs/fmt/fmt.ts CHANGED
@@ -34,14 +34,19 @@ function formatValue(value: any, verb: string): string {
34
34
  case 'v': // default format
35
35
  return defaultFormat(value)
36
36
  case 'd': // decimal integer
37
- return String(Math.floor(Number(value)))
37
+ return String(Math.trunc(Number(value)))
38
38
  case 'f': // decimal point, no exponent
39
39
  return Number(value).toString()
40
40
  case 's': // string
41
41
  return String(value)
42
42
  case 't': // boolean
43
43
  return value ? 'true' : 'false'
44
- case 'T': // type
44
+ case 'T': // type (approximate Go names for primitives we need)
45
+ if (typeof value === 'number') {
46
+ return Number.isInteger(value) ? 'int' : 'float64'
47
+ }
48
+ if (typeof value === 'boolean') return 'bool'
49
+ if (typeof value === 'string') return 'string'
45
50
  return typeof value
46
51
  case 'c': // character (Unicode code point)
47
52
  return String.fromCharCode(Number(value))
@@ -61,10 +66,19 @@ function formatValue(value: any, verb: string): string {
61
66
  return Number(value).toPrecision()
62
67
  case 'G': // %E for large exponents, %F otherwise
63
68
  return Number(value).toPrecision().toUpperCase()
64
- case 'q': // quoted string
69
+ case 'q': // quoted string / rune
70
+ if (typeof value === 'number' && Number.isInteger(value)) {
71
+ // emulate quoted rune for integers in basic range
72
+ const ch = String.fromCodePoint(value)
73
+ return JSON.stringify(ch)
74
+ }
65
75
  return JSON.stringify(String(value))
66
- case 'p': // pointer (address)
67
- return '0x' + (value as any)?.__address?.toString(16) || '0'
76
+ case 'p': {
77
+ // pointer (address)
78
+ const addr = (value as any)?.__address
79
+ if (typeof addr === 'number') return '0x' + addr.toString(16)
80
+ return '0x0'
81
+ }
68
82
  default:
69
83
  return String(value)
70
84
  }
@@ -78,17 +92,62 @@ function defaultFormat(value: any): string {
78
92
  if (Array.isArray(value))
79
93
  return '[' + value.map(defaultFormat).join(' ') + ']'
80
94
  if (typeof value === 'object') {
95
+ // Prefer GoStringer if present
96
+ if (
97
+ (value as any).GoString &&
98
+ typeof (value as any).GoString === 'function'
99
+ ) {
100
+ try {
101
+ return (value as any).GoString()
102
+ } catch {
103
+ // Ignore error by continuing to next case.
104
+ }
105
+ }
106
+ // Prefer error interface if present
107
+ if ((value as any).Error && typeof (value as any).Error === 'function') {
108
+ try {
109
+ return (value as any).Error()
110
+ } catch {
111
+ // Ignore error by continuing to next case.
112
+ }
113
+ }
81
114
  // Check for Stringer interface
82
- if (value.String && typeof value.String === 'function') {
83
- return value.String()
115
+ if ((value as any).String && typeof (value as any).String === 'function') {
116
+ try {
117
+ return (value as any).String()
118
+ } catch {
119
+ // Ignore error by continuing to next case.
120
+ }
121
+ }
122
+ // Basic Map/Set rendering
123
+ if (value instanceof Map) {
124
+ const parts: string[] = []
125
+ for (const [k, v] of (value as Map<any, any>).entries()) {
126
+ parts.push(`${defaultFormat(k)}:${defaultFormat(v)}`)
127
+ }
128
+ return `{${parts.join(' ')}}`
129
+ }
130
+ if (value instanceof Set) {
131
+ const parts: string[] = []
132
+ for (const v of (value as Set<any>).values()) {
133
+ parts.push(defaultFormat(v))
134
+ }
135
+ return '[' + parts.join(' ') + ']'
84
136
  }
85
137
  // Default object representation
86
- if (value.constructor?.name && value.constructor.name !== 'Object') {
87
- return `{${Object.entries(value)
138
+ if (
139
+ (value as any).constructor?.name &&
140
+ (value as any).constructor.name !== 'Object'
141
+ ) {
142
+ return `{${Object.entries(value as Record<string, any>)
88
143
  .map(([k, v]) => `${k}:${defaultFormat(v)}`)
89
144
  .join(' ')}}`
90
145
  }
91
- return JSON.stringify(value)
146
+ try {
147
+ return JSON.stringify(value)
148
+ } catch {
149
+ return String(value)
150
+ }
92
151
  }
93
152
  return String(value)
94
153
  }
@@ -227,9 +286,18 @@ let stdout = {
227
286
 
228
287
  // Print functions
229
288
  export function Print(...a: any[]): [number, $.GoError | null] {
230
- const result = a.map(defaultFormat).join(' ')
231
- stdout.write(result)
232
- return [result.length, null]
289
+ // Go rule: add spaces between operands only when neither is a string
290
+ let out = ''
291
+ for (let i = 0; i < a.length; i++) {
292
+ if (i > 0) {
293
+ const prevIsString = typeof a[i - 1] === 'string'
294
+ const currIsString = typeof a[i] === 'string'
295
+ if (!prevIsString && !currIsString) out += ' '
296
+ }
297
+ out += defaultFormat(a[i])
298
+ }
299
+ stdout.write(out)
300
+ return [out.length, null]
233
301
  }
234
302
 
235
303
  export function Printf(
@@ -242,14 +310,26 @@ export function Printf(
242
310
  }
243
311
 
244
312
  export function Println(...a: any[]): [number, $.GoError | null] {
245
- const result = a.map(defaultFormat).join(' ') + '\n'
313
+ // Go Println: always space-separate operands, then newline
314
+ const body = a.map(defaultFormat).join(' ')
315
+ const result = body + '\n'
246
316
  stdout.write(result)
247
317
  return [result.length, null]
248
318
  }
249
319
 
250
320
  // Sprint functions (return strings)
251
321
  export function Sprint(...a: any[]): string {
252
- return a.map(defaultFormat).join(' ')
322
+ // Go rule: add spaces between operands only when neither is a string
323
+ let out = ''
324
+ for (let i = 0; i < a.length; i++) {
325
+ if (i > 0) {
326
+ const prevIsString = typeof a[i - 1] === 'string'
327
+ const currIsString = typeof a[i] === 'string'
328
+ if (!prevIsString && !currIsString) out += ' '
329
+ }
330
+ out += defaultFormat(a[i])
331
+ }
332
+ return out
253
333
  }
254
334
 
255
335
  export function Sprintf(format: string, ...a: any[]): string {
@@ -262,9 +342,18 @@ export function Sprintln(...a: any[]): string {
262
342
 
263
343
  // Fprint functions (write to Writer) - simplified implementation
264
344
  export function Fprint(w: any, ...a: any[]): [number, $.GoError | null] {
265
- const result = a.map(defaultFormat).join(' ')
345
+ // Same spacing as Print
346
+ let out = ''
347
+ for (let i = 0; i < a.length; i++) {
348
+ if (i > 0) {
349
+ const prevIsString = typeof a[i - 1] === 'string'
350
+ const currIsString = typeof a[i] === 'string'
351
+ if (!prevIsString && !currIsString) out += ' '
352
+ }
353
+ out += defaultFormat(a[i])
354
+ }
266
355
  if (w && w.Write) {
267
- return w.Write(new TextEncoder().encode(result))
356
+ return w.Write(new TextEncoder().encode(out))
268
357
  }
269
358
  return [0, $.newError('Writer does not implement Write method')]
270
359
  }
@@ -282,7 +371,9 @@ export function Fprintf(
282
371
  }
283
372
 
284
373
  export function Fprintln(w: any, ...a: any[]): [number, $.GoError | null] {
285
- const result = a.map(defaultFormat).join(' ') + '\n'
374
+ // Same behavior as Println
375
+ const body = a.map(defaultFormat).join(' ')
376
+ const result = body + '\n'
286
377
  if (w && w.Write) {
287
378
  return w.Write(new TextEncoder().encode(result))
288
379
  }
@@ -3,7 +3,7 @@ export const GOOS = 'js'
3
3
  export const GOARCH = 'wasm'
4
4
 
5
5
  // Version returns the Go version as a string
6
- export const GOVERSION = 'go1.24.4'
6
+ export const GOVERSION = 'go1.25.3'
7
7
  export function Version(): string {
8
8
  return GOVERSION
9
9
  }
@@ -29,3 +29,71 @@ export function All<T>(
29
29
  export function Sort<T extends string | number>(s: $.Slice<T>): void {
30
30
  $.sortSlice(s)
31
31
  }
32
+
33
+ /**
34
+ * Delete removes the elements s[i:j] from s, returning the modified slice.
35
+ * Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
36
+ * This is equivalent to Go's slices.Delete function.
37
+ * @param s The slice to delete from
38
+ * @param i The start index (inclusive)
39
+ * @param j The end index (exclusive)
40
+ * @returns The modified slice
41
+ */
42
+ export function Delete<T>(s: $.Slice<T>, i: number, j: number): $.Slice<T> {
43
+ const length = $.len(s)
44
+ if (j > length || i < 0 || j < i) {
45
+ throw new Error(
46
+ `slice bounds out of range [${i}:${j}] with length ${length}`,
47
+ )
48
+ }
49
+ if (i === j) {
50
+ return s
51
+ }
52
+ // Shift elements after j to position i
53
+ const deleteCount = j - i
54
+ for (let k = j; k < length; k++) {
55
+ ;(s as any)[k - deleteCount] = (s as any)[k]
56
+ }
57
+ // Zero out the elements at the end
58
+ for (let k = length - deleteCount; k < length; k++) {
59
+ ;(s as any)[k] = null
60
+ }
61
+ // Update the slice length
62
+ return $.goSlice(s, 0, length - deleteCount) as $.Slice<T>
63
+ }
64
+
65
+ /**
66
+ * BinarySearchFunc works like BinarySearch, but uses a custom comparison function.
67
+ * The slice must be sorted in increasing order, where "increasing" is defined by cmp.
68
+ * cmp should return 0 if the slice element matches the target, a negative number if
69
+ * the slice element precedes the target, or a positive number if the slice element
70
+ * follows the target.
71
+ * This is equivalent to Go's slices.BinarySearchFunc function.
72
+ * @param x The sorted slice to search
73
+ * @param target The target value to search for
74
+ * @param cmp Comparison function
75
+ * @returns A tuple of [index, found] where index is the position and found indicates if target was found
76
+ */
77
+ export function BinarySearchFunc<E, T>(
78
+ x: $.Slice<E>,
79
+ target: T,
80
+ cmp: (a: E, b: T) => number,
81
+ ): [number, boolean] {
82
+ let left = 0
83
+ let right = $.len(x)
84
+
85
+ while (left < right) {
86
+ const mid = Math.floor((left + right) / 2)
87
+ const result = cmp((x as any)[mid] as E, target)
88
+
89
+ if (result < 0) {
90
+ left = mid + 1
91
+ } else if (result > 0) {
92
+ right = mid
93
+ } else {
94
+ return [mid, true]
95
+ }
96
+ }
97
+
98
+ return [left, false]
99
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "goscript",
3
3
  "description": "Go to TypeScript transpiler",
4
- "version": "0.0.58",
4
+ "version": "0.0.59",
5
5
  "author": {
6
6
  "name": "Aperture Robotics LLC.",
7
7
  "email": "support@aperture.us",
@@ -47,7 +47,7 @@
47
47
  "prepublishOnly": "npm run build",
48
48
  "example": "cd ./example/simple && bash run.bash",
49
49
  "test": "npm run test:go && npm run test:js",
50
- "test:go": "go test -v ./...",
50
+ "test:go": "go test ./...",
51
51
  "test:js": "npm run typecheck && vitest run",
52
52
  "typecheck": "tsgo --noEmit -p tsconfig.build.json",
53
53
  "format": "npm run format:go && npm run format:js && npm run format:config",
@@ -98,6 +98,6 @@
98
98
  "tsx": "^4.0.0",
99
99
  "typescript": "^5.8.3",
100
100
  "typescript-eslint": "^8.36.0",
101
- "vitest": "^3.1.2"
101
+ "vitest": "^4.0.0"
102
102
  }
103
103
  }