@harmoniclabs/pebble 0.2.0 → 0.3.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/dist/IR/CompilationCtx.d.ts +40 -0
- package/dist/IR/CompilationCtx.js +54 -0
- package/dist/IR/IRHash.d.ts +23 -2
- package/dist/IR/IRHash.js +10 -60
- package/dist/IR/IRNodes/IRConst.js +22 -2
- package/dist/IR/IRNodes/IRHoisted.d.ts +0 -1
- package/dist/IR/IRNodes/IRHoisted.js +4 -6
- package/dist/IR/IRNodes/IRLetted.d.ts +0 -1
- package/dist/IR/IRNodes/IRLetted.js +4 -6
- package/dist/IR/IRNodes/IRNative/IRNativeTag.d.ts +22 -2
- package/dist/IR/IRNodes/IRNative/IRNativeTag.js +26 -2
- package/dist/IR/IRNodes/IRNative/index.d.ts +16 -1
- package/dist/IR/IRNodes/IRNative/index.js +27 -2
- package/dist/IR/IRNodes/utils/hashVarSym.d.ts +0 -1
- package/dist/IR/IRNodes/utils/hashVarSym.js +27 -33
- package/dist/IR/toUPLC/CompilerOptions.d.ts +12 -0
- package/dist/IR/toUPLC/CompilerOptions.js +14 -9
- package/dist/IR/toUPLC/compileIRToUPLC.js +39 -3
- package/dist/IR/toUPLC/subRoutines/inlineSingleUseLetBindingsAndReturnRoot.d.ts +23 -0
- package/dist/IR/toUPLC/subRoutines/inlineSingleUseLetBindingsAndReturnRoot.js +263 -0
- package/dist/IR/toUPLC/subRoutines/introduceCaseForDualHeadTailAndReturnRoot.d.ts +35 -0
- package/dist/IR/toUPLC/subRoutines/introduceCaseForDualHeadTailAndReturnRoot.js +169 -0
- package/dist/IR/toUPLC/subRoutines/replaceHoistedWithLetted.d.ts +0 -1
- package/dist/IR/toUPLC/subRoutines/replaceHoistedWithLetted.js +6 -6
- package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.d.ts +2 -3
- package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.js +106 -65
- package/dist/IR/toUPLC/subRoutines/rewriteHeadTailInCaseConsAndReturnRoot.d.ts +30 -0
- package/dist/IR/toUPLC/subRoutines/rewriteHeadTailInCaseConsAndReturnRoot.js +95 -0
- package/dist/IR/toUPLC/subRoutines/rewriteNativesAppliedToConstantsAndReturnRoot.js +36 -5
- package/dist/IR/toUPLC/subRoutines/rewriteToCaseOverConstAndReturnRoot.d.ts +35 -0
- package/dist/IR/toUPLC/subRoutines/rewriteToCaseOverConstAndReturnRoot.js +169 -0
- package/dist/IR/tree_utils/_ir_caseList.d.ts +15 -0
- package/dist/IR/tree_utils/_ir_caseList.js +19 -0
- package/dist/ast/nodes/statements/declarations/StructDecl.d.ts +16 -2
- package/dist/ast/nodes/statements/declarations/StructDecl.js +15 -1
- package/dist/compiler/AstCompiler/AstCompiler.d.ts +1 -0
- package/dist/compiler/AstCompiler/AstCompiler.js +41 -4
- package/dist/compiler/AstCompiler/internal/_deriveContractBody/_deriveContractBody.js +3 -3
- package/dist/compiler/AstCompiler/internal/exprs/_compileCaseExpr.js +31 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compileIsExpr.js +12 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compilePropAccessExpr.js +36 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compileUnaryPrefixExpr.js +13 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileAddExpr.js +18 -5
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileEqualExpr.js +3 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileGreaterThanEqualExpr.js +2 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileGreaterThanExpr.js +2 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileLessThanEqualExpr.js +2 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileLessThanExpr.js +2 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileMultExpr.js +24 -6
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileNotEqualExpr.js +2 -1
- package/dist/compiler/AstCompiler/internal/exprs/binary/_compileSubExpr.js +16 -5
- package/dist/compiler/AstCompiler/internal/statements/_compileMatchStmt.js +33 -20
- package/dist/compiler/AstCompiler/utils/getPropAccessReturnType.js +11 -0
- package/dist/compiler/Compiler.js +20 -27
- package/dist/compiler/TirCompiler/expressify/ExpressifyCtx.js +1 -1
- package/dist/compiler/TirCompiler/expressify/expressify.js +30 -2
- package/dist/compiler/TirCompiler/expressify/expressifyForStmt.d.ts +2 -1
- package/dist/compiler/TirCompiler/expressify/expressifyForStmt.js +45 -7
- package/dist/compiler/TirCompiler/expressify/expressifyVars.d.ts +0 -1
- package/dist/compiler/TirCompiler/expressify/expressifyVars.js +23 -8
- package/dist/compiler/tir/expressions/TirCaseExpr.d.ts +9 -0
- package/dist/compiler/tir/expressions/TirCaseExpr.js +144 -122
- package/dist/compiler/tir/expressions/TirElemAccessExpr.js +2 -2
- package/dist/compiler/tir/expressions/TirFromDataExpr.js +102 -67
- package/dist/compiler/tir/expressions/TirIsExpr.js +14 -1
- package/dist/compiler/tir/expressions/TirNativeFunc.d.ts +1 -2
- package/dist/compiler/tir/expressions/TirNativeFunc.js +2 -12
- package/dist/compiler/tir/expressions/TirToDataExpr.js +3 -0
- package/dist/compiler/tir/expressions/TirTypeConversionExpr.js +10 -0
- package/dist/compiler/tir/expressions/TirVariableAccessExpr.d.ts +2 -3
- package/dist/compiler/tir/expressions/TirVariableAccessExpr.js +1 -4
- package/dist/compiler/tir/expressions/ToIRTermCtx.d.ts +20 -3
- package/dist/compiler/tir/expressions/ToIRTermCtx.js +48 -3
- package/dist/compiler/tir/expressions/binary/TirBinaryExpr.d.ts +2 -2
- package/dist/compiler/tir/expressions/binary/TirBinaryExpr.js +45 -8
- package/dist/compiler/tir/expressions/litteral/TirLitEnumMemberExpr.d.ts +19 -0
- package/dist/compiler/tir/expressions/litteral/TirLitEnumMemberExpr.js +24 -0
- package/dist/compiler/tir/expressions/litteral/TirLitteralExpr.d.ts +2 -1
- package/dist/compiler/tir/expressions/litteral/TirLitteralExpr.js +2 -0
- package/dist/compiler/tir/expressions/unary/TirUnaryMinus.js +4 -1
- package/dist/compiler/tir/program/stdScope/populateStdNamespace.js +49 -4
- package/dist/compiler/tir/program/stdScope/prelude/preludeTypesSrc.js +35 -2
- package/dist/compiler/tir/program/stdScope/stdScope.d.ts +7 -0
- package/dist/compiler/tir/program/stdScope/stdScope.js +83 -40
- package/dist/compiler/tir/types/TirEnumType.d.ts +21 -0
- package/dist/compiler/tir/types/TirEnumType.js +36 -0
- package/dist/compiler/tir/types/TirNativeType/TirNativeType.d.ts +4 -2
- package/dist/compiler/tir/types/TirNativeType/TirNativeType.js +5 -0
- package/dist/compiler/tir/types/TirNativeType/native/array.d.ts +16 -0
- package/dist/compiler/tir/types/TirNativeType/native/array.js +38 -0
- package/dist/compiler/tir/types/TirNativeType/native/index.d.ts +2 -0
- package/dist/compiler/tir/types/TirNativeType/native/index.js +2 -0
- package/dist/compiler/tir/types/TirNativeType/native/value.d.ts +18 -0
- package/dist/compiler/tir/types/TirNativeType/native/value.js +17 -0
- package/dist/compiler/tir/types/TirStructType.js +6 -1
- package/dist/compiler/tir/types/TirType.d.ts +3 -2
- package/dist/compiler/tir/types/TirType.js +4 -1
- package/dist/compiler/tir/types/utils/canAssignTo.js +28 -0
- package/dist/compiler/tir/types/utils/canCastTo.js +14 -1
- package/dist/compiler/tir/types/utils/getDeconstructableType.d.ts +2 -1
- package/dist/compiler/tir/types/utils/getDeconstructableType.js +2 -0
- package/dist/compiler/tir/types/utils/inferTypeArgs.js +4 -0
- package/dist/compiler/tir/types/utils/normalizeEnumToInt.d.ts +10 -0
- package/dist/compiler/tir/types/utils/normalizeEnumToInt.js +17 -0
- package/dist/compiler/tir/types/utils/substituteTypeParams.js +5 -0
- package/dist/diagnostics/diagnosticMessages.generated.d.ts +5 -0
- package/dist/diagnostics/diagnosticMessages.generated.js +10 -0
- package/dist/parser/Parser.js +29 -13
- package/dist/tokenizer/Token.d.ts +8 -7
- package/dist/tokenizer/Token.js +8 -7
- package/dist/tokenizer/utils/tokenFromKeyword.js +2 -0
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/package.json +3 -3
- package/dist/IR/tree_utils/_ir_lazyChooseList.d.ts +0 -3
- package/dist/IR/tree_utils/_ir_lazyChooseList.js +0 -7
|
@@ -2,6 +2,7 @@ import { DiagnosticCode } from "../../../../../diagnostics/diagnosticMessages.ge
|
|
|
2
2
|
import { TirLessThanEqualExpr } from "../../../../tir/expressions/binary/TirBinaryExpr.js";
|
|
3
3
|
import { TirAliasType } from "../../../../tir/types/TirAliasType.js";
|
|
4
4
|
import { canAssignTo } from "../../../../tir/types/utils/canAssignTo.js";
|
|
5
|
+
import { normalizeEnumToInt } from "../../../../tir/types/utils/normalizeEnumToInt.js";
|
|
5
6
|
import { int_t, bytes_t } from "../../../../tir/program/stdScope/stdScope.js";
|
|
6
7
|
import { _compileExpr } from "../_compileExpr.js";
|
|
7
8
|
export function _compileLessThanEqualExpr(ctx, expr, typeHint) {
|
|
@@ -11,7 +12,7 @@ export function _compileLessThanEqualExpr(ctx, expr, typeHint) {
|
|
|
11
12
|
if (!canAssignTo(left.type, int_t)
|
|
12
13
|
&& !canAssignTo(left.type, bytes_t))
|
|
13
14
|
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.left.range, left.type.toString(), int_t.toString());
|
|
14
|
-
let leftType = left.type;
|
|
15
|
+
let leftType = normalizeEnumToInt(left.type, int_t);
|
|
15
16
|
while (leftType instanceof TirAliasType)
|
|
16
17
|
leftType = leftType.aliased;
|
|
17
18
|
const right = _compileExpr(ctx, expr.right, leftType);
|
|
@@ -2,6 +2,7 @@ import { DiagnosticCode } from "../../../../../diagnostics/diagnosticMessages.ge
|
|
|
2
2
|
import { TirLessThanExpr } from "../../../../tir/expressions/binary/TirBinaryExpr.js";
|
|
3
3
|
import { TirAliasType } from "../../../../tir/types/TirAliasType.js";
|
|
4
4
|
import { canAssignTo } from "../../../../tir/types/utils/canAssignTo.js";
|
|
5
|
+
import { normalizeEnumToInt } from "../../../../tir/types/utils/normalizeEnumToInt.js";
|
|
5
6
|
import { _compileExpr } from "../_compileExpr.js";
|
|
6
7
|
export function _compileLessThanExpr(ctx, expr, typeHint) {
|
|
7
8
|
const int_t = ctx.program.stdTypes.int;
|
|
@@ -12,7 +13,7 @@ export function _compileLessThanExpr(ctx, expr, typeHint) {
|
|
|
12
13
|
if (!canAssignTo(left.type, int_t)
|
|
13
14
|
&& !canAssignTo(left.type, bytes_t))
|
|
14
15
|
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.left.range, left.type.toString(), int_t.toString());
|
|
15
|
-
let leftType = left.type;
|
|
16
|
+
let leftType = normalizeEnumToInt(left.type, int_t);
|
|
16
17
|
while (leftType instanceof TirAliasType)
|
|
17
18
|
leftType = leftType.aliased;
|
|
18
19
|
const right = _compileExpr(ctx, expr.right, leftType);
|
|
@@ -1,20 +1,38 @@
|
|
|
1
1
|
import { DiagnosticCode } from "../../../../../diagnostics/diagnosticMessages.generated.js";
|
|
2
2
|
import { TirMultExpr } from "../../../../tir/expressions/binary/TirBinaryExpr.js";
|
|
3
|
+
import { TirValueT } from "../../../../tir/types/TirNativeType/native/value.js";
|
|
3
4
|
import { canAssignTo } from "../../../../tir/types/utils/canAssignTo.js";
|
|
5
|
+
import { getUnaliased } from "../../../../tir/types/utils/getUnaliased.js";
|
|
4
6
|
import { _compileExpr } from "../_compileExpr.js";
|
|
5
7
|
export function _compileMultExpr(ctx, expr, _typeHint) {
|
|
6
8
|
const int_t = ctx.program.stdTypes.int;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
// Probe both sides without hints so we can disambiguate
|
|
10
|
+
// (int * Value) / (Value * int) / (int * int).
|
|
11
|
+
const leftProbe = _compileExpr(ctx, expr.left, undefined);
|
|
12
|
+
if (!leftProbe)
|
|
9
13
|
return undefined;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
const leftTy = getUnaliased(leftProbe.type);
|
|
15
|
+
if (leftTy instanceof TirValueT) {
|
|
16
|
+
const right = _compileExpr(ctx, expr.right, int_t);
|
|
17
|
+
if (!right)
|
|
18
|
+
return undefined;
|
|
19
|
+
if (!canAssignTo(right.type, int_t))
|
|
20
|
+
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.right.range, right.type.toString(), int_t.toString());
|
|
21
|
+
return new TirMultExpr(leftProbe, right, expr.range);
|
|
22
|
+
}
|
|
23
|
+
if (!canAssignTo(leftProbe.type, int_t))
|
|
24
|
+
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.left.range, leftProbe.type.toString(), int_t.toString());
|
|
25
|
+
// left is int — right may be int (regular product) or Value (scaleValue).
|
|
26
|
+
const right = _compileExpr(ctx, expr.right, undefined);
|
|
13
27
|
if (!right)
|
|
14
28
|
return undefined;
|
|
29
|
+
const rightTy = getUnaliased(right.type);
|
|
30
|
+
if (rightTy instanceof TirValueT) {
|
|
31
|
+
return new TirMultExpr(leftProbe, right, expr.range);
|
|
32
|
+
}
|
|
15
33
|
if (!canAssignTo(right.type, int_t))
|
|
16
34
|
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.right.range, right.type.toString(), int_t.toString());
|
|
17
|
-
return new TirMultExpr(
|
|
35
|
+
return new TirMultExpr(leftProbe, right,
|
|
18
36
|
// implicit int type,
|
|
19
37
|
expr.range);
|
|
20
38
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { DiagnosticCode } from "../../../../../diagnostics/diagnosticMessages.generated.js";
|
|
2
2
|
import { TirNotEqualExpr } from "../../../../tir/expressions/binary/TirBinaryExpr.js";
|
|
3
3
|
import { canAssignTo } from "../../../../tir/types/utils/canAssignTo.js";
|
|
4
|
+
import { normalizeEnumToInt } from "../../../../tir/types/utils/normalizeEnumToInt.js";
|
|
4
5
|
import { _compileExpr } from "../_compileExpr.js";
|
|
5
6
|
export function _compileNotEqualExpr(ctx, expr, typeHint) {
|
|
6
7
|
const left = _compileExpr(ctx, expr.left, typeHint);
|
|
7
8
|
if (!left)
|
|
8
9
|
return undefined;
|
|
9
|
-
const leftType = left.type;
|
|
10
|
+
const leftType = normalizeEnumToInt(left.type, ctx.program.stdTypes.int);
|
|
10
11
|
const right = _compileExpr(ctx, expr.right, leftType);
|
|
11
12
|
if (!right)
|
|
12
13
|
return undefined;
|
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
import { DiagnosticCode } from "../../../../../diagnostics/diagnosticMessages.generated.js";
|
|
2
2
|
import { TirSubExpr } from "../../../../tir/expressions/binary/TirBinaryExpr.js";
|
|
3
|
+
import { TirValueT } from "../../../../tir/types/TirNativeType/native/value.js";
|
|
3
4
|
import { canAssignTo } from "../../../../tir/types/utils/canAssignTo.js";
|
|
5
|
+
import { getUnaliased } from "../../../../tir/types/utils/getUnaliased.js";
|
|
4
6
|
import { _compileExpr } from "../_compileExpr.js";
|
|
5
7
|
export function _compileSubExpr(ctx, expr, _typeHint) {
|
|
6
8
|
const int_t = ctx.program.stdTypes.int;
|
|
7
|
-
const
|
|
8
|
-
if (!
|
|
9
|
+
const leftProbe = _compileExpr(ctx, expr.left, undefined);
|
|
10
|
+
if (!leftProbe)
|
|
9
11
|
return undefined;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
const leftTy = getUnaliased(leftProbe.type);
|
|
13
|
+
if (leftTy instanceof TirValueT) {
|
|
14
|
+
const right = _compileExpr(ctx, expr.right, leftProbe.type);
|
|
15
|
+
if (!right)
|
|
16
|
+
return undefined;
|
|
17
|
+
if (!(getUnaliased(right.type) instanceof TirValueT))
|
|
18
|
+
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.right.range, right.type.toString(), "Value");
|
|
19
|
+
return new TirSubExpr(leftProbe, right, expr.range);
|
|
20
|
+
}
|
|
21
|
+
if (!canAssignTo(leftProbe.type, int_t))
|
|
22
|
+
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.left.range, leftProbe.type.toString(), int_t.toString());
|
|
12
23
|
const right = _compileExpr(ctx, expr.right, int_t);
|
|
13
24
|
if (!right)
|
|
14
25
|
return undefined;
|
|
15
26
|
if (!canAssignTo(right.type, int_t))
|
|
16
27
|
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.right.range, right.type.toString(), int_t.toString());
|
|
17
|
-
return new TirSubExpr(
|
|
28
|
+
return new TirSubExpr(leftProbe, right,
|
|
18
29
|
// implicit int type,
|
|
19
30
|
expr.range);
|
|
20
31
|
}
|
|
@@ -11,6 +11,7 @@ import { TirDataT } from "../../../tir/types/TirNativeType/native/data.js";
|
|
|
11
11
|
import { TirDataOptT } from "../../../tir/types/TirNativeType/native/Optional/data.js";
|
|
12
12
|
import { TirSopOptT } from "../../../tir/types/TirNativeType/native/Optional/sop.js";
|
|
13
13
|
import { isTirStructType, TirDataStructType, TirSoPStructType } from "../../../tir/types/TirStructType.js";
|
|
14
|
+
import { TirEnumType } from "../../../tir/types/TirEnumType.js";
|
|
14
15
|
import { getDeconstructableType } from "../../../tir/types/utils/getDeconstructableType.js";
|
|
15
16
|
import { wrapManyStatements } from "../../utils/wrapManyStatementsOrReturnSame.js";
|
|
16
17
|
import { _compileExpr } from "../exprs/_compileExpr.js";
|
|
@@ -32,11 +33,13 @@ export function _compileMatchStmt(ctx, stmt) {
|
|
|
32
33
|
if (!deconstructableType)
|
|
33
34
|
return ctx.error(DiagnosticCode.A_value_of_type_0_cannot_be_deconstructed, stmt.matchExpr.range, matchExprType.toString());
|
|
34
35
|
// TODO: add support for all deconstructable types
|
|
35
|
-
if (!isTirStructType(deconstructableType)) {
|
|
36
|
-
return ctx.error(DiagnosticCode.Not_implemented_0, stmt.matchExpr.range, "only structs supported for now, sorry!");
|
|
36
|
+
if (!isTirStructType(deconstructableType) && !(deconstructableType instanceof TirEnumType)) {
|
|
37
|
+
return ctx.error(DiagnosticCode.Not_implemented_0, stmt.matchExpr.range, "only structs and enums supported for now, sorry!");
|
|
37
38
|
}
|
|
38
|
-
const
|
|
39
|
-
|
|
39
|
+
const ctorNames = deconstructableType instanceof TirEnumType
|
|
40
|
+
? deconstructableType.members.slice()
|
|
41
|
+
: deconstructableType.constructors.map(c => c.name);
|
|
42
|
+
const totalCtors = ctorNames.length;
|
|
40
43
|
const missingCtors = ctorNames.slice();
|
|
41
44
|
if (stmt.cases.length === 0)
|
|
42
45
|
return ctx.error(DiagnosticCode.A_match_statement_must_have_at_least_one_case, stmt.range);
|
|
@@ -70,7 +73,7 @@ export function _compileMatchStmt(ctx, stmt) {
|
|
|
70
73
|
return undefined;
|
|
71
74
|
wildcardCase = new TirMatchStmtWildcardCase(branchBody, matchCase.range);
|
|
72
75
|
}
|
|
73
|
-
if (!wildcardCase && cases.length <
|
|
76
|
+
if (!wildcardCase && cases.length < totalCtors) {
|
|
74
77
|
return ctx.error(DiagnosticCode.Match_cases_are_not_exhaustive, stmt.range);
|
|
75
78
|
}
|
|
76
79
|
return [new TirMatchStmt(matchExpr, cases, wildcardCase, stmt.range)];
|
|
@@ -82,23 +85,21 @@ export function _compileTirMatchStmtCase(ctx, matchCase, deconstructableType, co
|
|
|
82
85
|
//*/
|
|
83
86
|
const pattern = matchCase.pattern;
|
|
84
87
|
if (pattern instanceof SimpleVarDecl) {
|
|
85
|
-
|
|
86
|
-
if(
|
|
88
|
+
// bare-name pattern: only valid for enum scrutinees (`when Apple: ...`)
|
|
89
|
+
if (deconstructableType instanceof TirEnumType) {
|
|
90
|
+
const memberName = pattern.name.text;
|
|
91
|
+
const memberIdx = deconstructableType.indexOf(memberName);
|
|
92
|
+
if (memberIdx < 0)
|
|
93
|
+
return ctx.error(DiagnosticCode.Unknown_0_constructor_1, pattern.name.range, deconstructableType.toString(), memberName);
|
|
94
|
+
if (constrNamesAlreadySpecified.includes(memberName))
|
|
95
|
+
return ctx.error(DiagnosticCode.Constructor_0_was_already_specified, pattern.name.range, memberName);
|
|
96
|
+
constrNamesAlreadySpecified.push(memberName);
|
|
87
97
|
const branchCtx = ctx.newBranchChildScope();
|
|
88
|
-
const branchBody = wrapManyStatements(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
),
|
|
93
|
-
matchCase.body.range
|
|
94
|
-
);
|
|
95
|
-
if( !branchBody ) return undefined;
|
|
96
|
-
return new TirMatchStmtWildcardCase(
|
|
97
|
-
branchBody,
|
|
98
|
-
matchCase.range
|
|
99
|
-
);
|
|
98
|
+
const branchBody = wrapManyStatements(_compileStatement(branchCtx, matchCase.body), matchCase.body.range);
|
|
99
|
+
if (!branchBody)
|
|
100
|
+
return undefined;
|
|
101
|
+
return new TirMatchStmtCase(new TirNamedDeconstructVarDecl(memberName, new Map(), undefined, deconstructableType, undefined, true, pattern.name.range, pattern.name.range), branchBody, matchCase.range);
|
|
100
102
|
}
|
|
101
|
-
//*/
|
|
102
103
|
return ctx.error(DiagnosticCode.The_argument_of_a_match_statement_branch_must_be_deconstructed, matchCase.pattern.range);
|
|
103
104
|
}
|
|
104
105
|
else if (pattern instanceof NamedDeconstructVarDecl) {
|
|
@@ -107,6 +108,18 @@ export function _compileTirMatchStmtCase(ctx, matchCase, deconstructableType, co
|
|
|
107
108
|
if (constrNamesAlreadySpecified.includes(deconstructedCtorName))
|
|
108
109
|
return ctx.error(DiagnosticCode.Constructor_0_was_already_specified, deconstructedCtorIdentifier.range, deconstructedCtorName);
|
|
109
110
|
constrNamesAlreadySpecified.push(deconstructedCtorName);
|
|
111
|
+
if (deconstructableType instanceof TirEnumType) {
|
|
112
|
+
const memberIdx = deconstructableType.indexOf(deconstructedCtorName);
|
|
113
|
+
if (memberIdx < 0)
|
|
114
|
+
return ctx.error(DiagnosticCode.Unknown_0_constructor_1, pattern.name.range, deconstructableType.toString(), deconstructedCtorName);
|
|
115
|
+
if (pattern.fields.size > 0 || pattern.rest)
|
|
116
|
+
return ctx.error(DiagnosticCode.Enum_member_pattern_cannot_have_fields, pattern.range);
|
|
117
|
+
const branchCtx = ctx.newBranchChildScope();
|
|
118
|
+
const branchBody = wrapManyStatements(_compileStatement(branchCtx, matchCase.body), matchCase.body.range);
|
|
119
|
+
if (!branchBody)
|
|
120
|
+
return undefined;
|
|
121
|
+
return new TirMatchStmtCase(new TirNamedDeconstructVarDecl(deconstructedCtorName, new Map(), undefined, deconstructableType, undefined, true, pattern.range, pattern.name.range), branchBody, matchCase.range);
|
|
122
|
+
}
|
|
110
123
|
if (deconstructableType instanceof TirSoPStructType
|
|
111
124
|
|| deconstructableType instanceof TirDataStructType) {
|
|
112
125
|
const localIdx = deconstructableType.constructors.findIndex(c => c.name === deconstructedCtorName);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TirAliasType } from "../../tir/types/TirAliasType.js";
|
|
2
2
|
import { isTirStructType } from "../../tir/types/TirStructType.js";
|
|
3
|
+
import { TirEnumType } from "../../tir/types/TirEnumType.js";
|
|
3
4
|
import { TirTypeParam } from "../../tir/types/TirTypeParam.js";
|
|
4
5
|
import { int_t, bytes_t, bool_t, string_t } from "../../tir/program/stdScope/stdScope.js";
|
|
5
6
|
import { TirBlsG1T, TirBlsG2T, TirMlResultT, TirUnConstrDataResultT, TirPairDataT } from "../../tir/types/TirNativeType/index.js";
|
|
@@ -8,6 +9,8 @@ import { TirBytesT } from "../../tir/types/TirNativeType/native/bytes.js";
|
|
|
8
9
|
import { TirDataT } from "../../tir/types/TirNativeType/native/data.js";
|
|
9
10
|
import { TirFuncT } from "../../tir/types/TirNativeType/native/function.js";
|
|
10
11
|
import { TirIntT } from "../../tir/types/TirNativeType/native/int.js";
|
|
12
|
+
import { TirArrayT } from "../../tir/types/TirNativeType/native/array.js";
|
|
13
|
+
import { TirValueT } from "../../tir/types/TirNativeType/native/value.js";
|
|
11
14
|
import { TirLinearMapT } from "../../tir/types/TirNativeType/native/linearMap.js";
|
|
12
15
|
import { TirLinearMapEntryT } from "../../tir/types/TirNativeType/native/linearMapEntry.js";
|
|
13
16
|
import { TirListT } from "../../tir/types/TirNativeType/native/list.js";
|
|
@@ -84,6 +87,14 @@ export function getPropAccessReturnType(ctx, objType, propId) {
|
|
|
84
87
|
return undefined;
|
|
85
88
|
if (objType instanceof TirMlResultT)
|
|
86
89
|
return undefined;
|
|
90
|
+
// Native Value / Array<T> — methods are reached through prelude/std
|
|
91
|
+
// aliases, not via direct prop-access on the native type.
|
|
92
|
+
if (objType instanceof TirValueT)
|
|
93
|
+
return undefined;
|
|
94
|
+
if (objType instanceof TirArrayT)
|
|
95
|
+
return undefined;
|
|
96
|
+
if (objType instanceof TirEnumType)
|
|
97
|
+
return undefined;
|
|
87
98
|
const tsEnsureExhaustiveCheck = objType;
|
|
88
99
|
console.error(objType);
|
|
89
100
|
throw new Error("unreachable::getPropAccessReturnType");
|
|
@@ -7,12 +7,7 @@ import { semverSatisfies } from "../utils/semverSatisfies.js";
|
|
|
7
7
|
import { AstCompiler } from "./AstCompiler/AstCompiler.js";
|
|
8
8
|
import { createMemoryCompilerIoApi } from "./io/CompilerIoApi.js";
|
|
9
9
|
import { compileTypedProgram } from "./TirCompiler/compileTirProgram.js";
|
|
10
|
-
import {
|
|
11
|
-
import { __VERY_UNSAFE_FORGET_VAR_SYM_HASHES_ONLY_USE_AT_END_OF_UPLC_COMPILATION } from "../IR/IRNodes/utils/hashVarSym.js";
|
|
12
|
-
import { __unsafe_clear_hoisted_hash_to_symbol } from "../IR/IRNodes/IRHoisted.js";
|
|
13
|
-
import { __unsafe_clear_letted_hash_to_symbol } from "../IR/IRNodes/IRLetted.js";
|
|
14
|
-
import { __unsafe_clear_hoisted_cache } from "../IR/toUPLC/subRoutines/replaceHoistedWithLetted.js";
|
|
15
|
-
import { __unsafe_clear_mapToType_cache } from "./TirCompiler/expressify/expressifyVars.js";
|
|
10
|
+
import { CompilationCtx, withCompilationCtx } from "../IR/CompilationCtx.js";
|
|
16
11
|
import { compileIRToUPLC } from "../IR/toUPLC/compileIRToUPLC.js";
|
|
17
12
|
import { TirFuncExpr } from "./tir/expressions/TirFuncExpr.js";
|
|
18
13
|
import { addBudget, zeroBudget, } from "./test/TestResult.js";
|
|
@@ -57,7 +52,6 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
57
52
|
const program = await astCompiler.compile();
|
|
58
53
|
if (this.diagnostics.length > 0) {
|
|
59
54
|
let msg;
|
|
60
|
-
// globalThis.console && console.log( this.diagnostics );
|
|
61
55
|
const fstErrorMsg = this.diagnostics[0].toString();
|
|
62
56
|
const nDiags = this.diagnostics.length;
|
|
63
57
|
for (msg of this.diagnostics) {
|
|
@@ -82,7 +76,6 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
82
76
|
const program = await astCompiler.export(cfg.functionName, cfg.entry);
|
|
83
77
|
if (this.diagnostics.length > 0) {
|
|
84
78
|
let msg;
|
|
85
|
-
globalThis.console && console.log(this.diagnostics);
|
|
86
79
|
const fstErrorMsg = this.diagnostics[0].toString();
|
|
87
80
|
const nDiags = this.diagnostics.length;
|
|
88
81
|
while (msg = this.diagnostics.shift()) {
|
|
@@ -103,7 +96,6 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
103
96
|
const program = await astCompiler.run();
|
|
104
97
|
if (this.diagnostics.length > 0) {
|
|
105
98
|
let msg;
|
|
106
|
-
globalThis.console && console.log(this.diagnostics);
|
|
107
99
|
const fstErrorMsg = this.diagnostics[0].toString();
|
|
108
100
|
const nDiags = this.diagnostics.length;
|
|
109
101
|
while (msg = this.diagnostics.shift()) {
|
|
@@ -288,7 +280,6 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
288
280
|
const program = await astCompiler.runRepl();
|
|
289
281
|
if (this.diagnostics.length > 0) {
|
|
290
282
|
let msg;
|
|
291
|
-
globalThis.console && console.log(this.diagnostics);
|
|
292
283
|
const fstErrorMsg = this.diagnostics[0].toString();
|
|
293
284
|
const nDiags = this.diagnostics.length;
|
|
294
285
|
while (msg = this.diagnostics.shift()) {
|
|
@@ -303,23 +294,25 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
303
294
|
return Machine.eval(new Force(uplcProgram.body));
|
|
304
295
|
}
|
|
305
296
|
_compileBackend(cfg, program, skipFileOutput = false) {
|
|
306
|
-
// backend
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
297
|
+
// Run the whole backend under a fresh per-compilation context. All
|
|
298
|
+
// node-level caches (hoisted/letted naming, hoisted->letted lowering,
|
|
299
|
+
// the mapToType helper cache) live on this context, so they cannot
|
|
300
|
+
// leak into or be perturbed by any other compilation — and they are
|
|
301
|
+
// dropped automatically when this scope exits, even on throw. The
|
|
302
|
+
// content-addressed `IRHash` has no global state at all, so there is
|
|
303
|
+
// nothing else to reset.
|
|
304
|
+
return withCompilationCtx(new CompilationCtx(), () => {
|
|
305
|
+
const ir = compileTypedProgram(cfg, program);
|
|
306
|
+
const uplc = compileIRToUPLC(ir, cfg);
|
|
307
|
+
const serialized = compileUPLC(new UPLCProgram(cfg.targetUplcVersion, uplc));
|
|
308
|
+
if (!skipFileOutput) {
|
|
309
|
+
const outDir = cfg.outDir;
|
|
310
|
+
const outPath = outDir + (outDir.endsWith("/") ? "" : "/") + "out.flat";
|
|
311
|
+
this.io.writeFile(outPath, serialized, cfg.root);
|
|
312
|
+
this.io.stdout.write(`compiled program written to ${outPath}\n`);
|
|
313
|
+
}
|
|
314
|
+
return serialized;
|
|
315
|
+
});
|
|
323
316
|
}
|
|
324
317
|
}
|
|
325
318
|
function _failedTestResult(desc, msg, kind = "unit") {
|
|
@@ -303,7 +303,7 @@ export class ExpressifyCtx {
|
|
|
303
303
|
if (stmt.rest) {
|
|
304
304
|
if (isDestructuredField)
|
|
305
305
|
throw new Error("rest is not implemented in destructured field array-like deconstruct. TODO: map data elems to elem type");
|
|
306
|
-
const lettedRest = this.introduceLettedConstant(stmt.rest, new TirCallExpr(TirNativeFunc.
|
|
306
|
+
const lettedRest = this.introduceLettedConstant(stmt.rest, new TirCallExpr(TirNativeFunc.dropList(elemsType), [
|
|
307
307
|
new TirLitIntExpr(BigInt(nElems), stmt.range),
|
|
308
308
|
lettedArrayExpr
|
|
309
309
|
], new TirListT(elemsType), stmt.range), stmt.range);
|
|
@@ -200,7 +200,7 @@ loopReplacements, assertions = []) {
|
|
|
200
200
|
}
|
|
201
201
|
if (stmt.rest) {
|
|
202
202
|
const uniqueRestName = getUniqueInternalName(stmt.rest);
|
|
203
|
-
const restLetted = ctx.introduceLettedConstant(uniqueRestName, new TirCallExpr(TirNativeFunc.
|
|
203
|
+
const restLetted = ctx.introduceLettedConstant(uniqueRestName, new TirCallExpr(TirNativeFunc.dropList(elemType), [
|
|
204
204
|
new TirLitIntExpr(BigInt(stmt.elements.length % modTails), stmt.range),
|
|
205
205
|
lettedArr
|
|
206
206
|
], listType, stmt.range), stmt.range);
|
|
@@ -395,8 +395,36 @@ loopReplacements, assertions = []) {
|
|
|
395
395
|
const returnTypeAndInvalidInit = getBranchStmtReturnType(reassignedAndFlow, ctx, stmt.range);
|
|
396
396
|
const forStmt = loopToForStmt(stmt);
|
|
397
397
|
const { bodyStateType, initState } = getBodyStateType(returnTypeAndInvalidInit, forStmt);
|
|
398
|
+
// Optimization: when the loop reassigns exactly one variable
|
|
399
|
+
// and has no user-written `return` inside, skip the SoP wrap
|
|
400
|
+
// around the loop's result. The recursive loop function then
|
|
401
|
+
// returns the bare variable's type, saving one `Reassigns{…}`
|
|
402
|
+
// constructor build per iteration and one IRCase at the exit.
|
|
403
|
+
// Requires the loop to be non-terminating (terminating loops
|
|
404
|
+
// are tail-positioned and their value must match the outer
|
|
405
|
+
// function's expected return type — we don't try to reconcile
|
|
406
|
+
// that here).
|
|
407
|
+
const canBareLower = (reassignedAndFlow.reassigned.length === 1
|
|
408
|
+
&& !reassignedAndFlow.returns
|
|
409
|
+
&& !definitelyTerminates);
|
|
398
410
|
const loopExprCtx = ctx.newChild();
|
|
399
|
-
const
|
|
411
|
+
const bareReturnType = canBareLower
|
|
412
|
+
? bodyStateType.constructors[0].fields[0].type
|
|
413
|
+
: undefined;
|
|
414
|
+
const loopExpr = expressifyForStmt(loopExprCtx, forStmt, returnTypeAndInvalidInit.sop, bodyStateType, initState, bareReturnType);
|
|
415
|
+
if (canBareLower) {
|
|
416
|
+
// Bind the loop's bare result as the variable's new SSA
|
|
417
|
+
// name, then evaluate the rest of the body. No outer
|
|
418
|
+
// case-match needed. Use a fresh internal name so the
|
|
419
|
+
// existing `letted[varName] = initialValue` binding (from
|
|
420
|
+
// the original `let varName = ...` statement) isn't
|
|
421
|
+
// shadowed by a no-op `introduceLettedConstant` call.
|
|
422
|
+
const [varName] = reassignedAndFlow.reassigned;
|
|
423
|
+
const loopResultName = getUniqueInternalName(varName);
|
|
424
|
+
const lettedExpr = ctx.introduceLettedConstant(loopResultName, loopExpr, stmt.range);
|
|
425
|
+
ctx.setNewVariableName(varName, lettedExpr.varName);
|
|
426
|
+
return TirAssertAndContinueExpr.fromStmtsAndContinuation(assertions, expressifyFuncBody(ctx, bodyStmts, loopReplacements));
|
|
427
|
+
}
|
|
400
428
|
const result = TirAssertAndContinueExpr.fromStmtsAndContinuation(assertions, definitelyTerminates ? loopExpr : wrapNonTerminatingFinalStmtAsCaseExpr(loopExpr, returnTypeAndInvalidInit.sop, ctx, stmt.range, reassignedAndFlow, bodyStmts, loopReplacements));
|
|
401
429
|
return result;
|
|
402
430
|
}
|
|
@@ -4,6 +4,7 @@ import { TirForOfStmt } from "../../tir/statements/TirForOfStmt.js";
|
|
|
4
4
|
import { TirForStmt } from "../../tir/statements/TirForStmt.js";
|
|
5
5
|
import { TirWhileStmt } from "../../tir/statements/TirWhileStmt.js";
|
|
6
6
|
import { TirSoPStructType } from "../../tir/types/TirStructType.js";
|
|
7
|
+
import { TirType } from "../../tir/types/TirType.js";
|
|
7
8
|
import { ExpressifyCtx } from "./ExpressifyCtx.js";
|
|
8
9
|
export declare function loopToForStmt(stmt: TirWhileStmt | TirForOfStmt | TirForStmt): TirForStmt;
|
|
9
|
-
export declare function expressifyForStmt(ctx: ExpressifyCtx, stmt: TirForStmt, returnType: TirSoPStructType, bodyStateType: TirSoPStructType, initState: TirLitNamedObjExpr): TirCallExpr;
|
|
10
|
+
export declare function expressifyForStmt(ctx: ExpressifyCtx, stmt: TirForStmt, returnType: TirSoPStructType, bodyStateType: TirSoPStructType, initState: TirLitNamedObjExpr, bareReturnType?: TirType): TirCallExpr;
|
|
@@ -68,7 +68,16 @@ export function loopToForStmt(stmt) {
|
|
|
68
68
|
stmt.body, // loopBody
|
|
69
69
|
stmt.range);
|
|
70
70
|
}
|
|
71
|
-
export function expressifyForStmt(ctx, stmt, returnType, bodyStateType, initState
|
|
71
|
+
export function expressifyForStmt(ctx, stmt, returnType, bodyStateType, initState,
|
|
72
|
+
// Optimization: when the loop has exactly one reassigned variable
|
|
73
|
+
// and no user-written `return` inside its body, the SoP wrap
|
|
74
|
+
// (`Reassigns{var}`) on every iteration is unnecessary. The caller
|
|
75
|
+
// can opt into a bare-value lowering by passing the variable's type
|
|
76
|
+
// here; the loop function then returns that type directly, and the
|
|
77
|
+
// call site is expected to bind the result without a case-match.
|
|
78
|
+
bareReturnType) {
|
|
79
|
+
const effectiveReturnType = bareReturnType ?? returnType;
|
|
80
|
+
const isBareMode = bareReturnType !== undefined;
|
|
72
81
|
let loopBody = stmt.body instanceof TirBlockStmt ? stmt.body : new TirBlockStmt([stmt.body], stmt.range);
|
|
73
82
|
loopBody = new TirBlockStmt(loopBody.stmts.slice(), loopBody.range);
|
|
74
83
|
// add final loop updates
|
|
@@ -88,9 +97,27 @@ export function expressifyForStmt(ctx, stmt, returnType, bodyStateType, initStat
|
|
|
88
97
|
], loopBody.range);
|
|
89
98
|
}
|
|
90
99
|
const loopFuncName = getUniqueInternalName("loop");
|
|
91
|
-
const loopFuncType = new TirFuncT(bodyStateType.constructors[0].fields.map(f => f.type),
|
|
100
|
+
const loopFuncType = new TirFuncT(bodyStateType.constructors[0].fields.map(f => f.type), effectiveReturnType);
|
|
92
101
|
const loopReplacements = {
|
|
93
102
|
compileBreak(ctx, stmt) {
|
|
103
|
+
if (isBareMode) {
|
|
104
|
+
// Bare-value mode: the loop's return type IS the single
|
|
105
|
+
// user variable's type. `break` yields that var's current
|
|
106
|
+
// value directly, no SoP construction.
|
|
107
|
+
const userVarField = bodyStateType.constructors[0].fields[0];
|
|
108
|
+
const resolved = ctx.getVariable(userVarField.name);
|
|
109
|
+
if (isExpressifyFuncParam(resolved)) {
|
|
110
|
+
return new TirVariableAccessExpr({
|
|
111
|
+
variableInfos: {
|
|
112
|
+
name: resolved.name,
|
|
113
|
+
type: resolved.type,
|
|
114
|
+
isConstant: false
|
|
115
|
+
},
|
|
116
|
+
isDefinedOutsideFuncScope: false
|
|
117
|
+
}, stmt.range);
|
|
118
|
+
}
|
|
119
|
+
return resolved;
|
|
120
|
+
}
|
|
94
121
|
// return first constructor of the return type
|
|
95
122
|
const ctor = returnType.constructors[0];
|
|
96
123
|
return new TirLitNamedObjExpr(new Identifier(ctor.name, stmt.range), ctor.fields.map(f => new Identifier(f.name, stmt.range)), bodyStateType.constructors[0].fields
|
|
@@ -111,10 +138,21 @@ export function expressifyForStmt(ctx, stmt, returnType, bodyStateType, initStat
|
|
|
111
138
|
}), returnType, stmt.range);
|
|
112
139
|
},
|
|
113
140
|
replaceReturnValue(ctx, stmt) {
|
|
114
|
-
//
|
|
141
|
+
// Synthetic returns inserted by `expressifyIfBranch` (and
|
|
142
|
+
// analogous callers) carry the inner-if's SoP value as the
|
|
143
|
+
// continuation of the ternary they participate in — they are
|
|
144
|
+
// NOT user-written returns escaping the loop. When the loop
|
|
145
|
+
// has no user-written `return` in its body, `returnType` has
|
|
146
|
+
// only the "break/continue" constructor: in that case the
|
|
147
|
+
// value flowing through is already the right type and we
|
|
148
|
+
// must leave it untouched. (Previously this threw "No return
|
|
149
|
+
// constructor found in return type" when a for-of body
|
|
150
|
+
// contained an `if` that mutated a captured `let` — the
|
|
151
|
+
// synthesized branch-tail returns hit this path even though
|
|
152
|
+
// the user had no `return` inside the loop.)
|
|
115
153
|
const ctor = returnType.constructors[1];
|
|
116
154
|
if (!ctor) {
|
|
117
|
-
|
|
155
|
+
return stmt.value;
|
|
118
156
|
}
|
|
119
157
|
return new TirLitNamedObjExpr(new Identifier(ctor.name, stmt.range), [new Identifier(ctor.fields[0].name, stmt.range)], [stmt.value], returnType, stmt.range);
|
|
120
158
|
},
|
|
@@ -149,7 +187,7 @@ export function expressifyForStmt(ctx, stmt, returnType, bodyStateType, initStat
|
|
|
149
187
|
}, stmt.range);
|
|
150
188
|
}
|
|
151
189
|
return resolved;
|
|
152
|
-
}),
|
|
190
|
+
}), effectiveReturnType, stmt.range);
|
|
153
191
|
},
|
|
154
192
|
};
|
|
155
193
|
const loopCompilationCtx = ctx.newChild();
|
|
@@ -165,7 +203,7 @@ export function expressifyForStmt(ctx, stmt, returnType, bodyStateType, initStat
|
|
|
165
203
|
false, // is constant
|
|
166
204
|
stmt.range)),
|
|
167
205
|
// func return type
|
|
168
|
-
|
|
206
|
+
effectiveReturnType,
|
|
169
207
|
// func body
|
|
170
208
|
new TirBlockStmt([
|
|
171
209
|
new TirReturnStmt(expressifyFuncBody(loopCompilationCtx, loopBody.stmts, loopReplacements, [] // assertions
|
|
@@ -176,5 +214,5 @@ export function expressifyForStmt(ctx, stmt, returnType, bodyStateType, initStat
|
|
|
176
214
|
);
|
|
177
215
|
return new TirCallExpr(loopFuncExpr,
|
|
178
216
|
// loop call init args
|
|
179
|
-
initState.values.map(v => expressifyVars(ctx, v.clone())),
|
|
217
|
+
initState.values.map(v => expressifyVars(ctx, v.clone())), effectiveReturnType, stmt.range);
|
|
180
218
|
}
|
|
@@ -5,6 +5,7 @@ import { TirLitFailExpr } from "../../tir/expressions/litteral/TirLitFailExpr.js
|
|
|
5
5
|
import { TirLitFalseExpr } from "../../tir/expressions/litteral/TirLitFalseExpr.js";
|
|
6
6
|
import { TirLitHexBytesExpr } from "../../tir/expressions/litteral/TirLitHexBytesExpr.js";
|
|
7
7
|
import { TirLitIntExpr } from "../../tir/expressions/litteral/TirLitIntExpr.js";
|
|
8
|
+
import { TirLitEnumMemberExpr } from "../../tir/expressions/litteral/TirLitEnumMemberExpr.js";
|
|
8
9
|
import { TirLitNamedObjExpr } from "../../tir/expressions/litteral/TirLitNamedObjExpr.js";
|
|
9
10
|
import { TirLitObjExpr } from "../../tir/expressions/litteral/TirLitObjExpr.js";
|
|
10
11
|
import { TirLitStrExpr } from "../../tir/expressions/litteral/TirLitStrExpr.js";
|
|
@@ -38,8 +39,9 @@ import { TirUnaryMinus } from "../../tir/expressions/unary/TirUnaryMinus.js";
|
|
|
38
39
|
import { TirUnaryPlus } from "../../tir/expressions/unary/TirUnaryPlus.js";
|
|
39
40
|
import { isTirUnaryPrefixExpr } from "../../tir/expressions/unary/TirUnaryPrefixExpr.js";
|
|
40
41
|
import { TirUnaryTilde } from "../../tir/expressions/unary/TirUnaryTilde.js";
|
|
41
|
-
import { bool_t, bytes_t, data_t, int_t,
|
|
42
|
+
import { bool_t, bytes_t, data_t, int_t, valueMapAmountOfName } from "../../tir/program/stdScope/stdScope.js";
|
|
42
43
|
import { IRNativeTag } from "../../../IR/IRNodes/IRNative/IRNativeTag.js";
|
|
44
|
+
import { currentCompilationCtx } from "../../../IR/CompilationCtx.js";
|
|
43
45
|
import { TirReturnStmt } from "../../tir/statements/TirReturnStmt.js";
|
|
44
46
|
import { TirArrayLikeDeconstr } from "../../tir/statements/TirVarDecl/TirArrayLikeDeconstr.js";
|
|
45
47
|
import { TirNamedDeconstructVarDecl } from "../../tir/statements/TirVarDecl/TirNamedDeconstructVarDecl.js";
|
|
@@ -76,6 +78,7 @@ export function expressifyVars(ctx, expr) {
|
|
|
76
78
|
|| expr instanceof TirLitThisExpr
|
|
77
79
|
|| expr instanceof TirLitStrExpr
|
|
78
80
|
|| expr instanceof TirLitIntExpr
|
|
81
|
+
|| expr instanceof TirLitEnumMemberExpr
|
|
79
82
|
|| expr instanceof TirLitHexBytesExpr
|
|
80
83
|
|| expr instanceof TirNativeFunc
|
|
81
84
|
// hoisted expressions are necessarily closed, so no external variables
|
|
@@ -266,6 +269,7 @@ function expressifyPropAccess(ctx, propAccessExpr) {
|
|
|
266
269
|
|| expr instanceof TirLitArrExpr
|
|
267
270
|
|| expr instanceof TirLitStrExpr
|
|
268
271
|
|| expr instanceof TirLitIntExpr
|
|
272
|
+
|| expr instanceof TirLitEnumMemberExpr
|
|
269
273
|
|| expr instanceof TirLitHexBytesExpr
|
|
270
274
|
|| expr instanceof TirNativeFunc
|
|
271
275
|
|| expr instanceof TirPropAccessExpr // `expressifyVars` is called recursively on the object before this check
|
|
@@ -372,6 +376,20 @@ function expressifyPropAccess(ctx, propAccessExpr) {
|
|
|
372
376
|
throw new Error(`Property '${prop}' does not exist on type '${objType.toString()}'`);
|
|
373
377
|
const fName = ctor.fields[fIdx].name;
|
|
374
378
|
const fType = ctor.fields[fIdx].type;
|
|
379
|
+
// Untagged data structs encode as `listData(fields)` rather than
|
|
380
|
+
// `constrData(0, fields)`. Field access lowers directly to
|
|
381
|
+
// `unIData (or _inlineFromData) <$> headList (dropList idx (unListData v))`
|
|
382
|
+
// — no case-rewrite needed, no constructor index to check.
|
|
383
|
+
if (objType instanceof TirDataStructType
|
|
384
|
+
&& objType.untagged) {
|
|
385
|
+
const fieldsListT = new TirListT(data_t);
|
|
386
|
+
return new TirFromDataExpr(new TirCallExpr(TirNativeFunc.headList(data_t), [
|
|
387
|
+
new TirCallExpr(TirNativeFunc.dropList(data_t), [
|
|
388
|
+
new TirLitIntExpr(BigInt(fIdx), propAccessExpr.range),
|
|
389
|
+
new TirCallExpr(TirNativeFunc.unListData, [expr], fieldsListT, propAccessExpr.range)
|
|
390
|
+
], fieldsListT, propAccessExpr.range)
|
|
391
|
+
], data_t, propAccessExpr.range), fType, propAccessExpr.range);
|
|
392
|
+
}
|
|
375
393
|
return new TirCaseExpr(expr, [
|
|
376
394
|
new TirCaseMatcher(new TirNamedDeconstructVarDecl(ctor.name, new Map([
|
|
377
395
|
[fName, new TirSimpleVarDecl(fName, fType, undefined, true, propAccessExpr.range)]
|
|
@@ -412,7 +430,7 @@ function expressifyMethodCall(ctx, methodCall) {
|
|
|
412
430
|
// fast-path: `Value.amountOf(policy, name)` compiles directly to
|
|
413
431
|
// `_amountOfValue(eqByteString(policy))(value)(eqByteString(name))`
|
|
414
432
|
// skipping the wrapper function indirection.
|
|
415
|
-
if (tirMethodName ===
|
|
433
|
+
if (tirMethodName === valueMapAmountOfName
|
|
416
434
|
&& methodCall.args.length === 2) {
|
|
417
435
|
const [policyArg, nameArg] = methodCall.args;
|
|
418
436
|
const bytesToBoolT = new TirFuncT([bytes_t], bool_t);
|
|
@@ -582,7 +600,8 @@ function expressifyListMethodCall(ctx, objectExpr, methodCall, methodName, listT
|
|
|
582
600
|
throw new Error(`Argument 1 of method 'map' of type 'list' must be a function, got '${arg.type.toString()}'`);
|
|
583
601
|
const mapReturnT = argFuncType.returnType;
|
|
584
602
|
const elemTypeTirName = elemsType.toTirTypeKey();
|
|
585
|
-
|
|
603
|
+
const mapToTypeCache = currentCompilationCtx().mapToTypeCache;
|
|
604
|
+
let base_mapToType = mapToTypeCache.get(elemTypeTirName)?.clone();
|
|
586
605
|
if (!base_mapToType) {
|
|
587
606
|
base_mapToType = new TirHoistedExpr("_map_to_list_of_" + elemTypeTirName, new TirCallExpr(TirNativeFunc._mkMap(elemsType, mapReturnT), [new TirLitArrExpr([], new TirListT(mapReturnT), SourceRange.unknown)], new TirFuncT([
|
|
588
607
|
// mapping function
|
|
@@ -593,7 +612,7 @@ function expressifyListMethodCall(ctx, objectExpr, methodCall, methodName, listT
|
|
|
593
612
|
new TirListT(elemsType)
|
|
594
613
|
], new TirListT(mapReturnT)), SourceRange.unknown));
|
|
595
614
|
base_mapToType.varName; // precompute hash and symbol
|
|
596
|
-
|
|
615
|
+
mapToTypeCache.set(elemTypeTirName, base_mapToType.clone());
|
|
597
616
|
}
|
|
598
617
|
return new TirCallExpr(base_mapToType, [methodCall.args[0], objectExpr], methodCall.type, exprRange);
|
|
599
618
|
}
|
|
@@ -605,7 +624,3 @@ function expressifyListMethodCall(ctx, objectExpr, methodCall, methodName, listT
|
|
|
605
624
|
};
|
|
606
625
|
*/
|
|
607
626
|
}
|
|
608
|
-
const _base_mapToType_cache = new Map();
|
|
609
|
-
export function __unsafe_clear_mapToType_cache() {
|
|
610
|
-
_base_mapToType_cache.clear();
|
|
611
|
-
}
|
|
@@ -20,6 +20,15 @@ export declare class TirCaseExpr implements ITirExpr {
|
|
|
20
20
|
deps(): string[];
|
|
21
21
|
get isConstant(): boolean;
|
|
22
22
|
toIR(ctx: ToIRTermCtx): IRTerm;
|
|
23
|
+
/**
|
|
24
|
+
* Lowers a `case` over an untagged data struct (single constructor;
|
|
25
|
+
* runtime form is `listData(fields)`). No constructor dispatch is
|
|
26
|
+
* needed — there's only one possible ctor — so the lowering is just
|
|
27
|
+
* "find the matching arm (or wildcard), extract any bound fields, run
|
|
28
|
+
* the body".
|
|
29
|
+
*/
|
|
30
|
+
private _untaggedDataStructToIR;
|
|
31
|
+
private _enumToIR;
|
|
23
32
|
private _sopStructToIR;
|
|
24
33
|
private _dataStructToIR;
|
|
25
34
|
}
|