@harmoniclabs/pebble 0.1.4-dev0 → 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.
@@ -122,11 +122,11 @@ 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(1, [new IRVar(findSop_head)]), // Some{ head }
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
131
  // hoisted _lookupLinearMap
132
132
  // (key: data) -> (map: list<pair<data,data>>) -> SopOptional<data>
@@ -138,13 +138,13 @@ export const hoisted_lookupLinearMap = new IRHoisted(new IRFunc([lookup_key], ne
138
138
  // case nil => None
139
139
  new IRConstr(1, []),
140
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)),
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
142
  // then => Some(sndPair(head))
143
- new IRConstr(1, [
143
+ new IRConstr(0, [
144
144
  _ir_apps(IRNative.sndPair, new IRVar(lookup_head))
145
145
  ]),
146
146
  // else => self(tailList(map))
147
- _ir_apps(new IRSelfCall(lookup_self), _ir_apps(IRNative.tailList, new IRVar(lookup_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
148
  hoisted_lookupLinearMap.hash;
149
149
  // hoisted _mkFindDataOptional
150
150
  const mkFind_elemToData = Symbol("elemToData");
@@ -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
- new IRFunc([someBranchVarSym], someBranchIR),
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 new IRForced(_ir_let(_ir_apps(IRNative.unConstrData, this.matchExpr.toIR(ctx)), unConstrMatchSym => _ir_lazyIfThenElse(
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();
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harmoniclabs/pebble",
3
- "version": "0.1.4-dev0",
3
+ "version": "0.1.4-dev1",
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",