gofront 0.0.8 → 1.0.0
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 +88 -12
- package/package.json +8 -4
- package/src/codegen/expressions.js +520 -1717
- package/src/{codegen.js → codegen/index.js} +155 -184
- package/src/codegen/runtime.js +151 -0
- package/src/codegen/statements.js +305 -296
- package/src/codegen/stdlib/builder.js +36 -0
- package/src/codegen/stdlib/bytes.js +62 -0
- package/src/codegen/stdlib/errors.js +17 -0
- package/src/codegen/stdlib/fmt.js +101 -0
- package/src/codegen/stdlib/gom.js +152 -0
- package/src/codegen/stdlib/html.js +17 -0
- package/src/codegen/stdlib/index.js +95 -0
- package/src/codegen/stdlib/io.js +33 -0
- package/src/codegen/stdlib/maps.js +42 -0
- package/src/codegen/stdlib/math.js +53 -0
- package/src/codegen/stdlib/os.js +10 -0
- package/src/codegen/stdlib/path.js +31 -0
- package/src/codegen/stdlib/rand.js +24 -0
- package/src/codegen/stdlib/regexp.js +51 -0
- package/src/codegen/stdlib/slices.js +48 -0
- package/src/codegen/stdlib/sort.js +28 -0
- package/src/codegen/stdlib/strconv.js +30 -0
- package/src/codegen/stdlib/strings.js +83 -0
- package/src/codegen/stdlib/time.js +54 -0
- package/src/codegen/stdlib/unicode.js +22 -0
- package/src/codegen/stdlib/utf8.js +23 -0
- package/src/codegen/templ.js +281 -0
- package/src/compiler.js +102 -62
- package/src/dts-parser.js +355 -371
- package/src/index.js +22 -54
- package/src/lexer.js +200 -286
- package/src/minifier.js +305 -318
- package/src/parser/expressions.js +54 -36
- package/src/{parser.js → parser/index.js} +12 -5
- package/src/parser/statements.js +29 -35
- package/src/parser/types.js +31 -29
- package/src/templ-lexer.js +737 -0
- package/src/templ-parser.js +235 -0
- package/src/tokens.js +109 -0
- package/src/typechecker/assignability.js +258 -0
- package/src/typechecker/expressions.js +559 -549
- package/src/typechecker/index.js +555 -0
- package/src/typechecker/resolve.js +421 -0
- package/src/typechecker/statements.js +267 -280
- package/src/typechecker/stdlib/core.js +592 -0
- package/src/typechecker/stdlib/extended.js +332 -0
- package/src/typechecker/stdlib.js +9 -1060
- package/src/typechecker/termination.js +83 -0
- package/src/typechecker/types.js +6 -3
- package/src/typechecker.js +0 -1271
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Termination analysis — determines whether a statement/block always returns.
|
|
2
|
+
// Installed as a mixin on TypeChecker.prototype.
|
|
3
|
+
|
|
4
|
+
export const terminationMethods = {
|
|
5
|
+
_isPanicCall(expr) {
|
|
6
|
+
return (
|
|
7
|
+
expr?.kind === "CallExpr" &&
|
|
8
|
+
expr?.func?.kind === "Ident" &&
|
|
9
|
+
expr?.func?.name === "panic"
|
|
10
|
+
);
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
_isTerminating(stmt) {
|
|
14
|
+
if (!stmt) return false;
|
|
15
|
+
switch (stmt.kind) {
|
|
16
|
+
case "ReturnStmt":
|
|
17
|
+
return true;
|
|
18
|
+
case "BranchStmt":
|
|
19
|
+
return false;
|
|
20
|
+
case "ExprStmt":
|
|
21
|
+
return this._isPanicCall(stmt.expr);
|
|
22
|
+
case "LabeledStmt":
|
|
23
|
+
return this._isTerminating(stmt.body);
|
|
24
|
+
case "Block":
|
|
25
|
+
return this._isTerminatingBlock(stmt);
|
|
26
|
+
case "SwitchStmt":
|
|
27
|
+
return this._isTerminatingSwitch(stmt);
|
|
28
|
+
case "TypeSwitchStmt":
|
|
29
|
+
return this._isTerminatingTypeSwitch(stmt);
|
|
30
|
+
case "ForStmt":
|
|
31
|
+
return !stmt.cond && !this._blockHasBreak(stmt.body);
|
|
32
|
+
case "IfStmt":
|
|
33
|
+
return this._isTerminatingIfStmt(stmt);
|
|
34
|
+
default:
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
_isTerminatingIfStmt(stmt) {
|
|
40
|
+
if (!stmt.elseBody) return false;
|
|
41
|
+
return (
|
|
42
|
+
this._isTerminatingBlock(stmt.body) &&
|
|
43
|
+
(stmt.elseBody.kind === "Block"
|
|
44
|
+
? this._isTerminatingBlock(stmt.elseBody)
|
|
45
|
+
: this._isTerminating(stmt.elseBody))
|
|
46
|
+
);
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
_isTerminatingBlock(block) {
|
|
50
|
+
if (!block?.stmts?.length) return false;
|
|
51
|
+
return this._isTerminating(block.stmts[block.stmts.length - 1]);
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
_blockHasBreak(block) {
|
|
55
|
+
if (!block?.stmts) return false;
|
|
56
|
+
for (const s of block.stmts) {
|
|
57
|
+
if (s.kind === "BranchStmt" && s.keyword === "break") return true;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
_isTerminatingSwitch(stmt) {
|
|
63
|
+
let hasDefault = false;
|
|
64
|
+
for (const c of stmt.cases ?? []) {
|
|
65
|
+
if (!c.list) hasDefault = true;
|
|
66
|
+
if (!c.stmts?.length) return false;
|
|
67
|
+
const last = c.stmts[c.stmts.length - 1];
|
|
68
|
+
if (!this._isTerminating(last)) return false;
|
|
69
|
+
}
|
|
70
|
+
return hasDefault;
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
_isTerminatingTypeSwitch(stmt) {
|
|
74
|
+
let hasDefault = false;
|
|
75
|
+
for (const c of stmt.cases ?? []) {
|
|
76
|
+
if (!c.types) hasDefault = true;
|
|
77
|
+
if (!c.stmts?.length) return false;
|
|
78
|
+
const last = c.stmts[c.stmts.length - 1];
|
|
79
|
+
if (!this._isTerminating(last)) return false;
|
|
80
|
+
}
|
|
81
|
+
return hasDefault;
|
|
82
|
+
},
|
|
83
|
+
};
|
package/src/typechecker/types.js
CHANGED
|
@@ -15,19 +15,22 @@
|
|
|
15
15
|
export class TypeCheckError extends Error {
|
|
16
16
|
constructor(msg, node, filename, sourceCode) {
|
|
17
17
|
const lineNum = node?.line || node?._line;
|
|
18
|
+
const colNum = node?.col || node?._col;
|
|
18
19
|
const loc = filename
|
|
19
20
|
? lineNum
|
|
20
|
-
? ` in ${filename} at line ${lineNum}`
|
|
21
|
+
? ` in ${filename} at line ${lineNum}:${colNum ?? 1}`
|
|
21
22
|
: ` in ${filename}`
|
|
22
23
|
: lineNum
|
|
23
|
-
? ` at line ${lineNum}`
|
|
24
|
+
? ` at line ${lineNum}:${colNum ?? 1}`
|
|
24
25
|
: "";
|
|
25
26
|
let lineContext = "";
|
|
26
27
|
if (lineNum && sourceCode) {
|
|
27
28
|
const lines = sourceCode.split("\n");
|
|
28
29
|
const lineStr = lines[lineNum - 1];
|
|
29
30
|
if (lineStr !== undefined) {
|
|
30
|
-
|
|
31
|
+
const prefix = ` ${lineNum} | `;
|
|
32
|
+
const caretPad = " ".repeat((colNum ?? 1) - 1);
|
|
33
|
+
lineContext = `\n${prefix}${lineStr}\n${" ".repeat(prefix.length)}${caretPad}^`;
|
|
31
34
|
}
|
|
32
35
|
}
|
|
33
36
|
super(`Type error${loc}: ${msg}${lineContext}`);
|