@ascent-lang/dev 0.1.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 +68 -0
- package/dist/errors/index.d.ts +4 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +35 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/types.d.ts +9 -0
- package/dist/errors/types.d.ts.map +1 -0
- package/dist/errors/types.js +5 -0
- package/dist/errors/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +200 -0
- package/dist/index.js.map +1 -0
- package/dist/interpreter.d.ts +35 -0
- package/dist/interpreter.d.ts.map +1 -0
- package/dist/interpreter.js +305 -0
- package/dist/interpreter.js.map +1 -0
- package/dist/lexer/chars.d.ts +6 -0
- package/dist/lexer/chars.d.ts.map +1 -0
- package/dist/lexer/chars.js +6 -0
- package/dist/lexer/chars.js.map +1 -0
- package/dist/lexer/cursor.d.ts +16 -0
- package/dist/lexer/cursor.d.ts.map +1 -0
- package/dist/lexer/cursor.js +43 -0
- package/dist/lexer/cursor.js.map +1 -0
- package/dist/lexer/index.d.ts +21 -0
- package/dist/lexer/index.d.ts.map +1 -0
- package/dist/lexer/index.js +163 -0
- package/dist/lexer/index.js.map +1 -0
- package/dist/lexer/keywords.d.ts +5 -0
- package/dist/lexer/keywords.d.ts.map +1 -0
- package/dist/lexer/keywords.js +39 -0
- package/dist/lexer/keywords.js.map +1 -0
- package/dist/lexer/token.d.ts +20 -0
- package/dist/lexer/token.d.ts.map +1 -0
- package/dist/lexer/token.js +2 -0
- package/dist/lexer/token.js.map +1 -0
- package/dist/lib.d.ts +14 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +17 -0
- package/dist/lib.js.map +1 -0
- package/dist/parser/ast.d.ts +128 -0
- package/dist/parser/ast.d.ts.map +1 -0
- package/dist/parser/ast.js +2 -0
- package/dist/parser/ast.js.map +1 -0
- package/dist/parser/expr.d.ts +4 -0
- package/dist/parser/expr.d.ts.map +1 -0
- package/dist/parser/expr.js +277 -0
- package/dist/parser/expr.js.map +1 -0
- package/dist/parser/index.d.ts +12 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +40 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/printer.d.ts +7 -0
- package/dist/parser/printer.d.ts.map +1 -0
- package/dist/parser/printer.js +130 -0
- package/dist/parser/printer.js.map +1 -0
- package/dist/parser/stmt.d.ts +7 -0
- package/dist/parser/stmt.d.ts.map +1 -0
- package/dist/parser/stmt.js +153 -0
- package/dist/parser/stmt.js.map +1 -0
- package/dist/parser/token-stream.d.ts +19 -0
- package/dist/parser/token-stream.d.ts.map +1 -0
- package/dist/parser/token-stream.js +111 -0
- package/dist/parser/token-stream.js.map +1 -0
- package/dist/parser/type-expr.d.ts +5 -0
- package/dist/parser/type-expr.d.ts.map +1 -0
- package/dist/parser/type-expr.js +54 -0
- package/dist/parser/type-expr.js.map +1 -0
- package/dist/parser/typechecker.d.ts +9 -0
- package/dist/parser/typechecker.d.ts.map +1 -0
- package/dist/parser/typechecker.js +446 -0
- package/dist/parser/typechecker.js.map +1 -0
- package/dist/parser/typed-ast.d.ts +130 -0
- package/dist/parser/typed-ast.d.ts.map +1 -0
- package/dist/parser/typed-ast.js +2 -0
- package/dist/parser/typed-ast.js.map +1 -0
- package/dist/parser/typed-printer.d.ts +3 -0
- package/dist/parser/typed-printer.d.ts.map +1 -0
- package/dist/parser/typed-printer.js +91 -0
- package/dist/parser/typed-printer.js.map +1 -0
- package/dist/types/types.d.ts +28 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +48 -0
- package/dist/types/types.js.map +1 -0
- package/package.json +70 -0
- package/src/errors/index.ts +38 -0
- package/src/errors/lexical.yml +16 -0
- package/src/errors/name.yml +11 -0
- package/src/errors/syntactic.yml +66 -0
- package/src/errors/typechecker.yml +61 -0
- package/src/errors/types.ts +13 -0
- package/src/index.ts +213 -0
- package/src/interpreter.ts +332 -0
- package/src/lexer/chars.ts +12 -0
- package/src/lexer/cursor.ts +51 -0
- package/src/lexer/index.ts +174 -0
- package/src/lexer/keywords.ts +43 -0
- package/src/lexer/token.ts +62 -0
- package/src/lib.ts +33 -0
- package/src/parser/ast.ts +64 -0
- package/src/parser/expr.ts +313 -0
- package/src/parser/index.ts +50 -0
- package/src/parser/printer.ts +146 -0
- package/src/parser/stmt.ts +176 -0
- package/src/parser/token-stream.ts +121 -0
- package/src/parser/type-expr.ts +63 -0
- package/src/parser/typechecker.ts +406 -0
- package/src/parser/typed-ast.ts +63 -0
- package/src/parser/typed-printer.ts +105 -0
- package/src/types/types.ts +65 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
const formatTypeExpr = (te) => {
|
|
3
|
+
switch (te.kind) {
|
|
4
|
+
case 'TypeName': return te.name;
|
|
5
|
+
case 'ListType': return `List<${formatTypeExpr(te.elem)}>`;
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
// Returns the node as a list of lines so callers can prefix them with
|
|
9
|
+
// branch characters (├─, └─) when embedding inside a parent node.
|
|
10
|
+
const exprLines = (expr) => {
|
|
11
|
+
switch (expr.kind) {
|
|
12
|
+
case 'literal':
|
|
13
|
+
switch (expr.valueType) {
|
|
14
|
+
case 'Int':
|
|
15
|
+
return [`${chalk.cyan('Lit')} ${chalk.yellow(String(expr.value))}`];
|
|
16
|
+
case 'Float':
|
|
17
|
+
return [`${chalk.cyan('Lit')} ${chalk.yellow(String(expr.value))}`];
|
|
18
|
+
case 'Bool':
|
|
19
|
+
return [`${chalk.cyan('Lit')} ${chalk.yellow(expr.value ? 'True' : 'False')}`];
|
|
20
|
+
case 'String':
|
|
21
|
+
return [`${chalk.cyan('Lit')} ${chalk.green(JSON.stringify(expr.value))}`];
|
|
22
|
+
case 'None':
|
|
23
|
+
return [`${chalk.cyan('Lit')} ${chalk.yellow('None')}`];
|
|
24
|
+
case 'Done':
|
|
25
|
+
return [`${chalk.cyan('Lit')} ${chalk.yellow('Done')}`];
|
|
26
|
+
}
|
|
27
|
+
case 'slot':
|
|
28
|
+
return [`${chalk.cyan('Slot')} ${chalk.green(expr.name)}`];
|
|
29
|
+
case 'call': {
|
|
30
|
+
const argLines = expr.args.flatMap((arg, i) => branch(exprLines(arg), i === expr.args.length - 1));
|
|
31
|
+
return [`${chalk.cyan('Call')} ${chalk.green(expr.callee)}`, ...argLines];
|
|
32
|
+
}
|
|
33
|
+
case 'methodCall': {
|
|
34
|
+
const children = [expr.receiver, ...expr.args];
|
|
35
|
+
const childLines = children.flatMap((child, i) => branch(exprLines(child), i === children.length - 1));
|
|
36
|
+
return [`${chalk.cyan('MethodCall')} ${chalk.green('.' + expr.method)}`, ...childLines];
|
|
37
|
+
}
|
|
38
|
+
case 'list': {
|
|
39
|
+
if (expr.elements.length === 0) {
|
|
40
|
+
return [`${chalk.cyan('List')} ${chalk.dim('[]')}`];
|
|
41
|
+
}
|
|
42
|
+
const elementLines = expr.elements.flatMap((el, i) => branch(exprLines(el), i === expr.elements.length - 1));
|
|
43
|
+
return [`${chalk.cyan('List')}`, ...elementLines];
|
|
44
|
+
}
|
|
45
|
+
case 'index': {
|
|
46
|
+
const listLines = branch(exprLines(expr.list), false);
|
|
47
|
+
const indexLines = branch(exprLines(expr.index), true);
|
|
48
|
+
return [`${chalk.cyan('Index')}`, ...listLines, ...indexLines];
|
|
49
|
+
}
|
|
50
|
+
case 'unary': {
|
|
51
|
+
const operand = branch(exprLines(expr.operand), true);
|
|
52
|
+
return [`${chalk.cyan('Unary')} ${chalk.magenta(expr.op)}`, ...operand];
|
|
53
|
+
}
|
|
54
|
+
case 'binary': {
|
|
55
|
+
const left = branch(exprLines(expr.left), false);
|
|
56
|
+
const right = branch(exprLines(expr.right), true);
|
|
57
|
+
return [`${chalk.cyan('Binary')} ${chalk.magenta(expr.op)}`, ...left, ...right];
|
|
58
|
+
}
|
|
59
|
+
case 'block': {
|
|
60
|
+
if (expr.stmts.length === 0) {
|
|
61
|
+
return [`${chalk.cyan('Block')} ${chalk.dim('(empty)')}`];
|
|
62
|
+
}
|
|
63
|
+
const lines = expr.stmts.flatMap((stmt, i) => branch(stmtLines(stmt), i === expr.stmts.length - 1));
|
|
64
|
+
return [`${chalk.cyan('Block')}`, ...lines];
|
|
65
|
+
}
|
|
66
|
+
case 'if': {
|
|
67
|
+
const condLines = branch(exprLines(expr.cond), false);
|
|
68
|
+
const thenLines = branch(exprLines(expr.then), expr.else === null);
|
|
69
|
+
const elseLines = expr.else !== null ? branch(exprLines(expr.else), true) : [];
|
|
70
|
+
return [`${chalk.cyan('If')}`, ...condLines, ...thenLines, ...elseLines];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
// Prefixes a child's lines with tree-drawing characters.
|
|
75
|
+
// Used by parent nodes (Binary, Unary, …) when they are added.
|
|
76
|
+
export const branch = (lines, isLast) => {
|
|
77
|
+
const head = chalk.dim(isLast ? '└─ ' : '├─ ');
|
|
78
|
+
const body = chalk.dim(isLast ? ' ' : '│ ');
|
|
79
|
+
return lines.map((line, i) => (i === 0 ? head : body) + line);
|
|
80
|
+
};
|
|
81
|
+
export const formatExpr = (expr) => {
|
|
82
|
+
return exprLines(expr).join('\n');
|
|
83
|
+
};
|
|
84
|
+
// Same line-list shape as exprLines, for the same reason: a block needs
|
|
85
|
+
// to embed a statement's lines and prefix them with tree-drawing chars.
|
|
86
|
+
const stmtLines = (stmt) => {
|
|
87
|
+
switch (stmt.kind) {
|
|
88
|
+
case 'fix':
|
|
89
|
+
case 'mut': {
|
|
90
|
+
const init = branch(exprLines(stmt.init), true);
|
|
91
|
+
const label = stmt.kind === 'fix' ? 'Fix' : 'Mut';
|
|
92
|
+
const ann = stmt.typeAnnotation !== null ? chalk.dim(`: ${formatTypeExpr(stmt.typeAnnotation)}`) : '';
|
|
93
|
+
return [`${chalk.cyan(label)} ${chalk.green(stmt.name)}${ann}`, ...init];
|
|
94
|
+
}
|
|
95
|
+
case 'assign': {
|
|
96
|
+
const value = branch(exprLines(stmt.value), true);
|
|
97
|
+
return [`${chalk.cyan('Assign')} ${chalk.green(stmt.name)}`, ...value];
|
|
98
|
+
}
|
|
99
|
+
case 'expr':
|
|
100
|
+
return exprLines(stmt.expr);
|
|
101
|
+
case 'while': {
|
|
102
|
+
const cond = branch(exprLines(stmt.cond), false);
|
|
103
|
+
const body = branch(exprLines(stmt.body), true);
|
|
104
|
+
return [`${chalk.cyan('While')}`, ...cond, ...body];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
export const formatStmt = (stmt) => stmtLines(stmt).join('\n');
|
|
109
|
+
export const formatValue = (value) => {
|
|
110
|
+
switch (value.type) {
|
|
111
|
+
case 'Int':
|
|
112
|
+
return chalk.yellow(String(value.value));
|
|
113
|
+
case 'Float':
|
|
114
|
+
const floatStr = String(value.value);
|
|
115
|
+
return floatStr.includes('.') ? chalk.yellow(floatStr) : chalk.yellow(floatStr + '.0');
|
|
116
|
+
case 'Bool':
|
|
117
|
+
return chalk.yellow(value.value ? 'True' : 'False');
|
|
118
|
+
case 'String':
|
|
119
|
+
return chalk.green(JSON.stringify(value.value));
|
|
120
|
+
case 'List': {
|
|
121
|
+
const items = value.elements.map(formatValue).join(', ');
|
|
122
|
+
return chalk.yellow(`[${items}]`);
|
|
123
|
+
}
|
|
124
|
+
case 'None':
|
|
125
|
+
return chalk.yellow('None');
|
|
126
|
+
case 'Done':
|
|
127
|
+
return chalk.yellow('Done');
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=printer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"printer.js","sourceRoot":"","sources":["../../src/parser/printer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Token } from '../lexer/token.js';
|
|
2
|
+
import type { Statement, Block, If } from './ast.js';
|
|
3
|
+
import type { TokenStream } from './token-stream.js';
|
|
4
|
+
export declare function parseBlock(ts: TokenStream, openTok?: Token): Block | null;
|
|
5
|
+
export declare function parseIf(ts: TokenStream): If | null;
|
|
6
|
+
export declare function parseStmt(ts: TokenStream): Statement | null;
|
|
7
|
+
//# sourceMappingURL=stmt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stmt.d.ts","sourceRoot":"","sources":["../../src/parser/stmt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAQ,SAAS,EAAE,KAAK,EAAE,EAAE,EAAY,MAAM,UAAU,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAYrD,wBAAgB,UAAU,CAAC,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,IAAI,CAMzE;AA8BD,wBAAgB,OAAO,CAAC,EAAE,EAAE,WAAW,GAAG,EAAE,GAAG,IAAI,CA6BlD;AA6ED,wBAAgB,SAAS,CAAC,EAAE,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CAmB3D"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { parseExpr } from './expr.js';
|
|
2
|
+
import { parseTypeExpr } from './type-expr.js';
|
|
3
|
+
// A block is '{' stmt* '}', each statement separated by ';' — the
|
|
4
|
+
// same "item (sep item)* close" shape as a call's args or a list
|
|
5
|
+
// literal, just with SEMICOLON as the separator and RBRACE as the
|
|
6
|
+
// close (§ design.md: "semicolons terminate every statement"; the
|
|
7
|
+
// trailing one is optional exactly like a list's trailing comma).
|
|
8
|
+
// `openTok` lets parseRequiredBlock pass in a '{' it already consumed
|
|
9
|
+
// via `expect`; parseAtom, which hasn't consumed one, omits it and
|
|
10
|
+
// this consumes its own.
|
|
11
|
+
export function parseBlock(ts, openTok) {
|
|
12
|
+
openTok ??= ts.advance(); // consume '{' unless already consumed
|
|
13
|
+
const parsed = ts.parseSeparated(() => parseStmt(ts), 'SEMICOLON', 'RBRACE', 'S0005', true);
|
|
14
|
+
if (parsed === null)
|
|
15
|
+
return null;
|
|
16
|
+
return { kind: 'block', stmts: parsed.items, span: { start: openTok.span.start, end: parsed.close.span.end } };
|
|
17
|
+
}
|
|
18
|
+
// The parenthesized test shared by 'if' and 'while' — '(' expr ')'.
|
|
19
|
+
// The body braces already delimit the construct, but the test stays
|
|
20
|
+
// parenthesized to match the C-family/TS surface (§5).
|
|
21
|
+
function parseCond(ts) {
|
|
22
|
+
if (ts.expect('LPAREN', 'S0006') === null)
|
|
23
|
+
return null;
|
|
24
|
+
const cond = parseExpr(ts);
|
|
25
|
+
if (cond === null) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
if (ts.expect('RPAREN', 'S0001') === null)
|
|
29
|
+
return null;
|
|
30
|
+
return cond;
|
|
31
|
+
}
|
|
32
|
+
// A mandatory body block — every 'if'/'while' branch needs one, even
|
|
33
|
+
// single-statement (§2: no dangling-else, no goto-fail class of bug).
|
|
34
|
+
function parseRequiredBlock(ts) {
|
|
35
|
+
const openTok = ts.expect('LBRACE', 'S0007');
|
|
36
|
+
if (openTok === null)
|
|
37
|
+
return null;
|
|
38
|
+
return parseBlock(ts, openTok);
|
|
39
|
+
}
|
|
40
|
+
// 'if (cond) { } else if (cond) { } else { }' — 'else if' is not its
|
|
41
|
+
// own grammar rule, it's an If recursively parsed as the else branch.
|
|
42
|
+
// It's an expression (see parseAtom), but it clusters with the other
|
|
43
|
+
// braced control constructs, so it lives here beside 'while'.
|
|
44
|
+
export function parseIf(ts) {
|
|
45
|
+
const ifTok = ts.advance(); // consume 'if'
|
|
46
|
+
const cond = parseCond(ts);
|
|
47
|
+
if (cond === null) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const thenBlock = parseRequiredBlock(ts);
|
|
51
|
+
if (thenBlock === null) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
let elseBranch = null;
|
|
55
|
+
if (ts.peek().kind === 'KW_ELSE') {
|
|
56
|
+
ts.advance(); // consume 'else'
|
|
57
|
+
elseBranch = ts.peek().kind === 'KW_IF' ? parseIf(ts) : parseRequiredBlock(ts);
|
|
58
|
+
if (elseBranch === null) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
kind: 'if',
|
|
64
|
+
cond,
|
|
65
|
+
then: thenBlock,
|
|
66
|
+
else: elseBranch,
|
|
67
|
+
span: { start: ifTok.span.start, end: (elseBranch ?? thenBlock).span.end },
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// 'while (cond) { }' — a statement, not an expression (§5): a loop has
|
|
71
|
+
// no single meaningful result, so it isn't usable where a value is
|
|
72
|
+
// expected the way 'if' is.
|
|
73
|
+
function parseWhile(ts) {
|
|
74
|
+
const whileTok = ts.advance(); // consume 'while'
|
|
75
|
+
const cond = parseCond(ts);
|
|
76
|
+
if (cond === null) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const body = parseRequiredBlock(ts);
|
|
80
|
+
if (body === null) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return { kind: 'while', cond, body, span: { start: whileTok.span.start, end: body.span.end } };
|
|
84
|
+
}
|
|
85
|
+
// 'fix' and 'mut' share every rule but the keyword itself and the
|
|
86
|
+
// mutability it grants — one parse method, told which by 'kind'.
|
|
87
|
+
function parseDecl(ts, kind) {
|
|
88
|
+
const kwTok = ts.advance(); // consume 'fix' or 'mut'
|
|
89
|
+
const nameTok = ts.peek();
|
|
90
|
+
if (nameTok.kind !== 'SLOT') {
|
|
91
|
+
ts.report('S0003', nameTok.span);
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
ts.advance(); // consume slot name
|
|
95
|
+
let typeAnnotation = null;
|
|
96
|
+
if (ts.peek().kind === 'COLON') {
|
|
97
|
+
ts.advance(); // consume ':'
|
|
98
|
+
typeAnnotation = parseTypeExpr(ts);
|
|
99
|
+
if (typeAnnotation === null)
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
if (ts.expect('EQUALS', 'S0004') === null)
|
|
103
|
+
return null;
|
|
104
|
+
const init = parseExpr(ts);
|
|
105
|
+
if (init === null) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
kind,
|
|
110
|
+
name: nameTok.value,
|
|
111
|
+
typeAnnotation,
|
|
112
|
+
init,
|
|
113
|
+
span: { start: kwTok.span.start, end: init.span.end },
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// 'name = expr;' — reassigns a slot already declared with 'fix' or
|
|
117
|
+
// 'mut'. Whether that's actually allowed (the slot must be 'mut') is
|
|
118
|
+
// a name-binding rule, not a grammar rule, so it's checked at
|
|
119
|
+
// evaluation time (interpreter.ts), not here.
|
|
120
|
+
function parseAssign(ts) {
|
|
121
|
+
const nameTok = ts.advance(); // consume slot name
|
|
122
|
+
ts.advance(); // consume '='
|
|
123
|
+
const value = parseExpr(ts);
|
|
124
|
+
if (value === null) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
kind: 'assign',
|
|
129
|
+
name: nameTok.value,
|
|
130
|
+
value,
|
|
131
|
+
span: { start: nameTok.span.start, end: value.span.end },
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
export function parseStmt(ts) {
|
|
135
|
+
if (ts.peek().kind === 'KW_FIX') {
|
|
136
|
+
return parseDecl(ts, 'fix');
|
|
137
|
+
}
|
|
138
|
+
if (ts.peek().kind === 'KW_MUT') {
|
|
139
|
+
return parseDecl(ts, 'mut');
|
|
140
|
+
}
|
|
141
|
+
if (ts.peek().kind === 'KW_WHILE') {
|
|
142
|
+
return parseWhile(ts);
|
|
143
|
+
}
|
|
144
|
+
if (ts.peek().kind === 'SLOT' && ts.peekNext().kind === 'EQUALS') {
|
|
145
|
+
return parseAssign(ts);
|
|
146
|
+
}
|
|
147
|
+
const expr = parseExpr(ts);
|
|
148
|
+
if (expr === null) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
return { kind: 'expr', expr, span: expr.span };
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=stmt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stmt.js","sourceRoot":"","sources":["../../src/parser/stmt.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,kEAAkE;AAClE,iEAAiE;AACjE,kEAAkE;AAClE,kEAAkE;AAClE,kEAAkE;AAClE,sEAAsE;AACtE,mEAAmE;AACnE,yBAAyB;AACzB,MAAM,UAAU,UAAU,CAAC,EAAe,EAAE,OAAe;IACzD,OAAO,KAAK,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,sCAAsC;IAChE,MAAM,MAAM,GAAG,EAAE,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5F,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEjC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;AACjH,CAAC;AAED,oEAAoE;AACpE,oEAAoE;AACpE,uDAAuD;AACvD,SAAS,SAAS,CAAC,EAAe;IAChC,IAAI,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvD,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;IAC3B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qEAAqE;AACrE,sEAAsE;AACtE,SAAS,kBAAkB,CAAC,EAAe;IACzC,MAAM,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAClC,OAAO,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,qEAAqE;AACrE,sEAAsE;AACtE,qEAAqE;AACrE,8DAA8D;AAC9D,MAAM,UAAU,OAAO,CAAC,EAAe;IACrC,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,eAAe;IAE3C,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;IAC3B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,SAAS,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;IACzC,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,UAAU,GAAsB,IAAI,CAAC;IACzC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACjC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,iBAAiB;QAC/B,UAAU,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC/E,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,IAAI;QACV,IAAI;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;KAC3E,CAAC;AACJ,CAAC;AAED,uEAAuE;AACvE,mEAAmE;AACnE,4BAA4B;AAC5B,SAAS,UAAU,CAAC,EAAe;IACjC,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,kBAAkB;IAEjD,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;IAC3B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;IACpC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;AACjG,CAAC;AAED,kEAAkE;AAClE,iEAAiE;AACjE,SAAS,SAAS,CAAC,EAAe,EAAE,IAAmB;IACrD,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,yBAAyB;IAErD,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IAC1B,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,oBAAoB;IAElC,IAAI,cAAc,GAAoB,IAAI,CAAC;IAC3C,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC/B,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,cAAc;QAC5B,cAAc,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,cAAc,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;IAC3C,CAAC;IAED,IAAI,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvD,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;IAC3B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,OAAO,CAAC,KAAK;QACnB,cAAc;QACd,IAAI;QACJ,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;KACtD,CAAC;AACJ,CAAC;AAED,mEAAmE;AACnE,qEAAqE;AACrE,8DAA8D;AAC9D,8CAA8C;AAC9C,SAAS,WAAW,CAAC,EAAe;IAClC,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,oBAAoB;IAClD,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,cAAc;IAE5B,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;IAC5B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,OAAO,CAAC,KAAK;QACnB,KAAK;QACL,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;KACzD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EAAe;IACvC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAClC,OAAO,UAAU,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC;IACD,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,MAAM,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACjE,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;IAC3B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Token, TokenKind, Marker, Span } from '../lexer/token.js';
|
|
2
|
+
export declare class TokenStream {
|
|
3
|
+
private readonly tokens;
|
|
4
|
+
private pos;
|
|
5
|
+
readonly errors: Marker[];
|
|
6
|
+
constructor(tokens: Token[]);
|
|
7
|
+
peek(): Token;
|
|
8
|
+
advance(): Token;
|
|
9
|
+
peekNext(): Token;
|
|
10
|
+
report(code: string, span: Span): void;
|
|
11
|
+
expect(kind: TokenKind, code: string): Token | null;
|
|
12
|
+
private static readonly STMT_START_KINDS;
|
|
13
|
+
private synchronize;
|
|
14
|
+
parseSeparated<T>(parseItem: () => T | null, sep: TokenKind, close: TokenKind, closeCode: string, recover?: boolean): {
|
|
15
|
+
items: T[];
|
|
16
|
+
close: Token;
|
|
17
|
+
} | null;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=token-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-stream.d.ts","sourceRoot":"","sources":["../../src/parser/token-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AASxE,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,GAAG,CAAa;IAIxB,SAAgB,MAAM,EAAE,MAAM,EAAE,CAAM;gBAEnB,MAAM,EAAE,KAAK,EAAE;IAM3B,IAAI,IAAI,KAAK;IAIb,OAAO,IAAI,KAAK;IAOhB,QAAQ,IAAI,KAAK;IAOjB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI;IAOtC,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI;IAa1D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAqE;IAQ7G,OAAO,CAAC,WAAW;IAoBZ,cAAc,CAAC,CAAC,EACrB,SAAS,EAAE,MAAM,CAAC,GAAG,IAAI,EACzB,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,SAAS,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,UAAQ,GACd;QAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,GAAG,IAAI;CAyBvC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// The token stream is everything the grammar productions in expr.ts,
|
|
2
|
+
// stmt.ts and type-expr.ts share but that isn't grammar itself: the
|
|
3
|
+
// cursor (peek/advance/peekNext), the error log, and the two
|
|
4
|
+
// stream-level combinators (expect, parseSeparated) built on top of
|
|
5
|
+
// them. Each production is a free function taking one of these, instead
|
|
6
|
+
// of a method on a monolithic Parser — so "how do I read the next
|
|
7
|
+
// token" lives in one place and the grammar files only describe grammar.
|
|
8
|
+
export class TokenStream {
|
|
9
|
+
tokens;
|
|
10
|
+
pos = 0;
|
|
11
|
+
// The accumulated diagnostics. Productions append via report()/expect();
|
|
12
|
+
// the top-level parse() hands this straight out as errorMarkers.
|
|
13
|
+
errors = [];
|
|
14
|
+
constructor(tokens) {
|
|
15
|
+
this.tokens = tokens;
|
|
16
|
+
}
|
|
17
|
+
// The lexer guarantees the last token is always EOF, so the fallback
|
|
18
|
+
// is only reached if pos somehow exceeds the array — it never will.
|
|
19
|
+
peek() {
|
|
20
|
+
return this.tokens[this.pos] ?? this.tokens[this.tokens.length - 1];
|
|
21
|
+
}
|
|
22
|
+
advance() {
|
|
23
|
+
return this.tokens[this.pos++] ?? this.tokens[this.tokens.length - 1];
|
|
24
|
+
}
|
|
25
|
+
// Looks past the current token without consuming anything — needed to
|
|
26
|
+
// tell an assignment ('x = …') apart from an expression starting with
|
|
27
|
+
// a slot reference, which otherwise look identical for one token.
|
|
28
|
+
peekNext() {
|
|
29
|
+
return this.tokens[this.pos + 1] ?? this.tokens[this.tokens.length - 1];
|
|
30
|
+
}
|
|
31
|
+
// Record a diagnostic at a given span. The one place productions push
|
|
32
|
+
// to the error log when they need to report something expect() can't
|
|
33
|
+
// express (e.g. "this token was fine but the *next* thing is wrong").
|
|
34
|
+
report(code, span) {
|
|
35
|
+
this.errors.push({ code, span });
|
|
36
|
+
}
|
|
37
|
+
// Consume-or-diagnose: the shape every "expect this exact token here"
|
|
38
|
+
// check in the grammar shares. Returns the consumed token, or records
|
|
39
|
+
// `code` at the offending token's span and returns null.
|
|
40
|
+
expect(kind, code) {
|
|
41
|
+
const tok = this.peek();
|
|
42
|
+
if (tok.kind !== kind) {
|
|
43
|
+
this.report(code, tok.span);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return this.advance();
|
|
47
|
+
}
|
|
48
|
+
// Keywords that start a statement outright (mirrors parseStmt's own
|
|
49
|
+
// dispatch in stmt.ts). synchronize() treats one of these as a safe
|
|
50
|
+
// place to resume, since it's a far more reliable restart point than
|
|
51
|
+
// an arbitrary token that merely happens to also start an expression.
|
|
52
|
+
static STMT_START_KINDS = new Set(['KW_FIX', 'KW_MUT', 'KW_WHILE']);
|
|
53
|
+
// Panic-mode recovery: skip tokens until the next statement boundary —
|
|
54
|
+
// the separator, the enclosing close token, EOF, or a statement-start
|
|
55
|
+
// keyword — without consuming whichever of those it lands on. Only
|
|
56
|
+
// parseSeparated's `recover` path calls this; it never reports a
|
|
57
|
+
// diagnostic itself, since the caller already recorded one for
|
|
58
|
+
// whatever failed before giving up and calling this.
|
|
59
|
+
synchronize(sep, close) {
|
|
60
|
+
while (this.peek().kind !== sep && this.peek().kind !== close && this.peek().kind !== 'EOF') {
|
|
61
|
+
if (TokenStream.STMT_START_KINDS.has(this.peek().kind))
|
|
62
|
+
return;
|
|
63
|
+
this.advance();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Parses `item (sep item)* close`, allowing an empty list and a
|
|
67
|
+
// trailing separator right before `close`. `close` is returned
|
|
68
|
+
// alongside the items since callers need its span to close off the
|
|
69
|
+
// enclosing node.
|
|
70
|
+
//
|
|
71
|
+
// Without `recover`, a failing item or a missing close token aborts
|
|
72
|
+
// the whole list — the right call for a call's args or a list
|
|
73
|
+
// literal, where a bad element can't be recovered from without
|
|
74
|
+
// guessing. With `recover` (set only by parseBlock and parseProgram),
|
|
75
|
+
// a failing item instead calls synchronize() and keeps going, so one
|
|
76
|
+
// malformed statement doesn't take the rest of the file's diagnostics
|
|
77
|
+
// down with it. The list can still come back null if synchronize()
|
|
78
|
+
// runs all the way to EOF without ever finding `close`.
|
|
79
|
+
parseSeparated(parseItem, sep, close, closeCode, recover = false) {
|
|
80
|
+
const items = [];
|
|
81
|
+
if (this.peek().kind !== close) {
|
|
82
|
+
for (;;) {
|
|
83
|
+
const item = parseItem();
|
|
84
|
+
if (item === null) {
|
|
85
|
+
if (!recover)
|
|
86
|
+
return null;
|
|
87
|
+
this.synchronize(sep, close);
|
|
88
|
+
if (this.peek().kind === close || this.peek().kind === 'EOF')
|
|
89
|
+
break;
|
|
90
|
+
if (this.peek().kind === sep) {
|
|
91
|
+
this.advance(); // consume the separator synchronize stopped on
|
|
92
|
+
if (this.peek().kind === close)
|
|
93
|
+
break; // trailing separator after a recovered statement
|
|
94
|
+
}
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
items.push(item);
|
|
98
|
+
if (this.peek().kind !== sep)
|
|
99
|
+
break;
|
|
100
|
+
this.advance(); // consume separator
|
|
101
|
+
if (this.peek().kind === close)
|
|
102
|
+
break; // trailing separator
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const closeTok = this.expect(close, closeCode);
|
|
106
|
+
if (closeTok === null)
|
|
107
|
+
return null;
|
|
108
|
+
return { items, close: closeTok };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=token-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-stream.js","sourceRoot":"","sources":["../../src/parser/token-stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TypeExpr, ArgDef } from './ast.js';
|
|
2
|
+
import type { TokenStream } from './token-stream.js';
|
|
3
|
+
export declare function parseTypeExpr(ts: TokenStream): TypeExpr | null;
|
|
4
|
+
export declare function parseArgs(ts: TokenStream): ArgDef[] | null;
|
|
5
|
+
//# sourceMappingURL=type-expr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-expr.d.ts","sourceRoot":"","sources":["../../src/parser/type-expr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAW,MAAM,UAAU,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,wBAAgB,aAAa,CAAC,EAAE,EAAE,WAAW,GAAG,QAAQ,GAAG,IAAI,CAsB9D;AA2BD,wBAAgB,SAAS,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,EAAE,GAAG,IAAI,CAS1D"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// 'Int', 'Float', 'Bool', 'String', or 'List<Type>' — used in type annotations.
|
|
2
|
+
export function parseTypeExpr(ts) {
|
|
3
|
+
const tok = ts.peek();
|
|
4
|
+
if (tok.kind !== 'TYPE_NAME') {
|
|
5
|
+
ts.report('S0010', tok.span);
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
ts.advance(); // consume type name
|
|
9
|
+
if (tok.value === 'List') {
|
|
10
|
+
if (ts.expect('LT', 'S0010') === null)
|
|
11
|
+
return null;
|
|
12
|
+
const elem = parseTypeExpr(ts);
|
|
13
|
+
if (elem === null)
|
|
14
|
+
return null;
|
|
15
|
+
const gt = ts.expect('GT', 'S0010');
|
|
16
|
+
if (gt === null)
|
|
17
|
+
return null;
|
|
18
|
+
return { kind: 'ListType', elem, span: { start: tok.span.start, end: gt.span.end } };
|
|
19
|
+
}
|
|
20
|
+
const name = tok.value;
|
|
21
|
+
return { kind: 'TypeName', name, span: tok.span };
|
|
22
|
+
}
|
|
23
|
+
// 'name: Type' — one entry in an args declaration. Unlike a slot's type
|
|
24
|
+
// annotation this only allows a bare type name (no 'List<…>'), so it
|
|
25
|
+
// reads the TYPE_NAME token directly rather than going through
|
|
26
|
+
// parseTypeExpr.
|
|
27
|
+
function parseArgDef(ts) {
|
|
28
|
+
const nameTok = ts.peek();
|
|
29
|
+
if (nameTok.kind !== 'SLOT') {
|
|
30
|
+
ts.report('S0003', nameTok.span);
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
ts.advance(); // consume name
|
|
34
|
+
if (ts.expect('COLON', 'S0009') === null)
|
|
35
|
+
return null;
|
|
36
|
+
const typeTok = ts.peek();
|
|
37
|
+
if (typeTok.kind !== 'TYPE_NAME') {
|
|
38
|
+
ts.report('S0010', typeTok.span);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
ts.advance(); // consume type name
|
|
42
|
+
return { name: nameTok.value, type: typeTok.value };
|
|
43
|
+
}
|
|
44
|
+
// 'args (name: Type, …)' — the program's typed input declaration.
|
|
45
|
+
export function parseArgs(ts) {
|
|
46
|
+
ts.advance(); // consume 'args'
|
|
47
|
+
if (ts.expect('LPAREN', 'S0006') === null)
|
|
48
|
+
return null;
|
|
49
|
+
const parsed = ts.parseSeparated(() => parseArgDef(ts), 'COMMA', 'RPAREN', 'S0001');
|
|
50
|
+
if (parsed === null)
|
|
51
|
+
return null;
|
|
52
|
+
return parsed.items;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=type-expr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-expr.js","sourceRoot":"","sources":["../../src/parser/type-expr.ts"],"names":[],"mappings":"AAGA,gFAAgF;AAChF,MAAM,UAAU,aAAa,CAAC,EAAe;IAC3C,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IACtB,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAC7B,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,oBAAoB;IAElC,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;QACzB,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAEnD,MAAM,IAAI,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAE/B,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACpC,IAAI,EAAE,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAE7B,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACvF,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,KAA4C,CAAC;IAC9D,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;AACpD,CAAC;AAED,wEAAwE;AACxE,qEAAqE;AACrE,+DAA+D;AAC/D,iBAAiB;AACjB,SAAS,WAAW,CAAC,EAAe;IAClC,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IAC1B,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,eAAe;IAE7B,IAAI,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEtD,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IAC1B,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACjC,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,oBAAoB;IAElC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,KAAgB,EAAE,CAAC;AACjE,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,SAAS,CAAC,EAAe;IACvC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,iBAAiB;IAE/B,IAAI,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvD,MAAM,MAAM,GAAG,EAAE,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpF,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEjC,OAAO,MAAM,CAAC,KAAK,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Program } from './ast.js';
|
|
2
|
+
import type { Marker } from '../lexer/token.js';
|
|
3
|
+
import type { TypedProgram } from './typed-ast.js';
|
|
4
|
+
export interface TypeCheckResult {
|
|
5
|
+
typedProgram: TypedProgram | null;
|
|
6
|
+
errorMarkers: Marker[];
|
|
7
|
+
}
|
|
8
|
+
export declare const typecheck: (program: Program) => TypeCheckResult;
|
|
9
|
+
//# sourceMappingURL=typechecker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typechecker.d.ts","sourceRoot":"","sources":["../../src/parser/typechecker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,OAAO,EAAuB,MAAM,UAAU,CAAC;AAC9E,OAAO,KAAK,EAAE,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAkD,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAMnG,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAmXD,eAAO,MAAM,SAAS,GAAI,SAAS,OAAO,KAAG,eAuB5C,CAAC"}
|