@harmoniclabs/pebble 0.1.3-dev8 → 0.1.3
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/IRHoisted.d.ts +1 -0
- package/dist/IR/IRNodes/IRHoisted.js +3 -0
- package/dist/IR/IRNodes/IRLetted.d.ts +1 -0
- package/dist/IR/IRNodes/IRLetted.js +3 -0
- package/dist/IR/IRNodes/utils/hashVarSym.d.ts +1 -0
- package/dist/IR/IRNodes/utils/hashVarSym.js +5 -0
- package/dist/IR/toUPLC/subRoutines/replaceHoistedWithLetted.d.ts +1 -0
- package/dist/IR/toUPLC/subRoutines/replaceHoistedWithLetted.js +3 -0
- package/dist/compiler/AstCompiler/AstCompilationCtx.d.ts +3 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compileFuncExpr.js +72 -3
- package/dist/compiler/AstCompiler/internal/statements/_compileReturnStmt.js +3 -2
- package/dist/compiler/Compiler.js +10 -0
- package/dist/compiler/TirCompiler/expressify/expressifyVars.d.ts +1 -0
- package/dist/compiler/TirCompiler/expressify/expressifyVars.js +3 -0
- package/dist/compiler/tir/expressions/TirTraceExpr.js +8 -3
- 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;
|
|
@@ -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
|
|
@@ -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();
|
|
@@ -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())
|
|
72
|
-
if (!(expectedFuncType instanceof TirFuncT))
|
|
73
|
-
return
|
|
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 = [];
|
|
@@ -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
|
}
|
|
@@ -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
|
}
|
|
@@ -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
|
-
|
|
50
|
-
//
|
|
51
|
-
|
|
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
|
}
|
package/package.json
CHANGED