@helios-lang/contract-utils 0.3.5 → 0.3.7
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/package.json +1 -1
- package/src/artifacts/Artifact.js +14 -0
- package/src/artifacts/ArtifactWriter.js +199 -0
- package/src/artifacts/ChildArtifactWriter.js +118 -0
- package/src/artifacts/FunctionArtifact.js +90 -0
- package/src/artifacts/ModuleArtifact.js +83 -0
- package/src/artifacts/RootArtifact.js +105 -0
- package/src/artifacts/TypeArtifact.js +104 -0
- package/src/artifacts/ValidatorArtifact.js +158 -0
- package/src/artifacts/index.js +1 -0
- package/src/artifacts/symbols.js +16 -0
- package/src/cast/Cast.js +45 -9
- package/src/cast/UserFunc.js +182 -131
- package/src/cast/index.js +12 -3
- package/src/codegen/LoadedScriptsWriter.js +35 -11
- package/src/codegen/TypeSchema.js +126 -0
- package/src/context/index.js +1 -0
- package/src/hl2ts.js +0 -4
- package/src/index.js +36 -8
- package/src/internal.js +12 -0
- package/types/artifacts/Artifact.d.ts +11 -0
- package/types/artifacts/Artifact.d.ts.map +1 -0
- package/types/artifacts/ArtifactWriter.d.ts +64 -0
- package/types/artifacts/ArtifactWriter.d.ts.map +1 -0
- package/types/artifacts/ChildArtifactWriter.d.ts +35 -0
- package/types/artifacts/ChildArtifactWriter.d.ts.map +1 -0
- package/types/artifacts/FunctionArtifact.d.ts +14 -0
- package/types/artifacts/FunctionArtifact.d.ts.map +1 -0
- package/types/artifacts/ModuleArtifact.d.ts +29 -0
- package/types/artifacts/ModuleArtifact.d.ts.map +1 -0
- package/types/artifacts/RootArtifact.d.ts +11 -0
- package/types/artifacts/RootArtifact.d.ts.map +1 -0
- package/types/artifacts/TypeArtifact.d.ts +17 -0
- package/types/artifacts/TypeArtifact.d.ts.map +1 -0
- package/types/artifacts/ValidatorArtifact.d.ts +17 -0
- package/types/artifacts/ValidatorArtifact.d.ts.map +1 -0
- package/types/artifacts/index.d.ts +2 -0
- package/types/artifacts/index.d.ts.map +1 -0
- package/types/artifacts/symbols.d.ts +8 -0
- package/types/artifacts/symbols.d.ts.map +1 -0
- package/types/cast/Cast.d.ts +31 -0
- package/types/cast/Cast.d.ts.map +1 -1
- package/types/cast/UserFunc.d.ts +39 -0
- package/types/cast/UserFunc.d.ts.map +1 -1
- package/types/cast/index.d.ts +2 -2
- package/types/codegen/LoadedScriptsWriter.d.ts +18 -0
- package/types/codegen/LoadedScriptsWriter.d.ts.map +1 -1
- package/types/codegen/TypeSchema.d.ts +5 -0
- package/types/codegen/TypeSchema.d.ts.map +1 -1
- package/types/context/writeContractContextArtifacts.d.ts +30 -0
- package/types/context/writeContractContextArtifacts.d.ts.map +1 -0
- package/types/hl2ts.d.ts.map +1 -1
- package/types/index.d.ts +30 -4
- package/types/index.d.ts.map +1 -1
- package/types/internal.d.ts +5 -0
- package/types/internal.d.ts.map +1 -0
package/src/cast/UserFunc.js
CHANGED
|
@@ -37,7 +37,6 @@ class UserFuncImpl {
|
|
|
37
37
|
uplc
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
-
* @private
|
|
41
40
|
* @readonly
|
|
42
41
|
* @type {UserFuncProps}
|
|
43
42
|
*/
|
|
@@ -65,45 +64,7 @@ class UserFuncImpl {
|
|
|
65
64
|
* @returns {RetT}
|
|
66
65
|
*/
|
|
67
66
|
eval(namedArgs, logOptions = undefined) {
|
|
68
|
-
|
|
69
|
-
* @type {{[argName: string]: any}}
|
|
70
|
-
*/
|
|
71
|
-
const unsafeNamedArgs = {}
|
|
72
|
-
|
|
73
|
-
Object.entries(namedArgs).forEach(([argName, argValue]) => {
|
|
74
|
-
const argDetails = this.props.arguments.find(
|
|
75
|
-
(a) => a.name == argName
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
if (argDetails) {
|
|
79
|
-
const typeSchema = argDetails.type
|
|
80
|
-
|
|
81
|
-
unsafeNamedArgs[argName] = makeCast(
|
|
82
|
-
typeSchema,
|
|
83
|
-
this.props.castConfig
|
|
84
|
-
).toUplcData(argValue)
|
|
85
|
-
} else if (["$currentScript", "$scriptContext"].includes(argName)) {
|
|
86
|
-
unsafeNamedArgs[argName] = argValue
|
|
87
|
-
} else {
|
|
88
|
-
console.error(
|
|
89
|
-
`invalid arg '${argName}' for user function ${this.props.name}`
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
const result = this.evalUnsafe(
|
|
95
|
-
/** @type {UnsafeArgsT<ArgsT>} */ (unsafeNamedArgs),
|
|
96
|
-
logOptions
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
if (this.props.returns) {
|
|
100
|
-
return makeCast(
|
|
101
|
-
this.props.returns,
|
|
102
|
-
this.props.castConfig
|
|
103
|
-
).fromUplcData(expectDefined(/** @type {any} */ (result)))
|
|
104
|
-
} else {
|
|
105
|
-
return /** @type {any} */ (undefined)
|
|
106
|
-
}
|
|
67
|
+
return evalUserFunc(this.uplc, this.props, namedArgs, logOptions)
|
|
107
68
|
}
|
|
108
69
|
|
|
109
70
|
/**
|
|
@@ -112,17 +73,7 @@ class UserFuncImpl {
|
|
|
112
73
|
* @returns {RetT extends void ? void : UplcData}
|
|
113
74
|
*/
|
|
114
75
|
evalUnsafe(namedArgs, logOptions = undefined) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (isLeft(result)) {
|
|
118
|
-
throw new UplcRuntimeError(result.left.error, result.left.callSites)
|
|
119
|
-
} else if (!isString(result.right) && result.right.kind == "data") {
|
|
120
|
-
return /** @type {any} */ (result.right.value)
|
|
121
|
-
} else if (this.props.returns) {
|
|
122
|
-
throw new Error(`${result.right.toString()} isn't a UplcDataValue`)
|
|
123
|
-
} else {
|
|
124
|
-
return /** @type {any} */ (undefined)
|
|
125
|
-
}
|
|
76
|
+
return evalUserFuncUnsafe(this.uplc, this.props, namedArgs, logOptions)
|
|
126
77
|
}
|
|
127
78
|
|
|
128
79
|
/**
|
|
@@ -131,108 +82,208 @@ class UserFuncImpl {
|
|
|
131
82
|
* @returns {CekResult}
|
|
132
83
|
*/
|
|
133
84
|
profile(namedArgs, logOptions = undefined) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
85
|
+
return profileUserFunc(this.uplc, this.props, namedArgs, logOptions)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @template {{[argName: string]: any}} ArgsT
|
|
91
|
+
* @template RetT
|
|
92
|
+
* @param {UplcProgram} program
|
|
93
|
+
* @param {UserFuncProps} props
|
|
94
|
+
* @param {ArgsT} namedArgs
|
|
95
|
+
* @param {UplcLogger | undefined} logOptions
|
|
96
|
+
* @returns {RetT}
|
|
97
|
+
*/
|
|
98
|
+
export function evalUserFunc(
|
|
99
|
+
program,
|
|
100
|
+
props,
|
|
101
|
+
namedArgs,
|
|
102
|
+
logOptions = undefined
|
|
103
|
+
) {
|
|
104
|
+
/**
|
|
105
|
+
* @type {{[argName: string]: any}}
|
|
106
|
+
*/
|
|
107
|
+
const unsafeNamedArgs = {}
|
|
108
|
+
|
|
109
|
+
Object.entries(namedArgs).forEach(([argName, argValue]) => {
|
|
110
|
+
const argDetails = props.arguments.find((a) => a.name == argName)
|
|
111
|
+
|
|
112
|
+
if (argDetails) {
|
|
113
|
+
const typeSchema = argDetails.type
|
|
114
|
+
|
|
115
|
+
unsafeNamedArgs[argName] = makeCast(
|
|
116
|
+
typeSchema,
|
|
117
|
+
props.castConfig
|
|
118
|
+
).toUplcData(argValue)
|
|
119
|
+
} else if (["$currentScript", "$scriptContext"].includes(argName)) {
|
|
120
|
+
unsafeNamedArgs[argName] = argValue
|
|
121
|
+
} else {
|
|
122
|
+
console.error(
|
|
123
|
+
`invalid arg '${argName}' for user function ${props.name}`
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
const result = evalUserFuncUnsafe(
|
|
129
|
+
program,
|
|
130
|
+
props,
|
|
131
|
+
/** @type {UnsafeArgsT<ArgsT>} */ (unsafeNamedArgs),
|
|
132
|
+
logOptions
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
if (props.returns) {
|
|
136
|
+
return makeCast(props.returns, props.castConfig).fromUplcData(
|
|
137
|
+
expectDefined(/** @type {any} */ (result))
|
|
138
|
+
)
|
|
139
|
+
} else {
|
|
140
|
+
return /** @type {any} */ (undefined)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @template {{[argName: string]: any}} ArgsT
|
|
146
|
+
* @template RetT
|
|
147
|
+
* @param {UplcProgram} program
|
|
148
|
+
* @param {UserFuncProps} props
|
|
149
|
+
* @param {UnsafeArgsT<ArgsT>} namedArgs
|
|
150
|
+
* @param {UplcLogger | undefined} logOptions
|
|
151
|
+
* @returns {RetT extends void ? void : UplcData}
|
|
152
|
+
*/
|
|
153
|
+
export function evalUserFuncUnsafe(
|
|
154
|
+
program,
|
|
155
|
+
props,
|
|
156
|
+
namedArgs,
|
|
157
|
+
logOptions = undefined
|
|
158
|
+
) {
|
|
159
|
+
const result = profileUserFunc(program, props, namedArgs, logOptions).result
|
|
160
|
+
|
|
161
|
+
if (isLeft(result)) {
|
|
162
|
+
throw new UplcRuntimeError(result.left.error, result.left.callSites)
|
|
163
|
+
} else if (!isString(result.right) && result.right.kind == "data") {
|
|
164
|
+
return /** @type {any} */ (result.right.value)
|
|
165
|
+
} else if (props.returns) {
|
|
166
|
+
throw new Error(`${result.right.toString()} isn't a UplcDataValue`)
|
|
167
|
+
} else {
|
|
168
|
+
return /** @type {any} */ (undefined)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @template {{[argName: string]: any}} ArgsT
|
|
174
|
+
* @param {UplcProgram} program
|
|
175
|
+
* @param {UserFuncProps} props
|
|
176
|
+
* @param {UnsafeArgsT<ArgsT>} namedArgs
|
|
177
|
+
* @param {UplcLogger | undefined} logOptions - optional, passed to UplcProgram.eval if provided
|
|
178
|
+
* @returns {CekResult}
|
|
179
|
+
*/
|
|
180
|
+
export function profileUserFunc(
|
|
181
|
+
program,
|
|
182
|
+
props,
|
|
183
|
+
namedArgs,
|
|
184
|
+
logOptions = undefined
|
|
185
|
+
) {
|
|
186
|
+
const isMain = props.name == "main"
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @type {UplcData[]}
|
|
190
|
+
*/
|
|
191
|
+
const args = []
|
|
192
|
+
|
|
193
|
+
props.arguments.forEach(({ name, type, isOptional }) => {
|
|
194
|
+
if (isMain) {
|
|
195
|
+
if (isOptional) {
|
|
196
|
+
// used for $datum in mixed script
|
|
197
|
+
if (name in namedArgs && namedArgs[name]) {
|
|
198
|
+
args.push(namedArgs[name])
|
|
150
199
|
}
|
|
151
200
|
} else {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
201
|
+
args.push(expectDefined(namedArgs[name]))
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
if (isOptional) {
|
|
205
|
+
if (name in namedArgs && namedArgs[name]) {
|
|
206
|
+
args.push(makeConstrData(0, [namedArgs[name]]))
|
|
158
207
|
} else {
|
|
159
|
-
args.push(
|
|
208
|
+
args.push(makeConstrData(1, []))
|
|
160
209
|
}
|
|
210
|
+
} else {
|
|
211
|
+
args.push(expectDefined(namedArgs[name]))
|
|
161
212
|
}
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
if (this.props.requiresScriptContext) {
|
|
165
|
-
args.push(expectDefined(namedArgs["$scriptContext"]))
|
|
166
213
|
}
|
|
214
|
+
})
|
|
167
215
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
)
|
|
216
|
+
if (props.requiresScriptContext) {
|
|
217
|
+
args.push(expectDefined(namedArgs["$scriptContext"]))
|
|
218
|
+
}
|
|
172
219
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
)
|
|
220
|
+
if (props.requiresCurrentScript) {
|
|
221
|
+
const currentScriptName = expectDefined(
|
|
222
|
+
/** @type {any} */ (namedArgs)["$currentScript"]
|
|
223
|
+
)
|
|
176
224
|
|
|
177
|
-
|
|
178
|
-
|
|
225
|
+
const index = expectDefined(
|
|
226
|
+
expectDefined(props.validatorIndices)[currentScriptName]
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
args.push(makeConstrData(index, []))
|
|
230
|
+
}
|
|
179
231
|
|
|
180
|
-
|
|
232
|
+
const argValues = args.map((a) => makeUplcDataValue(a))
|
|
181
233
|
|
|
182
|
-
|
|
234
|
+
const cekResult = program.eval(argValues, {
|
|
235
|
+
logOptions: logOptions ?? undefined
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
if (program.alt?.plutusVersion == "PlutusScriptV2") {
|
|
239
|
+
const cekResultUnoptim = program.alt.eval(argValues, {
|
|
183
240
|
logOptions: logOptions ?? undefined
|
|
184
241
|
})
|
|
242
|
+
const resultUnoptim = cekResultUnoptim.result
|
|
243
|
+
const resultUnoptimStr = evalResultToString(resultUnoptim)
|
|
244
|
+
const resultStr = evalResultToString(cekResult.result)
|
|
245
|
+
|
|
246
|
+
if (resultStr != resultUnoptimStr) {
|
|
247
|
+
console.error(
|
|
248
|
+
`## Unoptimized IR:\n${program.alt.ir ?? "not available"}`
|
|
249
|
+
)
|
|
185
250
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
logOptions: logOptions ?? undefined
|
|
251
|
+
args.forEach((a, i) => {
|
|
252
|
+
console.error(`## Arg ${i}: ${bytesToHex(a.toCbor())}`)
|
|
189
253
|
})
|
|
190
|
-
const resultUnoptim = cekResultUnoptim.result
|
|
191
|
-
const resultUnoptimStr = evalResultToString(resultUnoptim)
|
|
192
|
-
const resultStr = evalResultToString(cekResult.result)
|
|
193
|
-
|
|
194
|
-
if (resultStr != resultUnoptimStr) {
|
|
195
|
-
console.error(
|
|
196
|
-
`## Unoptimized IR:\n${this.uplc.alt.ir ?? "not available"}`
|
|
197
|
-
)
|
|
198
|
-
|
|
199
|
-
args.forEach((a, i) => {
|
|
200
|
-
console.error(`## Arg ${i}: ${bytesToHex(a.toCbor())}`)
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
throw new Error(
|
|
204
|
-
`Critical error: expected ${resultUnoptimStr}, but got ${resultStr}. Contact Helios maintainers and share this console output`
|
|
205
|
-
)
|
|
206
|
-
}
|
|
207
254
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
)
|
|
213
|
-
}
|
|
255
|
+
throw new Error(
|
|
256
|
+
`Critical error: expected ${resultUnoptimStr}, but got ${resultStr}. Contact Helios maintainers and share this console output`
|
|
257
|
+
)
|
|
258
|
+
}
|
|
214
259
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
260
|
+
// also make sure the cost is an improvement
|
|
261
|
+
if (cekResult.cost.mem > cekResultUnoptim.cost.mem) {
|
|
262
|
+
throw new Error(
|
|
263
|
+
`Critical error: optimizer worsened memory cost of ${props.name}`
|
|
264
|
+
)
|
|
265
|
+
}
|
|
220
266
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
`Warning: optimizer didn't improve cost of ${this.props.name}`
|
|
227
|
-
)
|
|
228
|
-
}
|
|
267
|
+
if (cekResult.cost.cpu > cekResultUnoptim.cost.cpu) {
|
|
268
|
+
throw new Error(
|
|
269
|
+
`Critical error: optimizer worsened cpu cost of ${props.name}`
|
|
270
|
+
)
|
|
271
|
+
}
|
|
229
272
|
|
|
230
|
-
|
|
231
|
-
cekResult.
|
|
273
|
+
if (
|
|
274
|
+
cekResult.cost.mem == cekResultUnoptim.cost.mem &&
|
|
275
|
+
cekResult.cost.cpu == cekResultUnoptim.cost.cpu
|
|
276
|
+
) {
|
|
277
|
+
console.error(
|
|
278
|
+
`Warning: optimizer didn't improve cost of ${props.name}`
|
|
279
|
+
)
|
|
232
280
|
}
|
|
233
281
|
|
|
234
|
-
|
|
282
|
+
// overwrite the optimized cekResult.result with the unoptimized result because it contains more information
|
|
283
|
+
cekResult.result = resultUnoptim
|
|
235
284
|
}
|
|
285
|
+
|
|
286
|
+
return cekResult
|
|
236
287
|
}
|
|
237
288
|
|
|
238
289
|
/**
|
package/src/cast/index.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export {
|
|
2
|
+
configureCast,
|
|
3
|
+
convertFromUplcData,
|
|
4
|
+
convertToUplcData,
|
|
5
|
+
makeCast
|
|
6
|
+
} from "./Cast.js"
|
|
7
|
+
export {
|
|
8
|
+
evalUserFunc,
|
|
9
|
+
evalUserFuncUnsafe,
|
|
10
|
+
makeUserFunc,
|
|
11
|
+
profileUserFunc
|
|
12
|
+
} from "./UserFunc.js"
|
|
@@ -134,9 +134,8 @@ class LoadedScriptsWriterImpl {
|
|
|
134
134
|
* @returns {LoadedScriptsWriter}
|
|
135
135
|
*/
|
|
136
136
|
writeImportType(path, ...typeNames) {
|
|
137
|
-
this.definition.writeLine("/**")
|
|
138
|
-
|
|
139
137
|
this.definition
|
|
138
|
+
.writeLine("/**")
|
|
140
139
|
.writeLine(` * @import { ${typeNames.join(", ")} } from "${path}";`)
|
|
141
140
|
.writeLine(" */")
|
|
142
141
|
;[this.declaration, this.combined].forEach((w) => {
|
|
@@ -389,29 +388,54 @@ ${datumTypes ? ` $Datum: (config: CastConfig) => makeCast<${datumTypes[0]}, $
|
|
|
389
388
|
}
|
|
390
389
|
|
|
391
390
|
/**
|
|
392
|
-
* @param {TypeCheckedUserFunc}
|
|
393
|
-
* @
|
|
391
|
+
* @param {TypeCheckedUserFunc} props
|
|
392
|
+
* @param {boolean} unsafe
|
|
393
|
+
* @returns {string}
|
|
394
|
+
*/
|
|
395
|
+
export function genUserFuncRetType(props, unsafe = false) {
|
|
396
|
+
const retTypeStr = props?.returns ? genTypes(props.returns)[0] : "void"
|
|
397
|
+
|
|
398
|
+
if (unsafe) {
|
|
399
|
+
return retTypeStr == "void" ? "void" : "UplcData"
|
|
400
|
+
} else {
|
|
401
|
+
return retTypeStr
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* @param {TypeCheckedUserFunc} props
|
|
407
|
+
* @param {boolean} [unsafe]
|
|
408
|
+
* @returns {string}
|
|
394
409
|
*/
|
|
395
|
-
function
|
|
410
|
+
export function genUserFuncArgsType(props, unsafe = false) {
|
|
396
411
|
/**
|
|
397
412
|
* @type {string[]}
|
|
398
413
|
*/
|
|
399
414
|
const fields = []
|
|
400
415
|
|
|
401
|
-
if (
|
|
416
|
+
if (props.requiresScriptContext) {
|
|
402
417
|
fields.push("$scriptContext: UplcData")
|
|
403
418
|
}
|
|
404
419
|
|
|
405
|
-
if (
|
|
420
|
+
if (props.requiresCurrentScript) {
|
|
406
421
|
fields.push("$currentScript: string")
|
|
407
422
|
}
|
|
408
423
|
|
|
409
|
-
|
|
410
|
-
fields.push(
|
|
424
|
+
props.arguments.forEach(({ name, type, isOptional }, i) => {
|
|
425
|
+
fields.push(
|
|
426
|
+
`${name}${isOptional ? "?" : ""}: ${unsafe ? "UplcData" : genTypes(type)[1]}`
|
|
427
|
+
)
|
|
411
428
|
})
|
|
412
429
|
|
|
413
430
|
const argsTypeStr = `{${fields.join(", ")}}`
|
|
414
|
-
const retTypeStr = fn?.returns ? genTypes(fn.returns)[0] : "void"
|
|
415
431
|
|
|
416
|
-
return
|
|
432
|
+
return argsTypeStr
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* @param {TypeCheckedUserFunc} fn
|
|
437
|
+
* @returns {[string, string]}
|
|
438
|
+
*/
|
|
439
|
+
export function genFuncType(fn) {
|
|
440
|
+
return [genUserFuncArgsType(fn, false), genUserFuncRetType(fn)]
|
|
417
441
|
}
|
|
@@ -166,3 +166,129 @@ export function genTypes(schema) {
|
|
|
166
166
|
throw new Error(`unhandled TypeSchema kind '${kind}'`)
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @param {TypeSchema} schema
|
|
172
|
+
* @returns {Map<string, string>} - key=name, value=from
|
|
173
|
+
*/
|
|
174
|
+
export function collectBuiltinTypes(schema) {
|
|
175
|
+
/**
|
|
176
|
+
* @type {Map<string, string>}
|
|
177
|
+
*/
|
|
178
|
+
const m = new Map()
|
|
179
|
+
|
|
180
|
+
collectBuiltinTypesInternal(schema, m)
|
|
181
|
+
|
|
182
|
+
return m
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* @param {TypeSchema} schema
|
|
187
|
+
* @param {Map<string, string>} m - key=name, value=from
|
|
188
|
+
*/
|
|
189
|
+
function collectBuiltinTypesInternal(schema, m) {
|
|
190
|
+
const kind = schema.kind
|
|
191
|
+
|
|
192
|
+
switch (kind) {
|
|
193
|
+
case "internal":
|
|
194
|
+
const name = schema.name
|
|
195
|
+
switch (name) {
|
|
196
|
+
case "Bool":
|
|
197
|
+
case "ByteArray":
|
|
198
|
+
case "Real":
|
|
199
|
+
case "String":
|
|
200
|
+
break
|
|
201
|
+
case "AssetClass":
|
|
202
|
+
m.set("AssetClass", "@helios-lang/ledger")
|
|
203
|
+
m.set("MintingPolicyHash", "@helios-lang/ledger")
|
|
204
|
+
break
|
|
205
|
+
case "Any":
|
|
206
|
+
case "Data":
|
|
207
|
+
m.set("UplcData", "@helios-lang/uplc")
|
|
208
|
+
break
|
|
209
|
+
case "Int":
|
|
210
|
+
case "Duration":
|
|
211
|
+
case "Ratio":
|
|
212
|
+
m.set("IntLike", "@helios-lang/codec-utils")
|
|
213
|
+
break
|
|
214
|
+
case "Time":
|
|
215
|
+
m.set("TimeLike", "@helios-lang/ledger")
|
|
216
|
+
break
|
|
217
|
+
case "Address":
|
|
218
|
+
case "MintingPolicyHash":
|
|
219
|
+
case "PubKey":
|
|
220
|
+
case "PubKeyHash":
|
|
221
|
+
case "SpendingCredential":
|
|
222
|
+
case "StakingCredential":
|
|
223
|
+
case "StakingValidatorHash":
|
|
224
|
+
case "TimeLike":
|
|
225
|
+
case "TxId":
|
|
226
|
+
case "TxInput":
|
|
227
|
+
case "TxOutput":
|
|
228
|
+
case "TxOutputId":
|
|
229
|
+
case "ValidatorHash":
|
|
230
|
+
m.set(name, "@helios-lang/ledger")
|
|
231
|
+
break
|
|
232
|
+
case "StakingHash":
|
|
233
|
+
// TODO: implement this
|
|
234
|
+
return ["never", "never"]
|
|
235
|
+
case "TimeRange":
|
|
236
|
+
m.set("TimeRange", "@helios-lang/ledger")
|
|
237
|
+
m.set("TimeLike", "@helios-lang/ledger")
|
|
238
|
+
break
|
|
239
|
+
case "TxOutputDatum":
|
|
240
|
+
m.set("TxOutputDatum", "@helios-lang/ledger")
|
|
241
|
+
m.set("DatumHash", "@helios-lang/ledger")
|
|
242
|
+
m.set("UplcData", "@helios-lang/uplc")
|
|
243
|
+
break
|
|
244
|
+
case "Value":
|
|
245
|
+
m.set("Value", "@helios-lang/ledger")
|
|
246
|
+
m.set("IntLike", "@helios-lang/codec-utils")
|
|
247
|
+
m.set("MintingPolicyHash", "@helios-lang/ledger")
|
|
248
|
+
break
|
|
249
|
+
default:
|
|
250
|
+
throw new Error(`unhandled primitive '${name}' in hl2ts`)
|
|
251
|
+
}
|
|
252
|
+
break
|
|
253
|
+
case "list": {
|
|
254
|
+
collectBuiltinTypesInternal(schema.itemType, m)
|
|
255
|
+
break
|
|
256
|
+
}
|
|
257
|
+
case "map": {
|
|
258
|
+
collectBuiltinTypesInternal(schema.keyType, m)
|
|
259
|
+
collectBuiltinTypesInternal(schema.valueType, m)
|
|
260
|
+
break
|
|
261
|
+
}
|
|
262
|
+
case "tuple": {
|
|
263
|
+
schema.itemTypes.forEach((it) => collectBuiltinTypesInternal(it, m))
|
|
264
|
+
break
|
|
265
|
+
}
|
|
266
|
+
case "option": {
|
|
267
|
+
collectBuiltinTypesInternal(schema.someType, m)
|
|
268
|
+
break
|
|
269
|
+
}
|
|
270
|
+
case "struct": {
|
|
271
|
+
schema.fieldTypes.forEach(({ type }) => {
|
|
272
|
+
collectBuiltinTypesInternal(type, m)
|
|
273
|
+
})
|
|
274
|
+
break
|
|
275
|
+
}
|
|
276
|
+
case "enum": {
|
|
277
|
+
schema.variantTypes.forEach((variant) => {
|
|
278
|
+
collectBuiltinTypesInternal(variant, m)
|
|
279
|
+
})
|
|
280
|
+
break
|
|
281
|
+
}
|
|
282
|
+
case "variant": {
|
|
283
|
+
schema.fieldTypes.forEach(({ type }) => {
|
|
284
|
+
collectBuiltinTypesInternal(type, m)
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
break
|
|
288
|
+
}
|
|
289
|
+
case "reference":
|
|
290
|
+
throw new Error("recursive data structures not yet handled")
|
|
291
|
+
default:
|
|
292
|
+
throw new Error(`unhandled TypeSchema kind '${kind}'`)
|
|
293
|
+
}
|
|
294
|
+
}
|
package/src/context/index.js
CHANGED
package/src/hl2ts.js
CHANGED
|
@@ -13,10 +13,6 @@ import { makeLoadedScriptsWriter } from "./codegen/index.js"
|
|
|
13
13
|
import { loadCompilerLib } from "./compiler/index.js"
|
|
14
14
|
import { typeCheckFiles } from "./compiler/ops.js"
|
|
15
15
|
|
|
16
|
-
/**
|
|
17
|
-
* @import { CompilerLib, TypeCheckedModule, TypeCheckedValidator } from "./index.js"
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
16
|
/**
|
|
21
17
|
* @typedef {{
|
|
22
18
|
* name: string
|