@harmoniclabs/pebble 0.1.4 → 0.1.6

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 (27) hide show
  1. package/dist/IR/IRNodes/IRConst.js +6 -0
  2. package/dist/IR/IRNodes/IRNative/index.js +3 -2
  3. package/dist/compiler/AstCompiler/internal/exprs/_compileElemAccessExpr.d.ts +2 -2
  4. package/dist/compiler/AstCompiler/internal/exprs/_compileElemAccessExpr.js +39 -3
  5. package/dist/compiler/AstCompiler/internal/statements/_compileVarStmt.js +15 -0
  6. package/dist/compiler/AstCompiler/utils/getPropAccessReturnType.js +25 -2
  7. package/dist/compiler/Compiler.js +1 -1
  8. package/dist/compiler/SourceTypeMap.d.ts +1 -0
  9. package/dist/compiler/SourceTypeMap.js +25 -0
  10. package/dist/compiler/TirCompiler/expressify/expressify.js +21 -1
  11. package/dist/compiler/TirCompiler/expressify/expressifyVars.js +37 -1
  12. package/dist/compiler/TirCompiler/expressify/toNamedDeconstructVarDecl.js +7 -0
  13. package/dist/compiler/tir/expressions/TirFromDataExpr.js +4 -0
  14. package/dist/compiler/tir/expressions/TirNativeFunc.d.ts +2 -0
  15. package/dist/compiler/tir/expressions/TirNativeFunc.js +9 -0
  16. package/dist/compiler/tir/types/TirNativeType/TirNativeType.d.ts +2 -1
  17. package/dist/compiler/tir/types/TirNativeType/TirNativeType.js +2 -0
  18. package/dist/compiler/tir/types/TirNativeType/native/index.d.ts +1 -0
  19. package/dist/compiler/tir/types/TirNativeType/native/index.js +1 -0
  20. package/dist/compiler/tir/types/TirNativeType/native/linearMapEntry.d.ts +17 -0
  21. package/dist/compiler/tir/types/TirNativeType/native/linearMapEntry.js +44 -0
  22. package/dist/compiler/tir/types/utils/canAssignTo.js +7 -0
  23. package/dist/compiler/tir/types/utils/canCastTo.js +10 -4
  24. package/dist/compiler/tir/types/utils/getListTypeArg.d.ts +1 -0
  25. package/dist/compiler/tir/types/utils/getListTypeArg.js +11 -0
  26. package/dist/parser/Parser.js +24 -0
  27. package/package.json +1 -1
@@ -18,6 +18,7 @@ import { TirDataT } from "../../compiler/tir/types/TirNativeType/native/data.js"
18
18
  import { TirFuncT } from "../../compiler/tir/types/TirNativeType/native/function.js";
19
19
  import { TirIntT } from "../../compiler/tir/types/TirNativeType/native/int.js";
20
20
  import { TirLinearMapT } from "../../compiler/tir/types/TirNativeType/native/linearMap.js";
21
+ import { TirLinearMapEntryT } from "../../compiler/tir/types/TirNativeType/native/linearMapEntry.js";
21
22
  import { TirListT } from "../../compiler/tir/types/TirNativeType/native/list.js";
22
23
  import { TirDataOptT } from "../../compiler/tir/types/TirNativeType/native/Optional/data.js";
23
24
  import { TirSopOptT } from "../../compiler/tir/types/TirNativeType/native/Optional/sop.js";
@@ -166,6 +167,8 @@ function isValueAssignableToType(value, type) {
166
167
  return (Array.isArray(value) &&
167
168
  value.every(v => isValueAssignableToType(v, elemsT)));
168
169
  }
170
+ if (type instanceof TirLinearMapEntryT)
171
+ return isIRConstPair(value);
169
172
  const tsEnsureExsaustiveCheck = type;
170
173
  return false;
171
174
  }
@@ -216,6 +219,7 @@ function serializeIRConstValue(value, type) {
216
219
  return dataToCbor(value);
217
220
  if (type instanceof TirFuncT
218
221
  || type instanceof TirSopOptT
222
+ || type instanceof TirLinearMapEntryT
219
223
  || type instanceof TirSoPStructType
220
224
  || type instanceof TirTypeParam)
221
225
  throw new Error("invalid uplc const type");
@@ -270,6 +274,8 @@ export function tirTypeToUplcType(t) {
270
274
  return constT.listOf(constT.pairOf(constT.data, constT.data));
271
275
  if (t instanceof TirUnConstrDataResultT)
272
276
  return constT.pairOf(constT.int, constT.listOf(constT.data));
277
+ if (t instanceof TirLinearMapEntryT)
278
+ return constT.pairOf(constT.data, constT.data);
273
279
  if (t instanceof TirAliasType
274
280
  || t instanceof TirFuncT
275
281
  || t instanceof TirSopOptT
@@ -14,6 +14,7 @@ import { TirBytesT } from "../../../compiler/tir/types/TirNativeType/native/byte
14
14
  import { TirDataT } from "../../../compiler/tir/types/TirNativeType/native/data.js";
15
15
  import { TirIntT } from "../../../compiler/tir/types/TirNativeType/native/int.js";
16
16
  import { TirLinearMapT } from "../../../compiler/tir/types/TirNativeType/native/linearMap.js";
17
+ import { TirLinearMapEntryT } from "../../../compiler/tir/types/TirNativeType/native/linearMapEntry.js";
17
18
  import { TirListT } from "../../../compiler/tir/types/TirNativeType/native/list.js";
18
19
  import { TirDataOptT } from "../../../compiler/tir/types/TirNativeType/native/Optional/data.js";
19
20
  import { TirStringT } from "../../../compiler/tir/types/TirNativeType/native/string.js";
@@ -242,8 +243,8 @@ export class IRNative {
242
243
  return IRNative.equalListOf(getListTypeArg(type));
243
244
  if (type instanceof TirLinearMapT)
244
245
  return IRNative.equalListOf(new TirPairDataT());
245
- if (type instanceof TirLinearMapT)
246
- return IRNative.equalListOf(new TirPairDataT());
246
+ if (type instanceof TirLinearMapEntryT)
247
+ return IRNative._equalPairData;
247
248
  if (type instanceof TirUnConstrDataResultT)
248
249
  return getEqUnConstr();
249
250
  if (type instanceof TirVoidT)
@@ -1,5 +1,5 @@
1
1
  import { ElemAccessExpr } from "../../../../ast/nodes/expr/ElemAccessExpr.js";
2
- import { TirElemAccessExpr } from "../../../tir/expressions/TirElemAccessExpr.js";
2
+ import { TirExpr } from "../../../tir/expressions/TirExpr.js";
3
3
  import { TirType } from "../../../tir/types/TirType.js";
4
4
  import { AstCompilationCtx } from "../../AstCompilationCtx.js";
5
- export declare function _compileElemAccessExpr(ctx: AstCompilationCtx, expr: ElemAccessExpr, typeHint: TirType | undefined): TirElemAccessExpr | undefined;
5
+ export declare function _compileElemAccessExpr(ctx: AstCompilationCtx, expr: ElemAccessExpr, typeHint: TirType | undefined): TirExpr | undefined;
@@ -1,16 +1,52 @@
1
1
  import { DiagnosticCode } from "../../../../diagnostics/diagnosticMessages.generated.js";
2
+ import { TirCallExpr } from "../../../tir/expressions/TirCallExpr.js";
3
+ import { TirCaseExpr, TirCaseMatcher } from "../../../tir/expressions/TirCaseExpr.js";
2
4
  import { TirElemAccessExpr } from "../../../tir/expressions/TirElemAccessExpr.js";
5
+ import { TirFailExpr } from "../../../tir/expressions/TirFailExpr.js";
6
+ import { TirNativeFunc } from "../../../tir/expressions/TirNativeFunc.js";
7
+ import { TirToDataExpr } from "../../../tir/expressions/TirToDataExpr.js";
8
+ import { TirVariableAccessExpr } from "../../../tir/expressions/TirVariableAccessExpr.js";
9
+ import { TirNamedDeconstructVarDecl } from "../../../tir/statements/TirVarDecl/TirNamedDeconstructVarDecl.js";
10
+ import { TirSimpleVarDecl } from "../../../tir/statements/TirVarDecl/TirSimpleVarDecl.js";
3
11
  import { TirListT } from "../../../tir/types/TirNativeType/native/list.js";
12
+ import { TirSopOptT } from "../../../tir/types/TirNativeType/native/Optional/sop.js";
4
13
  import { canAssignTo } from "../../../tir/types/utils/canAssignTo.js";
14
+ import { getLinearMapTypeArgs } from "../../../tir/types/utils/getListTypeArg.js";
5
15
  import { getListTypeArg } from "../../../tir/types/utils/getListTypeArg.js";
16
+ import { getUnaliased } from "../../../tir/types/utils/getUnaliased.js";
6
17
  import { _compileExpr } from "./_compileExpr.js";
7
18
  export function _compileElemAccessExpr(ctx, expr, typeHint) {
8
19
  const int_t = ctx.program.stdTypes.int;
9
- const litsTypeHint = typeHint ? new TirListT(typeHint) : undefined;
10
- const arrLikeExpr = _compileExpr(ctx, expr.arrLikeExpr, litsTypeHint);
20
+ const arrLikeExpr = _compileExpr(ctx, expr.arrLikeExpr, undefined);
11
21
  if (!arrLikeExpr)
12
22
  return undefined;
13
- const arrLikeType = arrLikeExpr.type;
23
+ const arrLikeType = getUnaliased(arrLikeExpr.type);
24
+ // LinearMap<K,V>: map[key] desugars to map.lookup(key)!
25
+ const mapTypeArgs = getLinearMapTypeArgs(arrLikeType);
26
+ if (mapTypeArgs) {
27
+ const [kT, vT] = mapTypeArgs;
28
+ const indexExpr = _compileExpr(ctx, expr.indexExpr, kT);
29
+ if (!indexExpr)
30
+ return undefined;
31
+ if (!canAssignTo(indexExpr.type, kT))
32
+ return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.indexExpr.range, indexExpr.type.toString(), kT.toString());
33
+ const optType = new TirSopOptT(vT);
34
+ // _lookupLinearMap expects data-encoded key
35
+ const keyAsData = new TirToDataExpr(indexExpr, expr.indexExpr.range);
36
+ const lookupCall = new TirCallExpr(TirNativeFunc._lookupLinearMap(kT, vT), [keyAsData, arrLikeExpr], optType, expr.range);
37
+ // unwrap: case lookup is Some{ value } => value, None => fail
38
+ return new TirCaseExpr(lookupCall, [
39
+ new TirCaseMatcher(new TirNamedDeconstructVarDecl("Some", new Map([
40
+ ["value", new TirSimpleVarDecl("value", vT, undefined, true, expr.range)]
41
+ ]), undefined, optType, undefined, true, expr.range), new TirVariableAccessExpr({
42
+ variableInfos: { name: "value", type: vT, isConstant: true },
43
+ isDefinedOutsideFuncScope: false,
44
+ }, expr.range), expr.range),
45
+ new TirCaseMatcher(new TirNamedDeconstructVarDecl("None", new Map(), undefined, optType, undefined, true, expr.range), new TirFailExpr(undefined, vT, expr.range), expr.range)
46
+ ], undefined, vT, expr.range);
47
+ }
48
+ // List<T>: list[index]
49
+ const litsTypeHint = typeHint ? new TirListT(typeHint) : undefined;
14
50
  const elemsType = getListTypeArg(arrLikeType);
15
51
  if (!elemsType)
16
52
  return ctx.error(DiagnosticCode.This_expression_cannot_be_indexed, expr.arrLikeExpr.range);
@@ -9,10 +9,12 @@ import { TirSimpleVarDecl } from "../../../tir/statements/TirVarDecl/TirSimpleVa
9
9
  import { TirSingleDeconstructVarDecl } from "../../../tir/statements/TirVarDecl/TirSingleDeconstructVarDecl.js";
10
10
  import { TirDataT } from "../../../tir/types/TirNativeType/native/data.js";
11
11
  import { isTirOptType } from "../../../tir/types/TirNativeType/native/Optional/isTirOptType.js";
12
+ import { TirLinearMapEntryT } from "../../../tir/types/TirNativeType/native/linearMapEntry.js";
12
13
  import { isTirStructType, TirStructConstr, TirStructField } from "../../../tir/types/TirStructType.js";
13
14
  import { getNamedDestructableType, getStructType, canAssignTo } from "../../../tir/types/utils/canAssignTo.js";
14
15
  import { canCastToData } from "../../../tir/types/utils/canCastTo.js";
15
16
  import { getListTypeArg } from "../../../tir/types/utils/getListTypeArg.js";
17
+ import { getUnaliased } from "../../../tir/types/utils/getUnaliased.js";
16
18
  import { _compileExpr } from "../exprs/_compileExpr.js";
17
19
  import { _compileSopEncodedConcreteType } from "../types/_compileSopEncodedConcreteType.js";
18
20
  export function _compileVarStmt(ctx, stmt) {
@@ -105,6 +107,19 @@ export function _compileSingleDeconstructVarDecl(ctx, decl, typeHint) {
105
107
  if (!typeAndExpr)
106
108
  return undefined;
107
109
  const [finalVarType, initExpr, typeAnnotationRange] = typeAndExpr;
110
+ // LinearMapEntry<K,V> can be destructured as { key, value }
111
+ const unaliasedVarType = getUnaliased(finalVarType);
112
+ if (unaliasedVarType instanceof TirLinearMapEntryT) {
113
+ const virtualConstr = new TirStructConstr("Entry", [
114
+ new TirStructField("key", unaliasedVarType.keyTypeArg),
115
+ new TirStructField("value", unaliasedVarType.valTypeArg),
116
+ ]);
117
+ const deconstructedFields = _getDeconstructedFields(ctx, decl, virtualConstr);
118
+ if (!deconstructedFields)
119
+ return undefined;
120
+ const [fields, rest, fieldLabelRanges] = deconstructedFields;
121
+ return new TirSingleDeconstructVarDecl(fields, rest, finalVarType, initExpr, decl.isConst(), decl.range, fieldLabelRanges, typeAnnotationRange);
122
+ }
108
123
  const finalStructType = getStructType(finalVarType);
109
124
  if (!finalStructType)
110
125
  return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, decl.range, finalVarType.toString(), "Struct");
@@ -9,6 +9,7 @@ import { TirDataT } from "../../tir/types/TirNativeType/native/data.js";
9
9
  import { TirFuncT } from "../../tir/types/TirNativeType/native/function.js";
10
10
  import { TirIntT } from "../../tir/types/TirNativeType/native/int.js";
11
11
  import { TirLinearMapT } from "../../tir/types/TirNativeType/native/linearMap.js";
12
+ import { TirLinearMapEntryT } from "../../tir/types/TirNativeType/native/linearMapEntry.js";
12
13
  import { TirListT } from "../../tir/types/TirNativeType/native/list.js";
13
14
  import { isTirOptType } from "../../tir/types/TirNativeType/native/Optional/isTirOptType.js";
14
15
  import { TirSopOptT } from "../../tir/types/TirNativeType/native/Optional/sop.js";
@@ -46,6 +47,13 @@ export function getPropAccessReturnType(ctx, objType, propId) {
46
47
  return undefined;
47
48
  if (objType instanceof TirListT)
48
49
  return getListMethods(objType.typeArg)[propName];
50
+ if (objType instanceof TirLinearMapEntryT) {
51
+ if (propName === "key")
52
+ return objType.keyTypeArg;
53
+ if (propName === "value")
54
+ return objType.valTypeArg;
55
+ return undefined;
56
+ }
49
57
  if (objType instanceof TirLinearMapT)
50
58
  return getLinearMapMethods(objType.keyTypeArg, objType.valTypeArg)[propName];
51
59
  if (objType instanceof TirUnConstrDataResultT)
@@ -85,9 +93,24 @@ function getListMethods(elemsType) {
85
93
  };
86
94
  }
87
95
  function getLinearMapMethods(kT, vT) {
96
+ const entryType = new TirLinearMapEntryT(kT, vT);
97
+ const mapType = new TirLinearMapT(kT, vT);
98
+ const mapReturnT = new TirTypeParam("T");
88
99
  return {
89
- // ...getListMethods( /* to add when adding support for pairs */ ),
90
- lookup: new TirFuncT([kT], new TirSopOptT(vT))
100
+ length: new TirFuncT([], int_t),
101
+ isEmpty: new TirFuncT([], bool_t),
102
+ show: new TirFuncT([], bytes_t),
103
+ head: new TirFuncT([], entryType),
104
+ tail: new TirFuncT([], mapType),
105
+ reverse: new TirFuncT([], mapType),
106
+ find: new TirFuncT([new TirFuncT([entryType], bool_t)], new TirSopOptT(entryType)),
107
+ filter: new TirFuncT([new TirFuncT([entryType], bool_t)], mapType),
108
+ prepend: new TirFuncT([kT, vT], mapType),
109
+ map: new TirFuncT([new TirFuncT([entryType], mapReturnT)], new TirListT(mapReturnT)),
110
+ every: new TirFuncT([new TirFuncT([entryType], bool_t)], bool_t),
111
+ some: new TirFuncT([new TirFuncT([entryType], bool_t)], bool_t),
112
+ includes: new TirFuncT([entryType], bool_t),
113
+ lookup: new TirFuncT([kT], new TirSopOptT(vT)),
91
114
  };
92
115
  }
93
116
  const bytesMethods = Object.freeze({
@@ -42,7 +42,7 @@ export class Compiler extends DiagnosticEmitter {
42
42
  const program = await astCompiler.compile();
43
43
  if (this.diagnostics.length > 0) {
44
44
  let msg;
45
- globalThis.console && console.log(this.diagnostics);
45
+ // globalThis.console && console.log( this.diagnostics );
46
46
  const fstErrorMsg = this.diagnostics[0].toString();
47
47
  const nDiags = this.diagnostics.length;
48
48
  for (msg of this.diagnostics) {
@@ -35,6 +35,7 @@ export declare class SourceTypeMap {
35
35
  private listMembers;
36
36
  private bytesMembers;
37
37
  private stringMembers;
38
+ private linearMapEntryMembers;
38
39
  private linearMapMembers;
39
40
  private walkFuncExpr;
40
41
  private walkExpr;
@@ -4,6 +4,7 @@ import { isTirStructType } from "./tir/types/TirStructType.js";
4
4
  import { TirFuncT } from "./tir/types/TirNativeType/native/function.js";
5
5
  import { TirListT } from "./tir/types/TirNativeType/native/list.js";
6
6
  import { TirLinearMapT } from "./tir/types/TirNativeType/native/linearMap.js";
7
+ import { TirLinearMapEntryT } from "./tir/types/TirNativeType/native/linearMapEntry.js";
7
8
  import { TirBytesT } from "./tir/types/TirNativeType/native/bytes.js";
8
9
  import { TirStringT } from "./tir/types/TirNativeType/native/string.js";
9
10
  import { TirBoolT } from "./tir/types/TirNativeType/native/bool.js";
@@ -130,6 +131,8 @@ export class SourceTypeMap {
130
131
  return [];
131
132
  if (type instanceof TirListT)
132
133
  return this.listMembers(type.typeArg);
134
+ if (type instanceof TirLinearMapEntryT)
135
+ return this.linearMapEntryMembers(type);
133
136
  if (type instanceof TirLinearMapT)
134
137
  return this.linearMapMembers(type.keyTypeArg, type.valTypeArg);
135
138
  return [];
@@ -207,8 +210,30 @@ export class SourceTypeMap {
207
210
  { name: "encodeUtf8", type: new TirFuncT([], bytes_t), kind: "method" },
208
211
  ];
209
212
  }
213
+ linearMapEntryMembers(type) {
214
+ return [
215
+ { name: "key", type: type.keyTypeArg, kind: "field" },
216
+ { name: "value", type: type.valTypeArg, kind: "field" },
217
+ ];
218
+ }
210
219
  linearMapMembers(kT, vT) {
220
+ const entryType = new TirLinearMapEntryT(kT, vT);
221
+ const mapType = new TirLinearMapT(kT, vT);
222
+ const mapReturnT = new TirTypeParam("T");
211
223
  return [
224
+ { name: "length", type: new TirFuncT([], int_t), kind: "method" },
225
+ { name: "isEmpty", type: new TirFuncT([], bool_t), kind: "method" },
226
+ { name: "show", type: new TirFuncT([], bytes_t), kind: "method" },
227
+ { name: "head", type: new TirFuncT([], entryType), kind: "method" },
228
+ { name: "tail", type: new TirFuncT([], mapType), kind: "method" },
229
+ { name: "reverse", type: new TirFuncT([], mapType), kind: "method" },
230
+ { name: "find", type: new TirFuncT([new TirFuncT([entryType], bool_t)], new TirSopOptT(entryType)), kind: "method" },
231
+ { name: "filter", type: new TirFuncT([new TirFuncT([entryType], bool_t)], mapType), kind: "method" },
232
+ { name: "prepend", type: new TirFuncT([kT, vT], mapType), kind: "method" },
233
+ { name: "map", type: new TirFuncT([new TirFuncT([entryType], mapReturnT)], new TirListT(mapReturnT)), kind: "method" },
234
+ { name: "every", type: new TirFuncT([new TirFuncT([entryType], bool_t)], bool_t), kind: "method" },
235
+ { name: "some", type: new TirFuncT([new TirFuncT([entryType], bool_t)], bool_t), kind: "method" },
236
+ { name: "includes", type: new TirFuncT([entryType], bool_t), kind: "method" },
212
237
  { name: "lookup", type: new TirFuncT([kT], new TirSopOptT(vT)), kind: "method" },
213
238
  ];
214
239
  }
@@ -23,7 +23,11 @@ import { TirNamedDeconstructVarDecl } from "../../tir/statements/TirVarDecl/TirN
23
23
  import { TirSimpleVarDecl } from "../../tir/statements/TirVarDecl/TirSimpleVarDecl.js";
24
24
  import { TirSingleDeconstructVarDecl } from "../../tir/statements/TirVarDecl/TirSingleDeconstructVarDecl.js";
25
25
  import { TirWhileStmt } from "../../tir/statements/TirWhileStmt.js";
26
+ import { TirFromDataExpr } from "../../tir/expressions/TirFromDataExpr.js";
27
+ import { data_t } from "../../tir/program/stdScope/stdScope.js";
28
+ import { TirLinearMapEntryT } from "../../tir/types/TirNativeType/native/linearMapEntry.js";
26
29
  import { TirDataStructType, TirSoPStructType } from "../../tir/types/TirStructType.js";
30
+ import { getUnaliased } from "../../tir/types/utils/getUnaliased.js";
27
31
  import { ExpressifyCtx } from "./ExpressifyCtx.js";
28
32
  import { expressifyVarAssignmentStmt } from "./expressifyVarAssignmentStmt.js";
29
33
  import { isSingleConstrStruct } from "./isSingleConstrStruct.js";
@@ -130,7 +134,23 @@ loopReplacements, assertions = []) {
130
134
  stmt.initExpr = initExpr;
131
135
  const lettedName = getUniqueInternalName(stmt.type.toString().toLowerCase());
132
136
  const lettedExpr = ctx.introduceLettedConstant(lettedName, initExpr, stmt.range);
133
- if (stmt.type instanceof TirSoPStructType) {
137
+ const stmtUnaliasedType = getUnaliased(stmt.type);
138
+ if (stmtUnaliasedType instanceof TirLinearMapEntryT) {
139
+ // LinearMapEntry<K,V> is Pair<Data,Data> at runtime
140
+ // extract fields via fstPair/sndPair + _inlineFromData
141
+ for (const [fieldName, varDecl] of stmt.fields) {
142
+ if (!(varDecl instanceof TirSimpleVarDecl))
143
+ throw new Error("expected simple var decl in entry deconstruction");
144
+ const isKey = fieldName === "key";
145
+ const fieldType = isKey ? stmtUnaliasedType.keyTypeArg : stmtUnaliasedType.valTypeArg;
146
+ const pairAccessor = isKey ? TirNativeFunc.fstPairData : TirNativeFunc.sndPairData;
147
+ const fieldLettedName = getUniqueInternalName(`${lettedExpr.varName}_${fieldName}`);
148
+ const lettedField = ctx.introduceLettedConstant(fieldLettedName, expressifyVars(ctx, new TirFromDataExpr(new TirCallExpr(pairAccessor, [lettedExpr], data_t, stmt.range), fieldType, stmt.range)), stmt.range);
149
+ ctx.setNewVariableName(varDecl.name, lettedField.varName);
150
+ }
151
+ continue;
152
+ }
153
+ else if (stmtUnaliasedType instanceof TirSoPStructType) {
134
154
  const nestedDeconstructs = flattenSopNamedDeconstructInplace_addTopDestructToCtx_getNestedDeconstruct(stmt, ctx);
135
155
  // nested single constr structs
136
156
  // are added as destructed variables in the matcher body
@@ -36,15 +36,18 @@ import { TirUnaryMinus } from "../../tir/expressions/unary/TirUnaryMinus.js";
36
36
  import { TirUnaryPlus } from "../../tir/expressions/unary/TirUnaryPlus.js";
37
37
  import { isTirUnaryPrefixExpr } from "../../tir/expressions/unary/TirUnaryPrefixExpr.js";
38
38
  import { TirUnaryTilde } from "../../tir/expressions/unary/TirUnaryTilde.js";
39
- import { bool_t, bytes_t, int_t, valueAmountOfName } from "../../tir/program/stdScope/stdScope.js";
39
+ import { bool_t, bytes_t, data_t, int_t, valueAmountOfName } from "../../tir/program/stdScope/stdScope.js";
40
40
  import { IRNativeTag } from "../../../IR/IRNodes/IRNative/IRNativeTag.js";
41
41
  import { TirReturnStmt } from "../../tir/statements/TirReturnStmt.js";
42
42
  import { TirArrayLikeDeconstr } from "../../tir/statements/TirVarDecl/TirArrayLikeDeconstr.js";
43
43
  import { TirNamedDeconstructVarDecl } from "../../tir/statements/TirVarDecl/TirNamedDeconstructVarDecl.js";
44
44
  import { TirSimpleVarDecl } from "../../tir/statements/TirVarDecl/TirSimpleVarDecl.js";
45
45
  import { TirAliasType } from "../../tir/types/TirAliasType.js";
46
+ import { TirBytesT } from "../../tir/types/TirNativeType/native/bytes.js";
47
+ import { TirStringT } from "../../tir/types/TirNativeType/native/string.js";
46
48
  import { TirFuncT, TirListT, TirPairDataT } from "../../tir/types/TirNativeType/index.js";
47
49
  import { TirLinearMapT } from "../../tir/types/TirNativeType/native/linearMap.js";
50
+ import { TirLinearMapEntryT } from "../../tir/types/TirNativeType/native/linearMapEntry.js";
48
51
  import { TirDataStructType, TirSoPStructType } from "../../tir/types/TirStructType.js";
49
52
  import { getListTypeArg } from "../../tir/types/utils/getListTypeArg.js";
50
53
  import { getUnaliased } from "../../tir/types/utils/getUnaliased.js";
@@ -331,6 +334,18 @@ function expressifyPropAccess(ctx, propAccessExpr) {
331
334
  // we extract the property inplace below (outside this block)
332
335
  }
333
336
  const objType = getUnaliased(expr.type);
337
+ if (objType instanceof TirLinearMapEntryT) {
338
+ // LinearMapEntry<K,V> is Pair<Data,Data> at runtime
339
+ // .key => fstPair(expr) then decode from data to K
340
+ // .value => sndPair(expr) then decode from data to V
341
+ if (prop === "key") {
342
+ return new TirFromDataExpr(new TirCallExpr(TirNativeFunc.fstPairData, [expr], data_t, propAccessExpr.range), objType.keyTypeArg, propAccessExpr.range);
343
+ }
344
+ if (prop === "value") {
345
+ return new TirFromDataExpr(new TirCallExpr(TirNativeFunc.sndPairData, [expr], data_t, propAccessExpr.range), objType.valTypeArg, propAccessExpr.range);
346
+ }
347
+ throw new Error(`Property '${prop}' does not exist on LinearMapEntry`);
348
+ }
334
349
  if (!isSingleConstrStruct(objType)) {
335
350
  // IMPORTANT: we only care about fields here
336
351
  // any methods should have already been converted to functions
@@ -443,12 +458,33 @@ function expressifyMethodCall(ctx, methodCall) {
443
458
  throw new Error(`Method 'lookup' of type 'LinearMap' takes 1 argument, ${methodCall.args.length} provided`);
444
459
  return new TirCallExpr(TirNativeFunc._lookupLinearMap(objectType.keyTypeArg, objectType.valTypeArg), [methodCall.args[0], objectExpr], methodCall.type, exprRange);
445
460
  }
461
+ if (methodName === "prepend") {
462
+ if (methodCall.args.length !== 2)
463
+ throw new Error(`Method 'prepend' of type 'LinearMap' takes 2 arguments (key, value), ${methodCall.args.length} provided`);
464
+ // encode key and value to data, construct a Pair<Data,Data>, then mkCons
465
+ const keyToData = new TirToDataExpr(methodCall.args[0], methodCall.args[0].range);
466
+ const valToData = new TirToDataExpr(methodCall.args[1], methodCall.args[1].range);
467
+ const mkPair = new TirCallExpr(new TirNativeFunc(IRNativeTag.mkPairData, new TirFuncT([data_t, data_t], new TirPairDataT())), [keyToData, valToData], new TirPairDataT(), exprRange);
468
+ return new TirCallExpr(TirNativeFunc.mkCons(new TirPairDataT()), [mkPair, objectExpr], methodCall.type, exprRange);
469
+ }
446
470
  // LinearMap is List<PairData> at UPLC level; delegate list methods
447
471
  const listType = new TirListT(new TirPairDataT());
448
472
  const result = expressifyListMethodCall(ctx, objectExpr, methodCall, methodName, listType, exprRange);
449
473
  if (result)
450
474
  return result;
451
475
  }
476
+ if (objectType instanceof TirBytesT || objectType instanceof TirStringT) {
477
+ const exprRange = SourceRange.join(methodIdentifierProp.range, methodCall.range.atEnd());
478
+ if (methodName === "length") {
479
+ return new TirCallExpr(TirNativeFunc.lengthOfByteString, [objectExpr], int_t, exprRange);
480
+ }
481
+ if (methodName === "subByteString" || methodName === "slice") {
482
+ return new TirCallExpr(TirNativeFunc.sliceByteString, [methodCall.args[0], methodCall.args[1], objectExpr], bytes_t, exprRange);
483
+ }
484
+ if (methodName === "prepend") {
485
+ return new TirCallExpr(TirNativeFunc.consByteString, [methodCall.args[0], objectExpr], bytes_t, exprRange);
486
+ }
487
+ }
452
488
  throw new Error(`not implemented::expressifyMethodCall for type '${objectType.toString()}' (method name: '${methodName}')`);
453
489
  // const tsEnsureExhautstiveCheck: never = objectType;
454
490
  throw new Error(`Cannot call method '${methodName}' on non-struct type '${objectType.toString()}'`);
@@ -1,11 +1,18 @@
1
1
  import { TirNamedDeconstructVarDecl } from "../../tir/statements/TirVarDecl/TirNamedDeconstructVarDecl.js";
2
2
  import { TirSingleDeconstructVarDecl } from "../../tir/statements/TirVarDecl/TirSingleDeconstructVarDecl.js";
3
+ import { TirLinearMapEntryT } from "../../tir/types/TirNativeType/native/linearMapEntry.js";
4
+ import { getUnaliased } from "../../tir/types/utils/getUnaliased.js";
3
5
  import { isSingleConstrStruct } from "./isSingleConstrStruct.js";
4
6
  export function toNamedDeconstructVarDecl(varDecl) {
5
7
  if (varDecl instanceof TirNamedDeconstructVarDecl)
6
8
  return varDecl;
7
9
  if (varDecl instanceof TirSingleDeconstructVarDecl) {
8
10
  const declType = varDecl.type;
11
+ // LinearMapEntry<K,V> uses virtual "Entry" constructor name
12
+ const unaliased = getUnaliased(declType);
13
+ if (unaliased instanceof TirLinearMapEntryT) {
14
+ return new TirNamedDeconstructVarDecl("Entry", varDecl.fields, varDecl.rest, varDecl.type, varDecl.initExpr, varDecl.isConst, varDecl.range);
15
+ }
9
16
  if (!isSingleConstrStruct(declType))
10
17
  throw new Error("expected single constr struct type in single deconstruct var decl");
11
18
  const singleConstrName = declType.constructors[0].name;
@@ -13,6 +13,7 @@ import { TirBytesT } from "../types/TirNativeType/native/bytes.js";
13
13
  import { TirDataT } from "../types/TirNativeType/native/data.js";
14
14
  import { TirIntT } from "../types/TirNativeType/native/int.js";
15
15
  import { TirLinearMapT } from "../types/TirNativeType/native/linearMap.js";
16
+ import { TirLinearMapEntryT } from "../types/TirNativeType/native/linearMapEntry.js";
16
17
  import { TirListT } from "../types/TirNativeType/native/list.js";
17
18
  import { TirDataOptT } from "../types/TirNativeType/native/Optional/data.js";
18
19
  import { TirSopOptT } from "../types/TirNativeType/native/Optional/sop.js";
@@ -64,6 +65,9 @@ export function _inlineFromData(target_t, dataExprIR) {
64
65
  // linear maps only have pairs as elements
65
66
  // and we only support pairs of data (bc we only have `mkPairData`)
66
67
  IRNative.unMapData, dataExprIR);
68
+ // LinearMapEntry is Pair<Data,Data> at runtime — no conversion needed
69
+ if (to_t instanceof TirLinearMapEntryT)
70
+ return dataExprIR;
67
71
  if (to_t instanceof TirListT) {
68
72
  const elems_t = getUnaliased(getListTypeArg(to_t));
69
73
  const listOfDataExpr = _ir_apps(IRNative.unListData, dataExprIR);
@@ -99,6 +99,8 @@ export declare class TirNativeFunc implements ITirExpr {
99
99
  static get _gtEqBS(): TirNativeFunc;
100
100
  static get _gtInt(): TirNativeFunc;
101
101
  static get _gtEqInt(): TirNativeFunc;
102
+ static get fstPairData(): TirNativeFunc;
103
+ static get sndPairData(): TirNativeFunc;
102
104
  static get _pairDataToData(): TirNativeFunc;
103
105
  static get _pairDataFromData(): TirNativeFunc;
104
106
  static _mkEqualsList(elemT: TirType): TirNativeFunc;
@@ -5,6 +5,7 @@ import { bool_t, bytes_t, data_t, int_t, void_t } from "../program/stdScope/stdS
5
5
  import { TirUnConstrDataResultT, TirPairDataT, TirIntT, TirBytesT, TirDataT, TirBoolT, TirSopOptT } from "../types/TirNativeType/index.js";
6
6
  import { TirFuncT } from "../types/TirNativeType/native/function.js";
7
7
  import { TirLinearMapT } from "../types/TirNativeType/native/linearMap.js";
8
+ import { TirLinearMapEntryT } from "../types/TirNativeType/native/linearMapEntry.js";
8
9
  import { TirListT } from "../types/TirNativeType/native/list.js";
9
10
  import { TirDataOptT } from "../types/TirNativeType/native/Optional/data.js";
10
11
  import { TirDataStructType } from "../types/TirStructType.js";
@@ -783,6 +784,12 @@ export class TirNativeFunc {
783
784
  int_t
784
785
  ], bool_t));
785
786
  }
787
+ static get fstPairData() {
788
+ return new TirNativeFunc(IRNativeTag.fstPair, new TirFuncT([new TirPairDataT()], data_t));
789
+ }
790
+ static get sndPairData() {
791
+ return new TirNativeFunc(IRNativeTag.sndPair, new TirFuncT([new TirPairDataT()], data_t));
792
+ }
786
793
  static get _pairDataToData() {
787
794
  return new TirNativeFunc(IRNativeTag._pairDataToData, new TirFuncT([
788
795
  // pair
@@ -832,6 +839,8 @@ export class TirNativeFunc {
832
839
  return this.equalsByteString;
833
840
  if (t instanceof TirPairDataT)
834
841
  return this._equalPairData;
842
+ if (t instanceof TirLinearMapEntryT)
843
+ return this._equalPairData;
835
844
  if (t instanceof TirBoolT)
836
845
  return this._equalBoolean;
837
846
  if (t instanceof TirDataT
@@ -6,6 +6,7 @@ import { TirDataT } from "./native/data.js";
6
6
  import { TirFuncT } from "./native/function.js";
7
7
  import { TirIntT } from "./native/int.js";
8
8
  import { TirLinearMapT } from "./native/linearMap.js";
9
+ import { TirLinearMapEntryT } from "./native/linearMapEntry.js";
9
10
  import { TirListT } from "./native/list.js";
10
11
  import { TirDataOptT } from "./native/Optional/data.js";
11
12
  import { TirSopOptT } from "./native/Optional/sop.js";
@@ -13,7 +14,7 @@ import { TirStringT } from "./native/string.js";
13
14
  import { TirVoidT } from "./native/void.js";
14
15
  export type TirNamedDestructableNativeType = TirDataT | TirDataOptT<TirType> | TirSopOptT<TirType> | TirListT<TirType> | TirLinearMapT<TirType, TirType>;
15
16
  export declare function isTirNamedDestructableNativeType(t: any): t is TirNamedDestructableNativeType;
16
- export type TirNativeType = TirVoidT | TirBoolT | TirIntT | TirBytesT | TirStringT | TirDataT | TirDataOptT<TirType> | TirSopOptT<TirType> | TirListT<TirType> | TirLinearMapT<TirType, TirType> | TirFuncT | TirUnConstrDataResultT | TirPairDataT;
17
+ export type TirNativeType = TirVoidT | TirBoolT | TirIntT | TirBytesT | TirStringT | TirDataT | TirDataOptT<TirType> | TirSopOptT<TirType> | TirListT<TirType> | TirLinearMapT<TirType, TirType> | TirLinearMapEntryT<TirType, TirType> | TirFuncT | TirUnConstrDataResultT | TirPairDataT;
17
18
  export declare function isTirNativeType(t: any): t is TirNativeType;
18
19
  export declare class TirUnConstrDataResultT implements ITirType {
19
20
  constructor();
@@ -5,6 +5,7 @@ import { TirDataT } from "./native/data.js";
5
5
  import { TirFuncT } from "./native/function.js";
6
6
  import { TirIntT } from "./native/int.js";
7
7
  import { TirLinearMapT } from "./native/linearMap.js";
8
+ import { TirLinearMapEntryT } from "./native/linearMapEntry.js";
8
9
  import { TirListT } from "./native/list.js";
9
10
  import { TirDataOptT } from "./native/Optional/data.js";
10
11
  import { TirSopOptT } from "./native/Optional/sop.js";
@@ -28,6 +29,7 @@ export function isTirNativeType(t) {
28
29
  || t instanceof TirSopOptT
29
30
  || t instanceof TirListT
30
31
  || t instanceof TirLinearMapT
32
+ || t instanceof TirLinearMapEntryT
31
33
  || t instanceof TirFuncT // =>
32
34
  || t instanceof TirUnConstrDataResultT
33
35
  || t instanceof TirPairDataT);
@@ -5,6 +5,7 @@ export * from "./data.js";
5
5
  export * from "./function.js";
6
6
  export * from "./int.js";
7
7
  export * from "./linearMap.js";
8
+ export * from "./linearMapEntry.js";
8
9
  export * from "./list.js";
9
10
  export * from "./string.js";
10
11
  export * from "./void.js";
@@ -5,6 +5,7 @@ export * from "./data.js";
5
5
  export * from "./function.js";
6
6
  export * from "./int.js";
7
7
  export * from "./linearMap.js";
8
+ export * from "./linearMapEntry.js";
8
9
  export * from "./list.js";
9
10
  export * from "./string.js";
10
11
  export * from "./void.js";
@@ -0,0 +1,17 @@
1
+ import { ConstType } from "@harmoniclabs/uplc";
2
+ import { TirType, ITirType } from "../../TirType.js";
3
+ export declare class TirLinearMapEntryT<K extends TirType = TirType, V extends TirType = TirType> implements ITirType {
4
+ readonly keyTypeArg: K;
5
+ readonly valTypeArg: V;
6
+ constructor(keyTypeArg: K, valTypeArg: V);
7
+ hasDataEncoding(): boolean;
8
+ static toTirTypeKey(): string;
9
+ toTirTypeKey(): string;
10
+ toAstName(): string;
11
+ toConcreteTirTypeName(): string;
12
+ toString(): string;
13
+ private _isConcrete;
14
+ isConcrete(): boolean;
15
+ clone(): TirLinearMapEntryT<K, V>;
16
+ toUplcConstType(): ConstType;
17
+ }
@@ -0,0 +1,44 @@
1
+ import { constT } from "@harmoniclabs/uplc";
2
+ import { getAppliedTirTypeName } from "../../../program/TypedProgram.js";
3
+ export class TirLinearMapEntryT {
4
+ keyTypeArg;
5
+ valTypeArg;
6
+ constructor(keyTypeArg, valTypeArg) {
7
+ this.keyTypeArg = keyTypeArg;
8
+ this.valTypeArg = valTypeArg;
9
+ }
10
+ hasDataEncoding() { return false; }
11
+ static toTirTypeKey() {
12
+ return "linear_map_entry";
13
+ }
14
+ toTirTypeKey() {
15
+ return TirLinearMapEntryT.toTirTypeKey();
16
+ }
17
+ toAstName() {
18
+ return this.toTirTypeKey();
19
+ }
20
+ toConcreteTirTypeName() {
21
+ return getAppliedTirTypeName(this.toTirTypeKey(), [
22
+ this.keyTypeArg.toConcreteTirTypeName(),
23
+ this.valTypeArg.toConcreteTirTypeName()
24
+ ]);
25
+ }
26
+ toString() {
27
+ return `${this.toTirTypeKey()}<${this.keyTypeArg.toString()},${this.valTypeArg.toString()}>`;
28
+ }
29
+ _isConcrete = undefined;
30
+ isConcrete() {
31
+ if (typeof this._isConcrete !== "boolean")
32
+ this._isConcrete = (this.keyTypeArg.isConcrete()
33
+ && this.valTypeArg.isConcrete());
34
+ return this._isConcrete ?? false;
35
+ }
36
+ clone() {
37
+ const result = new TirLinearMapEntryT(this.keyTypeArg.clone(), this.valTypeArg.clone());
38
+ result._isConcrete = this._isConcrete;
39
+ return result;
40
+ }
41
+ toUplcConstType() {
42
+ return constT.pairOf(constT.data, constT.data);
43
+ }
44
+ }
@@ -6,6 +6,7 @@ import { TirDataT } from "../TirNativeType/native/data.js";
6
6
  import { TirFuncT } from "../TirNativeType/native/function.js";
7
7
  import { TirIntT } from "../TirNativeType/native/int.js";
8
8
  import { TirLinearMapT } from "../TirNativeType/native/linearMap.js";
9
+ import { TirLinearMapEntryT } from "../TirNativeType/native/linearMapEntry.js";
9
10
  import { TirListT } from "../TirNativeType/native/list.js";
10
11
  import { TirDataOptT } from "../TirNativeType/native/Optional/data.js";
11
12
  import { TirSopOptT } from "../TirNativeType/native/Optional/sop.js";
@@ -181,6 +182,12 @@ function uncheckedGetCanAssign(a, b, symbols) {
181
182
  return CanAssign.RequiresExplicitCast;
182
183
  return CanAssign.No;
183
184
  }
185
+ if (b instanceof TirLinearMapEntryT) {
186
+ if (a instanceof TirLinearMapEntryT) {
187
+ return decideCanAssignField(uncheckedGetCanAssign(a.keyTypeArg, b.keyTypeArg, symbols), uncheckedGetCanAssign(a.valTypeArg, b.valTypeArg, symbols));
188
+ }
189
+ return CanAssign.No;
190
+ }
184
191
  if (b instanceof TirDataT) {
185
192
  if (a instanceof TirDataT)
186
193
  return CanAssign.Yes;
@@ -5,6 +5,7 @@ import { TirDataT } from "../TirNativeType/native/data.js";
5
5
  import { TirFuncT } from "../TirNativeType/native/function.js";
6
6
  import { TirIntT } from "../TirNativeType/native/int.js";
7
7
  import { TirLinearMapT } from "../TirNativeType/native/linearMap.js";
8
+ import { TirLinearMapEntryT } from "../TirNativeType/native/linearMapEntry.js";
8
9
  import { TirListT } from "../TirNativeType/native/list.js";
9
10
  import { TirDataOptT } from "../TirNativeType/native/Optional/data.js";
10
11
  import { TirSopOptT } from "../TirNativeType/native/Optional/sop.js";
@@ -66,10 +67,8 @@ export function canCastTo(a, b) {
66
67
  return true;
67
68
  if (a instanceof TirStringT)
68
69
  return true; // string -> bytes // decode utf8
69
- // how do we handle this?
70
- // in theory we can encode but only fixed size
71
- // we have no idea of the size of ints
72
- // if( a instanceof TirIntT ) return true;
70
+ if (a instanceof TirIntT)
71
+ return true; // int -> bytes // big endian encoding
73
72
  return false;
74
73
  }
75
74
  if (b instanceof TirStringT) {
@@ -107,6 +106,13 @@ export function canCastTo(a, b) {
107
106
  && canCastToData(b.valTypeArg));
108
107
  return false;
109
108
  }
109
+ if (b instanceof TirLinearMapEntryT) {
110
+ if (a instanceof TirLinearMapEntryT) {
111
+ return (canCastTo(a.keyTypeArg, b.keyTypeArg)
112
+ && canCastTo(a.valTypeArg, b.valTypeArg));
113
+ }
114
+ return false;
115
+ }
110
116
  if (b instanceof TirFuncT) {
111
117
  if (!(a instanceof TirFuncT))
112
118
  return false;
@@ -1,2 +1,3 @@
1
1
  import { TirType } from "../TirType.js";
2
2
  export declare function getListTypeArg(list_t: TirType): TirType | undefined;
3
+ export declare function getLinearMapTypeArgs(map_t: TirType): [key: TirType, value: TirType] | undefined;
@@ -1,9 +1,20 @@
1
1
  import { TirAliasType } from "../TirAliasType.js";
2
+ import { TirLinearMapT } from "../TirNativeType/native/linearMap.js";
3
+ import { TirLinearMapEntryT } from "../TirNativeType/native/linearMapEntry.js";
2
4
  import { TirListT } from "../TirNativeType/native/list.js";
3
5
  export function getListTypeArg(list_t) {
4
6
  while (list_t instanceof TirAliasType)
5
7
  list_t = list_t.aliased;
6
8
  if (list_t instanceof TirListT)
7
9
  return list_t.typeArg;
10
+ if (list_t instanceof TirLinearMapT)
11
+ return new TirLinearMapEntryT(list_t.keyTypeArg, list_t.valTypeArg);
12
+ return undefined;
13
+ }
14
+ export function getLinearMapTypeArgs(map_t) {
15
+ while (map_t instanceof TirAliasType)
16
+ map_t = map_t.aliased;
17
+ if (map_t instanceof TirLinearMapT)
18
+ return [map_t.keyTypeArg, map_t.valTypeArg];
8
19
  return undefined;
9
20
  }
@@ -2409,6 +2409,30 @@ export class Parser extends DiagnosticEmitter {
2409
2409
  tn.reset(tnState);
2410
2410
  return true;
2411
2411
  }
2412
+ // possibly a destructured parameter
2413
+ // ( { field, ... } ) => ...
2414
+ // or a parenthesized object expression
2415
+ // ( { a: 1, b: 2 } )
2416
+ case Token.OpenBrace: {
2417
+ // skip past the balanced braces
2418
+ this.skipBlock(tn);
2419
+ // check what follows the `}`
2420
+ const afterBrace = tn.next();
2421
+ if (afterBrace === Token.CloseParen) {
2422
+ // ( { ... } ) — check for `=>`
2423
+ const isArrow = tn.skip(Token.FatArrow);
2424
+ tn.reset(tnState);
2425
+ return isArrow;
2426
+ }
2427
+ if (afterBrace === Token.Comma) {
2428
+ // ( { ... }, ... ) — multiple params, must be arrow func
2429
+ tn.reset(tnState);
2430
+ return true;
2431
+ }
2432
+ // anything else — parenthesized expression
2433
+ tn.reset(tnState);
2434
+ return false;
2435
+ }
2412
2436
  // can be both parenthesized expression or function parameter
2413
2437
  // ( Identifier...
2414
2438
  case Token.Identifier: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harmoniclabs/pebble",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
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",