gofront 0.0.5 → 0.0.7
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 +104 -37
- package/package.json +7 -4
- package/src/codegen/expressions.js +589 -7
- package/src/codegen/source-map.js +13 -5
- package/src/codegen/statements.js +30 -26
- package/src/codegen.js +99 -22
- package/src/compiler.js +10 -3
- package/src/dev-server.js +83 -0
- package/src/index.js +35 -5
- package/src/parser.js +0 -10
- package/src/typechecker/expressions.js +38 -9
- package/src/typechecker/stdlib.js +764 -0
- package/src/typechecker/types.js +15 -20
- package/src/typechecker.js +34 -394
|
@@ -111,8 +111,16 @@ export const expressionCheckMethods = {
|
|
|
111
111
|
if (expr.expr._isTypeRef) {
|
|
112
112
|
let base = baseType.kind === "named" ? baseType.underlying : baseType;
|
|
113
113
|
base = this.resolveType(base);
|
|
114
|
+
let methodType = null;
|
|
114
115
|
if (base?.kind === "struct" && base.methods?.has(expr.field)) {
|
|
115
|
-
|
|
116
|
+
methodType = base.methods.get(expr.field);
|
|
117
|
+
} else if (
|
|
118
|
+
baseType.kind === "named" &&
|
|
119
|
+
baseType.methods?.has(expr.field)
|
|
120
|
+
) {
|
|
121
|
+
methodType = baseType.methods.get(expr.field);
|
|
122
|
+
}
|
|
123
|
+
if (methodType) {
|
|
116
124
|
// Return a func type with the receiver prepended to params
|
|
117
125
|
expr._isMethodExpr = true;
|
|
118
126
|
expr._methodExprRecv = baseType;
|
|
@@ -129,7 +137,10 @@ export const expressionCheckMethods = {
|
|
|
129
137
|
if (ft?.kind === "func") {
|
|
130
138
|
let base = baseType.kind === "named" ? baseType.underlying : baseType;
|
|
131
139
|
base = this.resolveType(base);
|
|
132
|
-
if (
|
|
140
|
+
if (
|
|
141
|
+
(base?.kind === "struct" && base.methods?.has(expr.field)) ||
|
|
142
|
+
(baseType.kind === "named" && baseType.methods?.has(expr.field))
|
|
143
|
+
) {
|
|
133
144
|
expr._isMethodValue = true;
|
|
134
145
|
}
|
|
135
146
|
}
|
|
@@ -140,9 +151,14 @@ export const expressionCheckMethods = {
|
|
|
140
151
|
const bt = this.checkExpr(expr.expr, scope);
|
|
141
152
|
this.checkExpr(expr.index, scope);
|
|
142
153
|
if (isAny(bt)) return ANY;
|
|
143
|
-
|
|
154
|
+
// Named types (e.g. type Nums []int) are indexable via their underlying
|
|
155
|
+
const btu =
|
|
156
|
+
bt.kind === "named"
|
|
157
|
+
? (this.resolveType(bt.underlying) ?? bt.underlying)
|
|
158
|
+
: bt;
|
|
159
|
+
if (btu.kind === "slice" || btu.kind === "array") {
|
|
144
160
|
// Compile-time bounds checking for arrays
|
|
145
|
-
if (
|
|
161
|
+
if (btu.kind === "array" && btu.size != null) {
|
|
146
162
|
const idx = this._constIntValue(expr.index);
|
|
147
163
|
if (idx !== null) {
|
|
148
164
|
if (idx < 0) {
|
|
@@ -150,7 +166,7 @@ export const expressionCheckMethods = {
|
|
|
150
166
|
`invalid array index ${idx} (index must not be negative)`,
|
|
151
167
|
expr,
|
|
152
168
|
);
|
|
153
|
-
} else if (idx >=
|
|
169
|
+
} else if (idx >= btu.size) {
|
|
154
170
|
this.err(
|
|
155
171
|
`invalid array index ${idx} (out of bounds for ${typeStr(bt)})`,
|
|
156
172
|
expr,
|
|
@@ -158,11 +174,11 @@ export const expressionCheckMethods = {
|
|
|
158
174
|
}
|
|
159
175
|
}
|
|
160
176
|
}
|
|
161
|
-
return
|
|
177
|
+
return btu.elem;
|
|
162
178
|
}
|
|
163
|
-
if (
|
|
164
|
-
expr._mapValueType =
|
|
165
|
-
return
|
|
179
|
+
if (btu.kind === "map") {
|
|
180
|
+
expr._mapValueType = btu.value; // for codegen zero-value fallback
|
|
181
|
+
return btu.value;
|
|
166
182
|
}
|
|
167
183
|
if (isString(bt)) return INT; // byte
|
|
168
184
|
return this.err(`Cannot index type ${typeStr(bt)}`, expr);
|
|
@@ -410,6 +426,19 @@ export const expressionCheckMethods = {
|
|
|
410
426
|
|
|
411
427
|
if (isAny(fnType)) return ANY;
|
|
412
428
|
|
|
429
|
+
// Named type used as a constructor/conversion: Greeter(fn), NodeFunc(fn)
|
|
430
|
+
// The callee is a type name, not a callable variable.
|
|
431
|
+
if (fnType.kind === "named" && expr.func._isTypeRef) {
|
|
432
|
+
expr._isTypeConversion = true;
|
|
433
|
+
expr._conversionTargetType = fnType;
|
|
434
|
+
return fnType;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Named func types (e.g. type Handler func(int) int) are callable via variable
|
|
438
|
+
if (fnType.kind === "named" && fnType.underlying?.kind === "func") {
|
|
439
|
+
fnType = fnType.underlying;
|
|
440
|
+
}
|
|
441
|
+
|
|
413
442
|
// Generic function inference
|
|
414
443
|
if (fnType.kind === "generic") {
|
|
415
444
|
const typeArgs = this.inferTypeArgs(fnType, argTypes);
|