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.
- 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 +82 -24
- 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 +92 -203
- 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
|
@@ -8,95 +8,6 @@ import (
|
|
|
8
8
|
"github.com/pkg/errors"
|
|
9
9
|
)
|
|
10
10
|
|
|
11
|
-
// hasSliceConstraint checks if an interface constraint includes slice types
|
|
12
|
-
// For constraints like ~[]E, this returns true
|
|
13
|
-
func hasSliceConstraint(iface *types.Interface) bool {
|
|
14
|
-
// Check if the interface has type terms that include slice types
|
|
15
|
-
for i := 0; i < iface.NumEmbeddeds(); i++ {
|
|
16
|
-
embedded := iface.EmbeddedType(i)
|
|
17
|
-
if union, ok := embedded.(*types.Union); ok {
|
|
18
|
-
for j := 0; j < union.Len(); j++ {
|
|
19
|
-
term := union.Term(j)
|
|
20
|
-
if _, isSlice := term.Type().Underlying().(*types.Slice); isSlice {
|
|
21
|
-
return true
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
} else if _, isSlice := embedded.Underlying().(*types.Slice); isSlice {
|
|
25
|
-
return true
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return false
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// getSliceElementTypeFromConstraint extracts the element type from a slice constraint
|
|
32
|
-
// For constraints like ~[]E, this returns E
|
|
33
|
-
func getSliceElementTypeFromConstraint(iface *types.Interface) types.Type {
|
|
34
|
-
// Check if the interface has type terms that include slice types
|
|
35
|
-
for i := 0; i < iface.NumEmbeddeds(); i++ {
|
|
36
|
-
embedded := iface.EmbeddedType(i)
|
|
37
|
-
if union, ok := embedded.(*types.Union); ok {
|
|
38
|
-
for j := 0; j < union.Len(); j++ {
|
|
39
|
-
term := union.Term(j)
|
|
40
|
-
if sliceType, isSlice := term.Type().Underlying().(*types.Slice); isSlice {
|
|
41
|
-
return sliceType.Elem()
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
} else if sliceType, isSlice := embedded.Underlying().(*types.Slice); isSlice {
|
|
45
|
-
return sliceType.Elem()
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return nil
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// hasMixedStringByteConstraint checks if an interface constraint includes both string and []byte types
|
|
52
|
-
// For constraints like string | []byte, this returns true
|
|
53
|
-
// For pure slice constraints like ~[]E, this returns false
|
|
54
|
-
func hasMixedStringByteConstraint(iface *types.Interface) bool {
|
|
55
|
-
hasString := false
|
|
56
|
-
hasByteSlice := false
|
|
57
|
-
|
|
58
|
-
// Check if the interface has type terms that include both string and []byte
|
|
59
|
-
for i := 0; i < iface.NumEmbeddeds(); i++ {
|
|
60
|
-
embedded := iface.EmbeddedType(i)
|
|
61
|
-
if union, ok := embedded.(*types.Union); ok {
|
|
62
|
-
for j := 0; j < union.Len(); j++ {
|
|
63
|
-
term := union.Term(j)
|
|
64
|
-
termType := term.Type().Underlying()
|
|
65
|
-
|
|
66
|
-
// Check for string type
|
|
67
|
-
if basicType, isBasic := termType.(*types.Basic); isBasic && (basicType.Info()&types.IsString) != 0 {
|
|
68
|
-
hasString = true
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Check for []byte type
|
|
72
|
-
if sliceType, isSlice := termType.(*types.Slice); isSlice {
|
|
73
|
-
if elemType, isBasic := sliceType.Elem().(*types.Basic); isBasic && elemType.Kind() == types.Uint8 {
|
|
74
|
-
hasByteSlice = true
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
} else {
|
|
79
|
-
// Handle non-union embedded types
|
|
80
|
-
termType := embedded.Underlying()
|
|
81
|
-
|
|
82
|
-
// Check for string type
|
|
83
|
-
if basicType, isBasic := termType.(*types.Basic); isBasic && (basicType.Info()&types.IsString) != 0 {
|
|
84
|
-
hasString = true
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Check for []byte type
|
|
88
|
-
if sliceType, isSlice := termType.(*types.Slice); isSlice {
|
|
89
|
-
if elemType, isBasic := sliceType.Elem().(*types.Basic); isBasic && elemType.Kind() == types.Uint8 {
|
|
90
|
-
hasByteSlice = true
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Return true only if we have both string and []byte in the constraint
|
|
97
|
-
return hasString && hasByteSlice
|
|
98
|
-
}
|
|
99
|
-
|
|
100
11
|
// getTypeHintForSliceElement returns the appropriate type hint for makeSlice based on the Go element type
|
|
101
12
|
func (c *GoToTSCompiler) getTypeHintForSliceElement(elemType types.Type) string {
|
|
102
13
|
if basicType, isBasic := elemType.(*types.Basic); isBasic {
|
|
@@ -116,6 +27,81 @@ func (c *GoToTSCompiler) getTypeHintForSliceElement(elemType types.Type) string
|
|
|
116
27
|
return ""
|
|
117
28
|
}
|
|
118
29
|
|
|
30
|
+
// writeMakeChannel writes the TypeScript code for creating a channel with $.makeChannel
|
|
31
|
+
// It handles buffer size, zero value, and direction parameters
|
|
32
|
+
func (c *GoToTSCompiler) writeMakeChannel(chanType *types.Chan, bufferArg ast.Expr) error {
|
|
33
|
+
c.tsw.WriteLiterally("$.makeChannel<")
|
|
34
|
+
c.WriteGoType(chanType.Elem(), GoTypeContextGeneral)
|
|
35
|
+
c.tsw.WriteLiterally(">(")
|
|
36
|
+
|
|
37
|
+
// If buffer size is provided, add it
|
|
38
|
+
if bufferArg != nil {
|
|
39
|
+
if err := c.WriteValueExpr(bufferArg); err != nil {
|
|
40
|
+
return fmt.Errorf("failed to write buffer size in makeChannel: %w", err)
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
// Default to 0 (unbuffered channel)
|
|
44
|
+
c.tsw.WriteLiterally("0")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
c.tsw.WriteLiterally(", ") // Add comma for zero value argument
|
|
48
|
+
|
|
49
|
+
// Write the zero value for the channel's element type
|
|
50
|
+
if chanType.Elem().String() == "struct{}" {
|
|
51
|
+
c.tsw.WriteLiterally("{}")
|
|
52
|
+
} else {
|
|
53
|
+
c.WriteZeroValueForType(chanType.Elem())
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Add direction parameter
|
|
57
|
+
c.tsw.WriteLiterally(", ")
|
|
58
|
+
|
|
59
|
+
// Determine channel direction
|
|
60
|
+
switch chanType.Dir() {
|
|
61
|
+
case types.SendRecv:
|
|
62
|
+
c.tsw.WriteLiterally("'both'")
|
|
63
|
+
case types.SendOnly:
|
|
64
|
+
c.tsw.WriteLiterally("'send'")
|
|
65
|
+
case types.RecvOnly:
|
|
66
|
+
c.tsw.WriteLiterally("'receive'")
|
|
67
|
+
default:
|
|
68
|
+
c.tsw.WriteLiterally("'both'") // Default to bidirectional
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
c.tsw.WriteLiterally(")")
|
|
72
|
+
return nil
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// writeMakeSlice writes the TypeScript code for creating a slice
|
|
76
|
+
// It handles []byte special case and generic slice creation
|
|
77
|
+
func (c *GoToTSCompiler) writeMakeSlice(sliceType *types.Slice, exp *ast.CallExpr) error {
|
|
78
|
+
goElemType := sliceType.Elem()
|
|
79
|
+
|
|
80
|
+
// Check if it's []byte
|
|
81
|
+
if c.isByteSliceType(sliceType) {
|
|
82
|
+
var lengthArg, capacityArg interface{}
|
|
83
|
+
if len(exp.Args) >= 2 {
|
|
84
|
+
lengthArg = exp.Args[1]
|
|
85
|
+
}
|
|
86
|
+
if len(exp.Args) == 3 {
|
|
87
|
+
capacityArg = exp.Args[2]
|
|
88
|
+
}
|
|
89
|
+
return c.writeByteSliceCreation(lengthArg, capacityArg)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Handle other slice types
|
|
93
|
+
var lengthArg, capacityArg interface{}
|
|
94
|
+
if len(exp.Args) >= 2 {
|
|
95
|
+
lengthArg = exp.Args[1]
|
|
96
|
+
}
|
|
97
|
+
if len(exp.Args) == 3 {
|
|
98
|
+
capacityArg = exp.Args[2]
|
|
99
|
+
} else if len(exp.Args) > 3 {
|
|
100
|
+
return errors.New("makeSlice expects 2 or 3 arguments")
|
|
101
|
+
}
|
|
102
|
+
return c.writeGenericSliceCreation(goElemType, lengthArg, capacityArg)
|
|
103
|
+
}
|
|
104
|
+
|
|
119
105
|
// WriteCallExprMake handles make() function calls and translates them to TypeScript.
|
|
120
106
|
// It handles channel, map, and slice creation with different type patterns including:
|
|
121
107
|
// - Channel creation with different directions
|
|
@@ -126,46 +112,11 @@ func (c *GoToTSCompiler) WriteCallExprMake(exp *ast.CallExpr) error {
|
|
|
126
112
|
if typ := c.pkg.TypesInfo.TypeOf(exp.Args[0]); typ != nil {
|
|
127
113
|
if chanType, ok := typ.Underlying().(*types.Chan); ok {
|
|
128
114
|
// Handle channel creation: make(chan T, bufferSize) or make(chan T)
|
|
129
|
-
|
|
130
|
-
c.WriteGoType(chanType.Elem(), GoTypeContextGeneral)
|
|
131
|
-
c.tsw.WriteLiterally(">(")
|
|
132
|
-
|
|
133
|
-
// If buffer size is provided, add it
|
|
115
|
+
var bufferArg ast.Expr
|
|
134
116
|
if len(exp.Args) >= 2 {
|
|
135
|
-
|
|
136
|
-
return fmt.Errorf("failed to write buffer size in makeChannel: %w", err)
|
|
137
|
-
}
|
|
138
|
-
} else {
|
|
139
|
-
// Default to 0 (unbuffered channel)
|
|
140
|
-
c.tsw.WriteLiterally("0")
|
|
117
|
+
bufferArg = exp.Args[1]
|
|
141
118
|
}
|
|
142
|
-
|
|
143
|
-
c.tsw.WriteLiterally(", ") // Add comma for zero value argument
|
|
144
|
-
|
|
145
|
-
// Write the zero value for the channel's element type
|
|
146
|
-
if chanType.Elem().String() == "struct{}" {
|
|
147
|
-
c.tsw.WriteLiterally("{}")
|
|
148
|
-
} else {
|
|
149
|
-
c.WriteZeroValueForType(chanType.Elem())
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Add direction parameter
|
|
153
|
-
c.tsw.WriteLiterally(", ")
|
|
154
|
-
|
|
155
|
-
// Determine channel direction
|
|
156
|
-
switch chanType.Dir() {
|
|
157
|
-
case types.SendRecv:
|
|
158
|
-
c.tsw.WriteLiterally("'both'")
|
|
159
|
-
case types.SendOnly:
|
|
160
|
-
c.tsw.WriteLiterally("'send'")
|
|
161
|
-
case types.RecvOnly:
|
|
162
|
-
c.tsw.WriteLiterally("'receive'")
|
|
163
|
-
default:
|
|
164
|
-
c.tsw.WriteLiterally("'both'") // Default to bidirectional
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
c.tsw.WriteLiterally(")")
|
|
168
|
-
return nil // Handled make for channel
|
|
119
|
+
return c.writeMakeChannel(chanType, bufferArg)
|
|
169
120
|
}
|
|
170
121
|
}
|
|
171
122
|
// Handle make for slices: make([]T, len, cap) or make([]T, len)
|
|
@@ -191,25 +142,12 @@ func (c *GoToTSCompiler) WriteCallExprMake(exp *ast.CallExpr) error {
|
|
|
191
142
|
if !ok {
|
|
192
143
|
return errors.New("expected slice type for make call")
|
|
193
144
|
}
|
|
194
|
-
goElemType := goUnderlyingType.Elem()
|
|
195
|
-
|
|
196
|
-
// Check if it's make([]byte, ...)
|
|
197
|
-
if c.isByteSliceType(sliceType) {
|
|
198
|
-
var lengthArg, capacityArg interface{}
|
|
199
|
-
if len(exp.Args) >= 2 {
|
|
200
|
-
lengthArg = exp.Args[1]
|
|
201
|
-
}
|
|
202
|
-
if len(exp.Args) == 3 {
|
|
203
|
-
capacityArg = exp.Args[2]
|
|
204
|
-
}
|
|
205
|
-
return c.writeByteSliceCreation(lengthArg, capacityArg)
|
|
206
|
-
}
|
|
207
145
|
|
|
208
146
|
// Check if the element type is a generic type parameter
|
|
209
|
-
if _, isTypeParam :=
|
|
147
|
+
if _, isTypeParam := goUnderlyingType.Elem().(*types.TypeParam); isTypeParam {
|
|
210
148
|
// This is make([]E, n) where E is a type parameter
|
|
211
149
|
c.tsw.WriteLiterally("$.makeSlice<")
|
|
212
|
-
c.WriteGoType(
|
|
150
|
+
c.WriteGoType(goUnderlyingType.Elem(), GoTypeContextGeneral) // Write the element type parameter
|
|
213
151
|
c.tsw.WriteLiterally(">(")
|
|
214
152
|
|
|
215
153
|
if len(exp.Args) >= 2 {
|
|
@@ -232,17 +170,7 @@ func (c *GoToTSCompiler) WriteCallExprMake(exp *ast.CallExpr) error {
|
|
|
232
170
|
return nil // Handled make for []E where E is type parameter
|
|
233
171
|
}
|
|
234
172
|
|
|
235
|
-
|
|
236
|
-
if len(exp.Args) >= 2 {
|
|
237
|
-
lengthArg = exp.Args[1]
|
|
238
|
-
}
|
|
239
|
-
if len(exp.Args) == 3 {
|
|
240
|
-
capacityArg = exp.Args[2]
|
|
241
|
-
} else if len(exp.Args) > 3 {
|
|
242
|
-
return errors.New("makeSlice expects 2 or 3 arguments")
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
return c.writeGenericSliceCreation(goElemType, lengthArg, capacityArg)
|
|
173
|
+
return c.writeMakeSlice(goUnderlyingType, exp)
|
|
246
174
|
}
|
|
247
175
|
|
|
248
176
|
// Handle generic type parameter make calls: make(S, len, cap) where S ~[]E
|
|
@@ -291,34 +219,9 @@ func (c *GoToTSCompiler) WriteCallExprMake(exp *ast.CallExpr) error {
|
|
|
291
219
|
}
|
|
292
220
|
} else {
|
|
293
221
|
// Handle named types with slice underlying types: make(NamedSliceType, len, cap)
|
|
294
|
-
// This handles cases like: type appendSliceWriter []byte; make(appendSliceWriter, 0, len(s))
|
|
295
222
|
namedType := typeName.Type()
|
|
296
223
|
if sliceType, isSlice := namedType.Underlying().(*types.Slice); isSlice {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
// Check if it's a named type with []byte underlying type
|
|
300
|
-
if c.isByteSliceType(sliceType) {
|
|
301
|
-
var lengthArg, capacityArg interface{}
|
|
302
|
-
if len(exp.Args) >= 2 {
|
|
303
|
-
lengthArg = exp.Args[1]
|
|
304
|
-
}
|
|
305
|
-
if len(exp.Args) == 3 {
|
|
306
|
-
capacityArg = exp.Args[2]
|
|
307
|
-
}
|
|
308
|
-
return c.writeByteSliceCreation(lengthArg, capacityArg)
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// Handle other named slice types
|
|
312
|
-
var lengthArg, capacityArg interface{}
|
|
313
|
-
if len(exp.Args) >= 2 {
|
|
314
|
-
lengthArg = exp.Args[1]
|
|
315
|
-
}
|
|
316
|
-
if len(exp.Args) == 3 {
|
|
317
|
-
capacityArg = exp.Args[2]
|
|
318
|
-
} else if len(exp.Args) > 3 {
|
|
319
|
-
return errors.New("makeSlice expects 2 or 3 arguments")
|
|
320
|
-
}
|
|
321
|
-
return c.writeGenericSliceCreation(goElemType, lengthArg, capacityArg)
|
|
224
|
+
return c.writeMakeSlice(sliceType, exp)
|
|
322
225
|
}
|
|
323
226
|
|
|
324
227
|
// Handle named types with map underlying types: make(NamedMapType)
|
|
@@ -333,46 +236,11 @@ func (c *GoToTSCompiler) WriteCallExprMake(exp *ast.CallExpr) error {
|
|
|
333
236
|
|
|
334
237
|
// Handle named types with channel underlying types: make(NamedChannelType, bufferSize)
|
|
335
238
|
if chanType, isChan := namedType.Underlying().(*types.Chan); isChan {
|
|
336
|
-
|
|
337
|
-
c.WriteGoType(chanType.Elem(), GoTypeContextGeneral)
|
|
338
|
-
c.tsw.WriteLiterally(">(")
|
|
339
|
-
|
|
340
|
-
// If buffer size is provided, add it
|
|
239
|
+
var bufferArg ast.Expr
|
|
341
240
|
if len(exp.Args) >= 2 {
|
|
342
|
-
|
|
343
|
-
return fmt.Errorf("failed to write buffer size in makeChannel: %w", err)
|
|
344
|
-
}
|
|
345
|
-
} else {
|
|
346
|
-
// Default to 0 (unbuffered channel)
|
|
347
|
-
c.tsw.WriteLiterally("0")
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
c.tsw.WriteLiterally(", ") // Add comma for zero value argument
|
|
351
|
-
|
|
352
|
-
// Write the zero value for the channel's element type
|
|
353
|
-
if chanType.Elem().String() == "struct{}" {
|
|
354
|
-
c.tsw.WriteLiterally("{}")
|
|
355
|
-
} else {
|
|
356
|
-
c.WriteZeroValueForType(chanType.Elem())
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// Add direction parameter
|
|
360
|
-
c.tsw.WriteLiterally(", ")
|
|
361
|
-
|
|
362
|
-
// Determine channel direction
|
|
363
|
-
switch chanType.Dir() {
|
|
364
|
-
case types.SendRecv:
|
|
365
|
-
c.tsw.WriteLiterally("'both'")
|
|
366
|
-
case types.SendOnly:
|
|
367
|
-
c.tsw.WriteLiterally("'send'")
|
|
368
|
-
case types.RecvOnly:
|
|
369
|
-
c.tsw.WriteLiterally("'receive'")
|
|
370
|
-
default:
|
|
371
|
-
c.tsw.WriteLiterally("'both'") // Default to bidirectional
|
|
241
|
+
bufferArg = exp.Args[1]
|
|
372
242
|
}
|
|
373
|
-
|
|
374
|
-
c.tsw.WriteLiterally(")")
|
|
375
|
-
return nil // Handled make for named channel type
|
|
243
|
+
return c.writeMakeChannel(chanType, bufferArg)
|
|
376
244
|
}
|
|
377
245
|
}
|
|
378
246
|
}
|
|
@@ -399,75 +267,16 @@ func (c *GoToTSCompiler) WriteCallExprMake(exp *ast.CallExpr) error {
|
|
|
399
267
|
|
|
400
268
|
// Handle instantiated generic slice types: make(GenericSlice[T], len, cap)
|
|
401
269
|
if sliceType, isSlice := underlying.(*types.Slice); isSlice {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
// Check if it's an instantiated generic type with []byte underlying type
|
|
405
|
-
if c.isByteSliceType(types.NewSlice(goElemType)) {
|
|
406
|
-
var lengthArg, capacityArg interface{}
|
|
407
|
-
if len(exp.Args) >= 2 {
|
|
408
|
-
lengthArg = exp.Args[1]
|
|
409
|
-
}
|
|
410
|
-
if len(exp.Args) == 3 {
|
|
411
|
-
capacityArg = exp.Args[2]
|
|
412
|
-
}
|
|
413
|
-
return c.writeByteSliceCreation(lengthArg, capacityArg)
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// Handle other instantiated generic slice types
|
|
417
|
-
var lengthArg, capacityArg interface{}
|
|
418
|
-
if len(exp.Args) >= 2 {
|
|
419
|
-
lengthArg = exp.Args[1]
|
|
420
|
-
}
|
|
421
|
-
if len(exp.Args) == 3 {
|
|
422
|
-
capacityArg = exp.Args[2]
|
|
423
|
-
} else if len(exp.Args) > 3 {
|
|
424
|
-
return errors.New("makeSlice expects 2 or 3 arguments")
|
|
425
|
-
}
|
|
426
|
-
return c.writeGenericSliceCreation(goElemType, lengthArg, capacityArg)
|
|
270
|
+
return c.writeMakeSlice(sliceType, exp)
|
|
427
271
|
}
|
|
428
272
|
|
|
429
273
|
// Handle instantiated generic channel types: make(GenericChannel[T], bufferSize)
|
|
430
274
|
if chanType, isChan := underlying.(*types.Chan); isChan {
|
|
431
|
-
|
|
432
|
-
c.WriteGoType(chanType.Elem(), GoTypeContextGeneral)
|
|
433
|
-
c.tsw.WriteLiterally(">(")
|
|
434
|
-
|
|
435
|
-
// If buffer size is provided, add it
|
|
275
|
+
var bufferArg ast.Expr
|
|
436
276
|
if len(exp.Args) >= 2 {
|
|
437
|
-
|
|
438
|
-
return fmt.Errorf("failed to write buffer size in makeChannel: %w", err)
|
|
439
|
-
}
|
|
440
|
-
} else {
|
|
441
|
-
// Default to 0 (unbuffered channel)
|
|
442
|
-
c.tsw.WriteLiterally("0")
|
|
277
|
+
bufferArg = exp.Args[1]
|
|
443
278
|
}
|
|
444
|
-
|
|
445
|
-
c.tsw.WriteLiterally(", ") // Add comma for zero value argument
|
|
446
|
-
|
|
447
|
-
// Write the zero value for the channel's element type
|
|
448
|
-
if chanType.Elem().String() == "struct{}" {
|
|
449
|
-
c.tsw.WriteLiterally("{}")
|
|
450
|
-
} else {
|
|
451
|
-
c.WriteZeroValueForType(chanType.Elem())
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
// Add direction parameter
|
|
455
|
-
c.tsw.WriteLiterally(", ")
|
|
456
|
-
|
|
457
|
-
// Determine channel direction
|
|
458
|
-
switch chanType.Dir() {
|
|
459
|
-
case types.SendRecv:
|
|
460
|
-
c.tsw.WriteLiterally("'both'")
|
|
461
|
-
case types.SendOnly:
|
|
462
|
-
c.tsw.WriteLiterally("'send'")
|
|
463
|
-
case types.RecvOnly:
|
|
464
|
-
c.tsw.WriteLiterally("'receive'")
|
|
465
|
-
default:
|
|
466
|
-
c.tsw.WriteLiterally("'both'") // Default to bidirectional
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
c.tsw.WriteLiterally(")")
|
|
470
|
-
return nil // Handled make for instantiated generic channel type
|
|
279
|
+
return c.writeMakeChannel(chanType, bufferArg)
|
|
471
280
|
}
|
|
472
281
|
}
|
|
473
282
|
}
|
|
@@ -491,75 +300,16 @@ func (c *GoToTSCompiler) WriteCallExprMake(exp *ast.CallExpr) error {
|
|
|
491
300
|
|
|
492
301
|
// Handle selector expression slice types: make(pkg.SliceType, len, cap)
|
|
493
302
|
if sliceType, isSlice := underlying.(*types.Slice); isSlice {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
// Check if it's a selector expression with []byte underlying type
|
|
497
|
-
if c.isByteSliceType(sliceType) {
|
|
498
|
-
var lengthArg, capacityArg interface{}
|
|
499
|
-
if len(exp.Args) >= 2 {
|
|
500
|
-
lengthArg = exp.Args[1]
|
|
501
|
-
}
|
|
502
|
-
if len(exp.Args) == 3 {
|
|
503
|
-
capacityArg = exp.Args[2]
|
|
504
|
-
}
|
|
505
|
-
return c.writeByteSliceCreation(lengthArg, capacityArg)
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
// Handle other selector expression slice types
|
|
509
|
-
var lengthArg, capacityArg interface{}
|
|
510
|
-
if len(exp.Args) >= 2 {
|
|
511
|
-
lengthArg = exp.Args[1]
|
|
512
|
-
}
|
|
513
|
-
if len(exp.Args) == 3 {
|
|
514
|
-
capacityArg = exp.Args[2]
|
|
515
|
-
} else if len(exp.Args) > 3 {
|
|
516
|
-
return errors.New("makeSlice expects 2 or 3 arguments")
|
|
517
|
-
}
|
|
518
|
-
return c.writeGenericSliceCreation(goElemType, lengthArg, capacityArg)
|
|
303
|
+
return c.writeMakeSlice(sliceType, exp)
|
|
519
304
|
}
|
|
520
305
|
|
|
521
306
|
// Handle selector expression channel types: make(pkg.ChannelType, bufferSize)
|
|
522
307
|
if chanType, isChan := underlying.(*types.Chan); isChan {
|
|
523
|
-
|
|
524
|
-
c.WriteGoType(chanType.Elem(), GoTypeContextGeneral)
|
|
525
|
-
c.tsw.WriteLiterally(">(")
|
|
526
|
-
|
|
527
|
-
// If buffer size is provided, add it
|
|
308
|
+
var bufferArg ast.Expr
|
|
528
309
|
if len(exp.Args) >= 2 {
|
|
529
|
-
|
|
530
|
-
return fmt.Errorf("failed to write buffer size in makeChannel: %w", err)
|
|
531
|
-
}
|
|
532
|
-
} else {
|
|
533
|
-
// Default to 0 (unbuffered channel)
|
|
534
|
-
c.tsw.WriteLiterally("0")
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
c.tsw.WriteLiterally(", ") // Add comma for zero value argument
|
|
538
|
-
|
|
539
|
-
// Write the zero value for the channel's element type
|
|
540
|
-
if chanType.Elem().String() == "struct{}" {
|
|
541
|
-
c.tsw.WriteLiterally("{}")
|
|
542
|
-
} else {
|
|
543
|
-
c.WriteZeroValueForType(chanType.Elem())
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
// Add direction parameter
|
|
547
|
-
c.tsw.WriteLiterally(", ")
|
|
548
|
-
|
|
549
|
-
// Determine channel direction
|
|
550
|
-
switch chanType.Dir() {
|
|
551
|
-
case types.SendRecv:
|
|
552
|
-
c.tsw.WriteLiterally("'both'")
|
|
553
|
-
case types.SendOnly:
|
|
554
|
-
c.tsw.WriteLiterally("'send'")
|
|
555
|
-
case types.RecvOnly:
|
|
556
|
-
c.tsw.WriteLiterally("'receive'")
|
|
557
|
-
default:
|
|
558
|
-
c.tsw.WriteLiterally("'both'") // Default to bidirectional
|
|
310
|
+
bufferArg = exp.Args[1]
|
|
559
311
|
}
|
|
560
|
-
|
|
561
|
-
c.tsw.WriteLiterally(")")
|
|
562
|
-
return nil // Handled make for selector expression channel type
|
|
312
|
+
return c.writeMakeChannel(chanType, bufferArg)
|
|
563
313
|
}
|
|
564
314
|
}
|
|
565
315
|
}
|