@harmoniclabs/pebble 0.1.0-dev6 → 0.1.0-dev8
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/dist/IR/IRNodes/IRConst.js +1 -1
- package/dist/IR/IRNodes/IRNative/IRNativeTag.d.ts +6 -3
- package/dist/IR/IRNodes/IRNative/IRNativeTag.js +12 -4
- package/dist/IR/IRNodes/IRNative/index.d.ts +5 -2
- package/dist/IR/IRNodes/IRNative/index.js +6 -2
- package/dist/IR/toUPLC/CompilerOptions.d.ts +6 -1
- package/dist/IR/toUPLC/CompilerOptions.js +11 -1
- package/dist/IR/toUPLC/compileIRToUPLC.js +34 -35
- package/dist/IR/toUPLC/ctx/ToUplcCtx.js +2 -10
- package/dist/IR/toUPLC/subRoutines/handleLetted/groupByScope.js +0 -2
- package/dist/IR/toUPLC/subRoutines/handleLetted/index.js +69 -3
- package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.d.ts +3 -1
- package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.js +42 -10
- package/dist/IR/toUPLC/subRoutines/rewriteNativesAppliedToConstantsAndReturnRoot.js +292 -17
- package/dist/IR/utils/isClosedIRTerm.js +1 -1
- package/dist/IR/utils/positiveIntAsBytes.js +1 -5
- package/dist/compiler/AstCompiler/AstCompiler.d.ts +3 -0
- package/dist/compiler/AstCompiler/AstCompiler.js +66 -3
- package/dist/compiler/AstCompiler/internal/_deriveContractBody/_deriveContractBody.js +1 -1
- package/dist/compiler/AstCompiler/internal/exprs/_compileExpr.js +4 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compileFuncExpr.js +13 -4
- package/dist/compiler/AstCompiler/internal/exprs/_compileTypeConversionExpr.js +0 -1
- package/dist/compiler/AstCompiler/internal/exprs/_compileVarAccessExpr.js +3 -1
- package/dist/compiler/AstCompiler/internal/statements/_compileAssignmentStmt.js +7 -7
- package/dist/compiler/AstCompiler/internal/statements/_compileVarStmt.d.ts +2 -1
- package/dist/compiler/AstCompiler/internal/statements/_compileVarStmt.js +2 -1
- package/dist/compiler/AstCompiler/scope/AstScope.d.ts +1 -0
- package/dist/compiler/AstCompiler/scope/AstScope.js +5 -0
- package/dist/compiler/Compiler.d.ts +8 -1
- package/dist/compiler/Compiler.js +38 -1
- package/dist/compiler/TirCompiler/compileTirProgram.js +2 -1
- package/dist/compiler/TirCompiler/expressify/ExpressifyCtx.d.ts +4 -2
- package/dist/compiler/TirCompiler/expressify/ExpressifyCtx.js +42 -16
- package/dist/compiler/TirCompiler/expressify/determineReassignedVariablesAndReturn.js +2 -0
- package/dist/compiler/TirCompiler/expressify/expressify.js +26 -9
- package/dist/compiler/TirCompiler/expressify/expressifyForStmt.js +23 -7
- package/dist/compiler/TirCompiler/expressify/expressifyVarAssignmentStmt.d.ts +1 -2
- package/dist/compiler/TirCompiler/expressify/expressifyVarAssignmentStmt.js +15 -8
- package/dist/compiler/TirCompiler/expressify/expressifyVarDecl.js +6 -9
- package/dist/compiler/TirCompiler/expressify/expressifyVars.js +51 -16
- package/dist/compiler/TirCompiler/expressify/flattenSopNamedDeconstructInplace_addTopDestructToCtx_getNestedDeconstruct.js +1 -0
- package/dist/compiler/internalVar.d.ts +1 -1
- package/dist/compiler/internalVar.js +31 -24
- package/dist/compiler/io/CompilerIoApi.d.ts +1 -1
- package/dist/compiler/tir/expressions/TirCallExpr.d.ts +1 -1
- package/dist/compiler/tir/expressions/TirCallExpr.js +1 -1
- package/dist/compiler/tir/expressions/TirCaseExpr.js +2 -0
- package/dist/compiler/tir/expressions/TirFromDataExpr.js +2 -2
- package/dist/compiler/tir/expressions/TirFuncExpr.d.ts +1 -1
- package/dist/compiler/tir/expressions/TirFuncExpr.js +1 -1
- package/dist/compiler/tir/expressions/TirLettedExpr.d.ts +2 -2
- package/dist/compiler/tir/expressions/TirLettedExpr.js +4 -6
- package/dist/compiler/tir/expressions/TirNativeFunc.d.ts +3 -2
- package/dist/compiler/tir/expressions/TirNativeFunc.js +33 -12
- package/dist/compiler/tir/expressions/TirPropAccessExpr.js +1 -2
- package/dist/compiler/tir/expressions/TirVariableAccessExpr.d.ts +0 -1
- package/dist/compiler/tir/expressions/TirVariableAccessExpr.js +9 -5
- package/dist/compiler/tir/expressions/ToIRTermCtx.d.ts +3 -0
- package/dist/compiler/tir/expressions/ToIRTermCtx.js +8 -1
- package/dist/compiler/tir/expressions/binary/TirBinaryExpr.d.ts +1 -0
- package/dist/compiler/tir/expressions/binary/TirBinaryExpr.js +6 -1
- package/dist/compiler/tir/program/TypedProgram.d.ts +2 -2
- package/dist/compiler/tir/program/stdScope/stdScope.js +9 -23
- package/dist/compiler/tir/statements/TirIfStmt.d.ts +0 -1
- package/dist/compiler/tir/statements/TirIfStmt.js +0 -3
- package/dist/parser/Parser.js +18 -2
- package/dist/parser/Precedence.js +1 -0
- package/dist/utils/BitUtils/index.d.ts +1 -1
- package/dist/utils/BitUtils/index.js +1 -1
- package/dist/utils/IsSingleKey.d.ts +1 -1
- package/dist/utils/UPLCFlatUtils/index.d.ts +1 -1
- package/dist/utils/UPLCFlatUtils/index.js +2 -2
- package/dist/utils/array/keepSortedArrInplace.js +1 -0
- package/package.json +7 -6
- package/dist/compiler/TirCompiler/internal/_compileHoistedDeps.d.ts +0 -5
- package/dist/compiler/TirCompiler/internal/_compileHoistedDeps.js +0 -39
|
@@ -10,13 +10,14 @@ import { SourceRange } from "../../../../ast/Source/SourceRange.js";
|
|
|
10
10
|
import { TirExpr } from "../../../tir/expressions/TirExpr.js";
|
|
11
11
|
import { TirArrayLikeDeconstr } from "../../../tir/statements/TirVarDecl/TirArrayLikeDeconstr.js";
|
|
12
12
|
import { TirNamedDeconstructVarDecl } from "../../../tir/statements/TirVarDecl/TirNamedDeconstructVarDecl.js";
|
|
13
|
+
import { TirSimpleVarDecl } from "../../../tir/statements/TirVarDecl/TirSimpleVarDecl.js";
|
|
13
14
|
import { TirVarDecl } from "../../../tir/statements/TirVarDecl/TirVarDecl.js";
|
|
14
15
|
import { TirStructConstr } from "../../../tir/types/TirStructType.js";
|
|
15
16
|
import { TirType } from "../../../tir/types/TirType.js";
|
|
16
17
|
import { AstCompilationCtx } from "../../AstCompilationCtx.js";
|
|
17
18
|
export declare function _compileVarStmt(ctx: AstCompilationCtx, stmt: VarStmt): TirVarDecl[] | undefined;
|
|
18
19
|
export declare function _compileVarDecl(ctx: AstCompilationCtx, decl: VarDecl, typeHint: TirType | undefined): TirVarDecl | undefined;
|
|
19
|
-
export declare function _compileSimpleVarDecl(ctx: AstCompilationCtx, decl: SimpleVarDecl, typeHint: TirType | undefined):
|
|
20
|
+
export declare function _compileSimpleVarDecl(ctx: AstCompilationCtx, decl: SimpleVarDecl, typeHint: TirType | undefined): TirSimpleVarDecl | undefined;
|
|
20
21
|
export declare function _compileNamedDeconstructVarDecl(ctx: AstCompilationCtx, decl: NamedDeconstructVarDecl, typeHint: TirType | undefined): TirNamedDeconstructVarDecl | undefined;
|
|
21
22
|
export declare function _compileSingleDeconstructVarDecl(ctx: AstCompilationCtx, decl: SingleDeconstructVarDecl, typeHint: TirType | undefined): TirVarDecl | undefined;
|
|
22
23
|
export declare function _compileArrayLikeDeconstr(ctx: AstCompilationCtx, decl: ArrayLikeDeconstr, typeHint: TirType | undefined): TirArrayLikeDeconstr | undefined;
|
|
@@ -27,8 +27,9 @@ export function _compileVarStmt(ctx, stmt) {
|
|
|
27
27
|
return tirVarDecls;
|
|
28
28
|
}
|
|
29
29
|
export function _compileVarDecl(ctx, decl, typeHint) {
|
|
30
|
-
if (decl instanceof SimpleVarDecl)
|
|
30
|
+
if (decl instanceof SimpleVarDecl) {
|
|
31
31
|
return _compileSimpleVarDecl(ctx, decl, typeHint);
|
|
32
|
+
}
|
|
32
33
|
if (decl instanceof NamedDeconstructVarDecl)
|
|
33
34
|
return _compileNamedDeconstructVarDecl(ctx, decl, typeHint);
|
|
34
35
|
if (decl instanceof SingleDeconstructVarDecl)
|
|
@@ -80,6 +80,7 @@ export declare class AstScope {
|
|
|
80
80
|
constructor(parent: AstScope | undefined, program: TypedProgram, infos: Partial<ScopeInfos>);
|
|
81
81
|
defineValue(valueInfos: IVariableInfos): boolean;
|
|
82
82
|
resolveValue(name: string): ResolveValueResult | undefined;
|
|
83
|
+
allVariables(): string[];
|
|
83
84
|
defineUnambigousType(name: string, tirTypeKey: string, allowsDataEncoding: boolean, methodsNames: Map<AstFuncName, TirFuncName>): boolean;
|
|
84
85
|
defineType(name: string, possibleTirTypes: PossibleTirTypes): boolean;
|
|
85
86
|
resolveLocalType(name: string): PossibleTirTypes | undefined;
|
|
@@ -62,6 +62,8 @@ export class AstScope {
|
|
|
62
62
|
this.parent = parent;
|
|
63
63
|
}
|
|
64
64
|
defineValue(valueInfos) {
|
|
65
|
+
if (valueInfos.name === "§tx_3")
|
|
66
|
+
console.log("Defining variable tx3");
|
|
65
67
|
if (this._isReadonly)
|
|
66
68
|
return false;
|
|
67
69
|
if (invalidSymbolNames.has(valueInfos.name)
|
|
@@ -90,6 +92,9 @@ export class AstScope {
|
|
|
90
92
|
}
|
|
91
93
|
return undefined;
|
|
92
94
|
}
|
|
95
|
+
allVariables() {
|
|
96
|
+
return (this.parent?.allVariables() ?? []).concat(Array.from(this.variables.keys()));
|
|
97
|
+
}
|
|
93
98
|
defineUnambigousType(name, tirTypeKey, allowsDataEncoding, methodsNames) {
|
|
94
99
|
if (this._isReadonly)
|
|
95
100
|
return false;
|
|
@@ -6,5 +6,12 @@ export declare class Compiler extends DiagnosticEmitter {
|
|
|
6
6
|
readonly io: CompilerIoApi;
|
|
7
7
|
readonly cfg: CompilerOptions;
|
|
8
8
|
constructor(io?: CompilerIoApi, cfg?: CompilerOptions, diagnostics?: DiagnosticMessage[]);
|
|
9
|
-
compile(config?: Partial<CompilerOptions>): Promise<
|
|
9
|
+
compile(config?: Partial<CompilerOptions>): Promise<Uint8Array>;
|
|
10
|
+
export(config: Partial<ExportOptions> & HasFuncitonName): Promise<Uint8Array>;
|
|
10
11
|
}
|
|
12
|
+
interface HasFuncitonName {
|
|
13
|
+
functionName: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ExportOptions extends CompilerOptions, HasFuncitonName {
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -13,6 +13,9 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
13
13
|
super(diagnostics);
|
|
14
14
|
this.io = io;
|
|
15
15
|
this.cfg = cfg;
|
|
16
|
+
if (cfg.silent === true) {
|
|
17
|
+
this.io.stdout = { write() { } };
|
|
18
|
+
}
|
|
16
19
|
}
|
|
17
20
|
async compile(config) {
|
|
18
21
|
const cfg = {
|
|
@@ -31,6 +34,7 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
31
34
|
}
|
|
32
35
|
throw new Error("compilation failed with " + nDiags + " diagnostic messages; first message: " + fstErrorMsg);
|
|
33
36
|
}
|
|
37
|
+
// backend starts here
|
|
34
38
|
const ir = compileTypedProgram(cfg, program);
|
|
35
39
|
const uplc = compileIRToUPLC(ir);
|
|
36
40
|
const serialized = compileUPLC(new UPLCProgram(cfg.targetUplcVersion, uplc)).toBuffer().buffer;
|
|
@@ -39,6 +43,39 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
39
43
|
this.io.writeFile(outPath, serialized, cfg.root);
|
|
40
44
|
this.io.stdout.write(`compiled program written to ${outPath}\n`);
|
|
41
45
|
__VERY_UNSAFE_FORGET_IRHASH_ONLY_USE_AT_END_OF_UPLC_COMPILATION();
|
|
42
|
-
return;
|
|
46
|
+
return serialized;
|
|
47
|
+
}
|
|
48
|
+
async export(config) {
|
|
49
|
+
const cfg = {
|
|
50
|
+
...this.cfg,
|
|
51
|
+
...config,
|
|
52
|
+
// NEVER generate markers when exporting a function
|
|
53
|
+
addMarker: false,
|
|
54
|
+
};
|
|
55
|
+
if (typeof cfg.functionName !== "string" || cfg.functionName.length === 0) {
|
|
56
|
+
throw new Error("Compiler::export - invalid function name in export options");
|
|
57
|
+
}
|
|
58
|
+
const astCompiler = new AstCompiler(cfg, this.io, this.diagnostics);
|
|
59
|
+
const program = await astCompiler.export(cfg.functionName, cfg.entry);
|
|
60
|
+
if (this.diagnostics.length > 0) {
|
|
61
|
+
let msg;
|
|
62
|
+
globalThis.console && console.log(this.diagnostics);
|
|
63
|
+
const fstErrorMsg = this.diagnostics[0].toString();
|
|
64
|
+
const nDiags = this.diagnostics.length;
|
|
65
|
+
while (msg = this.diagnostics.shift()) {
|
|
66
|
+
this.io.stdout.write(msg.toString() + "\n");
|
|
67
|
+
}
|
|
68
|
+
throw new Error("compilation failed with " + nDiags + " diagnostic messages; first message: " + fstErrorMsg);
|
|
69
|
+
}
|
|
70
|
+
// backend starts here
|
|
71
|
+
const ir = compileTypedProgram(cfg, program);
|
|
72
|
+
const uplc = compileIRToUPLC(ir, cfg);
|
|
73
|
+
const serialized = compileUPLC(new UPLCProgram(cfg.targetUplcVersion, uplc)).toBuffer().buffer;
|
|
74
|
+
const outDir = cfg.outDir;
|
|
75
|
+
const outPath = outDir + (outDir.endsWith("/") ? "" : "/") + "out.flat";
|
|
76
|
+
this.io.writeFile(outPath, serialized, cfg.root);
|
|
77
|
+
this.io.stdout.write(`compiled program written to ${outPath}\n`);
|
|
78
|
+
__VERY_UNSAFE_FORGET_IRHASH_ONLY_USE_AT_END_OF_UPLC_COMPILATION();
|
|
79
|
+
return serialized;
|
|
43
80
|
}
|
|
44
81
|
}
|
|
@@ -13,8 +13,9 @@ export function compileTypedProgram(cfg, tirProgram) {
|
|
|
13
13
|
);
|
|
14
14
|
//*/
|
|
15
15
|
const mainFuncExpr = tirProgram.getMainOrThrow();
|
|
16
|
-
// console.log("main func
|
|
16
|
+
// console.log("main func:", mainFuncExpr.pretty() );
|
|
17
17
|
void expressify(mainFuncExpr, undefined, // loopReplacements
|
|
18
18
|
tirProgram);
|
|
19
|
+
// console.log("main func expressified:", mainFuncExpr.pretty() );
|
|
19
20
|
return mainFuncExpr.toIR(ToIRTermCtx.root());
|
|
20
21
|
}
|
|
@@ -33,11 +33,11 @@ export declare class ExpressifyCtx {
|
|
|
33
33
|
returnType: TirType;
|
|
34
34
|
readonly program: TypedProgram;
|
|
35
35
|
/** var name -> latest constant name */
|
|
36
|
-
readonly variables
|
|
36
|
+
private readonly variables;
|
|
37
37
|
/** constant name -> func param name (to build var access) */
|
|
38
38
|
readonly funcParams: Map<string, ExpressifyFuncParam>;
|
|
39
39
|
/** constant name -> letted expr */
|
|
40
|
-
readonly lettedConstants
|
|
40
|
+
private readonly lettedConstants;
|
|
41
41
|
/** var name -> prop name -> constant name (letted field extraction expr or var access for SoP)*/
|
|
42
42
|
readonly properties: Map<string, Map<string, string>>;
|
|
43
43
|
readonly hoisted: Map<string, TirHoistedExpr | TirNativeFunc>;
|
|
@@ -50,6 +50,7 @@ export declare class ExpressifyCtx {
|
|
|
50
50
|
lettedConstants?: Map<string, TirLettedExpr>,
|
|
51
51
|
/** var name -> prop name -> constant name (letted field extraction expr or var access for SoP)*/
|
|
52
52
|
properties?: Map<string, Map<string, string>>);
|
|
53
|
+
allVariablesNoLetted(): string[];
|
|
53
54
|
allVariables(): string[];
|
|
54
55
|
newChild(): ExpressifyCtx;
|
|
55
56
|
setNewVariableName(oldName: string, newName: string): void;
|
|
@@ -66,6 +67,7 @@ export declare class ExpressifyCtx {
|
|
|
66
67
|
*/
|
|
67
68
|
private _getNonHoistedVariable;
|
|
68
69
|
getVariable(name: string): ExpressifyFuncParam | TirHoistedExpr | TirNativeFunc | TirLettedExpr;
|
|
70
|
+
getVariableSSA(name: string): LatestVarNameSSA | undefined;
|
|
69
71
|
introduceFuncParams(params: readonly TirSimpleVarDecl[]): void;
|
|
70
72
|
introduceLettedConstant(name: string, lettedExpr: TirExpr, declRange: SourceRange): TirLettedExpr;
|
|
71
73
|
introduceSopConstrFieldsAsProperties(sopName: string, destructuredPattern: TirNamedDeconstructVarDecl): void;
|
|
@@ -5,6 +5,7 @@ import { TirLitIntExpr } from "../../tir/expressions/litteral/TirLitIntExpr.js";
|
|
|
5
5
|
import { TirCallExpr } from "../../tir/expressions/TirCallExpr.js";
|
|
6
6
|
import { TirElemAccessExpr } from "../../tir/expressions/TirElemAccessExpr.js";
|
|
7
7
|
import { TirFromDataExpr } from "../../tir/expressions/TirFromDataExpr.js";
|
|
8
|
+
import { TirHoistedExpr } from "../../tir/expressions/TirHoistedExpr.js";
|
|
8
9
|
import { TirLettedExpr } from "../../tir/expressions/TirLettedExpr.js";
|
|
9
10
|
import { TirNativeFunc } from "../../tir/expressions/TirNativeFunc.js";
|
|
10
11
|
import { data_t, int_t } from "../../tir/program/stdScope/stdScope.js";
|
|
@@ -48,12 +49,23 @@ export class ExpressifyCtx {
|
|
|
48
49
|
this.funcParams = funcParams;
|
|
49
50
|
this.lettedConstants = lettedConstants;
|
|
50
51
|
this.properties = properties;
|
|
51
|
-
this.hoisted = hoisted
|
|
52
|
+
this.hoisted = (hoisted
|
|
53
|
+
?? this.parent?.hoisted
|
|
54
|
+
?? new Map([...program.constants.entries()].map(([name, decl]) => {
|
|
55
|
+
if (!decl.initExpr)
|
|
56
|
+
throw new Error(`expected init expr in hoisted constant '${name}'`);
|
|
57
|
+
const expr = decl.initExpr instanceof TirHoistedExpr ? decl.initExpr : new TirHoistedExpr(name, decl.initExpr);
|
|
58
|
+
return [name, expr];
|
|
59
|
+
})));
|
|
60
|
+
}
|
|
61
|
+
allVariablesNoLetted() {
|
|
62
|
+
return (this.parent?.allVariablesNoLetted() ?? []).concat(...this.variables.keys());
|
|
52
63
|
}
|
|
53
64
|
allVariables() {
|
|
54
65
|
const thisVars = new Set([
|
|
55
66
|
...this.variables.keys(),
|
|
56
|
-
...this.lettedConstants.keys()
|
|
67
|
+
...this.lettedConstants.keys(),
|
|
68
|
+
...this.hoisted.keys(),
|
|
57
69
|
]);
|
|
58
70
|
return (this.parent?.allVariables() ?? []).concat(...thisVars);
|
|
59
71
|
}
|
|
@@ -64,26 +76,32 @@ export class ExpressifyCtx {
|
|
|
64
76
|
let latestNameSSA = this.variables.get(oldName);
|
|
65
77
|
if (!latestNameSSA)
|
|
66
78
|
this.variables.set(oldName, { latestName: newName });
|
|
67
|
-
else
|
|
79
|
+
else {
|
|
80
|
+
const prevName = latestNameSSA.latestName;
|
|
81
|
+
if (prevName === newName)
|
|
82
|
+
return; // no change
|
|
68
83
|
latestNameSSA.latestName = newName;
|
|
84
|
+
this.setNewVariableName(prevName, newName);
|
|
85
|
+
this.setNewVariableName(newName, newName);
|
|
86
|
+
}
|
|
69
87
|
}
|
|
70
88
|
setFuncParam(name, type) {
|
|
71
|
-
this.
|
|
89
|
+
this.setNewVariableName(name, name);
|
|
72
90
|
this.funcParams.set(name, { name, type });
|
|
73
91
|
}
|
|
74
92
|
/**
|
|
75
93
|
* `undefined` means the variable is not in the local context.
|
|
76
94
|
*/
|
|
77
95
|
getLocalVariable(name) {
|
|
78
|
-
// declared as constant shortcut
|
|
79
|
-
const constResult = this.lettedConstants.get(name);
|
|
80
|
-
if (constResult)
|
|
81
|
-
return constResult;
|
|
82
96
|
// declared as variable or param
|
|
83
97
|
const latestConstName = this.variables.get(name)?.latestName;
|
|
84
|
-
// no such variable
|
|
85
|
-
if (!latestConstName)
|
|
86
|
-
|
|
98
|
+
// no such variable (mutable at least)
|
|
99
|
+
if (!latestConstName) {
|
|
100
|
+
// try to get var declared as constant
|
|
101
|
+
// return undefined if not present
|
|
102
|
+
return this.lettedConstants.get(name);
|
|
103
|
+
}
|
|
104
|
+
;
|
|
87
105
|
return (this.lettedConstants.get(latestConstName)
|
|
88
106
|
?? this.funcParams.get(latestConstName));
|
|
89
107
|
}
|
|
@@ -101,11 +119,15 @@ export class ExpressifyCtx {
|
|
|
101
119
|
const result = (this._getNonHoistedVariable(name)
|
|
102
120
|
?? this.hoisted.get(name));
|
|
103
121
|
if (!result) {
|
|
104
|
-
|
|
122
|
+
console.log("[error log]: allVariables", this.allVariables());
|
|
105
123
|
throw new Error(`variable '${name}' not found in the context`);
|
|
106
124
|
}
|
|
107
125
|
return result;
|
|
108
126
|
}
|
|
127
|
+
getVariableSSA(name) {
|
|
128
|
+
return (this.variables.get(name)
|
|
129
|
+
?? this.parent?.getVariableSSA(name));
|
|
130
|
+
}
|
|
109
131
|
introduceFuncParams(params) {
|
|
110
132
|
for (const param of params) {
|
|
111
133
|
param.isConst = true;
|
|
@@ -113,9 +135,13 @@ export class ExpressifyCtx {
|
|
|
113
135
|
}
|
|
114
136
|
}
|
|
115
137
|
introduceLettedConstant(name, lettedExpr, declRange) {
|
|
138
|
+
// if( this.lettedConstants.has( name ) ) throw new Error(`constant '${name}' already introduced in the context`);
|
|
139
|
+
const existing = this.lettedConstants.get(name);
|
|
140
|
+
if (existing)
|
|
141
|
+
return existing.clone();
|
|
116
142
|
const result = new TirLettedExpr(name, lettedExpr, declRange);
|
|
117
143
|
this.lettedConstants.set(name, result);
|
|
118
|
-
return result.
|
|
144
|
+
return result.clone();
|
|
119
145
|
}
|
|
120
146
|
introduceSopConstrFieldsAsProperties(sopName, destructuredPattern) {
|
|
121
147
|
const fieldsMap = new Map();
|
|
@@ -182,7 +208,7 @@ export class ExpressifyCtx {
|
|
|
182
208
|
assertions.push(new TirAssertStmt(new TirEqualExpr(new TirCallExpr(TirNativeFunc.unConstrDataResultIndex, [lettedUnconstr], int_t, stmt.range), new TirLitIntExpr(BigInt(constrIdx), stmt.range), stmt.range), undefined, // no trace message
|
|
183
209
|
stmt.range));
|
|
184
210
|
const lettedRawFieldsName = getUniqueInternalName(`${varName}_fields`);
|
|
185
|
-
const lettedFields = this.introduceLettedConstant(lettedRawFieldsName, new
|
|
211
|
+
const lettedFields = this.introduceLettedConstant(lettedRawFieldsName, new TirCallExpr(TirNativeFunc.unConstrDataResultFields, [lettedUnconstr], new TirListT(data_t), stmt.range), stmt.range);
|
|
186
212
|
const fieldsToIntroduce = [...stmt.fields.keys()];
|
|
187
213
|
const hasRest = typeof stmt.rest === "string";
|
|
188
214
|
const fieldsMap = new Map();
|
|
@@ -206,7 +232,7 @@ export class ExpressifyCtx {
|
|
|
206
232
|
if (!fieldVarDecl)
|
|
207
233
|
throw new Error(`field '${fieldName}' not found in deconstruct data statement`);
|
|
208
234
|
if (fieldVarDecl instanceof TirSimpleVarDecl) {
|
|
209
|
-
this.
|
|
235
|
+
this.setNewVariableName(fieldVarDecl.name, lettedField.varName);
|
|
210
236
|
}
|
|
211
237
|
else {
|
|
212
238
|
// fieldVarDecl.type ??= fieldType;
|
|
@@ -246,7 +272,7 @@ export class ExpressifyCtx {
|
|
|
246
272
|
lettedExpr = new TirFromDataExpr(lettedExpr, elemVarDecl.type, elemVarDecl.range);
|
|
247
273
|
const lettedElem = this.introduceLettedConstant(lettedElemName, lettedExpr, elemVarDecl.range);
|
|
248
274
|
if (elemVarDecl instanceof TirSimpleVarDecl) {
|
|
249
|
-
this.
|
|
275
|
+
this.setNewVariableName(elemVarDecl.name, lettedElem.varName);
|
|
250
276
|
if (lettedElem.type instanceof TirDataStructType
|
|
251
277
|
&& lettedElem.type.constructors.length === 1) {
|
|
252
278
|
// if the element is a single-constructor data struct,
|
|
@@ -148,6 +148,8 @@ export function determineReassignedVariablesAndFlowInfos(stmt) {
|
|
|
148
148
|
continue;
|
|
149
149
|
}
|
|
150
150
|
const tsEnsureExsaustiveCheck = stmt;
|
|
151
|
+
console.error("unexpected", stmt);
|
|
152
|
+
throw new Error("unexpected statement type");
|
|
151
153
|
}
|
|
152
154
|
let reassigned = [...reassignedSet].sort();
|
|
153
155
|
reassigned = keepSortedStrArrInplace(reassigned, originalStmtDeps);
|
|
@@ -41,6 +41,8 @@ import { TirCallExpr } from "../../tir/expressions/TirCallExpr.js";
|
|
|
41
41
|
import { TirNativeFunc } from "../../tir/expressions/TirNativeFunc.js";
|
|
42
42
|
export function expressify(func, loopReplacements, program, parentCtx = undefined) {
|
|
43
43
|
const ctx = new ExpressifyCtx(parentCtx, func.returnType, program);
|
|
44
|
+
// define in case of recursion
|
|
45
|
+
ctx.setFuncParam(func.name, func.type);
|
|
44
46
|
ctx.introduceFuncParams(func.params);
|
|
45
47
|
func.body.stmts = [
|
|
46
48
|
new TirReturnStmt(expressifyFuncBody(ctx, func.body.stmts, loopReplacements), func.body.range)
|
|
@@ -52,8 +54,9 @@ loopReplacements, assertions = []) {
|
|
|
52
54
|
bodyStmts = bodyStmts.slice();
|
|
53
55
|
let stmt;
|
|
54
56
|
while (stmt = bodyStmts.shift()) {
|
|
55
|
-
//
|
|
56
|
-
// console.log(
|
|
57
|
+
// const isEdgeCase = stmt instanceof TirForStmt || stmt instanceof TirForOfStmt || stmt instanceof TirWhileStmt;
|
|
58
|
+
// if( isEdgeCase ) console.log([stmt, ...bodyStmts].map(s => s.toString()));
|
|
59
|
+
// if( isEdgeCase ) console.log( stmt );
|
|
57
60
|
if (stmt instanceof TirBreakStmt) {
|
|
58
61
|
if (typeof loopReplacements?.compileBreak !== "function")
|
|
59
62
|
throw new Error("break statement in function body.");
|
|
@@ -83,9 +86,8 @@ loopReplacements, assertions = []) {
|
|
|
83
86
|
throw new Error("simple var decl without init expr");
|
|
84
87
|
const initExpr = expressifyVars(ctx, stmt.initExpr);
|
|
85
88
|
stmt.initExpr = initExpr;
|
|
86
|
-
const lettedExpr = ctx.introduceLettedConstant(stmt.name, initExpr, stmt.range);
|
|
89
|
+
const lettedExpr = initExpr instanceof TirLettedExpr ? initExpr : ctx.introduceLettedConstant(stmt.name, initExpr, stmt.range);
|
|
87
90
|
if (!stmt.isConst) {
|
|
88
|
-
// console.log("setting variable")
|
|
89
91
|
ctx.setNewVariableName(stmt.name, lettedExpr.varName);
|
|
90
92
|
}
|
|
91
93
|
if (!isSingleConstrStruct(stmt.type))
|
|
@@ -186,7 +188,18 @@ loopReplacements, assertions = []) {
|
|
|
186
188
|
continue;
|
|
187
189
|
}
|
|
188
190
|
else if (stmt instanceof TirAssignmentStmt) {
|
|
189
|
-
|
|
191
|
+
void expressifyVarAssignmentStmt(ctx, stmt);
|
|
192
|
+
// !!! IMPORTANT BUG !!!
|
|
193
|
+
// .unshift the resulting `TirSimpleVarDecl` into bodyStmts
|
|
194
|
+
// will cause the assigned expression to be re-expressified
|
|
195
|
+
// meaning that variables that depend on themselves (e.g. `x = x + 1`) will be processed twice
|
|
196
|
+
//
|
|
197
|
+
// x = (x + 1) --> const x_i = (x + 1) --> const x_i = (x_i/*x + 1*/ */ + 1) (??? BUG ???)
|
|
198
|
+
//
|
|
199
|
+
// so ultimately `x = x + 1` would be compiled as `x = x + 1 + 1`
|
|
200
|
+
//
|
|
201
|
+
// const constDecl = expressifyVarAssignmentStmt( ctx, stmt );
|
|
202
|
+
// bodyStmts.unshift( constDecl );
|
|
190
203
|
continue;
|
|
191
204
|
}
|
|
192
205
|
else if (stmt instanceof TirBlockStmt) {
|
|
@@ -354,8 +367,10 @@ loopReplacements, assertions = []) {
|
|
|
354
367
|
const returnTypeAndInvalidInit = getBranchStmtReturnType(reassignedAndFlow, ctx, stmt.range);
|
|
355
368
|
const forStmt = loopToForStmt(stmt);
|
|
356
369
|
const { bodyStateType, initState } = getBodyStateType(returnTypeAndInvalidInit, forStmt);
|
|
357
|
-
const
|
|
358
|
-
|
|
370
|
+
const loopExprCtx = ctx.newChild();
|
|
371
|
+
const loopExpr = expressifyForStmt(loopExprCtx, forStmt, returnTypeAndInvalidInit.sop, bodyStateType, initState);
|
|
372
|
+
const result = TirAssertAndContinueExpr.fromStmtsAndContinuation(assertions, definitelyTerminates ? loopExpr : wrapNonTerminatingFinalStmtAsCaseExpr(loopExpr, returnTypeAndInvalidInit.sop, ctx, stmt.range, reassignedAndFlow, bodyStmts, loopReplacements));
|
|
373
|
+
return result;
|
|
359
374
|
}
|
|
360
375
|
else {
|
|
361
376
|
// const tsEnsureExhautstiveCheck: never = stmt;
|
|
@@ -402,6 +417,7 @@ function getNestedDestructsInSingleSopDestructPattern(pattern) {
|
|
|
402
417
|
return result;
|
|
403
418
|
}
|
|
404
419
|
function wrapNonTerminatingFinalStmtAsCaseExpr(finalStmtExpr, sop, ctx, stmtRange, reassignsAndReturns, nextBodyStmts, loopReplacements) {
|
|
420
|
+
nextBodyStmts = nextBodyStmts.slice();
|
|
405
421
|
const continuations = [];
|
|
406
422
|
const contBranchCtx = ctx.newChild();
|
|
407
423
|
const contConstr = sop.constructors[0];
|
|
@@ -416,9 +432,10 @@ function wrapNonTerminatingFinalStmtAsCaseExpr(finalStmtExpr, sop, ctx, stmtRang
|
|
|
416
432
|
false, // not a constant
|
|
417
433
|
stmtRange);
|
|
418
434
|
const nestedDeconstructs = flattenSopNamedDeconstructInplace_addTopDestructToCtx_getNestedDeconstruct(contPattern, contBranchCtx);
|
|
419
|
-
|
|
435
|
+
const mainContinuaiton = expressifyFuncBody(contBranchCtx, nestedDeconstructs
|
|
420
436
|
.concat(nextBodyStmts), loopReplacements, [] // assertions are added before if statement exectution
|
|
421
|
-
)
|
|
437
|
+
);
|
|
438
|
+
continuations.push(new TirCaseMatcher(contPattern, mainContinuaiton, stmtRange));
|
|
422
439
|
if (reassignsAndReturns.returns) {
|
|
423
440
|
const earlyRetConstr = sop.constructors[1];
|
|
424
441
|
const earlyRetField = earlyRetConstr.fields[0];
|
|
@@ -20,6 +20,7 @@ import { TirFuncT } from "../../tir/types/TirNativeType/native/function.js";
|
|
|
20
20
|
import { getListTypeArg } from "../../tir/types/utils/getListTypeArg.js";
|
|
21
21
|
import { expressifyFuncBody } from "./expressify.js";
|
|
22
22
|
import { isExpressifyFuncParam } from "./ExpressifyCtx.js";
|
|
23
|
+
import { expressifyVars } from "./expressifyVars.js";
|
|
23
24
|
export function loopToForStmt(stmt) {
|
|
24
25
|
if (stmt instanceof TirForStmt)
|
|
25
26
|
return stmt;
|
|
@@ -70,8 +71,14 @@ export function loopToForStmt(stmt) {
|
|
|
70
71
|
export function expressifyForStmt(ctx, stmt, returnType, bodyStateType, initState) {
|
|
71
72
|
let loopBody = stmt.body instanceof TirBlockStmt ? stmt.body : new TirBlockStmt([stmt.body], stmt.range);
|
|
72
73
|
loopBody = new TirBlockStmt(loopBody.stmts.slice(), loopBody.range);
|
|
74
|
+
// add final loop updates
|
|
75
|
+
if (Array.isArray(stmt.update))
|
|
76
|
+
for (const updateStmt of stmt.update) {
|
|
77
|
+
loopBody.stmts.push(updateStmt);
|
|
78
|
+
}
|
|
79
|
+
// ALWAYS add a final `continue;` to the end of the loop body
|
|
80
|
+
loopBody.stmts.push(new TirContinueStmt(loopBody.range.atEnd()));
|
|
73
81
|
if (stmt.condition) {
|
|
74
|
-
loopBody.stmts.push(new TirContinueStmt(loopBody.range.atEnd()));
|
|
75
82
|
loopBody = new TirBlockStmt([
|
|
76
83
|
new TirIfStmt(stmt.condition,
|
|
77
84
|
// then
|
|
@@ -80,8 +87,6 @@ export function expressifyForStmt(ctx, stmt, returnType, bodyStateType, initStat
|
|
|
80
87
|
new TirBlockStmt([new TirBreakStmt(stmt.condition.range)], stmt.condition.range), stmt.condition.range)
|
|
81
88
|
], loopBody.range);
|
|
82
89
|
}
|
|
83
|
-
// ALWAYS add a final `continue;` to the end of the loop body
|
|
84
|
-
loopBody.stmts.push(new TirContinueStmt(loopBody.range.atEnd()));
|
|
85
90
|
const loopFuncName = getUniqueInternalName("loop");
|
|
86
91
|
const loopFuncType = new TirFuncT(bodyStateType.constructors[0].fields.map(f => f.type), returnType);
|
|
87
92
|
const loopReplacements = {
|
|
@@ -154,11 +159,22 @@ export function expressifyForStmt(ctx, stmt, returnType, bodyStateType, initStat
|
|
|
154
159
|
for (const { name, type } of bodyStateType.constructors[0].fields) {
|
|
155
160
|
loopCompilationCtx.setFuncParam(name, type);
|
|
156
161
|
}
|
|
157
|
-
|
|
162
|
+
const loopFuncExpr = new TirFuncExpr(loopFuncName, // func name
|
|
163
|
+
// func params
|
|
164
|
+
bodyStateType.constructors[0].fields.map(f => new TirSimpleVarDecl(f.name, f.type, undefined, // no initial value
|
|
158
165
|
false, // is constant
|
|
159
|
-
stmt.range)),
|
|
166
|
+
stmt.range)),
|
|
167
|
+
// func return type
|
|
168
|
+
returnType,
|
|
169
|
+
// func body
|
|
170
|
+
new TirBlockStmt([
|
|
160
171
|
new TirReturnStmt(expressifyFuncBody(loopCompilationCtx, loopBody.stmts, loopReplacements, [] // assertions
|
|
161
172
|
), stmt.range)
|
|
162
|
-
], stmt.range),
|
|
163
|
-
|
|
173
|
+
], stmt.range),
|
|
174
|
+
// func range
|
|
175
|
+
stmt.range, true // is loop
|
|
176
|
+
);
|
|
177
|
+
return new TirCallExpr(loopFuncExpr,
|
|
178
|
+
// loop call init args
|
|
179
|
+
initState.values.map(v => expressifyVars(ctx, v.clone())), returnType, stmt.range);
|
|
164
180
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import { TirAssignmentStmt } from "../../tir/statements/TirAssignmentStmt.js";
|
|
2
|
-
import { TirSimpleVarDecl } from "../../tir/statements/TirVarDecl/TirSimpleVarDecl.js";
|
|
3
2
|
import { ExpressifyCtx } from "./ExpressifyCtx.js";
|
|
4
|
-
export declare function expressifyVarAssignmentStmt(ctx: ExpressifyCtx, stmt: TirAssignmentStmt):
|
|
3
|
+
export declare function expressifyVarAssignmentStmt(ctx: ExpressifyCtx, stmt: TirAssignmentStmt): void;
|
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import { getUniqueInternalName } from "../../internalVar.js";
|
|
2
|
-
import { TirLettedExpr } from "../../tir/expressions/TirLettedExpr.js";
|
|
3
|
-
import { TirSimpleVarDecl } from "../../tir/statements/TirVarDecl/TirSimpleVarDecl.js";
|
|
4
2
|
import { expressifyVars } from "./expressifyVars.js";
|
|
5
3
|
export function expressifyVarAssignmentStmt(ctx, stmt) {
|
|
4
|
+
// since we no longer return a new TirSimpleVarDecl,
|
|
5
|
+
// we need to expressify the assigned expression here
|
|
6
|
+
//
|
|
7
|
+
// !!! IMPORTANT !!! we MUST NOT do it if we instead returned a new TirSimpleVarDecl,
|
|
8
|
+
// otherwise it would be re-processed, casing bugs
|
|
6
9
|
const assignedExpr = expressifyVars(ctx, stmt.assignedExpr);
|
|
7
10
|
const originalName = stmt.varIdentifier.resolvedValue.variableInfos.name;
|
|
8
|
-
const latestVarNameSSA = ctx.
|
|
11
|
+
const latestVarNameSSA = ctx.getVariableSSA(originalName);
|
|
9
12
|
if (!latestVarNameSSA) {
|
|
10
13
|
throw new Error("re-assigning constant variable '" + originalName + "'");
|
|
11
14
|
}
|
|
12
15
|
const newUniqueName = getUniqueInternalName(originalName);
|
|
13
|
-
|
|
16
|
+
ctx.setNewVariableName(originalName, newUniqueName);
|
|
14
17
|
// point to the same object
|
|
15
|
-
ctx.
|
|
16
|
-
ctx.lettedConstants.set(newUniqueName, new TirLettedExpr(newUniqueName, assignedExpr, stmt.range));
|
|
18
|
+
ctx.introduceLettedConstant(newUniqueName, assignedExpr, stmt.range);
|
|
17
19
|
// will replace re-assignment in body
|
|
18
|
-
return new TirSimpleVarDecl(
|
|
19
|
-
|
|
20
|
+
// return new TirSimpleVarDecl(
|
|
21
|
+
// newUniqueName,
|
|
22
|
+
// stmt.varIdentifier.resolvedValue.variableInfos.type,
|
|
23
|
+
// assignedExpr,
|
|
24
|
+
// true, // isConst
|
|
25
|
+
// stmt.range,
|
|
26
|
+
// );
|
|
20
27
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { TirLettedExpr } from "../../tir/expressions/TirLettedExpr.js";
|
|
2
1
|
import { TirArrayLikeDeconstr } from "../../tir/statements/TirVarDecl/TirArrayLikeDeconstr.js";
|
|
3
2
|
import { TirNamedDeconstructVarDecl } from "../../tir/statements/TirVarDecl/TirNamedDeconstructVarDecl.js";
|
|
4
3
|
import { TirSimpleVarDecl } from "../../tir/statements/TirVarDecl/TirSimpleVarDecl.js";
|
|
@@ -6,30 +5,28 @@ import { TirSingleDeconstructVarDecl } from "../../tir/statements/TirVarDecl/Tir
|
|
|
6
5
|
import { expressifyVars } from "./expressifyVars.js";
|
|
7
6
|
export function expressifyVarDecl(ctx, stmt) {
|
|
8
7
|
const isConst = stmt.isConst;
|
|
9
|
-
console.log("expressifyVarDecl", stmt);
|
|
10
8
|
if (stmt.initExpr)
|
|
11
9
|
expressifyVars(ctx, stmt.initExpr);
|
|
12
10
|
if (stmt instanceof TirSimpleVarDecl) {
|
|
13
|
-
if (stmt.isConst) {
|
|
14
|
-
void ctx.
|
|
15
|
-
|
|
16
|
-
stmt.isConst = true;
|
|
11
|
+
if (!stmt.isConst) {
|
|
12
|
+
void ctx.setNewVariableName(stmt.name, stmt.name);
|
|
13
|
+
// stmt.isConst = true;
|
|
17
14
|
}
|
|
18
|
-
ctx.
|
|
15
|
+
ctx.introduceLettedConstant(stmt.name, stmt.initExpr, stmt.range);
|
|
19
16
|
}
|
|
20
17
|
if (stmt instanceof TirNamedDeconstructVarDecl
|
|
21
18
|
|| stmt instanceof TirSingleDeconstructVarDecl) {
|
|
22
19
|
for (const [_field, varDecl] of stmt.fields)
|
|
23
20
|
expressifyVarDecl(ctx, varDecl);
|
|
24
21
|
if (stmt.rest)
|
|
25
|
-
ctx.
|
|
22
|
+
ctx.setNewVariableName(stmt.rest, stmt.rest);
|
|
26
23
|
return;
|
|
27
24
|
}
|
|
28
25
|
if (stmt instanceof TirArrayLikeDeconstr) {
|
|
29
26
|
for (const varDecl of stmt.elements)
|
|
30
27
|
expressifyVarDecl(ctx, varDecl);
|
|
31
28
|
if (stmt.rest)
|
|
32
|
-
ctx.
|
|
29
|
+
ctx.setNewVariableName(stmt.rest, stmt.rest);
|
|
33
30
|
return;
|
|
34
31
|
}
|
|
35
32
|
}
|