@harmoniclabs/pebble 0.1.3-dev8 → 0.1.4-dev0

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.
Files changed (28) hide show
  1. package/dist/IR/IRNodes/IRHoisted.d.ts +1 -0
  2. package/dist/IR/IRNodes/IRHoisted.js +3 -0
  3. package/dist/IR/IRNodes/IRLetted.d.ts +1 -0
  4. package/dist/IR/IRNodes/IRLetted.js +3 -0
  5. package/dist/IR/IRNodes/IRNative/IRNativeTag.d.ts +2 -1
  6. package/dist/IR/IRNodes/IRNative/IRNativeTag.js +2 -0
  7. package/dist/IR/IRNodes/utils/hashVarSym.d.ts +1 -0
  8. package/dist/IR/IRNodes/utils/hashVarSym.js +5 -0
  9. package/dist/IR/toUPLC/subRoutines/replaceHoistedWithLetted.d.ts +1 -0
  10. package/dist/IR/toUPLC/subRoutines/replaceHoistedWithLetted.js +3 -0
  11. package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.d.ts +1 -0
  12. package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.js +19 -0
  13. package/dist/ast/nodes/expr/litteral/LitNamedObjExpr.d.ts +5 -1
  14. package/dist/ast/nodes/expr/litteral/LitNamedObjExpr.js +5 -1
  15. package/dist/compiler/AstCompiler/AstCompilationCtx.d.ts +3 -0
  16. package/dist/compiler/AstCompiler/internal/exprs/_compileFuncExpr.js +72 -3
  17. package/dist/compiler/AstCompiler/internal/exprs/_compileLitteralExpr.js +22 -2
  18. package/dist/compiler/AstCompiler/internal/statements/_compileReturnStmt.js +3 -2
  19. package/dist/compiler/AstCompiler/utils/getPropAccessReturnType.js +9 -0
  20. package/dist/compiler/Compiler.js +10 -0
  21. package/dist/compiler/SourceTypeMap.js +13 -0
  22. package/dist/compiler/TirCompiler/expressify/expressifyVars.d.ts +1 -0
  23. package/dist/compiler/TirCompiler/expressify/expressifyVars.js +55 -5
  24. package/dist/compiler/tir/expressions/TirNativeFunc.d.ts +1 -0
  25. package/dist/compiler/tir/expressions/TirNativeFunc.js +8 -0
  26. package/dist/compiler/tir/expressions/TirTraceExpr.js +8 -3
  27. package/dist/parser/Parser.js +17 -0
  28. package/package.json +1 -1
@@ -24,6 +24,7 @@ export interface IRHoistedMeta {
24
24
  export interface IRHoistedMetadata extends IRMetadata {
25
25
  meta: IRHoistedMeta;
26
26
  }
27
+ export declare function __unsafe_clear_hoisted_hash_to_symbol(): void;
27
28
  export declare class IRHoisted implements IIRTerm, Cloneable<IRHoisted>, IIRParent, ToJson, IRHoistedMetadata {
28
29
  readonly meta: IRHoistedMeta;
29
30
  get name(): symbol;
@@ -19,6 +19,9 @@ const defaultHoistedMeta = freezeAll({
19
19
  forceHoist: false
20
20
  });
21
21
  const _hoisted_hash_to_symbol = new Map();
22
+ export function __unsafe_clear_hoisted_hash_to_symbol() {
23
+ _hoisted_hash_to_symbol.clear();
24
+ }
22
25
  export class IRHoisted {
23
26
  meta;
24
27
  get name() {
@@ -34,6 +34,7 @@ export interface IRLettedMeta extends BaseIRMetadata {
34
34
  export interface IRLettedMetadata extends IRMetadata {
35
35
  meta: IRLettedMeta;
36
36
  }
37
+ export declare function __unsafe_clear_letted_hash_to_symbol(): void;
37
38
  export declare class IRLetted implements IIRTerm, Cloneable<IRLetted>, IIRParent, ToJson, IRLettedMetadata {
38
39
  private _name;
39
40
  readonly meta: IRLettedMeta;
@@ -26,6 +26,9 @@ const defaultLettedMeta = freezeAll({
26
26
  isClosed: false
27
27
  });
28
28
  const _letted_hash_to_symbol = new Map();
29
+ export function __unsafe_clear_letted_hash_to_symbol() {
30
+ _letted_hash_to_symbol.clear();
31
+ }
29
32
  export class IRLetted {
30
33
  _name;
31
34
  meta;
@@ -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
  }
@@ -1 +1,2 @@
1
+ export declare function __VERY_UNSAFE_FORGET_VAR_SYM_HASHES_ONLY_USE_AT_END_OF_UPLC_COMPILATION(): void;
1
2
  export declare function hashVarSym(s: symbol): Uint8Array;
@@ -19,6 +19,11 @@ function _collectUnusedHashes() {
19
19
  }
20
20
  }
21
21
  }
22
+ export function __VERY_UNSAFE_FORGET_VAR_SYM_HASHES_ONLY_USE_AT_END_OF_UPLC_COMPILATION() {
23
+ _hash_to_sym.clear();
24
+ unusedHashes.length = 0;
25
+ _next_hash = MIN_SAFE_INTEGER;
26
+ }
22
27
  export function hashVarSym(s) {
23
28
  const limitReached = _next_hash >= MAX_SAFE_INTEGER;
24
29
  if (_next_hash % 0xffff === 0
@@ -1,2 +1,3 @@
1
1
  import { IRTerm } from "../../IRTerm.js";
2
+ export declare function __unsafe_clear_hoisted_cache(): void;
2
3
  export declare function replaceHoistedWithLetted(term: IRTerm): void;
@@ -2,6 +2,9 @@ import { IRHoisted } from "../../IRNodes/IRHoisted.js";
2
2
  import { IRLetted } from "../../IRNodes/IRLetted.js";
3
3
  import { _modifyChildFromTo } from "../_internal/_modifyChildFromTo.js";
4
4
  const _hoisted_cache = new Map();
5
+ export function __unsafe_clear_hoisted_cache() {
6
+ _hoisted_cache.clear();
7
+ }
5
8
  export function replaceHoistedWithLetted(term) {
6
9
  // children first
7
10
  const children = term.children();
@@ -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;
@@ -128,6 +128,24 @@ new IRConstr(1, [new IRVar(findSop_head)]), // Some{ head }
128
128
  // else => self(tail)
129
129
  _ir_apps(new IRSelfCall(findSop_self), _ir_apps(IRNative.tailList, 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 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(1, [
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))))))))));
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
- constructor(name: Identifier, fieldNames: Identifier[], values: PebbleExpr[], range: SourceRange);
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
- constructor(name, fieldNames, values, range) {
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
  }
@@ -11,6 +11,9 @@ export interface AstCompilationCtxFuncInfo {
11
11
  **/
12
12
  parentFunctionCtx: AstCompilationCtxFuncInfo | undefined;
13
13
  returnType: TirType;
14
+ /** when true, skip the return type assignability check
15
+ * and infer the return type from the returned expression */
16
+ inferReturnType?: boolean;
14
17
  }
15
18
  export interface IAstCompilationCtx {
16
19
  scope: AstScope;
@@ -5,8 +5,10 @@ import { DiagnosticCode } from "../../../../diagnostics/diagnosticMessages.gener
5
5
  import { getUniqueInternalName } from "../../../internalVar.js";
6
6
  import { TirFuncExpr } from "../../../tir/expressions/TirFuncExpr.js";
7
7
  import { TirVariableAccessExpr } from "../../../tir/expressions/TirVariableAccessExpr.js";
8
+ import { TirReturnStmt } from "../../../tir/statements/TirReturnStmt.js";
8
9
  import { TirSimpleVarDecl } from "../../../tir/statements/TirVarDecl/TirSimpleVarDecl.js";
9
10
  import { TirFuncT } from "../../../tir/types/TirNativeType/native/function.js";
11
+ import { void_t } from "../../../tir/program/stdScope/stdScope.js";
10
12
  import { TirTypeParam } from "../../../tir/types/TirTypeParam.js";
11
13
  import { getUnaliased } from "../../../tir/types/utils/getUnaliased.js";
12
14
  import { _compileBlockStmt } from "../statements/_compileBlockStmt.js";
@@ -68,9 +70,17 @@ export function _compileFuncExpr(ctx, expr, expectedFuncType, isMethod = false)
68
70
  }
69
71
  else {
70
72
  expectedFuncType = (isMethod ? undefined :
71
- ctx.program.functions.get(expr.name.text)?.sig()) ?? getDataFuncSignature(ctx, expr.signature);
72
- if (!(expectedFuncType instanceof TirFuncT))
73
- return undefined;
73
+ ctx.program.functions.get(expr.name.text)?.sig());
74
+ if (!(expectedFuncType instanceof TirFuncT)) {
75
+ // if the return type annotation is missing,
76
+ // infer it from the body instead of erroring
77
+ if (!expr.signature.returnType) {
78
+ return _compileFuncExprInferReturnType(ctx, expr, isMethod);
79
+ }
80
+ expectedFuncType = getDataFuncSignature(ctx, expr.signature);
81
+ if (!(expectedFuncType instanceof TirFuncT))
82
+ return undefined;
83
+ }
74
84
  }
75
85
  const returnType = expectedFuncType.returnType;
76
86
  const funcCtx = ctx.newFunctionChildScope(returnType, isMethod);
@@ -97,6 +107,65 @@ export function _compileFuncExpr(ctx, expr, expectedFuncType, isMethod = false)
97
107
  const funcExpr = new TirFuncExpr(expr.name.text, params, returnType, body, expr.range);
98
108
  return funcExpr;
99
109
  }
110
+ /**
111
+ * compiles a function expression whose return type annotation is missing,
112
+ * inferring the return type from the body's return expressions.
113
+ *
114
+ * uses `inferReturnType` flag on the function context so that
115
+ * `_compileReturnStmt` skips the return type assignability check.
116
+ */
117
+ function _compileFuncExprInferReturnType(ctx, expr, isMethod) {
118
+ // compile param types (reuse getDataFuncSignature logic for params only)
119
+ const funcParams = expr.signature.params;
120
+ const paramTypes = new Array(funcParams.length);
121
+ for (let i = 0; i < funcParams.length; i++) {
122
+ const param = funcParams[i];
123
+ if (!param.type)
124
+ return ctx.error(DiagnosticCode.Could_not_infer_function_signature_parameter_type_is_missing, param.range);
125
+ const type = _compileDataEncodedConcreteType(ctx, param.type, true);
126
+ if (!type)
127
+ return undefined;
128
+ paramTypes[i] = type;
129
+ }
130
+ // use void as a temporary return type; the real type will be inferred
131
+ // from the body's return expressions after compilation
132
+ const tempReturnType = void_t;
133
+ const tempFuncType = new TirFuncT(paramTypes, tempReturnType);
134
+ const funcCtx = ctx.newFunctionChildScope(tempReturnType, isMethod);
135
+ // mark the context as inferring so _compileReturnStmt
136
+ // skips the return type assignability check
137
+ funcCtx.functionCtx.inferReturnType = true;
138
+ funcCtx.scope.defineValue({
139
+ name: expr.name.text,
140
+ type: tempFuncType,
141
+ isConstant: true,
142
+ });
143
+ if (expr.typeParams.length > 0)
144
+ return ctx.error(DiagnosticCode.Not_implemented_0, expr.typeParams[0].range, "generic functions");
145
+ const destructuredParamsResult = _getDestructuredParamsAsVarDecls(funcCtx, expr, tempFuncType);
146
+ if (!destructuredParamsResult)
147
+ return undefined;
148
+ const { blockInitStmts, params } = destructuredParamsResult;
149
+ const astBody = expr.body instanceof BlockStmt ? expr.body :
150
+ new BlockStmt([new ReturnStmt(expr.body, expr.body.range)], expr.body.range);
151
+ const compileResult = _compileBlockStmt(funcCtx, astBody);
152
+ if (!compileResult)
153
+ return undefined;
154
+ const body = compileResult[0];
155
+ body.stmts.unshift(...blockInitStmts);
156
+ // infer return type from the first return statement in the body
157
+ const returnType = _inferReturnType(body.stmts) ?? tempReturnType;
158
+ const funcExpr = new TirFuncExpr(expr.name.text, params, returnType, body, expr.range);
159
+ return funcExpr;
160
+ }
161
+ function _inferReturnType(stmts) {
162
+ for (const stmt of stmts) {
163
+ if (stmt instanceof TirReturnStmt && stmt.value) {
164
+ return stmt.value.type;
165
+ }
166
+ }
167
+ return undefined;
168
+ }
100
169
  function _getDestructuredParamsAsVarDecls(funcCtx, expr, expectedFuncType) {
101
170
  const blockInitStmts = [];
102
171
  const params = [];
@@ -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
- const inferredStructType = getStructType(ctx.scope.inferStructTypeFromConstructorName(constructorName)?.structType);
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 fieldValues = __commonCompileStructFieldValues(ctx, expr, typeHint, structType, structType?.constructors.findIndex(c => c.name === constructorName) ?? -1);
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);
@@ -7,11 +7,12 @@ export function _compileReturnStmt(ctx, stmt) {
7
7
  if (!ctx.functionCtx)
8
8
  return ctx.error(DiagnosticCode.A_return_statement_can_only_be_used_within_a_function_body, stmt.range);
9
9
  const hintReturn = ctx.functionCtx.returnType;
10
+ const inferring = ctx.functionCtx.inferReturnType === true;
10
11
  const expr = stmt.value ?
11
- _compileExpr(ctx, stmt.value, hintReturn) : new TirLitVoidExpr(stmt.range);
12
+ _compileExpr(ctx, stmt.value, inferring ? undefined : hintReturn) : new TirLitVoidExpr(stmt.range);
12
13
  if (!expr)
13
14
  return undefined;
14
- if (!canAssignTo(expr.type, hintReturn))
15
+ if (!inferring && !canAssignTo(expr.type, hintReturn))
15
16
  return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, stmt.value?.range ?? stmt.range, expr.type.toString(), hintReturn.toString());
16
17
  return [new TirReturnStmt(expr, stmt.range)];
17
18
  }
@@ -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) {
@@ -6,6 +6,11 @@ import { AstCompiler } from "./AstCompiler/AstCompiler.js";
6
6
  import { createMemoryCompilerIoApi } from "./io/CompilerIoApi.js";
7
7
  import { compileTypedProgram } from "./TirCompiler/compileTirProgram.js";
8
8
  import { __VERY_UNSAFE_FORGET_IRHASH_ONLY_USE_AT_END_OF_UPLC_COMPILATION } from "../IR/IRHash.js";
9
+ import { __VERY_UNSAFE_FORGET_VAR_SYM_HASHES_ONLY_USE_AT_END_OF_UPLC_COMPILATION } from "../IR/IRNodes/utils/hashVarSym.js";
10
+ import { __unsafe_clear_hoisted_hash_to_symbol } from "../IR/IRNodes/IRHoisted.js";
11
+ import { __unsafe_clear_letted_hash_to_symbol } from "../IR/IRNodes/IRLetted.js";
12
+ import { __unsafe_clear_hoisted_cache } from "../IR/toUPLC/subRoutines/replaceHoistedWithLetted.js";
13
+ import { __unsafe_clear_mapToType_cache } from "./TirCompiler/expressify/expressifyVars.js";
9
14
  import { compileIRToUPLC } from "../IR/toUPLC/compileIRToUPLC.js";
10
15
  export { SourceTypeMap } from "./SourceTypeMap.js";
11
16
  export class Compiler extends DiagnosticEmitter {
@@ -127,6 +132,11 @@ export class Compiler extends DiagnosticEmitter {
127
132
  this.io.writeFile(outPath, serialized, cfg.root);
128
133
  this.io.stdout.write(`compiled program written to ${outPath}\n`);
129
134
  __VERY_UNSAFE_FORGET_IRHASH_ONLY_USE_AT_END_OF_UPLC_COMPILATION();
135
+ __VERY_UNSAFE_FORGET_VAR_SYM_HASHES_ONLY_USE_AT_END_OF_UPLC_COMPILATION();
136
+ __unsafe_clear_hoisted_hash_to_symbol();
137
+ __unsafe_clear_letted_hash_to_symbol();
138
+ __unsafe_clear_hoisted_cache();
139
+ __unsafe_clear_mapToType_cache();
130
140
  return serialized;
131
141
  }
132
142
  }
@@ -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;
@@ -8,3 +8,4 @@ import { ExpressifyCtx } from "./ExpressifyCtx.js";
8
8
  * @returns a the modified expression
9
9
  **/
10
10
  export declare function expressifyVars(ctx: ExpressifyCtx, expr: TirExpr): TirExpr;
11
+ export declare function __unsafe_clear_mapToType_cache(): void;
@@ -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()}'`);
@@ -484,3 +531,6 @@ function expressifyListMethodCall(ctx, objectExpr, methodCall, methodName, listT
484
531
  */
485
532
  }
486
533
  const _base_mapToType_cache = new Map();
534
+ export function __unsafe_clear_mapToType_cache() {
535
+ _base_mapToType_cache.clear();
536
+ }
@@ -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
@@ -1,4 +1,6 @@
1
1
  import { _ir_apps } from "../../../IR/IRNodes/IRApp.js";
2
+ import { IRDelayed } from "../../../IR/IRNodes/IRDelayed.js";
3
+ import { IRForced } from "../../../IR/IRNodes/IRForced.js";
2
4
  import { IRNative } from "../../../IR/IRNodes/IRNative/index.js";
3
5
  import { hoisted_intToUtf8Bytes } from "../../../IR/tree_utils/intToUtf8Bytes.js";
4
6
  import { mergeSortedStrArrInplace } from "../../../utils/array/mergeSortedStrArrInplace.js";
@@ -46,8 +48,11 @@ export class TirTraceExpr {
46
48
  // assume bytes
47
49
  bytesIR = this.traceExpr.toIR(ctx);
48
50
  }
49
- return _ir_apps(IRNative.trace,
50
- // bytes -> string via decodeUtf8
51
- _ir_apps(IRNative.decodeUtf8, bytesIR), this.continuation.toIR(ctx));
51
+ // Force(trace(msg, Delay(continuation)))
52
+ // Delay prevents the continuation from being evaluated
53
+ // as a trace argument; Force evaluates it after the
54
+ // trace call has logged the message.
55
+ // This gives correct trace order in loops and nested traces.
56
+ return new IRForced(_ir_apps(IRNative.trace, _ir_apps(IRNative.decodeUtf8, bytesIR), new IRDelayed(this.continuation.toIR(ctx))));
52
57
  }
53
58
  }
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harmoniclabs/pebble",
3
- "version": "0.1.3-dev8",
3
+ "version": "0.1.4-dev0",
4
4
  "description": "A simple, yet rock solid, functional language with an imperative bias, targeting UPLC",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",