goscript 0.0.57 → 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.
- package/README.md +40 -33
- package/compiler/analysis.go +115 -19
- package/compiler/assignment.go +163 -217
- package/compiler/compiler.go +35 -31
- package/compiler/composite-lit.go +233 -196
- package/compiler/constraint.go +88 -0
- package/compiler/decl.go +418 -7
- package/compiler/expr-call-async.go +20 -34
- package/compiler/expr-call-builtins.go +19 -0
- package/compiler/expr-call-helpers.go +0 -28
- package/compiler/expr-call-make.go +93 -343
- package/compiler/expr-call-type-conversion.go +221 -249
- package/compiler/expr-call.go +70 -69
- package/compiler/expr-selector.go +21 -24
- package/compiler/expr.go +3 -60
- package/compiler/protobuf.go +180 -36
- package/compiler/spec-value.go +132 -24
- package/compiler/spec.go +14 -55
- package/compiler/stmt-assign.go +338 -356
- package/compiler/stmt-range.go +4 -24
- package/compiler/stmt.go +99 -172
- package/compiler/type-utils.go +185 -0
- package/compiler/type.go +26 -80
- package/dist/gs/builtin/slice.d.ts +1 -1
- package/dist/gs/builtin/slice.js +3 -0
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.js +8 -2
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/fmt/fmt.js +113 -16
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/runtime/runtime.d.ts +1 -1
- package/dist/gs/runtime/runtime.js +1 -1
- package/dist/gs/slices/slices.d.ts +23 -0
- package/dist/gs/slices/slices.js +61 -0
- package/dist/gs/slices/slices.js.map +1 -1
- package/go.mod +8 -8
- package/go.sum +14 -14
- package/gs/builtin/slice.ts +5 -2
- package/gs/builtin/type.ts +13 -6
- package/gs/fmt/fmt.test.ts +176 -0
- package/gs/fmt/fmt.ts +109 -18
- package/gs/runtime/runtime.ts +1 -1
- package/gs/slices/slices.ts +68 -0
- 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.
|
|
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':
|
|
67
|
-
|
|
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
|
-
|
|
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 (
|
|
87
|
-
|
|
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
|
-
|
|
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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
}
|
package/gs/runtime/runtime.ts
CHANGED
package/gs/slices/slices.ts
CHANGED
|
@@ -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.
|
|
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
|
|
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": "^
|
|
101
|
+
"vitest": "^4.0.0"
|
|
102
102
|
}
|
|
103
103
|
}
|