@harmoniclabs/pebble 0.3.0 → 0.3.1

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.
@@ -1,3 +1,4 @@
1
+ import { FuncExpr } from "../../../../ast/nodes/expr/functions/FuncExpr.js";
1
2
  import { DiagnosticCode } from "../../../../diagnostics/diagnosticMessages.generated.js";
2
3
  import { TirCallExpr } from "../../../tir/expressions/TirCallExpr.js";
3
4
  import { TirFuncT } from "../../../tir/types/TirNativeType/native/function.js";
@@ -48,15 +49,62 @@ export function _compileCallExpr(ctx, expr, typeHint) {
48
49
  }
49
50
  // 2) Compile arguments. We need them anyway, and they're used for
50
51
  // inference when no explicit args were given.
51
- const tirArgs = expr.args.map((arg, i) => {
52
- const expected = explicitArgs
53
- ? substituteTypeParams(funcType.argTypes[i], new Map(template.typeParams.map((tp, idx) => [tp.symbol, explicitArgs[idx]])))
54
- : undefined;
55
- return _compileExpr(ctx, arg, expected);
56
- });
57
- for (const a of tirArgs)
58
- if (!a)
59
- return undefined;
52
+ //
53
+ // For inferred-type-args calls, lambda arguments cannot be compiled
54
+ // without an expected function type (their param types would be
55
+ // unannotated). So we compile non-lambda args first, build an
56
+ // inference environment from them, then compile lambda args with
57
+ // the substituted expected type from `funcType.argTypes[i]`.
58
+ const tirArgs = new Array(expr.args.length);
59
+ const usable = Math.min(expr.args.length, funcType.argTypes.length);
60
+ if (explicitArgs) {
61
+ const explicitSubst = new Map(template.typeParams.map((tp, idx) => [tp.symbol, explicitArgs[idx]]));
62
+ for (let i = 0; i < expr.args.length; i++) {
63
+ const expected = i < funcType.argTypes.length
64
+ ? substituteTypeParams(funcType.argTypes[i], explicitSubst)
65
+ : undefined;
66
+ const compiled = _compileExpr(ctx, expr.args[i], expected);
67
+ if (!compiled)
68
+ return undefined;
69
+ tirArgs[i] = compiled;
70
+ }
71
+ }
72
+ else {
73
+ const env = new Map();
74
+ // Pass 1: compile non-FuncExpr args (no type hint needed) and
75
+ // populate `env` from each arg's resolved type.
76
+ for (let i = 0; i < expr.args.length; i++) {
77
+ if (expr.args[i] instanceof FuncExpr)
78
+ continue;
79
+ const compiled = _compileExpr(ctx, expr.args[i], undefined);
80
+ if (!compiled)
81
+ return undefined;
82
+ tirArgs[i] = compiled;
83
+ if (i < usable) {
84
+ if (!inferTypeArgs(funcType.argTypes[i], compiled.type, env))
85
+ return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.args[i].range, compiled.type.toString(), funcType.argTypes[i].toString());
86
+ }
87
+ }
88
+ // Pass 2: compile FuncExpr args with the substituted expected
89
+ // type so lambda param types can be inferred from context.
90
+ for (let i = 0; i < expr.args.length; i++) {
91
+ if (!(expr.args[i] instanceof FuncExpr))
92
+ continue;
93
+ const expected = i < funcType.argTypes.length
94
+ ? substituteTypeParams(funcType.argTypes[i], env)
95
+ : undefined;
96
+ const compiled = _compileExpr(ctx, expr.args[i], expected);
97
+ if (!compiled)
98
+ return undefined;
99
+ tirArgs[i] = compiled;
100
+ if (i < usable) {
101
+ // re-run to capture type params bound only via the
102
+ // lambda's return type (e.g. `map<T, A>(f: (T) -> A, ...)`)
103
+ if (!inferTypeArgs(funcType.argTypes[i], compiled.type, env))
104
+ return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.args[i].range, compiled.type.toString(), funcType.argTypes[i].toString());
105
+ }
106
+ }
107
+ }
60
108
  // 3) Determine final type arguments
61
109
  let resolvedArgs;
62
110
  if (explicitArgs) {
@@ -64,7 +112,6 @@ export function _compileCallExpr(ctx, expr, typeHint) {
64
112
  }
65
113
  else {
66
114
  const env = new Map();
67
- const usable = Math.min(tirArgs.length, funcType.argTypes.length);
68
115
  for (let i = 0; i < usable; i++) {
69
116
  if (!inferTypeArgs(funcType.argTypes[i], tirArgs[i].type, env)) {
70
117
  return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.args[i].range, tirArgs[i].type.toString(), funcType.argTypes[i].toString());
@@ -1 +1 @@
1
- export declare const COMPILER_VERSION = "0.3.0";
1
+ export declare const COMPILER_VERSION = "0.3.1";
@@ -1,2 +1,2 @@
1
1
  // This file is auto-generated by scripts/genVersion.js. Do not edit.
2
- export const COMPILER_VERSION = "0.3.0";
2
+ export const COMPILER_VERSION = "0.3.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harmoniclabs/pebble",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
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",