oclang 1.2.2 → 1.3.2
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/.gitattributes +7 -0
- package/BUG_REGISTRY.md +6 -1
- package/CHANGELOG.md +20 -3
- package/README.md +2 -0
- package/dist/cli/ocat/index.js +0 -0
- package/dist/cli/ocm/commands/run.js +0 -5
- package/dist/cli/ocm/index.js +0 -0
- package/dist/core/ast/astBuilder.js +20 -144
- package/dist/core/ast/statements/_base.js +1 -0
- package/dist/core/ast/statements/function.js +53 -0
- package/dist/core/ast/statements/import.js +16 -0
- package/dist/core/ast/statements/io.js +45 -0
- package/dist/core/ast/statements/vars.js +37 -0
- package/dist/core/ast/types/base/statement.js +1 -0
- package/dist/core/ast/types/statements/importStatement.js +1 -0
- package/dist/core/ast/types/statements/index.js +5 -4
- package/dist/core/index.js +7 -5
- package/dist/core/lexer/tokens/keywords.js +2 -1
- package/dist/core/parser/parser.js +42 -15
- package/dist/core/runner/funcs/_base.js +1 -0
- package/dist/core/runner/funcs/functions.js +28 -0
- package/dist/core/runner/funcs/io.js +29 -0
- package/dist/core/runner/funcs/modules.js +11 -0
- package/dist/core/runner/funcs/variables.js +42 -0
- package/dist/core/runner/runner.js +16 -101
- package/dist/core/services/log.service.js +7 -7
- package/dist/shared/context/globalContext.js +7 -1
- package/dist/shared/manager/baseManager.js +5 -3
- package/dist/shared/manager/warn/coreWarnings.js +2 -2
- package/package.json +30 -30
- package/src/cli/ocm/commands/run.ts +0 -5
- package/src/core/ast/astBuilder.ts +21 -152
- package/src/core/ast/statements/_base.ts +3 -0
- package/src/core/ast/statements/function.ts +60 -0
- package/src/core/ast/statements/import.ts +22 -0
- package/src/core/ast/statements/io.ts +50 -0
- package/src/core/ast/statements/vars.ts +46 -0
- package/src/core/ast/types/base/statement.ts +2 -1
- package/src/core/ast/types/statements/callStatement.ts +1 -2
- package/src/core/ast/types/statements/functionStatement.ts +2 -2
- package/src/core/ast/types/statements/importStatement.ts +6 -0
- package/src/core/ast/types/statements/index.ts +12 -9
- package/src/core/ast/types/statements/printStatement.ts +2 -2
- package/src/core/ast/types/statements/variableStatement.ts +2 -2
- package/src/core/context/coreContext.ts +3 -3
- package/src/core/index.ts +8 -5
- package/src/core/lexer/tokens/keywords.ts +3 -1
- package/src/core/parser/parser.ts +49 -15
- package/src/core/runner/funcs/_base.ts +3 -0
- package/src/core/runner/funcs/functions.ts +46 -0
- package/src/core/runner/funcs/io.ts +38 -0
- package/src/core/runner/funcs/modules.ts +17 -0
- package/src/core/runner/funcs/variables.ts +57 -0
- package/src/core/runner/runner.ts +27 -121
- package/src/core/services/log.service.ts +24 -16
- package/src/shared/context/globalContext.ts +12 -1
- package/src/shared/manager/baseManager.ts +5 -3
- package/src/shared/manager/warn/coreWarnings.ts +2 -2
- package/src/shared/models/func.ts +1 -1
- package/tsconfig.json +3 -3
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ValueType } from "../../../shared/models/value.js";
|
|
2
|
+
import { StatementKind } from "../types/base/index.js";
|
|
3
|
+
import type { VariableStatement } from "../types/statements/index.js";
|
|
4
|
+
import type { FBuilder } from "./_base.js";
|
|
5
|
+
|
|
6
|
+
const variableStatement: FBuilder<VariableStatement> = (statement: any) => {
|
|
7
|
+
const varStmt = statement.children.variableStatement?.[0];
|
|
8
|
+
if (!varStmt) return null;
|
|
9
|
+
|
|
10
|
+
const typeToken = varStmt.children.VarType?.[0];
|
|
11
|
+
const idToken = varStmt.children.Identifier?.[0];
|
|
12
|
+
|
|
13
|
+
const valueToken =
|
|
14
|
+
varStmt.children.StringLiteral?.[0] ??
|
|
15
|
+
varStmt.children.NumberLiteral?.[0] ??
|
|
16
|
+
varStmt.children.BooleanLiteral?.[0];
|
|
17
|
+
|
|
18
|
+
if (!typeToken || !idToken || !valueToken) return null;
|
|
19
|
+
|
|
20
|
+
const type = typeToken.image as ValueType;
|
|
21
|
+
const id = idToken.image;
|
|
22
|
+
const value: string = valueToken.image;
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
kind: StatementKind.VariableStatement,
|
|
26
|
+
sourceInfo: {
|
|
27
|
+
tokens: varStmt.children,
|
|
28
|
+
cstNode: varStmt,
|
|
29
|
+
startLine: varStmt.startLine,
|
|
30
|
+
endLine: varStmt.endLine,
|
|
31
|
+
startColumn: varStmt.startColumn,
|
|
32
|
+
endColumn: varStmt.endColumn,
|
|
33
|
+
},
|
|
34
|
+
id,
|
|
35
|
+
var: {
|
|
36
|
+
type,
|
|
37
|
+
value,
|
|
38
|
+
props: {
|
|
39
|
+
isConst: false,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
set: false,
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const variableStatements = [variableStatement];
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { SourceInfo } from "./source";
|
|
1
|
+
import type { SourceInfo } from "./source.js";
|
|
2
2
|
|
|
3
3
|
export enum StatementKind {
|
|
4
4
|
PrintStatement,
|
|
5
5
|
VariableStatement,
|
|
6
6
|
FunctionStatement,
|
|
7
7
|
CallStatement,
|
|
8
|
+
ImportStatement,
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
export interface Statement {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Statement, StatementKind } from "../base";
|
|
1
|
+
import type { Statement, StatementKind } from "../base/index.js";
|
|
3
2
|
|
|
4
3
|
export interface CallStatement extends Statement {
|
|
5
4
|
kind: StatementKind.CallStatement;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Statement, StatementKind } from "../base";
|
|
2
|
-
import type { Function } from "../../../../shared/models/func";
|
|
1
|
+
import type { Statement, StatementKind } from "../base/index.js";
|
|
2
|
+
import type { Function } from "../../../../shared/models/func.js";
|
|
3
3
|
|
|
4
4
|
export interface FunctionStatement extends Statement {
|
|
5
5
|
kind: StatementKind.FunctionStatement;
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import type { FunctionStatement } from "./functionStatement";
|
|
2
|
-
import type { PrintStatement } from "./printStatement";
|
|
3
|
-
import type { VariableStatement } from "./variableStatement";
|
|
4
|
-
import type { CallStatement } from "./callStatement";
|
|
1
|
+
import type { FunctionStatement } from "./functionStatement.js";
|
|
2
|
+
import type { PrintStatement } from "./printStatement.js";
|
|
3
|
+
import type { VariableStatement } from "./variableStatement.js";
|
|
4
|
+
import type { CallStatement } from "./callStatement.js";
|
|
5
|
+
import type { ImportStatement } from "./importStatement.js";
|
|
5
6
|
|
|
6
|
-
export * from "./printStatement";
|
|
7
|
-
export * from "./variableStatement";
|
|
8
|
-
export * from "./functionStatement";
|
|
9
|
-
export * from "./callStatement";
|
|
7
|
+
export * from "./printStatement.js";
|
|
8
|
+
export * from "./variableStatement.js";
|
|
9
|
+
export * from "./functionStatement.js";
|
|
10
|
+
export * from "./callStatement.js";
|
|
11
|
+
export * from "./importStatement.js";
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
export type AnyStatement =
|
|
13
15
|
| PrintStatement
|
|
14
16
|
| VariableStatement
|
|
15
17
|
| FunctionStatement
|
|
16
|
-
| CallStatement
|
|
18
|
+
| CallStatement
|
|
19
|
+
| ImportStatement;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Value } from "../../../../shared/models/value";
|
|
2
|
-
import type { Statement, StatementKind } from "../base";
|
|
1
|
+
import type { Value } from "../../../../shared/models/value.js";
|
|
2
|
+
import type { Statement, StatementKind } from "../base/index.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
export interface PrintStatement extends Statement {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Variable } from "../../../../shared/models/var";
|
|
2
|
-
import type { Statement, StatementKind } from "../base";
|
|
1
|
+
import type { Variable } from "../../../../shared/models/var.js";
|
|
2
|
+
import type { Statement, StatementKind } from "../base/index.js";
|
|
3
3
|
|
|
4
4
|
export interface VariableStatement extends Statement {
|
|
5
5
|
kind: StatementKind.VariableStatement;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Variable } from "../../shared/models/var";
|
|
2
|
-
import type { Function } from "../../shared/models/func";
|
|
1
|
+
import type { Variable } from "../../shared/models/var.js";
|
|
2
|
+
import type { Function } from "../../shared/models/func.js";
|
|
3
3
|
|
|
4
4
|
export interface CoreContext {
|
|
5
5
|
variables: Record<string, Variable>;
|
|
@@ -11,4 +11,4 @@ export function createCoreContext(): CoreContext {
|
|
|
11
11
|
variables: {},
|
|
12
12
|
functions: {},
|
|
13
13
|
};
|
|
14
|
-
}
|
|
14
|
+
}
|
package/src/core/index.ts
CHANGED
|
@@ -3,8 +3,9 @@ import { OcatParser } from "./parser/parser.js";
|
|
|
3
3
|
import { run } from "./runner/runner.js";
|
|
4
4
|
import { createCoreContext } from "./context/coreContext.js";
|
|
5
5
|
import { buildAst } from "./ast/astBuilder.js";
|
|
6
|
-
import * as
|
|
6
|
+
import * as gctx from "../shared/context/globalContext.js";
|
|
7
7
|
import fs from "fs";
|
|
8
|
+
import { defaultLoggerConfig, LoggerService } from "./services/log.service.js";
|
|
8
9
|
|
|
9
10
|
export function execute(code: string) {
|
|
10
11
|
const lexingResult = ocatLexer.tokenize(code);
|
|
@@ -15,12 +16,14 @@ export function execute(code: string) {
|
|
|
15
16
|
const ast = buildAst(cst);
|
|
16
17
|
|
|
17
18
|
process.on("exit", () => {
|
|
18
|
-
if (
|
|
19
|
-
const logs =
|
|
19
|
+
if (gctx.get("isProject")) {
|
|
20
|
+
const logs = gctx.get("services").log.toString();
|
|
20
21
|
fs.writeFileSync(".ocat/logs.txt", logs);
|
|
21
22
|
}
|
|
22
23
|
});
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
gctx.pushService(new LoggerService(defaultLoggerConfig), "log");
|
|
26
|
+
|
|
27
|
+
const ctx = run(ast, createCoreContext());
|
|
28
|
+
return ctx;
|
|
26
29
|
}
|
|
@@ -2,4 +2,6 @@ import { createToken } from "chevrotain";
|
|
|
2
2
|
|
|
3
3
|
export const Output = createToken({ name: "Output", pattern: /print/ });
|
|
4
4
|
|
|
5
|
-
export const
|
|
5
|
+
export const Import = createToken({ name: "Import", pattern: /import/ });
|
|
6
|
+
|
|
7
|
+
export const keywords = [Output, Import];
|
|
@@ -4,9 +4,7 @@ import * as token from "../lexer/tokens/index.js";
|
|
|
4
4
|
|
|
5
5
|
export class OcatParser extends CstParser {
|
|
6
6
|
constructor() {
|
|
7
|
-
super(token.allTokens, {
|
|
8
|
-
recoveryEnabled: true,
|
|
9
|
-
});
|
|
7
|
+
super(token.allTokens, { recoveryEnabled: true });
|
|
10
8
|
this.performSelfAnalysis();
|
|
11
9
|
}
|
|
12
10
|
|
|
@@ -16,6 +14,12 @@ export class OcatParser extends CstParser {
|
|
|
16
14
|
|
|
17
15
|
public statement = this.RULE("statement", () => {
|
|
18
16
|
this.OR([
|
|
17
|
+
{
|
|
18
|
+
ALT: () =>
|
|
19
|
+
this.SUBRULE(this.importStatement, {
|
|
20
|
+
LABEL: "importStatement",
|
|
21
|
+
}),
|
|
22
|
+
},
|
|
19
23
|
{
|
|
20
24
|
ALT: () =>
|
|
21
25
|
this.SUBRULE(this.printStatement, {
|
|
@@ -43,8 +47,14 @@ export class OcatParser extends CstParser {
|
|
|
43
47
|
]);
|
|
44
48
|
});
|
|
45
49
|
|
|
50
|
+
public importStatement = this.RULE("importStatement", () => {
|
|
51
|
+
const imp = this.CONSUME(token.Import);
|
|
52
|
+
const path = this.CONSUME(token.StringLiteral);
|
|
53
|
+
// opcional: guardar tokens para el AST
|
|
54
|
+
});
|
|
55
|
+
|
|
46
56
|
public printStatement = this.RULE("printStatement", () => {
|
|
47
|
-
this.CONSUME(token.Output);
|
|
57
|
+
const output = this.CONSUME(token.Output);
|
|
48
58
|
this.CONSUME(token.LeftParen);
|
|
49
59
|
this.OR([
|
|
50
60
|
...token.literals.map((lit) => ({
|
|
@@ -59,17 +69,12 @@ export class OcatParser extends CstParser {
|
|
|
59
69
|
});
|
|
60
70
|
|
|
61
71
|
public variableStatement = this.RULE("variableStatement", () => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
{ ALT: () => this.CONSUME(token.Const, { LABEL: "Const" }) },
|
|
66
|
-
]);
|
|
67
|
-
});
|
|
68
|
-
const type = this.CONSUME(token.VarType).image as ValueType;
|
|
69
|
-
this.CONSUME(token.Identifier);
|
|
72
|
+
|
|
73
|
+
const typeToken = this.CONSUME(token.VarType);
|
|
74
|
+
const idToken = this.CONSUME(token.Identifier);
|
|
70
75
|
this.CONSUME(token.Assign);
|
|
71
76
|
|
|
72
|
-
switch (
|
|
77
|
+
switch (typeToken.image as ValueType) {
|
|
73
78
|
case ValueType.String:
|
|
74
79
|
this.CONSUME(token.StringLiteral);
|
|
75
80
|
break;
|
|
@@ -80,11 +85,26 @@ export class OcatParser extends CstParser {
|
|
|
80
85
|
this.CONSUME(token.BooleanLiteral);
|
|
81
86
|
break;
|
|
82
87
|
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
typeToken, idToken
|
|
91
|
+
};
|
|
83
92
|
});
|
|
84
93
|
|
|
85
94
|
public functionStatement = this.RULE("functionStatement", () => {
|
|
86
|
-
this.CONSUME(token.Function);
|
|
87
|
-
this.CONSUME(token.Identifier);
|
|
95
|
+
const funcKeyword = this.CONSUME(token.Function);
|
|
96
|
+
const idToken = this.CONSUME(token.Identifier);
|
|
97
|
+
|
|
98
|
+
this.CONSUME(token.LeftParen);
|
|
99
|
+
this.MANY_SEP({
|
|
100
|
+
SEP: token.Comma,
|
|
101
|
+
DEF: () => {
|
|
102
|
+
this.CONSUME(token.VarType);
|
|
103
|
+
this.CONSUME2(token.Identifier);
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
this.CONSUME(token.RightParen);
|
|
107
|
+
|
|
88
108
|
this.CONSUME(token.LeftBrace);
|
|
89
109
|
this.MANY(() => this.SUBRULE(this.statement));
|
|
90
110
|
this.CONSUME(token.RightBrace);
|
|
@@ -93,5 +113,19 @@ export class OcatParser extends CstParser {
|
|
|
93
113
|
public callStatement = this.RULE("callStatement", () => {
|
|
94
114
|
this.CONSUME(token.Call);
|
|
95
115
|
this.CONSUME(token.Identifier);
|
|
116
|
+
|
|
117
|
+
this.CONSUME(token.LeftParen);
|
|
118
|
+
this.MANY_SEP({
|
|
119
|
+
SEP: token.Comma,
|
|
120
|
+
DEF: () => {
|
|
121
|
+
this.OR([
|
|
122
|
+
...token.literals.map((lit) => ({
|
|
123
|
+
ALT: () => this.CONSUME(lit),
|
|
124
|
+
})),
|
|
125
|
+
{ ALT: () => this.CONSUME2(token.Identifier) },
|
|
126
|
+
]);
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
this.CONSUME(token.RightParen);
|
|
96
130
|
});
|
|
97
131
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { AlreadyDeclaredFunctionError } from "../../../shared/manager/errors/semantic/undefined/declared.js";
|
|
2
|
+
import type {
|
|
3
|
+
CallStatement,
|
|
4
|
+
FunctionStatement,
|
|
5
|
+
} from "../../ast/types/statements/index.js";
|
|
6
|
+
import type { RunnerFunc } from "./_base.js";
|
|
7
|
+
import { UndeclaredFunctionError } from "../../../shared/manager/errors/semantic/undefined/undeclared.js";
|
|
8
|
+
import { run } from "../runner.js";
|
|
9
|
+
|
|
10
|
+
export const functionStatement: RunnerFunc<FunctionStatement> = (
|
|
11
|
+
statement,
|
|
12
|
+
context,
|
|
13
|
+
) => {
|
|
14
|
+
const idToken = statement.id;
|
|
15
|
+
if (!idToken) return;
|
|
16
|
+
|
|
17
|
+
const funcData = context.functions[idToken];
|
|
18
|
+
if (funcData) {
|
|
19
|
+
new AlreadyDeclaredFunctionError(idToken).throw(
|
|
20
|
+
statement.sourceInfo.startLine,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const body = statement.func.body ?? [];
|
|
25
|
+
const scope = statement.func.scope;
|
|
26
|
+
context.functions[idToken] = {
|
|
27
|
+
body,
|
|
28
|
+
scope,
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const callStatement: RunnerFunc<CallStatement> = (
|
|
33
|
+
statement,
|
|
34
|
+
context,
|
|
35
|
+
) => {
|
|
36
|
+
const funcId = statement.id;
|
|
37
|
+
if (!funcId) return;
|
|
38
|
+
|
|
39
|
+
const funcData = context.functions[funcId];
|
|
40
|
+
if (!funcData) {
|
|
41
|
+
new UndeclaredFunctionError(funcId).throw(
|
|
42
|
+
statement.sourceInfo.startLine,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
run(funcData.body, funcData.scope);
|
|
46
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { UndeclaredVariableError } from "../../../shared/manager/errors/semantic/undefined/undeclared.js";
|
|
2
|
+
import { ValueType } from "../../../shared/models/value.js";
|
|
3
|
+
import type { PrintStatement } from "../../ast/types/statements/index.js";
|
|
4
|
+
import { solveString } from "../utils/string.js";
|
|
5
|
+
import * as ctx from "../../../shared/context/globalContext.js";
|
|
6
|
+
import type { RunnerFunc } from "./_base.js";
|
|
7
|
+
|
|
8
|
+
export const printStatement: RunnerFunc<PrintStatement> = (
|
|
9
|
+
statement,
|
|
10
|
+
context,
|
|
11
|
+
) => {
|
|
12
|
+
let val;
|
|
13
|
+
switch (statement.value.type) {
|
|
14
|
+
case ValueType.Identifier:
|
|
15
|
+
const id = statement.value.value;
|
|
16
|
+
const varData = context.variables[id];
|
|
17
|
+
if (varData !== undefined) {
|
|
18
|
+
val = varData.value;
|
|
19
|
+
} else {
|
|
20
|
+
new UndeclaredVariableError(id).throw(
|
|
21
|
+
statement.sourceInfo.startLine,
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
break;
|
|
25
|
+
|
|
26
|
+
case ValueType.String:
|
|
27
|
+
val = solveString(statement.value.value, context, (err) => {
|
|
28
|
+
err.throw(statement.sourceInfo.startLine);
|
|
29
|
+
});
|
|
30
|
+
break;
|
|
31
|
+
|
|
32
|
+
default:
|
|
33
|
+
val = statement.value.value;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
const info = ctx.getService("log");
|
|
37
|
+
info?.info(val);
|
|
38
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { execute } from "../../index.js";
|
|
2
|
+
import type { ImportStatement } from "../../ast/types/statements/index.js";
|
|
3
|
+
import type { RunnerFunc } from "./_base.js";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
|
|
6
|
+
export const importStatement: RunnerFunc<ImportStatement> = (
|
|
7
|
+
statement,
|
|
8
|
+
context,
|
|
9
|
+
) => {
|
|
10
|
+
const fctx = execute(fs.readFileSync(statement.path).toString());
|
|
11
|
+
for (const [key, value] of Object.entries(fctx.variables)) {
|
|
12
|
+
context.variables[key] = value;
|
|
13
|
+
}
|
|
14
|
+
for (const [key, value] of Object.entries(fctx.functions)) {
|
|
15
|
+
context.functions[key] = value;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AlreadyDeclaredVariableError,
|
|
3
|
+
CantModifyConstError,
|
|
4
|
+
} from "../../../shared/manager/errors/semantic/undefined/declared.js";
|
|
5
|
+
import { UndeclaredVariableError } from "../../../shared/manager/errors/semantic/undefined/undeclared.js";
|
|
6
|
+
import { ValueType } from "../../../shared/models/value.js";
|
|
7
|
+
import type { VariableStatement } from "../../ast/types/statements/index.js";
|
|
8
|
+
import { solveString } from "../utils/string.js";
|
|
9
|
+
import type { RunnerFunc } from "./_base.js";
|
|
10
|
+
|
|
11
|
+
export const variableStatement: RunnerFunc<VariableStatement> = (
|
|
12
|
+
statement,
|
|
13
|
+
context,
|
|
14
|
+
) => {
|
|
15
|
+
|
|
16
|
+
const varId = statement.id;
|
|
17
|
+
|
|
18
|
+
/*if (statement.set) {
|
|
19
|
+
if (!context.variables[varId]) {
|
|
20
|
+
new UndeclaredVariableError(varId).throw(
|
|
21
|
+
statement.sourceInfo.startLine,
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
if (context.variables[varId]?.props.isConst) {
|
|
25
|
+
new CantModifyConstError(varId).throw(
|
|
26
|
+
statement.sourceInfo.startLine,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
} else if (!statement.var.props.isConst) {
|
|
30
|
+
if (context.variables[varId]) {
|
|
31
|
+
new AlreadyDeclaredVariableError(varId).throw(
|
|
32
|
+
statement.sourceInfo.startLine,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}*/
|
|
36
|
+
|
|
37
|
+
let value: string = statement.var.value;
|
|
38
|
+
|
|
39
|
+
switch (statement.var.type) {
|
|
40
|
+
case ValueType.String:
|
|
41
|
+
value = solveString(value, context, (err) => {
|
|
42
|
+
err.throw(statement.sourceInfo.startLine);
|
|
43
|
+
});
|
|
44
|
+
break;
|
|
45
|
+
default:
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
context.variables[varId] = {
|
|
50
|
+
type: statement.var.type,
|
|
51
|
+
value,
|
|
52
|
+
props: {
|
|
53
|
+
isConst: !!statement.var.props.isConst,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
};
|
|
@@ -1,133 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AlreadyDeclaredFunctionError,
|
|
3
|
-
AlreadyDeclaredVariableError,
|
|
4
|
-
CantModifyConstError,
|
|
5
|
-
} from "../../shared/manager/errors/semantic/undefined/declared.js";
|
|
1
|
+
import { AlreadyDeclaredFunctionError } from "../../shared/manager/errors/semantic/undefined/declared.js";
|
|
6
2
|
import {
|
|
7
3
|
UndeclaredFunctionError,
|
|
8
4
|
UndeclaredVariableError,
|
|
9
5
|
} from "../../shared/manager/errors/semantic/undefined/undeclared.js";
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
import type {
|
|
7
|
+
AnyStatement,
|
|
8
|
+
CallStatement,
|
|
9
|
+
FunctionStatement,
|
|
10
|
+
PrintStatement,
|
|
11
|
+
VariableStatement,
|
|
12
|
+
} from "../ast/types/statements/index.js";
|
|
14
13
|
import { StatementKind } from "../ast/types/base/statement.js";
|
|
15
|
-
import
|
|
14
|
+
import type { RunnerFunc } from "./funcs/_base.js";
|
|
15
|
+
// import { coreContext as context } from "../context/coreContext.js";
|
|
16
|
+
import { printStatement } from "./funcs/io.js";
|
|
17
|
+
import { variableStatement } from "./funcs/variables.js";
|
|
18
|
+
import { callStatement, functionStatement } from "./funcs/functions.js";
|
|
19
|
+
import type { CoreContext } from "../context/coreContext.js";
|
|
20
|
+
|
|
21
|
+
const statementMap = new Map<StatementKind, RunnerFunc<any>>([
|
|
22
|
+
[StatementKind.PrintStatement, printStatement],
|
|
23
|
+
[StatementKind.VariableStatement, variableStatement],
|
|
24
|
+
[StatementKind.FunctionStatement, functionStatement],
|
|
25
|
+
[StatementKind.CallStatement, callStatement],
|
|
26
|
+
]);
|
|
16
27
|
|
|
17
28
|
export function run(ast: AnyStatement[], context: CoreContext) {
|
|
18
|
-
|
|
19
29
|
for (const statement of ast) {
|
|
20
|
-
|
|
21
|
-
case StatementKind.PrintStatement:
|
|
22
|
-
printStatement(statement, context);
|
|
23
|
-
break;
|
|
24
|
-
case StatementKind.VariableStatement:
|
|
25
|
-
variableStatement(statement, context);
|
|
26
|
-
break;
|
|
27
|
-
case StatementKind.FunctionStatement:
|
|
28
|
-
functionStatement(statement, context);
|
|
29
|
-
break;
|
|
30
|
-
case StatementKind.CallStatement:
|
|
31
|
-
callStatement(statement, context);
|
|
32
|
-
break;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function printStatement(statement: PrintStatement, context: CoreContext) {
|
|
38
|
-
let val;
|
|
39
|
-
switch (statement.value.type) {
|
|
40
|
-
case ValueType.Identifier:
|
|
41
|
-
const id = statement.value.value;
|
|
42
|
-
const varData = context.variables[id];
|
|
43
|
-
if (varData !== undefined) {
|
|
44
|
-
val = varData.value;
|
|
45
|
-
} else {
|
|
46
|
-
new UndeclaredVariableError(id).throw(statement.sourceInfo.startLine);
|
|
47
|
-
}
|
|
48
|
-
break;
|
|
49
|
-
|
|
50
|
-
case ValueType.String:
|
|
51
|
-
val = solveString(statement.value.value, context, (err) => {
|
|
52
|
-
err.throw(statement.sourceInfo.startLine);
|
|
53
|
-
})
|
|
54
|
-
break;
|
|
55
|
-
|
|
56
|
-
default:
|
|
57
|
-
val = statement.value.value;
|
|
58
|
-
break;
|
|
59
|
-
}
|
|
60
|
-
const info = ctx.get("services").log;
|
|
61
|
-
info.info(val);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function variableStatement(statement: VariableStatement, context: CoreContext) {
|
|
65
|
-
const varId = statement.id;
|
|
30
|
+
const runner = statementMap.get(statement.kind);
|
|
66
31
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
new UndeclaredVariableError(varId).throw(
|
|
70
|
-
statement.sourceInfo.startLine
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
if (context.variables[varId]?.props.isConst) {
|
|
74
|
-
new CantModifyConstError(varId).throw(
|
|
75
|
-
statement.sourceInfo.startLine
|
|
76
|
-
);
|
|
32
|
+
if (!runner) {
|
|
33
|
+
throw new Error(`No runner for statement kind: ${statement.kind}`);
|
|
77
34
|
}
|
|
78
|
-
} else if (!statement.var.props.isConst) {
|
|
79
|
-
if (context.variables[varId]) {
|
|
80
|
-
new AlreadyDeclaredVariableError(varId).throw(
|
|
81
|
-
statement.sourceInfo.startLine
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
let value: string = statement.var.value;
|
|
87
|
-
|
|
88
|
-
switch (statement.var.type) {
|
|
89
|
-
case ValueType.String:
|
|
90
|
-
value = solveString(value, context, (err) => {
|
|
91
|
-
err.throw(statement.sourceInfo.startLine);
|
|
92
|
-
});
|
|
93
|
-
break;
|
|
94
|
-
default:
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
context.variables[varId] = {
|
|
99
|
-
type: statement.var.type,
|
|
100
|
-
value,
|
|
101
|
-
props: {
|
|
102
|
-
isConst: !!statement.var.props.isConst,
|
|
103
|
-
},
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function functionStatement(statement: FunctionStatement, context: CoreContext) {
|
|
108
|
-
const idToken = statement.id;
|
|
109
|
-
if (!idToken) return;
|
|
110
|
-
|
|
111
|
-
const funcData = context.functions[idToken];
|
|
112
|
-
if (funcData) {
|
|
113
|
-
new AlreadyDeclaredFunctionError(idToken).throw(statement.sourceInfo.startLine);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const body = statement.func.body ?? [];
|
|
117
|
-
const scope = statement.func.scope;
|
|
118
|
-
context.functions[idToken] = {
|
|
119
|
-
body,
|
|
120
|
-
scope,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function callStatement(statement: CallStatement, context: CoreContext) {
|
|
125
|
-
const funcId = statement.id
|
|
126
|
-
if (!funcId) return;
|
|
127
35
|
|
|
128
|
-
|
|
129
|
-
if (!funcData) {
|
|
130
|
-
new UndeclaredFunctionError(funcId).throw(statement.sourceInfo.startLine);
|
|
36
|
+
runner(statement, context);
|
|
131
37
|
}
|
|
132
|
-
|
|
133
|
-
}
|
|
38
|
+
return context;
|
|
39
|
+
}
|