goscript 0.0.48 → 0.0.50
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/cmd/goscript/deps.go +1 -4
- package/compiler/analysis.go +1120 -513
- package/compiler/analysis_test.go +113 -4
- package/compiler/compiler.go +88 -124
- package/compiler/decl.go +22 -0
- package/compiler/expr-call-async.go +46 -52
- package/compiler/expr-call-type-conversion.go +144 -59
- package/compiler/expr-call.go +235 -12
- package/compiler/expr.go +5 -82
- package/compiler/gs_dependencies_test.go +60 -1
- package/compiler/spec-value.go +73 -51
- package/compiler/spec.go +337 -151
- package/compiler/stmt-assign.go +7 -4
- package/compiler/stmt.go +250 -81
- package/compiler/type.go +13 -0
- package/dist/gs/builtin/builtin.d.ts +1 -5
- package/dist/gs/builtin/builtin.js +1 -34
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/context/context.d.ts +16 -18
- package/dist/gs/context/context.js +23 -13
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/fmt/fmt.js +22 -4
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/io/fs/fs.d.ts +6 -12
- package/dist/gs/io/fs/fs.js +52 -67
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/os/index.d.ts +2 -1
- package/dist/gs/os/index.js +1 -1
- package/dist/gs/os/index.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +7 -1
- package/dist/gs/os/types_js.gs.js +16 -1
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.js +2 -2
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +3 -3
- package/dist/gs/reflect/index.js +2 -2
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/map.js +2 -2
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +8 -9
- package/dist/gs/reflect/type.js +98 -103
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.d.ts +1 -10
- package/dist/gs/reflect/types.js +3 -26
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/value.js +23 -23
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js +3 -3
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/time/time.d.ts +13 -23
- package/dist/gs/time/time.js +57 -75
- package/dist/gs/time/time.js.map +1 -1
- package/gs/builtin/builtin.ts +3 -47
- package/gs/builtin/slice.ts +1 -1
- package/gs/bytes/meta.json +10 -0
- package/gs/context/context.ts +63 -45
- package/gs/fmt/fmt.ts +22 -4
- package/gs/fmt/meta.json +5 -0
- package/gs/internal/meta.json +5 -0
- package/gs/io/fs/fs.ts +58 -73
- package/gs/io/meta.json +9 -0
- package/gs/maps/meta.json +6 -0
- package/gs/math/meta.json +5 -0
- package/gs/os/index.ts +8 -1
- package/gs/os/meta.json +15 -0
- package/gs/os/types_js.gs.ts +22 -1
- package/gs/os/types_unix.gs.ts +2 -2
- package/gs/path/meta.json +6 -0
- package/gs/reflect/function-types.test.ts +10 -10
- package/gs/reflect/index.ts +6 -6
- package/gs/reflect/map.ts +2 -2
- package/gs/reflect/meta.json +5 -0
- package/gs/reflect/type.ts +105 -105
- package/gs/reflect/types.ts +2 -28
- package/gs/reflect/value.ts +23 -23
- package/gs/reflect/visiblefields.ts +3 -3
- package/gs/strconv/meta.json +5 -0
- package/gs/strings/meta.json +9 -0
- package/gs/sync/meta.json +19 -0
- package/gs/time/time.ts +65 -84
- package/package.json +2 -2
- package/dist/gs/builtin/io.d.ts +0 -16
- package/dist/gs/builtin/io.js +0 -15
- package/dist/gs/builtin/io.js.map +0 -1
- package/dist/gs/internal/testlog/index.d.ts +0 -1
- package/dist/gs/internal/testlog/index.js +0 -5
- package/dist/gs/internal/testlog/index.js.map +0 -1
- package/dist/gs/maps/iter.gs.d.ts +0 -7
- package/dist/gs/maps/iter.gs.js +0 -65
- package/dist/gs/maps/iter.gs.js.map +0 -1
- package/dist/gs/maps/maps.gs.d.ts +0 -7
- package/dist/gs/maps/maps.gs.js +0 -79
- package/dist/gs/maps/maps.gs.js.map +0 -1
- package/dist/gs/reflect/abi.d.ts +0 -59
- package/dist/gs/reflect/abi.gs.d.ts +0 -59
- package/dist/gs/reflect/abi.gs.js +0 -79
- package/dist/gs/reflect/abi.gs.js.map +0 -1
- package/dist/gs/reflect/abi.js +0 -79
- package/dist/gs/reflect/abi.js.map +0 -1
- package/dist/gs/reflect/badlinkname.d.ts +0 -52
- package/dist/gs/reflect/badlinkname.gs.d.ts +0 -52
- package/dist/gs/reflect/badlinkname.gs.js +0 -72
- package/dist/gs/reflect/badlinkname.gs.js.map +0 -1
- package/dist/gs/reflect/badlinkname.js +0 -72
- package/dist/gs/reflect/badlinkname.js.map +0 -1
- package/dist/gs/reflect/deepequal.gs.d.ts +0 -25
- package/dist/gs/reflect/deepequal.gs.js +0 -308
- package/dist/gs/reflect/deepequal.gs.js.map +0 -1
- package/dist/gs/reflect/float32reg_generic.gs.d.ts +0 -2
- package/dist/gs/reflect/float32reg_generic.gs.js +0 -10
- package/dist/gs/reflect/float32reg_generic.gs.js.map +0 -1
- package/dist/gs/reflect/index.gs.d.ts +0 -1
- package/dist/gs/reflect/index.gs.js +0 -3
- package/dist/gs/reflect/index.gs.js.map +0 -1
- package/dist/gs/reflect/iter.gs.d.ts +0 -3
- package/dist/gs/reflect/iter.gs.js +0 -24
- package/dist/gs/reflect/iter.gs.js.map +0 -1
- package/dist/gs/reflect/makefunc.gs.d.ts +0 -34
- package/dist/gs/reflect/makefunc.gs.js +0 -288
- package/dist/gs/reflect/makefunc.gs.js.map +0 -1
- package/dist/gs/reflect/map_swiss.gs.d.ts +0 -14
- package/dist/gs/reflect/map_swiss.gs.js +0 -70
- package/dist/gs/reflect/map_swiss.gs.js.map +0 -1
- package/dist/gs/reflect/reflect.gs.d.ts +0 -132
- package/dist/gs/reflect/reflect.gs.js +0 -437
- package/dist/gs/reflect/reflect.gs.js.map +0 -1
- package/dist/gs/reflect/swapper.gs.d.ts +0 -1
- package/dist/gs/reflect/swapper.gs.js +0 -32
- package/dist/gs/reflect/swapper.gs.js.map +0 -1
- package/dist/gs/reflect/type.gs.d.ts +0 -4
- package/dist/gs/reflect/type.gs.js +0 -21
- package/dist/gs/reflect/type.gs.js.map +0 -1
- package/dist/gs/reflect/value.gs.d.ts +0 -4
- package/dist/gs/reflect/value.gs.js +0 -12
- package/dist/gs/reflect/value.gs.js.map +0 -1
- package/dist/gs/reflect/visiblefields.gs.d.ts +0 -3
- package/dist/gs/reflect/visiblefields.gs.js +0 -123
- package/dist/gs/reflect/visiblefields.gs.js.map +0 -1
- package/dist/gs/stringslite/index.d.ts +0 -1
- package/dist/gs/stringslite/index.js +0 -2
- package/dist/gs/stringslite/index.js.map +0 -1
- package/dist/gs/stringslite/strings.d.ts +0 -11
- package/dist/gs/stringslite/strings.js +0 -67
- package/dist/gs/stringslite/strings.js.map +0 -1
- package/gs/bytes/metadata.go +0 -12
- package/gs/fmt/metadata.go +0 -7
- package/gs/internal/metadata.go +0 -7
- package/gs/io/io.go +0 -75
- package/gs/io/metadata.go +0 -11
- package/gs/maps/metadata.go +0 -8
- package/gs/math/metadata.go +0 -7
- package/gs/os/metadata.go +0 -17
- package/gs/path/metadata.go +0 -8
- package/gs/reflect/metadata.go +0 -7
- package/gs/strconv/metadata.go +0 -7
- package/gs/strings/metadata.go +0 -11
- package/gs/sync/metadata.go +0 -7
- package/gs/sync/sync.go +0 -64
package/compiler/spec.go
CHANGED
|
@@ -92,123 +92,240 @@ func (c *GoToTSCompiler) writeVarRefedFieldInitializer(fieldName string, fieldTy
|
|
|
92
92
|
c.tsw.WriteLiterally(": $.varRef(")
|
|
93
93
|
|
|
94
94
|
if isEmbedded {
|
|
95
|
-
|
|
96
|
-
_, isInterface := fieldType.Underlying().(*types.Interface)
|
|
97
|
-
if isPtr || isInterface {
|
|
98
|
-
c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
|
|
99
|
-
} else {
|
|
100
|
-
// Check if the embedded type is an interface
|
|
101
|
-
embeddedTypeUnderlying := fieldType
|
|
102
|
-
if named, isNamed := embeddedTypeUnderlying.(*types.Named); isNamed {
|
|
103
|
-
embeddedTypeUnderlying = named.Underlying()
|
|
104
|
-
}
|
|
105
|
-
if _, isInterface := embeddedTypeUnderlying.(*types.Interface); isInterface {
|
|
106
|
-
// For interfaces, use the provided value or null instead of trying to instantiate
|
|
107
|
-
c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
|
|
108
|
-
} else {
|
|
109
|
-
// For structs, instantiate with provided fields
|
|
110
|
-
typeForNew := fieldName
|
|
111
|
-
c.tsw.WriteLiterallyf("new %s(init?.%s)", typeForNew, fieldName)
|
|
112
|
-
}
|
|
113
|
-
}
|
|
95
|
+
c.writeEmbeddedFieldInitializer(fieldName, fieldType)
|
|
114
96
|
} else {
|
|
115
|
-
|
|
116
|
-
|
|
97
|
+
c.writeRegularFieldInitializer(fieldName, fieldType, astType)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
c.tsw.WriteLiterally(")")
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
func (c *GoToTSCompiler) writeEmbeddedFieldInitializer(fieldName string, fieldType types.Type) {
|
|
104
|
+
_, isPtr := fieldType.(*types.Pointer)
|
|
105
|
+
_, isInterface := fieldType.Underlying().(*types.Interface)
|
|
106
|
+
|
|
107
|
+
if isPtr || isInterface {
|
|
108
|
+
c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Check if the embedded type is an interface
|
|
113
|
+
embeddedTypeUnderlying := fieldType
|
|
114
|
+
if named, isNamed := embeddedTypeUnderlying.(*types.Named); isNamed {
|
|
115
|
+
embeddedTypeUnderlying = named.Underlying()
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if _, isInterface := embeddedTypeUnderlying.(*types.Interface); isInterface {
|
|
119
|
+
// For interfaces, use the provided value or null instead of trying to instantiate
|
|
120
|
+
c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// For structs, instantiate with provided fields
|
|
125
|
+
typeForNew := fieldName
|
|
126
|
+
c.tsw.WriteLiterallyf("new %s(init?.%s)", typeForNew, fieldName)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
func (c *GoToTSCompiler) writeRegularFieldInitializer(fieldName string, fieldType types.Type, astType ast.Expr) {
|
|
130
|
+
// Check if this is a struct value type that needs cloning
|
|
131
|
+
if c.isStructValueType(fieldType) {
|
|
132
|
+
structTypeNameForClone := c.getTypeString(fieldType)
|
|
133
|
+
c.tsw.WriteLiterallyf("init?.%s?.clone() ?? new %s()", fieldName, structTypeNameForClone)
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
c.tsw.WriteLiterallyf("init?.%s ?? ", fieldName)
|
|
138
|
+
|
|
139
|
+
// Debug for Mode field specifically
|
|
140
|
+
if fieldName == "Mode" {
|
|
141
|
+
fmt.Printf("DEBUG Mode field: Type=%T, String=%s\n", fieldType, fieldType.String())
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Priority 1: Check if this is a wrapper type
|
|
145
|
+
if c.analysis.IsNamedBasicType(fieldType) {
|
|
146
|
+
// For wrapper types, use the zero value of the underlying type with type casting
|
|
117
147
|
if named, ok := fieldType.(*types.Named); ok {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
148
|
+
c.WriteZeroValueForType(named.Underlying())
|
|
149
|
+
c.tsw.WriteLiterally(" as ")
|
|
150
|
+
c.WriteGoType(fieldType, GoTypeContextGeneral)
|
|
151
|
+
} else if alias, ok := fieldType.(*types.Alias); ok {
|
|
152
|
+
c.WriteZeroValueForType(alias.Underlying())
|
|
153
|
+
c.tsw.WriteLiterally(" as ")
|
|
154
|
+
c.WriteGoType(fieldType, GoTypeContextGeneral)
|
|
155
|
+
} else {
|
|
156
|
+
// Fallback to original behavior
|
|
157
|
+
c.WriteZeroValueForType(fieldType)
|
|
122
158
|
}
|
|
159
|
+
return
|
|
160
|
+
}
|
|
123
161
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
// Check if this is a named type or type alias and use constructor instead of null
|
|
129
|
-
if named, isNamed := fieldType.(*types.Named); isNamed {
|
|
130
|
-
// This is a named type
|
|
131
|
-
// Check if underlying type is an interface
|
|
132
|
-
if _, isInterface := named.Underlying().(*types.Interface); isInterface {
|
|
133
|
-
// For interfaces, use null as the zero value
|
|
134
|
-
c.tsw.WriteLiterally("null")
|
|
135
|
-
} else if _, isStruct := named.Underlying().(*types.Struct); !isStruct {
|
|
136
|
-
// For non-struct, non-interface named types, use constructor
|
|
137
|
-
c.tsw.WriteLiterally("new ")
|
|
138
|
-
c.WriteNamedType(named)
|
|
139
|
-
c.tsw.WriteLiterally("(")
|
|
140
|
-
c.WriteZeroValueForType(named.Underlying())
|
|
141
|
-
c.tsw.WriteLiterally(")")
|
|
142
|
-
} else {
|
|
143
|
-
c.WriteZeroValueForType(fieldType)
|
|
144
|
-
}
|
|
145
|
-
} else if alias, isAlias := fieldType.(*types.Alias); isAlias {
|
|
146
|
-
// This is a type alias (like os.FileMode)
|
|
147
|
-
// Check if underlying type is an interface
|
|
148
|
-
if _, isInterface := alias.Underlying().(*types.Interface); isInterface {
|
|
149
|
-
// For interface type aliases, use null as the zero value
|
|
150
|
-
c.tsw.WriteLiterally("null")
|
|
151
|
-
} else if _, isStruct := alias.Underlying().(*types.Struct); !isStruct {
|
|
152
|
-
// For non-struct, non-interface type aliases, use constructor
|
|
153
|
-
c.tsw.WriteLiterally("new ")
|
|
154
|
-
// Use AST type information if available to preserve qualified names
|
|
155
|
-
if astType != nil {
|
|
156
|
-
c.WriteTypeExpr(astType)
|
|
157
|
-
} else {
|
|
158
|
-
c.WriteGoType(fieldType, GoTypeContextGeneral)
|
|
159
|
-
}
|
|
160
|
-
c.tsw.WriteLiterally("(")
|
|
161
|
-
c.WriteZeroValueForType(alias.Underlying())
|
|
162
|
-
c.tsw.WriteLiterally(")")
|
|
163
|
-
} else {
|
|
164
|
-
c.WriteZeroValueForType(fieldType)
|
|
165
|
-
}
|
|
166
|
-
} else {
|
|
167
|
-
c.WriteZeroValueForType(fieldType)
|
|
168
|
-
}
|
|
162
|
+
// Priority 2: Handle imported types with basic underlying types (like os.FileMode)
|
|
163
|
+
if c.isImportedBasicType(fieldType) {
|
|
164
|
+
if fieldName == "Mode" {
|
|
165
|
+
fmt.Printf("DEBUG Mode field: Using imported basic type zero value\n")
|
|
169
166
|
}
|
|
167
|
+
c.writeImportedBasicTypeZeroValue(fieldType)
|
|
168
|
+
return
|
|
170
169
|
}
|
|
171
170
|
|
|
172
|
-
|
|
171
|
+
// Priority 3: Handle named types
|
|
172
|
+
if named, isNamed := fieldType.(*types.Named); isNamed {
|
|
173
|
+
if fieldName == "Mode" {
|
|
174
|
+
fmt.Printf("DEBUG Mode field: Using named type zero value\n")
|
|
175
|
+
}
|
|
176
|
+
c.writeNamedTypeZeroValue(named)
|
|
177
|
+
return
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Priority 4: Handle type aliases
|
|
181
|
+
if alias, isAlias := fieldType.(*types.Alias); isAlias {
|
|
182
|
+
if fieldName == "Mode" {
|
|
183
|
+
fmt.Printf("DEBUG Mode field: Using type alias zero value\n")
|
|
184
|
+
}
|
|
185
|
+
c.writeTypeAliasZeroValue(alias, astType)
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Default: use WriteZeroValueForType
|
|
190
|
+
if fieldName == "Mode" {
|
|
191
|
+
fmt.Printf("DEBUG Mode field: Using default WriteZeroValueForType\n")
|
|
192
|
+
}
|
|
193
|
+
c.WriteZeroValueForType(fieldType)
|
|
173
194
|
}
|
|
174
195
|
|
|
175
|
-
func (c *GoToTSCompiler)
|
|
176
|
-
|
|
177
|
-
|
|
196
|
+
func (c *GoToTSCompiler) isStructValueType(fieldType types.Type) bool {
|
|
197
|
+
if named, ok := fieldType.(*types.Named); ok {
|
|
198
|
+
if _, isStruct := named.Underlying().(*types.Struct); isStruct {
|
|
199
|
+
return true
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return false
|
|
203
|
+
}
|
|
178
204
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
205
|
+
func (c *GoToTSCompiler) isImportedBasicType(fieldType types.Type) bool {
|
|
206
|
+
// Handle named types
|
|
207
|
+
if named, isNamed := fieldType.(*types.Named); isNamed {
|
|
208
|
+
obj := named.Obj()
|
|
209
|
+
if obj == nil || obj.Pkg() == nil || obj.Pkg() == c.pkg.Types {
|
|
210
|
+
return false // Not imported or is local
|
|
185
211
|
}
|
|
186
212
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
c.tsw.WriteLiterallyf("this._fields.%s.value.clone()", fieldName)
|
|
191
|
-
} else { // Is a pointer to a struct, or not a struct
|
|
192
|
-
c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
|
|
193
|
-
}
|
|
194
|
-
} else {
|
|
195
|
-
c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
|
|
213
|
+
underlying := named.Underlying()
|
|
214
|
+
if underlying == nil {
|
|
215
|
+
return false
|
|
196
216
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
217
|
+
|
|
218
|
+
_, isBasic := underlying.(*types.Basic)
|
|
219
|
+
return isBasic
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Handle type aliases (like os.FileMode = fs.FileMode)
|
|
223
|
+
if alias, isAlias := fieldType.(*types.Alias); isAlias {
|
|
224
|
+
obj := alias.Obj()
|
|
225
|
+
if obj == nil || obj.Pkg() == nil || obj.Pkg() == c.pkg.Types {
|
|
226
|
+
return false // Not imported or is local
|
|
203
227
|
}
|
|
204
228
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
|
|
229
|
+
underlying := alias.Underlying()
|
|
230
|
+
if underlying == nil {
|
|
231
|
+
return false
|
|
209
232
|
}
|
|
233
|
+
|
|
234
|
+
_, isBasic := underlying.(*types.Basic)
|
|
235
|
+
return isBasic
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return false
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
func (c *GoToTSCompiler) writeImportedBasicTypeZeroValue(fieldType types.Type) {
|
|
242
|
+
if named, ok := fieldType.(*types.Named); ok {
|
|
243
|
+
underlying := named.Underlying()
|
|
244
|
+
fmt.Printf("DEBUG writeImportedBasicTypeZeroValue: Named type, underlying=%T\n", underlying)
|
|
245
|
+
// Write zero value of underlying type with type casting
|
|
246
|
+
c.WriteZeroValueForType(underlying)
|
|
247
|
+
c.tsw.WriteLiterally(" as ")
|
|
248
|
+
c.WriteGoType(fieldType, GoTypeContextGeneral)
|
|
249
|
+
return
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if alias, ok := fieldType.(*types.Alias); ok {
|
|
253
|
+
underlying := alias.Underlying()
|
|
254
|
+
fmt.Printf("DEBUG writeImportedBasicTypeZeroValue: Alias type, underlying=%T\n", underlying)
|
|
255
|
+
// Write zero value of underlying type with type casting
|
|
256
|
+
c.WriteZeroValueForType(underlying)
|
|
257
|
+
c.tsw.WriteLiterally(" as ")
|
|
258
|
+
c.WriteGoType(fieldType, GoTypeContextGeneral)
|
|
259
|
+
return
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Fallback (should not happen if isImportedBasicType was correct)
|
|
263
|
+
fmt.Printf("DEBUG writeImportedBasicTypeZeroValue: Fallback path\n")
|
|
264
|
+
c.WriteZeroValueForType(fieldType)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
func (c *GoToTSCompiler) writeNamedTypeZeroValue(named *types.Named) {
|
|
268
|
+
// Check if this is a wrapper type first
|
|
269
|
+
if c.analysis.IsNamedBasicType(named) {
|
|
270
|
+
// For wrapper types, use the zero value of the underlying type with type casting
|
|
271
|
+
c.WriteZeroValueForType(named.Underlying())
|
|
272
|
+
c.tsw.WriteLiterally(" as ")
|
|
273
|
+
c.WriteGoType(named, GoTypeContextGeneral)
|
|
274
|
+
return
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Check if underlying type is an interface
|
|
278
|
+
if _, isInterface := named.Underlying().(*types.Interface); isInterface {
|
|
279
|
+
c.tsw.WriteLiterally("null")
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Check if underlying type is a struct
|
|
284
|
+
if _, isStruct := named.Underlying().(*types.Struct); isStruct {
|
|
285
|
+
c.WriteZeroValueForType(named)
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// For non-struct, non-interface named types, use constructor
|
|
290
|
+
c.tsw.WriteLiterally("new ")
|
|
291
|
+
c.WriteNamedType(named)
|
|
292
|
+
c.tsw.WriteLiterally("(")
|
|
293
|
+
c.WriteZeroValueForType(named.Underlying())
|
|
294
|
+
c.tsw.WriteLiterally(")")
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
func (c *GoToTSCompiler) writeTypeAliasZeroValue(alias *types.Alias, astType ast.Expr) {
|
|
298
|
+
// Check if this is a wrapper type first
|
|
299
|
+
if c.analysis.IsNamedBasicType(alias) {
|
|
300
|
+
// For wrapper types, use the zero value of the underlying type with type casting
|
|
301
|
+
c.WriteZeroValueForType(alias.Underlying())
|
|
302
|
+
c.tsw.WriteLiterally(" as ")
|
|
303
|
+
c.WriteGoType(alias, GoTypeContextGeneral)
|
|
304
|
+
return
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Check if underlying type is an interface
|
|
308
|
+
if _, isInterface := alias.Underlying().(*types.Interface); isInterface {
|
|
309
|
+
c.tsw.WriteLiterally("null")
|
|
310
|
+
return
|
|
210
311
|
}
|
|
211
312
|
|
|
313
|
+
// Check if underlying type is a struct
|
|
314
|
+
if _, isStruct := alias.Underlying().(*types.Struct); isStruct {
|
|
315
|
+
c.WriteZeroValueForType(alias)
|
|
316
|
+
return
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// For non-struct, non-interface type aliases, use constructor
|
|
320
|
+
c.tsw.WriteLiterally("new ")
|
|
321
|
+
// Use AST type information if available to preserve qualified names
|
|
322
|
+
if astType != nil {
|
|
323
|
+
c.WriteTypeExpr(astType)
|
|
324
|
+
} else {
|
|
325
|
+
c.WriteGoType(alias, GoTypeContextGeneral)
|
|
326
|
+
}
|
|
327
|
+
c.tsw.WriteLiterally("(")
|
|
328
|
+
c.WriteZeroValueForType(alias.Underlying())
|
|
212
329
|
c.tsw.WriteLiterally(")")
|
|
213
330
|
}
|
|
214
331
|
|
|
@@ -244,7 +361,11 @@ func (c *GoToTSCompiler) hasReceiverMethods(typeName string) bool {
|
|
|
244
361
|
return false
|
|
245
362
|
}
|
|
246
363
|
|
|
247
|
-
// WriteNamedTypeWithMethods generates
|
|
364
|
+
// WriteNamedTypeWithMethods generates TypeScript code for Go named types that have methods.
|
|
365
|
+
// Instead of generating a class, it now generates:
|
|
366
|
+
// 1. A type alias for the underlying type
|
|
367
|
+
// 2. Function declarations for each method (TypeName_MethodName)
|
|
368
|
+
// 3. Function implementations for each method
|
|
248
369
|
func (c *GoToTSCompiler) WriteNamedTypeWithMethods(a *ast.TypeSpec) error {
|
|
249
370
|
className := a.Name.Name
|
|
250
371
|
|
|
@@ -258,49 +379,16 @@ func (c *GoToTSCompiler) WriteNamedTypeWithMethods(a *ast.TypeSpec) error {
|
|
|
258
379
|
c.tsw.WriteLiterally("export ")
|
|
259
380
|
}
|
|
260
381
|
|
|
261
|
-
|
|
262
|
-
c.tsw.
|
|
263
|
-
c.tsw.
|
|
264
|
-
|
|
265
|
-
// Constructor that takes the underlying type value
|
|
266
|
-
c.tsw.WriteLiterally("constructor(private _value: ")
|
|
267
|
-
// Use AST-based type writing to preserve qualified names like os.FileInfo
|
|
268
|
-
c.WriteTypeExpr(a.Type)
|
|
269
|
-
c.tsw.WriteLine(") {}")
|
|
270
|
-
c.tsw.WriteLine("")
|
|
271
|
-
|
|
272
|
-
// valueOf method to get the underlying value (for type conversions and operations)
|
|
273
|
-
c.tsw.WriteLiterally("valueOf(): ")
|
|
274
|
-
// Use AST-based type writing to preserve qualified names like os.FileInfo
|
|
275
|
-
c.WriteTypeExpr(a.Type)
|
|
276
|
-
c.tsw.WriteLine(" {")
|
|
277
|
-
c.tsw.Indent(1)
|
|
278
|
-
c.tsw.WriteLine("return this._value")
|
|
279
|
-
c.tsw.Indent(-1)
|
|
280
|
-
c.tsw.WriteLine("}")
|
|
281
|
-
c.tsw.WriteLine("")
|
|
282
|
-
|
|
283
|
-
// toString method for string conversion
|
|
284
|
-
c.tsw.WriteLine("toString(): string {")
|
|
285
|
-
c.tsw.Indent(1)
|
|
286
|
-
c.tsw.WriteLine("return String(this._value)")
|
|
287
|
-
c.tsw.Indent(-1)
|
|
288
|
-
c.tsw.WriteLine("}")
|
|
289
|
-
c.tsw.WriteLine("")
|
|
290
|
-
|
|
291
|
-
// Static from method for type conversion
|
|
292
|
-
c.tsw.WriteLiterallyf("static from(value: ")
|
|
382
|
+
// Generate type alias instead of class
|
|
383
|
+
c.tsw.WriteLiterally("type ")
|
|
384
|
+
c.tsw.WriteLiterally(className)
|
|
385
|
+
c.tsw.WriteLiterally(" = ")
|
|
293
386
|
// Use AST-based type writing to preserve qualified names like os.FileInfo
|
|
294
387
|
c.WriteTypeExpr(a.Type)
|
|
295
|
-
c.tsw.
|
|
296
|
-
c.tsw.WriteLine("")
|
|
297
|
-
c.tsw.Indent(1)
|
|
298
|
-
c.tsw.WriteLiterallyf("return new %s(value)", className)
|
|
388
|
+
c.tsw.WriteLine(";")
|
|
299
389
|
c.tsw.WriteLine("")
|
|
300
|
-
c.tsw.Indent(-1)
|
|
301
|
-
c.tsw.WriteLine("}")
|
|
302
390
|
|
|
303
|
-
//
|
|
391
|
+
// Generate function declarations and implementations for each method
|
|
304
392
|
for _, fileSyntax := range c.pkg.Syntax {
|
|
305
393
|
for _, decl := range fileSyntax.Decls {
|
|
306
394
|
funcDecl, isFunc := decl.(*ast.FuncDecl)
|
|
@@ -324,28 +412,86 @@ func (c *GoToTSCompiler) WriteNamedTypeWithMethods(a *ast.TypeSpec) error {
|
|
|
324
412
|
}
|
|
325
413
|
|
|
326
414
|
if recvTypeName == className {
|
|
327
|
-
|
|
328
|
-
|
|
415
|
+
if !isInsideFunction {
|
|
416
|
+
c.tsw.WriteLiterally("export ")
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Generate function signature: export function TypeName_MethodName(receiver: TypeName, ...args): ReturnType
|
|
420
|
+
c.tsw.WriteLiterally("function ")
|
|
421
|
+
c.tsw.WriteLiterally(className)
|
|
422
|
+
c.tsw.WriteLiterally("_")
|
|
423
|
+
c.tsw.WriteLiterally(funcDecl.Name.Name)
|
|
424
|
+
c.tsw.WriteLiterally("(")
|
|
425
|
+
|
|
426
|
+
// First parameter is the receiver - use the original receiver parameter name
|
|
427
|
+
var receiverParamName string = "receiver" // default fallback
|
|
428
|
+
if funcDecl.Recv != nil && len(funcDecl.Recv.List) > 0 {
|
|
429
|
+
if len(funcDecl.Recv.List[0].Names) > 0 {
|
|
430
|
+
if name := funcDecl.Recv.List[0].Names[0]; name != nil && name.Name != "_" {
|
|
431
|
+
receiverParamName = name.Name
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
c.tsw.WriteLiterally(receiverParamName)
|
|
436
|
+
c.tsw.WriteLiterally(": ")
|
|
437
|
+
c.tsw.WriteLiterally(className)
|
|
438
|
+
|
|
439
|
+
// Add other parameters
|
|
440
|
+
if funcDecl.Type.Params != nil && len(funcDecl.Type.Params.List) > 0 {
|
|
441
|
+
c.tsw.WriteLiterally(", ")
|
|
442
|
+
c.WriteFieldList(funcDecl.Type.Params, true) // true = arguments
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
c.tsw.WriteLiterally(")")
|
|
446
|
+
|
|
447
|
+
// Add return type
|
|
448
|
+
if funcDecl.Type.Results != nil && len(funcDecl.Type.Results.List) > 0 {
|
|
449
|
+
c.tsw.WriteLiterally(": ")
|
|
450
|
+
if len(funcDecl.Type.Results.List) == 1 {
|
|
451
|
+
c.WriteTypeExpr(funcDecl.Type.Results.List[0].Type)
|
|
452
|
+
} else {
|
|
453
|
+
c.tsw.WriteLiterally("[")
|
|
454
|
+
for i, field := range funcDecl.Type.Results.List {
|
|
455
|
+
if i > 0 {
|
|
456
|
+
c.tsw.WriteLiterally(", ")
|
|
457
|
+
}
|
|
458
|
+
c.WriteTypeExpr(field.Type)
|
|
459
|
+
}
|
|
460
|
+
c.tsw.WriteLiterally("]")
|
|
461
|
+
}
|
|
462
|
+
} else {
|
|
463
|
+
c.tsw.WriteLiterally(": void")
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
c.tsw.WriteLine(" {")
|
|
467
|
+
c.tsw.Indent(1)
|
|
468
|
+
|
|
469
|
+
// Write method body with receiver as first parameter
|
|
470
|
+
if err := c.writeWrapperFunctionBody(funcDecl, className); err != nil {
|
|
329
471
|
return err
|
|
330
472
|
}
|
|
473
|
+
|
|
474
|
+
c.tsw.Indent(-1)
|
|
475
|
+
c.tsw.WriteLine("}")
|
|
476
|
+
c.tsw.WriteLine("")
|
|
331
477
|
}
|
|
332
478
|
}
|
|
333
479
|
}
|
|
334
480
|
|
|
335
|
-
c.tsw.Indent(-1)
|
|
336
|
-
c.tsw.WriteLine("}")
|
|
337
|
-
|
|
338
481
|
return nil
|
|
339
482
|
}
|
|
340
483
|
|
|
341
|
-
//
|
|
342
|
-
func (c *GoToTSCompiler)
|
|
343
|
-
|
|
344
|
-
if
|
|
345
|
-
|
|
484
|
+
// writeWrapperFunctionBody writes the body of a wrapper function, treating the receiver as the first parameter
|
|
485
|
+
func (c *GoToTSCompiler) writeWrapperFunctionBody(decl *ast.FuncDecl, typeName string) error {
|
|
486
|
+
// Write function body statements directly - identifier mapping is handled by pre-computed analysis
|
|
487
|
+
if decl.Body != nil {
|
|
488
|
+
for _, stmt := range decl.Body.List {
|
|
489
|
+
if err := c.WriteStmt(stmt); err != nil {
|
|
490
|
+
return err
|
|
491
|
+
}
|
|
492
|
+
}
|
|
346
493
|
}
|
|
347
|
-
|
|
348
|
-
return c.writeMethodBodyWithReceiverBinding(decl, "this._value")
|
|
494
|
+
return nil
|
|
349
495
|
}
|
|
350
496
|
|
|
351
497
|
// WriteTypeSpec writes the type specification to the output.
|
|
@@ -515,3 +661,43 @@ func (c *GoToTSCompiler) WriteImportSpec(a *ast.ImportSpec) {
|
|
|
515
661
|
|
|
516
662
|
c.tsw.WriteImport(impName, tsImportPath+"/index.js")
|
|
517
663
|
}
|
|
664
|
+
|
|
665
|
+
func (c *GoToTSCompiler) writeClonedFieldInitializer(fieldName string, fieldType types.Type, isEmbedded bool) {
|
|
666
|
+
c.tsw.WriteLiterally(fieldName)
|
|
667
|
+
c.tsw.WriteLiterally(": $.varRef(")
|
|
668
|
+
|
|
669
|
+
if isEmbedded {
|
|
670
|
+
isPointerToStruct := false
|
|
671
|
+
trueType := fieldType
|
|
672
|
+
if ptr, isPtr := trueType.(*types.Pointer); isPtr {
|
|
673
|
+
trueType = ptr.Elem()
|
|
674
|
+
isPointerToStruct = true
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
if named, isNamed := trueType.(*types.Named); isNamed {
|
|
678
|
+
_, isUnderlyingStruct := named.Underlying().(*types.Struct)
|
|
679
|
+
if isUnderlyingStruct && !isPointerToStruct { // Is a value struct
|
|
680
|
+
c.tsw.WriteLiterallyf("this._fields.%s.value.clone()", fieldName)
|
|
681
|
+
} else { // Is a pointer to a struct, or not a struct
|
|
682
|
+
c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
|
|
683
|
+
}
|
|
684
|
+
} else {
|
|
685
|
+
c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
|
|
686
|
+
}
|
|
687
|
+
} else {
|
|
688
|
+
isValueTypeStruct := false
|
|
689
|
+
if named, ok := fieldType.(*types.Named); ok {
|
|
690
|
+
if _, isStruct := named.Underlying().(*types.Struct); isStruct {
|
|
691
|
+
isValueTypeStruct = true
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if isValueTypeStruct {
|
|
696
|
+
c.tsw.WriteLiterallyf("this._fields.%s.value?.clone() ?? null", fieldName)
|
|
697
|
+
} else {
|
|
698
|
+
c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
c.tsw.WriteLiterally(")")
|
|
703
|
+
}
|
package/compiler/stmt-assign.go
CHANGED
|
@@ -117,6 +117,8 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
c.tsw.WriteLiterally("] = ")
|
|
120
|
+
// Add await if the call is async
|
|
121
|
+
c.writeAsyncCallIfNeeded(callExpr)
|
|
120
122
|
c.WriteValueExpr(callExpr)
|
|
121
123
|
c.tsw.WriteLine("")
|
|
122
124
|
return nil
|
|
@@ -165,6 +167,8 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
|
|
|
165
167
|
|
|
166
168
|
// Write a temporary variable to hold the function call result
|
|
167
169
|
c.tsw.WriteLiterally(" const _tmp = ")
|
|
170
|
+
// Add await if the call is async
|
|
171
|
+
c.writeAsyncCallIfNeeded(callExpr)
|
|
168
172
|
if err := c.WriteValueExpr(callExpr); err != nil {
|
|
169
173
|
return fmt.Errorf("failed to write RHS call expression in assignment: %w", err)
|
|
170
174
|
}
|
|
@@ -287,10 +291,9 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
|
|
|
287
291
|
}
|
|
288
292
|
c.tsw.WriteLiterally("] = ")
|
|
289
293
|
|
|
290
|
-
//
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
}
|
|
294
|
+
// Add await if the call is async
|
|
295
|
+
c.writeAsyncCallIfNeeded(callExpr)
|
|
296
|
+
c.WriteValueExpr(callExpr)
|
|
294
297
|
|
|
295
298
|
c.tsw.WriteLine("")
|
|
296
299
|
return nil
|