@harmoniclabs/pebble 0.1.3 → 0.1.4-dev1
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/IRNative/IRNativeTag.d.ts +2 -1
- package/dist/IR/IRNodes/IRNative/IRNativeTag.js +2 -0
- package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.d.ts +1 -0
- package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.js +22 -3
- package/dist/ast/nodes/expr/litteral/LitNamedObjExpr.d.ts +5 -1
- package/dist/ast/nodes/expr/litteral/LitNamedObjExpr.js +5 -1
- package/dist/compiler/AstCompiler/internal/exprs/_compileLitteralExpr.js +22 -2
- package/dist/compiler/AstCompiler/utils/getPropAccessReturnType.js +9 -0
- package/dist/compiler/SourceTypeMap.js +13 -0
- package/dist/compiler/TirCompiler/expressify/expressifyVars.js +52 -5
- package/dist/compiler/tir/expressions/TirCaseExpr.js +12 -4
- package/dist/compiler/tir/expressions/TirNativeFunc.d.ts +1 -0
- package/dist/compiler/tir/expressions/TirNativeFunc.js +8 -0
- package/dist/compiler/tir/expressions/TirSopOptToBoolExpr.d.ts +30 -0
- package/dist/compiler/tir/expressions/TirSopOptToBoolExpr.js +49 -0
- package/dist/compiler/tir/expressions/TirTraceIfFalseExpr.js +15 -0
- package/dist/compiler/tir/statements/TirAssertStmt.js +4 -2
- package/dist/parser/Parser.js +17 -0
- package/package.json +1 -1
|
@@ -134,6 +134,7 @@ export declare enum IRNativeTag {
|
|
|
134
134
|
_getCredentialsHash = -44,
|
|
135
135
|
_findSopOptional = -45,
|
|
136
136
|
_increment = -46,
|
|
137
|
-
_decrement = -47
|
|
137
|
+
_decrement = -47,
|
|
138
|
+
_lookupLinearMap = -48
|
|
138
139
|
}
|
|
139
140
|
export declare function nativeTagToString(nativeTag: IRNativeTag): string;
|
|
@@ -158,6 +158,7 @@ export var IRNativeTag;
|
|
|
158
158
|
IRNativeTag[IRNativeTag["_findSopOptional"] = -45] = "_findSopOptional";
|
|
159
159
|
IRNativeTag[IRNativeTag["_increment"] = -46] = "_increment";
|
|
160
160
|
IRNativeTag[IRNativeTag["_decrement"] = -47] = "_decrement";
|
|
161
|
+
IRNativeTag[IRNativeTag["_lookupLinearMap"] = -48] = "_lookupLinearMap";
|
|
161
162
|
})(IRNativeTag || (IRNativeTag = {}));
|
|
162
163
|
Object.freeze(IRNativeTag);
|
|
163
164
|
export function nativeTagToString(nativeTag) {
|
|
@@ -203,6 +204,7 @@ export function nativeTagToString(nativeTag) {
|
|
|
203
204
|
case IRNativeTag._getCredentialsHash: return "getCredentialHash";
|
|
204
205
|
case IRNativeTag._increment: return "increment";
|
|
205
206
|
case IRNativeTag._decrement: return "decrement";
|
|
207
|
+
case IRNativeTag._lookupLinearMap: return "lookupLinearMap";
|
|
206
208
|
default: return "";
|
|
207
209
|
}
|
|
208
210
|
}
|
|
@@ -24,6 +24,7 @@ export declare const hoisted_length: IRHoisted;
|
|
|
24
24
|
export declare const hoisted_dropList: IRHoisted;
|
|
25
25
|
export declare const hoisted_sizeofPositiveInt: IRHoisted;
|
|
26
26
|
export declare const hoisted_findSopOptional: IRHoisted;
|
|
27
|
+
export declare const hoisted_lookupLinearMap: IRHoisted;
|
|
27
28
|
export declare const hoisted_mkFindDataOptional: IRHoisted;
|
|
28
29
|
export declare const hoisted_strictAnd: IRHoisted;
|
|
29
30
|
export declare const hoisted_strictOr: IRHoisted;
|
|
@@ -122,12 +122,30 @@ export const hoisted_findSopOptional = new IRHoisted(new IRFunc([findSop_predica
|
|
|
122
122
|
// case nil
|
|
123
123
|
new IRConstr(1, []), // None
|
|
124
124
|
// case cons
|
|
125
|
-
new IRFunc([findSop_head], _ir_lazyIfThenElse(_ir_apps(new IRVar(findSop_predicate), new IRVar(findSop_head)),
|
|
125
|
+
new IRApp(new IRFunc([findSop_head], _ir_lazyIfThenElse(_ir_apps(new IRVar(findSop_predicate), new IRVar(findSop_head)),
|
|
126
126
|
// then => Some(head)
|
|
127
|
-
new IRConstr(
|
|
127
|
+
new IRConstr(0, [new IRVar(findSop_head)]), // Some{ head }
|
|
128
128
|
// else => self(tail)
|
|
129
|
-
_ir_apps(new IRSelfCall(findSop_self), _ir_apps(IRNative.tailList, new IRVar(findSop_list))))))))));
|
|
129
|
+
_ir_apps(new IRSelfCall(findSop_self), _ir_apps(IRNative.tailList, new IRVar(findSop_list))))), new IRApp(IRNative.headList, new IRVar(findSop_list))))))));
|
|
130
130
|
hoisted_findSopOptional.hash;
|
|
131
|
+
// hoisted _lookupLinearMap
|
|
132
|
+
// (key: data) -> (map: list<pair<data,data>>) -> SopOptional<data>
|
|
133
|
+
const lookup_key = Symbol("lookup_key");
|
|
134
|
+
const lookup_self = Symbol("lookup_self");
|
|
135
|
+
const lookup_map = Symbol("lookup_map");
|
|
136
|
+
const lookup_head = Symbol("lookup_head");
|
|
137
|
+
export const hoisted_lookupLinearMap = new IRHoisted(new IRFunc([lookup_key], new IRRecursive(lookup_self, new IRFunc([lookup_map], _ir_lazyChooseList(new IRVar(lookup_map),
|
|
138
|
+
// case nil => None
|
|
139
|
+
new IRConstr(1, []),
|
|
140
|
+
// case cons
|
|
141
|
+
new IRApp(new IRFunc([lookup_head], _ir_lazyIfThenElse(_ir_apps(IRNative.equalsData, _ir_apps(IRNative.fstPair, new IRVar(lookup_head)), new IRVar(lookup_key)),
|
|
142
|
+
// then => Some(sndPair(head))
|
|
143
|
+
new IRConstr(0, [
|
|
144
|
+
_ir_apps(IRNative.sndPair, new IRVar(lookup_head))
|
|
145
|
+
]),
|
|
146
|
+
// else => self(tailList(map))
|
|
147
|
+
_ir_apps(new IRSelfCall(lookup_self), _ir_apps(IRNative.tailList, new IRVar(lookup_map))))), new IRApp(IRNative.headList, new IRVar(lookup_map))))))));
|
|
148
|
+
hoisted_lookupLinearMap.hash;
|
|
131
149
|
// hoisted _mkFindDataOptional
|
|
132
150
|
const mkFind_elemToData = Symbol("elemToData");
|
|
133
151
|
const mkFind_pred = Symbol("predicate");
|
|
@@ -265,6 +283,7 @@ export function nativeToIR(native) {
|
|
|
265
283
|
// case IRNativeTag._equalPairData: ;
|
|
266
284
|
case IRNativeTag._mkEqualsList: return hoisted_mkEqualsList.clone();
|
|
267
285
|
case IRNativeTag._negateInt: return hoisted_negateInteger.clone();
|
|
286
|
+
case IRNativeTag._lookupLinearMap: return hoisted_lookupLinearMap.clone();
|
|
268
287
|
// case IRNativeTag._mkEqualsList: return hoisted_mkEqualsList.clone();
|
|
269
288
|
default:
|
|
270
289
|
throw new Error("unknown (negative) native calling 'nativeToIR'; " +
|
|
@@ -8,5 +8,9 @@ export declare class LitNamedObjExpr implements HasSourceRange, ILibObjExpr {
|
|
|
8
8
|
readonly fieldNames: Identifier[];
|
|
9
9
|
readonly values: PebbleExpr[];
|
|
10
10
|
readonly range: SourceRange;
|
|
11
|
-
|
|
11
|
+
/** When using `Type.Constructor{ ... }` syntax, this is the type name */
|
|
12
|
+
readonly typeName: Identifier | undefined;
|
|
13
|
+
constructor(name: Identifier, fieldNames: Identifier[], values: PebbleExpr[], range: SourceRange,
|
|
14
|
+
/** When using `Type.Constructor{ ... }` syntax, this is the type name */
|
|
15
|
+
typeName?: Identifier | undefined);
|
|
12
16
|
}
|
|
@@ -3,10 +3,14 @@ export class LitNamedObjExpr {
|
|
|
3
3
|
fieldNames;
|
|
4
4
|
values;
|
|
5
5
|
range;
|
|
6
|
-
|
|
6
|
+
typeName;
|
|
7
|
+
constructor(name, fieldNames, values, range,
|
|
8
|
+
/** When using `Type.Constructor{ ... }` syntax, this is the type name */
|
|
9
|
+
typeName = undefined) {
|
|
7
10
|
this.name = name;
|
|
8
11
|
this.fieldNames = fieldNames;
|
|
9
12
|
this.values = values;
|
|
10
13
|
this.range = range;
|
|
14
|
+
this.typeName = typeName;
|
|
11
15
|
}
|
|
12
16
|
}
|
|
@@ -93,7 +93,23 @@ export function _compileLitteralNamedObjExpr(ctx, expr, typeHint) {
|
|
|
93
93
|
else
|
|
94
94
|
typeHint = undefined;
|
|
95
95
|
const constructorName = expr.name.text;
|
|
96
|
-
|
|
96
|
+
let inferredStructType = undefined;
|
|
97
|
+
// Type.Constructor{ ... } syntax — resolve type directly
|
|
98
|
+
if (expr.typeName) {
|
|
99
|
+
const possibleTypes = ctx.scope.resolveType(expr.typeName.text);
|
|
100
|
+
if (possibleTypes) {
|
|
101
|
+
const dataTirName = possibleTypes.dataTirName;
|
|
102
|
+
const sopTirName = possibleTypes.sopTirName;
|
|
103
|
+
inferredStructType = getStructType((dataTirName ? ctx.program.types.get(dataTirName) : undefined)
|
|
104
|
+
?? ctx.program.types.get(sopTirName));
|
|
105
|
+
}
|
|
106
|
+
if (!inferredStructType) {
|
|
107
|
+
return ctx.error(DiagnosticCode._0_is_not_defined, expr.typeName.range, expr.typeName.text);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
inferredStructType = getStructType(ctx.scope.inferStructTypeFromConstructorName(constructorName)?.structType);
|
|
112
|
+
}
|
|
97
113
|
if (!inferredStructType) {
|
|
98
114
|
return ctx.error(DiagnosticCode._0_is_not_defined, expr.name.range, constructorName);
|
|
99
115
|
}
|
|
@@ -105,7 +121,11 @@ export function _compileLitteralNamedObjExpr(ctx, expr, typeHint) {
|
|
|
105
121
|
structType = inferredStructType;
|
|
106
122
|
if (!isTirType(typeHint))
|
|
107
123
|
typeHint = structType ?? inferredStructType;
|
|
108
|
-
const
|
|
124
|
+
const constructorIndex = structType?.constructors.findIndex(c => c.name === constructorName) ?? -1;
|
|
125
|
+
if (constructorIndex < 0) {
|
|
126
|
+
return ctx.error(DiagnosticCode._0_is_not_defined, expr.name.range, constructorName);
|
|
127
|
+
}
|
|
128
|
+
const fieldValues = __commonCompileStructFieldValues(ctx, expr, typeHint, structType, constructorIndex);
|
|
109
129
|
if (!Array.isArray(fieldValues))
|
|
110
130
|
return undefined;
|
|
111
131
|
typeHint = getUnaliased(typeHint);
|
|
@@ -108,6 +108,15 @@ function getStructPropAccessReturnType(ctx, structType, propName) {
|
|
|
108
108
|
if (field)
|
|
109
109
|
return field.type;
|
|
110
110
|
}
|
|
111
|
+
// constructor accessor methods for multi-constructor data structs
|
|
112
|
+
// e.g. ExtendedInteger.finite() returns int (the field of the Finite constructor)
|
|
113
|
+
if (structType.constructors.length > 1) {
|
|
114
|
+
const lowerPropName = propName.toLowerCase();
|
|
115
|
+
const ctor = structType.constructors.find(c => c.name.toLowerCase() === lowerPropName);
|
|
116
|
+
if (ctor && ctor.fields.length === 1) {
|
|
117
|
+
return new TirFuncT([], ctor.fields[0].type);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
111
120
|
return findPropInImpls(ctx, structType.methodNamesPtr, propName);
|
|
112
121
|
}
|
|
113
122
|
function findPropInImpls(ctx, methodsNamesPtr, propName) {
|
|
@@ -143,6 +143,19 @@ export class SourceTypeMap {
|
|
|
143
143
|
result.push({ name: field.name, type: field.type, kind: "field" });
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
|
+
// constructor accessor methods for multi-constructor structs
|
|
147
|
+
// e.g. ExtendedInteger.finite() returns int
|
|
148
|
+
if (type.constructors.length > 1) {
|
|
149
|
+
for (const ctor of type.constructors) {
|
|
150
|
+
if (ctor.fields.length === 1) {
|
|
151
|
+
result.push({
|
|
152
|
+
name: ctor.name.toLowerCase(),
|
|
153
|
+
type: new TirFuncT([], ctor.fields[0].type),
|
|
154
|
+
kind: "method"
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
146
159
|
// methods
|
|
147
160
|
result.push(...this.methodsFromMap(type.methodNamesPtr));
|
|
148
161
|
return result;
|
|
@@ -14,7 +14,7 @@ import { TirLitUndefExpr } from "../../tir/expressions/litteral/TirLitUndefExpr.
|
|
|
14
14
|
import { TirLitVoidExpr } from "../../tir/expressions/litteral/TirLitVoidExpr.js";
|
|
15
15
|
import { TirAssertAndContinueExpr } from "../../tir/expressions/TirAssertAndContinueExpr.js";
|
|
16
16
|
import { TirCallExpr } from "../../tir/expressions/TirCallExpr.js";
|
|
17
|
-
import { TirCaseExpr, TirCaseMatcher } from "../../tir/expressions/TirCaseExpr.js";
|
|
17
|
+
import { TirCaseExpr, TirCaseMatcher, TirWildcardCaseMatcher } from "../../tir/expressions/TirCaseExpr.js";
|
|
18
18
|
import { TirElemAccessExpr } from "../../tir/expressions/TirElemAccessExpr.js";
|
|
19
19
|
import { TirFailExpr } from "../../tir/expressions/TirFailExpr.js";
|
|
20
20
|
import { TirFromDataExpr } from "../../tir/expressions/TirFromDataExpr.js";
|
|
@@ -42,7 +42,8 @@ import { TirArrayLikeDeconstr } from "../../tir/statements/TirVarDecl/TirArrayLi
|
|
|
42
42
|
import { TirNamedDeconstructVarDecl } from "../../tir/statements/TirVarDecl/TirNamedDeconstructVarDecl.js";
|
|
43
43
|
import { TirSimpleVarDecl } from "../../tir/statements/TirVarDecl/TirSimpleVarDecl.js";
|
|
44
44
|
import { TirAliasType } from "../../tir/types/TirAliasType.js";
|
|
45
|
-
import { TirFuncT, TirListT } from "../../tir/types/TirNativeType/index.js";
|
|
45
|
+
import { TirFuncT, TirListT, TirPairDataT } from "../../tir/types/TirNativeType/index.js";
|
|
46
|
+
import { TirLinearMapT } from "../../tir/types/TirNativeType/native/linearMap.js";
|
|
46
47
|
import { TirDataStructType, TirSoPStructType } from "../../tir/types/TirStructType.js";
|
|
47
48
|
import { getListTypeArg } from "../../tir/types/utils/getListTypeArg.js";
|
|
48
49
|
import { getUnaliased } from "../../tir/types/utils/getUnaliased.js";
|
|
@@ -67,9 +68,6 @@ export function expressifyVars(ctx, expr) {
|
|
|
67
68
|
|| expr instanceof TirLitTrueExpr
|
|
68
69
|
|| expr instanceof TirLitFalseExpr
|
|
69
70
|
|| expr instanceof TirLitThisExpr
|
|
70
|
-
|| expr instanceof TirLitArrExpr
|
|
71
|
-
|| expr instanceof TirLitObjExpr
|
|
72
|
-
|| expr instanceof TirLitNamedObjExpr
|
|
73
71
|
|| expr instanceof TirLitStrExpr
|
|
74
72
|
|| expr instanceof TirLitIntExpr
|
|
75
73
|
|| expr instanceof TirLitHexBytesExpr
|
|
@@ -77,6 +75,19 @@ export function expressifyVars(ctx, expr) {
|
|
|
77
75
|
// hoisted expressions are necessarily closed, so no external variables
|
|
78
76
|
|| expr instanceof TirHoistedExpr)
|
|
79
77
|
return expr;
|
|
78
|
+
if (expr instanceof TirLitObjExpr
|
|
79
|
+
|| expr instanceof TirLitNamedObjExpr) {
|
|
80
|
+
for (let i = 0; i < expr.values.length; i++) {
|
|
81
|
+
expr.values[i] = expressifyVars(ctx, expr.values[i]);
|
|
82
|
+
}
|
|
83
|
+
return expr;
|
|
84
|
+
}
|
|
85
|
+
if (expr instanceof TirLitArrExpr) {
|
|
86
|
+
for (let i = 0; i < expr.elems.length; i++) {
|
|
87
|
+
expr.elems[i] = expressifyVars(ctx, expr.elems[i]);
|
|
88
|
+
}
|
|
89
|
+
return expr;
|
|
90
|
+
}
|
|
80
91
|
// every property access must be replaced with a variable access (or similar)
|
|
81
92
|
// that is either letted/hoisted/nativeFunc/varAccess expression
|
|
82
93
|
//
|
|
@@ -374,6 +385,29 @@ function expressifyMethodCall(ctx, methodCall) {
|
|
|
374
385
|
}
|
|
375
386
|
if (objectType instanceof TirDataStructType
|
|
376
387
|
|| objectType instanceof TirSoPStructType) {
|
|
388
|
+
// constructor accessor methods for multi-constructor structs
|
|
389
|
+
// e.g. ExtendedInteger.finite() asserts Finite and returns int
|
|
390
|
+
if (objectType.constructors.length > 1 && methodCall.args.length === 0) {
|
|
391
|
+
const lowerMethodName = methodName.toLowerCase();
|
|
392
|
+
const ctor = objectType.constructors.find(c => c.name.toLowerCase() === lowerMethodName);
|
|
393
|
+
if (ctor && ctor.fields.length === 1) {
|
|
394
|
+
const fName = ctor.fields[0].name;
|
|
395
|
+
const fType = ctor.fields[0].type;
|
|
396
|
+
const exprRange = SourceRange.join(methodIdentifierProp.range, methodCall.range.atEnd());
|
|
397
|
+
return new TirCaseExpr(objectExpr, [
|
|
398
|
+
new TirCaseMatcher(new TirNamedDeconstructVarDecl(ctor.name, new Map([
|
|
399
|
+
[fName, new TirSimpleVarDecl(fName, fType, undefined, true, exprRange)]
|
|
400
|
+
]), undefined, objectExpr.type, undefined, true, exprRange), new TirVariableAccessExpr({
|
|
401
|
+
variableInfos: {
|
|
402
|
+
name: fName,
|
|
403
|
+
type: fType,
|
|
404
|
+
isConstant: true,
|
|
405
|
+
},
|
|
406
|
+
isDefinedOutsideFuncScope: false,
|
|
407
|
+
}, exprRange), exprRange)
|
|
408
|
+
], new TirWildcardCaseMatcher(new TirFailExpr(undefined, fType, exprRange), exprRange), fType, exprRange);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
377
411
|
const structMethods = objectType.methodNamesPtr;
|
|
378
412
|
const tirMethodName = structMethods.get(methodName);
|
|
379
413
|
if (!tirMethodName)
|
|
@@ -388,6 +422,19 @@ function expressifyMethodCall(ctx, methodCall) {
|
|
|
388
422
|
if (result)
|
|
389
423
|
return result;
|
|
390
424
|
}
|
|
425
|
+
if (objectType instanceof TirLinearMapT) {
|
|
426
|
+
const exprRange = SourceRange.join(methodIdentifierProp.range, methodCall.range.atEnd());
|
|
427
|
+
if (methodName === "lookup") {
|
|
428
|
+
if (methodCall.args.length !== 1)
|
|
429
|
+
throw new Error(`Method 'lookup' of type 'LinearMap' takes 1 argument, ${methodCall.args.length} provided`);
|
|
430
|
+
return new TirCallExpr(TirNativeFunc._lookupLinearMap(objectType.keyTypeArg, objectType.valTypeArg), [methodCall.args[0], objectExpr], methodCall.type, exprRange);
|
|
431
|
+
}
|
|
432
|
+
// LinearMap is List<PairData> at UPLC level; delegate list methods
|
|
433
|
+
const listType = new TirListT(new TirPairDataT());
|
|
434
|
+
const result = expressifyListMethodCall(ctx, objectExpr, methodCall, methodName, listType, exprRange);
|
|
435
|
+
if (result)
|
|
436
|
+
return result;
|
|
437
|
+
}
|
|
391
438
|
throw new Error(`not implemented::expressifyMethodCall for type '${objectType.toString()}' (method name: '${methodName}')`);
|
|
392
439
|
// const tsEnsureExhautstiveCheck: never = objectType;
|
|
393
440
|
throw new Error(`Cannot call method '${methodName}' on non-struct type '${objectType.toString()}'`);
|
|
@@ -3,7 +3,6 @@ import { IRCase } from "../../../IR/IRNodes/IRCase.js";
|
|
|
3
3
|
import { IRConst } from "../../../IR/IRNodes/IRConst.js";
|
|
4
4
|
import { IRDelayed } from "../../../IR/IRNodes/IRDelayed.js";
|
|
5
5
|
import { IRError } from "../../../IR/IRNodes/IRError.js";
|
|
6
|
-
import { IRForced } from "../../../IR/IRNodes/IRForced.js";
|
|
7
6
|
import { IRFunc } from "../../../IR/IRNodes/IRFunc.js";
|
|
8
7
|
import { IRNative } from "../../../IR/IRNodes/IRNative/index.js";
|
|
9
8
|
import { IRVar } from "../../../IR/IRNodes/IRVar.js";
|
|
@@ -87,17 +86,26 @@ export class TirCaseExpr {
|
|
|
87
86
|
const someBranchCtx = ctx.newChild();
|
|
88
87
|
const someBranch = this.cases.find(c => c.pattern.constrName === "Some");
|
|
89
88
|
let someBranchVarSym = Symbol("some_value_unused");
|
|
89
|
+
let someValueType = undefined;
|
|
90
90
|
if (someBranch) {
|
|
91
91
|
const varDecl = someBranch.pattern.fields.values().next().value;
|
|
92
92
|
if (!(varDecl instanceof TirSimpleVarDecl))
|
|
93
93
|
throw new Error("case pattern not expressified.");
|
|
94
94
|
someBranchVarSym = someBranchCtx.defineVar(varDecl.name);
|
|
95
|
+
someValueType = varDecl.type;
|
|
95
96
|
}
|
|
96
97
|
const someBranchIR = someBranch?.body.toIR(someBranchCtx) ?? wildcardBodyIR;
|
|
97
98
|
const noneBranchIR = this.cases.find(c => c.pattern.constrName === "None")?.body.toIR(ctx) ?? wildcardBodyIR;
|
|
99
|
+
// The SoP Optional wraps raw data values from lookups;
|
|
100
|
+
// apply _inlineFromData to convert to the expected native type
|
|
101
|
+
// (e.g., unMapData for LinearMap values)
|
|
102
|
+
const rawValueSym = Symbol("sop_opt_raw_value");
|
|
103
|
+
const someHandler = someValueType
|
|
104
|
+
? new IRFunc([rawValueSym], new IRApp(new IRFunc([someBranchVarSym], someBranchIR), _inlineFromData(someValueType, new IRVar(rawValueSym))))
|
|
105
|
+
: new IRFunc([someBranchVarSym], someBranchIR);
|
|
98
106
|
return new IRCase(this.matchExpr.toIR(ctx), [
|
|
99
107
|
// Some{ value }
|
|
100
|
-
|
|
108
|
+
someHandler,
|
|
101
109
|
// None
|
|
102
110
|
noneBranchIR
|
|
103
111
|
]);
|
|
@@ -160,14 +168,14 @@ export class TirCaseExpr {
|
|
|
160
168
|
)));
|
|
161
169
|
}
|
|
162
170
|
const noneBranchIR = this.cases.find(c => c.pattern.constrName === "None")?.body.toIR(stmtCtx) ?? wildcardBodyIR;
|
|
163
|
-
return
|
|
171
|
+
return _ir_let(_ir_apps(IRNative.unConstrData, this.matchExpr.toIR(ctx)), unConstrMatchSym => _ir_lazyIfThenElse(
|
|
164
172
|
// condition
|
|
165
173
|
_ir_apps(IRNative.equalsInteger, IRConst.int(0), _ir_apps(IRNative.fstPair, new IRVar(unConstrMatchSym) // unConstrData result
|
|
166
174
|
)),
|
|
167
175
|
// then Just{ value }
|
|
168
176
|
someBranchIR(unConstrMatchSym),
|
|
169
177
|
// else None
|
|
170
|
-
noneBranchIR))
|
|
178
|
+
noneBranchIR));
|
|
171
179
|
}
|
|
172
180
|
// TirDataStructType
|
|
173
181
|
const stmtCtx = ctx.newChild();
|
|
@@ -85,6 +85,7 @@ export declare class TirNativeFunc implements ITirExpr {
|
|
|
85
85
|
static _foldr(elemT: TirType, returnT: TirType): TirNativeFunc;
|
|
86
86
|
static _foldl(elemT: TirType, returnT: TirType): TirNativeFunc;
|
|
87
87
|
static _findSopOptional(elems_t: TirType): TirNativeFunc;
|
|
88
|
+
static _lookupLinearMap(keyT: TirType, valT: TirType): TirNativeFunc;
|
|
88
89
|
static _length(elemT: TirType): TirNativeFunc;
|
|
89
90
|
static _some(elemT: TirType): TirNativeFunc;
|
|
90
91
|
static _every(elemT: TirType): TirNativeFunc;
|
|
@@ -684,6 +684,14 @@ export class TirNativeFunc {
|
|
|
684
684
|
new TirListT(elems_t)
|
|
685
685
|
], new TirSopOptT(elems_t)));
|
|
686
686
|
}
|
|
687
|
+
static _lookupLinearMap(keyT, valT) {
|
|
688
|
+
return new TirNativeFunc(IRNativeTag._lookupLinearMap, new TirFuncT([
|
|
689
|
+
// key: data
|
|
690
|
+
data_t,
|
|
691
|
+
// map: list<pair<data,data>>
|
|
692
|
+
new TirLinearMapT(keyT, valT)
|
|
693
|
+
], new TirSopOptT(valT)));
|
|
694
|
+
}
|
|
687
695
|
static _length(elemT) {
|
|
688
696
|
return new TirNativeFunc(IRNativeTag._length, new TirFuncT([
|
|
689
697
|
// list
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SourceRange } from "../../../ast/Source/SourceRange.js";
|
|
2
|
+
import type { IRTerm } from "../../../IR/IRTerm.js";
|
|
3
|
+
import { TirType } from "../types/TirType.js";
|
|
4
|
+
import { ITirExpr } from "./ITirExpr.js";
|
|
5
|
+
import { TirExpr } from "./TirExpr.js";
|
|
6
|
+
import { ToIRTermCtx } from "./ToIRTermCtx.js";
|
|
7
|
+
/**
|
|
8
|
+
* Converts a SoP Optional value to a boolean at the IR level
|
|
9
|
+
* using `case(opt, [\_ -> true, false])`.
|
|
10
|
+
*
|
|
11
|
+
* This is needed because `ifThenElse` expects a boolean, but
|
|
12
|
+
* SoP Optional values are Constr nodes, not boolean constants.
|
|
13
|
+
*/
|
|
14
|
+
export declare class TirSopOptToBoolExpr implements ITirExpr {
|
|
15
|
+
readonly operand: TirExpr;
|
|
16
|
+
readonly range: SourceRange;
|
|
17
|
+
readonly type: TirType;
|
|
18
|
+
constructor(operand: TirExpr, range: SourceRange);
|
|
19
|
+
toString(): string;
|
|
20
|
+
pretty(indent: number): string;
|
|
21
|
+
clone(): TirExpr;
|
|
22
|
+
deps(): string[];
|
|
23
|
+
get isConstant(): boolean;
|
|
24
|
+
toIR(ctx: ToIRTermCtx): IRTerm;
|
|
25
|
+
/**
|
|
26
|
+
* Wraps the expression in TirSopOptToBoolExpr if its type is SoP Optional,
|
|
27
|
+
* otherwise returns it as-is.
|
|
28
|
+
*/
|
|
29
|
+
static wrapIfNeeded(expr: TirExpr): TirExpr;
|
|
30
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { IRCase } from "../../../IR/IRNodes/IRCase.js";
|
|
2
|
+
import { IRConst } from "../../../IR/IRNodes/IRConst.js";
|
|
3
|
+
import { IRFunc } from "../../../IR/IRNodes/IRFunc.js";
|
|
4
|
+
import { bool_t } from "../program/stdScope/stdScope.js";
|
|
5
|
+
import { TirSopOptT } from "../types/TirNativeType/native/Optional/sop.js";
|
|
6
|
+
import { getUnaliased } from "../types/utils/getUnaliased.js";
|
|
7
|
+
/**
|
|
8
|
+
* Converts a SoP Optional value to a boolean at the IR level
|
|
9
|
+
* using `case(opt, [\_ -> true, false])`.
|
|
10
|
+
*
|
|
11
|
+
* This is needed because `ifThenElse` expects a boolean, but
|
|
12
|
+
* SoP Optional values are Constr nodes, not boolean constants.
|
|
13
|
+
*/
|
|
14
|
+
export class TirSopOptToBoolExpr {
|
|
15
|
+
operand;
|
|
16
|
+
range;
|
|
17
|
+
type = bool_t;
|
|
18
|
+
constructor(operand, range) {
|
|
19
|
+
this.operand = operand;
|
|
20
|
+
this.range = range;
|
|
21
|
+
}
|
|
22
|
+
toString() { return `isSome(${this.operand.toString()})`; }
|
|
23
|
+
pretty(indent) { return `isSome(${this.operand.pretty(indent)})`; }
|
|
24
|
+
clone() {
|
|
25
|
+
return new TirSopOptToBoolExpr(this.operand.clone(), this.range.clone());
|
|
26
|
+
}
|
|
27
|
+
deps() { return this.operand.deps(); }
|
|
28
|
+
get isConstant() { return this.operand.isConstant; }
|
|
29
|
+
toIR(ctx) {
|
|
30
|
+
const unusedSym = Symbol("_some_val");
|
|
31
|
+
return new IRCase(this.operand.toIR(ctx), [
|
|
32
|
+
// Some{ value } => true
|
|
33
|
+
new IRFunc([unusedSym], IRConst.bool(true)),
|
|
34
|
+
// None => false
|
|
35
|
+
IRConst.bool(false)
|
|
36
|
+
]);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Wraps the expression in TirSopOptToBoolExpr if its type is SoP Optional,
|
|
40
|
+
* otherwise returns it as-is.
|
|
41
|
+
*/
|
|
42
|
+
static wrapIfNeeded(expr) {
|
|
43
|
+
const t = getUnaliased(expr.type);
|
|
44
|
+
if (t instanceof TirSopOptT) {
|
|
45
|
+
return new TirSopOptToBoolExpr(expr, expr.range);
|
|
46
|
+
}
|
|
47
|
+
return expr;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -4,6 +4,10 @@ import { IRConst } from "../../../IR/IRNodes/IRConst.js";
|
|
|
4
4
|
import { IRNative } from "../../../IR/IRNodes/IRNative/index.js";
|
|
5
5
|
import { _ir_apps } from "../../../IR/IRNodes/IRApp.js";
|
|
6
6
|
import { _ir_lazyIfThenElse } from "../../../IR/tree_utils/_ir_lazyIfThenElse.js";
|
|
7
|
+
import { IRCase } from "../../../IR/IRNodes/index.js";
|
|
8
|
+
import { IRFunc } from "../../../IR/IRNodes/IRFunc.js";
|
|
9
|
+
import { TirSopOptT } from "../types/TirNativeType/native/Optional/sop.js";
|
|
10
|
+
import { getUnaliased } from "../types/utils/getUnaliased.js";
|
|
7
11
|
export class TirTraceIfFalseExpr {
|
|
8
12
|
condition;
|
|
9
13
|
traceStrExpr;
|
|
@@ -34,6 +38,17 @@ export class TirTraceIfFalseExpr {
|
|
|
34
38
|
return new TirTraceIfFalseExpr(this.condition.clone(), this.traceStrExpr.clone(), this.range.clone());
|
|
35
39
|
}
|
|
36
40
|
toIR(ctx) {
|
|
41
|
+
const condType = getUnaliased(this.condition.type);
|
|
42
|
+
// SoP Optional: use case expression to convert to bool
|
|
43
|
+
if (condType instanceof TirSopOptT) {
|
|
44
|
+
const unusedSym = Symbol("_some_val");
|
|
45
|
+
return new IRCase(this.condition.toIR(ctx), [
|
|
46
|
+
// Some{ value } => true
|
|
47
|
+
new IRFunc([unusedSym], IRConst.bool(true)),
|
|
48
|
+
// None => trace(msg, false)
|
|
49
|
+
_ir_apps(IRNative.trace, this.traceStrExpr.toIR(ctx), IRConst.bool(false))
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
37
52
|
return _ir_lazyIfThenElse(
|
|
38
53
|
// condition
|
|
39
54
|
this.condition.toIR(ctx),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mergeSortedStrArrInplace } from "../../../utils/array/mergeSortedStrArrInplace.js";
|
|
2
2
|
import { TirTraceIfFalseExpr } from "../expressions/TirTraceIfFalseExpr.js";
|
|
3
|
+
import { TirSopOptToBoolExpr } from "../expressions/TirSopOptToBoolExpr.js";
|
|
3
4
|
export class TirAssertStmt {
|
|
4
5
|
condition;
|
|
5
6
|
elseExpr;
|
|
@@ -32,8 +33,9 @@ export class TirAssertStmt {
|
|
|
32
33
|
return deps;
|
|
33
34
|
}
|
|
34
35
|
toSafeCondition() {
|
|
35
|
-
if (!this.elseExpr)
|
|
36
|
-
return this.condition;
|
|
36
|
+
if (!this.elseExpr) {
|
|
37
|
+
return TirSopOptToBoolExpr.wrapIfNeeded(this.condition);
|
|
38
|
+
}
|
|
37
39
|
return new TirTraceIfFalseExpr(this.condition, this.elseExpr, this.range);
|
|
38
40
|
}
|
|
39
41
|
}
|
package/dist/parser/Parser.js
CHANGED
|
@@ -1491,6 +1491,23 @@ export class Parser extends DiagnosticEmitter {
|
|
|
1491
1491
|
}
|
|
1492
1492
|
return new LitNamedObjExpr(identifier, litObjExpr.fieldNames, litObjExpr.values, SourceRange.join(identifier.range, litObjExpr.range));
|
|
1493
1493
|
}
|
|
1494
|
+
// LitNamedObjExpr with type qualifier
|
|
1495
|
+
// eg: `Type.Constructor{ a: 1, b: 2 }`
|
|
1496
|
+
if (tn.peek() === Token.Dot) {
|
|
1497
|
+
const savedState = tn.mark();
|
|
1498
|
+
tn.next(); // consume '.'
|
|
1499
|
+
if (tn.skipIdentifier(IdentifierHandling.Always)) {
|
|
1500
|
+
const ctorIdentifier = new Identifier(tn.readIdentifier(), tn.range());
|
|
1501
|
+
if (tn.peek() === Token.OpenBrace) {
|
|
1502
|
+
const litObjExpr = this.parseExprStart();
|
|
1503
|
+
if (litObjExpr instanceof LitObjExpr) {
|
|
1504
|
+
return new LitNamedObjExpr(ctorIdentifier, litObjExpr.fieldNames, litObjExpr.values, SourceRange.join(identifier.range, litObjExpr.range), identifier // typeName
|
|
1505
|
+
);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
tn.reset(savedState);
|
|
1510
|
+
}
|
|
1494
1511
|
// param => ...
|
|
1495
1512
|
if (tn.peek() === Token.FatArrow
|
|
1496
1513
|
// && !tn.isNextTokenOnNewLine() // original impl had this, not sure why
|
package/package.json
CHANGED