gofront 0.0.3 → 0.0.5
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 +110 -135
- package/package.json +2 -3
- package/src/codegen/expressions.js +529 -234
- package/src/codegen/statements.js +259 -14
- package/src/codegen.js +98 -9
- package/src/dts-parser.js +1 -1
- package/src/index.js +13 -12
- package/src/lexer.js +24 -1
- package/src/minifier.js +698 -0
- package/src/parser/expressions.js +115 -15
- package/src/parser/statements.js +4 -4
- package/src/parser/types.js +108 -3
- package/src/parser.js +93 -18
- package/src/typechecker/expressions.js +370 -13
- package/src/typechecker/statements.js +103 -5
- package/src/typechecker/types.js +96 -28
- package/src/typechecker.js +658 -22
package/src/typechecker/types.js
CHANGED
|
@@ -47,7 +47,13 @@ export const BOOL = { kind: "basic", name: "bool" };
|
|
|
47
47
|
export const ANY = { kind: "basic", name: "any" };
|
|
48
48
|
export const VOID = { kind: "basic", name: "void" };
|
|
49
49
|
export const NIL = { kind: "basic", name: "nil" };
|
|
50
|
-
export const ERROR = {
|
|
50
|
+
export const ERROR = {
|
|
51
|
+
kind: "interface",
|
|
52
|
+
name: "error",
|
|
53
|
+
methods: new Map([
|
|
54
|
+
["Error", { kind: "func", params: [], returns: [STRING], async: false }],
|
|
55
|
+
]),
|
|
56
|
+
};
|
|
51
57
|
|
|
52
58
|
// ── Untyped constant types (Go spec §Constants) ─────────────
|
|
53
59
|
// Untyped constants coerce to any compatible typed context.
|
|
@@ -56,6 +62,11 @@ export const UNTYPED_FLOAT = { kind: "untyped", base: "float64" };
|
|
|
56
62
|
export const UNTYPED_STRING = { kind: "untyped", base: "string" };
|
|
57
63
|
export const UNTYPED_BOOL = { kind: "untyped", base: "bool" };
|
|
58
64
|
|
|
65
|
+
// ── Complex types ────────────────────────────────────────────
|
|
66
|
+
export const COMPLEX128 = { kind: "basic", name: "complex128" };
|
|
67
|
+
export const COMPLEX64 = { kind: "basic", name: "complex64" };
|
|
68
|
+
export const UNTYPED_COMPLEX = { kind: "untyped", base: "complex128" };
|
|
69
|
+
|
|
59
70
|
export const BASIC_TYPES = {
|
|
60
71
|
int: INT,
|
|
61
72
|
float64: FLOAT64,
|
|
@@ -64,7 +75,6 @@ export const BASIC_TYPES = {
|
|
|
64
75
|
any: ANY,
|
|
65
76
|
byte: INT,
|
|
66
77
|
rune: INT,
|
|
67
|
-
error: ERROR,
|
|
68
78
|
// Sized integer / float aliases — all map to int or float64 at runtime
|
|
69
79
|
uint: INT,
|
|
70
80
|
int8: INT,
|
|
@@ -77,19 +87,51 @@ export const BASIC_TYPES = {
|
|
|
77
87
|
uint64: INT,
|
|
78
88
|
uintptr: INT,
|
|
79
89
|
float32: FLOAT64,
|
|
90
|
+
complex64: COMPLEX64,
|
|
91
|
+
complex128: COMPLEX128,
|
|
80
92
|
};
|
|
81
93
|
|
|
94
|
+
export const COMPARABLE = { kind: "basic", name: "comparable" };
|
|
95
|
+
|
|
96
|
+
export function isTypeParam(t) {
|
|
97
|
+
return t?.kind === "typeParam";
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function isGeneric(t) {
|
|
101
|
+
return t?.kind === "generic";
|
|
102
|
+
}
|
|
103
|
+
|
|
82
104
|
export function isNumeric(t) {
|
|
83
|
-
if (t
|
|
84
|
-
|
|
105
|
+
if (!t) return false;
|
|
106
|
+
if (t.kind === "untyped") return t.base === "int" || t.base === "float64";
|
|
107
|
+
if (t.kind === "basic") return t.name === "int" || t.name === "float64";
|
|
108
|
+
if (t.kind === "named") return isNumeric(t.underlying);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
export function isComplex(t) {
|
|
112
|
+
if (!t) return false;
|
|
113
|
+
if (t.kind === "basic" && (t.name === "complex128" || t.name === "complex64"))
|
|
114
|
+
return true;
|
|
115
|
+
if (t.kind === "untyped" && t.base === "complex128") return true;
|
|
116
|
+
if (t.kind === "named") return isComplex(t.underlying);
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
export function isComplexOrNumeric(t) {
|
|
120
|
+
return isNumeric(t) || isComplex(t);
|
|
85
121
|
}
|
|
86
122
|
export function isString(t) {
|
|
87
|
-
if (t
|
|
88
|
-
|
|
123
|
+
if (!t) return false;
|
|
124
|
+
if (t.kind === "untyped") return t.base === "string";
|
|
125
|
+
if (t.kind === "basic") return t.name === "string";
|
|
126
|
+
if (t.kind === "named") return isString(t.underlying);
|
|
127
|
+
return false;
|
|
89
128
|
}
|
|
90
129
|
export function isBool(t) {
|
|
91
|
-
if (t
|
|
92
|
-
|
|
130
|
+
if (!t) return false;
|
|
131
|
+
if (t.kind === "untyped") return t.base === "bool";
|
|
132
|
+
if (t.kind === "basic") return t.name === "bool";
|
|
133
|
+
if (t.kind === "named") return isBool(t.underlying);
|
|
134
|
+
return false;
|
|
93
135
|
}
|
|
94
136
|
export function isAny(t) {
|
|
95
137
|
return t?.kind === "basic" && t.name === "any";
|
|
@@ -101,7 +143,23 @@ export function isVoid(t) {
|
|
|
101
143
|
return t?.kind === "basic" && t.name === "void";
|
|
102
144
|
}
|
|
103
145
|
export function isError(t) {
|
|
104
|
-
|
|
146
|
+
if (!t) return false;
|
|
147
|
+
if (t === ERROR) return true;
|
|
148
|
+
if (t.kind === "interface" && t.name === "error") return true;
|
|
149
|
+
if (t.kind === "named" && isError(t.underlying)) return true;
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
export function isPointer(t) {
|
|
153
|
+
if (!t) return false;
|
|
154
|
+
if (t.kind === "pointer") return true;
|
|
155
|
+
if (t.kind === "named") return t.underlying?.kind === "pointer";
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
export function isArray(t) {
|
|
159
|
+
if (!t) return false;
|
|
160
|
+
if (t.kind === "array") return true;
|
|
161
|
+
if (t.kind === "named") return t.underlying?.kind === "array";
|
|
162
|
+
return false;
|
|
105
163
|
}
|
|
106
164
|
export function isUntyped(t) {
|
|
107
165
|
return t?.kind === "untyped";
|
|
@@ -119,29 +177,13 @@ export function defaultType(t) {
|
|
|
119
177
|
return STRING;
|
|
120
178
|
case "bool":
|
|
121
179
|
return BOOL;
|
|
180
|
+
case "complex128":
|
|
181
|
+
return COMPLEX128;
|
|
122
182
|
default:
|
|
123
183
|
return ANY;
|
|
124
184
|
}
|
|
125
185
|
}
|
|
126
186
|
|
|
127
|
-
/** Convert a concrete basic type to its untyped equivalent (for const inference). */
|
|
128
|
-
export function toUntyped(t) {
|
|
129
|
-
if (t?.kind === "untyped") return t;
|
|
130
|
-
if (t?.kind === "basic") {
|
|
131
|
-
switch (t.name) {
|
|
132
|
-
case "int":
|
|
133
|
-
return UNTYPED_INT;
|
|
134
|
-
case "float64":
|
|
135
|
-
return UNTYPED_FLOAT;
|
|
136
|
-
case "string":
|
|
137
|
-
return UNTYPED_STRING;
|
|
138
|
-
case "bool":
|
|
139
|
-
return UNTYPED_BOOL;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return t;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
187
|
export function typeStr(t) {
|
|
146
188
|
if (!t) return "void";
|
|
147
189
|
if (t.kind === "basic" && t.alias) return t.alias;
|
|
@@ -153,7 +195,7 @@ export function typeStr(t) {
|
|
|
153
195
|
case "slice":
|
|
154
196
|
return `[]${typeStr(t.elem)}`;
|
|
155
197
|
case "array":
|
|
156
|
-
return `[${t.size}]${typeStr(t.elem)}`;
|
|
198
|
+
return `[${t.size ?? "..."}]${typeStr(t.elem)}`;
|
|
157
199
|
case "map":
|
|
158
200
|
return `map[${typeStr(t.key)}]${typeStr(t.value)}`;
|
|
159
201
|
case "struct":
|
|
@@ -170,11 +212,37 @@ export function typeStr(t) {
|
|
|
170
212
|
return t.name;
|
|
171
213
|
case "pointer":
|
|
172
214
|
return `*${typeStr(t.base)}`;
|
|
215
|
+
case "typeParam":
|
|
216
|
+
return t.name;
|
|
217
|
+
case "generic":
|
|
218
|
+
return t.name || `generic(${typeStr(t.underlying)})`;
|
|
173
219
|
default:
|
|
174
220
|
return "?";
|
|
175
221
|
}
|
|
176
222
|
}
|
|
177
223
|
|
|
224
|
+
// ── Iterator function detection (Go 1.23 range-over-func) ───
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Returns null if t is not an iterator function.
|
|
228
|
+
* Returns { yieldParams: Type[] } if it is, where yieldParams are the
|
|
229
|
+
* types the range variables will be bound to (0, 1, or 2 elements).
|
|
230
|
+
*
|
|
231
|
+
* An iterator is func(yield func(...) bool) — single param that is a
|
|
232
|
+
* func returning bool with 0-2 params.
|
|
233
|
+
*/
|
|
234
|
+
export function iteratorYieldParams(t) {
|
|
235
|
+
const fn = t?.kind === "named" ? t.underlying : t;
|
|
236
|
+
if (fn?.kind !== "func") return null;
|
|
237
|
+
if (fn.params.length !== 1) return null;
|
|
238
|
+
const yieldFn =
|
|
239
|
+
fn.params[0]?.kind === "named" ? fn.params[0].underlying : fn.params[0];
|
|
240
|
+
if (yieldFn?.kind !== "func") return null;
|
|
241
|
+
if (yieldFn.returns.length !== 1 || !isBool(yieldFn.returns[0])) return null;
|
|
242
|
+
if (yieldFn.params.length > 2) return null;
|
|
243
|
+
return { yieldParams: yieldFn.params };
|
|
244
|
+
}
|
|
245
|
+
|
|
178
246
|
// ── Scope / environment ──────────────────────────────────────
|
|
179
247
|
|
|
180
248
|
export class Scope {
|