diff --git a/packages/onchain/src/IR/interfaces/ToIR.ts b/packages/onchain/src/IR/interfaces/ToIR.ts index 69f9ab18..70b29d4f 100644 --- a/packages/onchain/src/IR/interfaces/ToIR.ts +++ b/packages/onchain/src/IR/interfaces/ToIR.ts @@ -1,5 +1,6 @@ import { IRTerm } from "../IRTerm"; +import { CompilerOptions } from "../toUPLC/CompilerOptions"; export interface ToIR { - toIR: ( dbn?: number | bigint ) => IRTerm + toIR: ( config: CompilerOptions, dbn?: number | bigint ) => IRTerm } \ No newline at end of file diff --git a/packages/onchain/src/IR/toUPLC/CompilerOptions.ts b/packages/onchain/src/IR/toUPLC/CompilerOptions.ts index 5b328dab..de26c599 100644 --- a/packages/onchain/src/IR/toUPLC/CompilerOptions.ts +++ b/packages/onchain/src/IR/toUPLC/CompilerOptions.ts @@ -1,4 +1,70 @@ +import { defaultUplcVersion, UPLCVersion } from "@harmoniclabs/uplc"; + +export interface CompilerUplcOptimizations { + /** + * + **/ + groupApplications: boolean; + /** + **/ + inlineSingleUse: boolean; + /** + **/ + simplifyWrappedPartialFuncApps: boolean; + /** + * + **/ + removeForceDelay: boolean; +} + +export const productionUplcOptimizations: CompilerUplcOptimizations = Object.freeze({ + groupApplications: true, + inlineSingleUse: true, + simplifyWrappedPartialFuncApps: true, + removeForceDelay: true +}); + +export const debugUplcOptimizations: CompilerUplcOptimizations = Object.freeze({ + groupApplications: false, + inlineSingleUse: false, + simplifyWrappedPartialFuncApps: false, + removeForceDelay: true +}); + +export const defaultUplcOptimizations: CompilerUplcOptimizations = productionUplcOptimizations; + +export function isDebugUplcOptimizations( + options: Partial = {} +): boolean +{ + return Object.keys( debugUplcOptimizations ) + .every((key: keyof CompilerUplcOptimizations) => { + + // keys to ignore + if( key === "removeForceDelay" ) return true; + + return options[ key ] === debugUplcOptimizations[ key ] + }); +} + +export function completeUplcOptimizations( + options: Partial, + complete: CompilerUplcOptimizations = defaultUplcOptimizations +): CompilerUplcOptimizations +{ + return { + groupApplications: options.groupApplications ?? complete.groupApplications, + inlineSingleUse: options.inlineSingleUse ?? complete.inlineSingleUse, + simplifyWrappedPartialFuncApps: options.simplifyWrappedPartialFuncApps ?? complete.simplifyWrappedPartialFuncApps, + removeForceDelay: options.removeForceDelay ?? complete.removeForceDelay + }; +} + export interface CompilerOptions { + /** + * uplc version (encoded in the script) + */ + targetUplcVersion: UPLCVersion; /** * @todo TODO * @@ -25,35 +91,75 @@ export interface CompilerOptions { * for this reason it is best to set this option to `true` only for production **/ delayHoists: boolean; + /** + * + **/ + uplcOptimizations: /* boolean |*/ Partial; + /** + * + **/ + addMarker: boolean; } export const extremeOptions: CompilerOptions = Object.freeze({ + targetUplcVersion: defaultUplcVersion, removeTraces: true, - delayHoists: true -} as CompilerOptions); - + delayHoists: true, + uplcOptimizations: productionUplcOptimizations, + addMarker: true +}); export const productionOptions: CompilerOptions = Object.freeze({ + targetUplcVersion: defaultUplcVersion, removeTraces: true, - delayHoists: true -} as CompilerOptions); + delayHoists: true, + uplcOptimizations: productionUplcOptimizations, + addMarker: true +}); export const debugOptions: CompilerOptions = Object.freeze({ + targetUplcVersion: defaultUplcVersion, removeTraces: false, - delayHoists: false -} as CompilerOptions); + delayHoists: false, + uplcOptimizations: debugUplcOptimizations, + addMarker: false +}); + +export const defaultOptions: CompilerOptions = productionOptions; export function completeCompilerOptions( options: Partial, - complete: CompilerOptions = productionOptions + complete: CompilerOptions = defaultOptions ): CompilerOptions { + let targetUplcVersion = options.targetUplcVersion instanceof UPLCVersion ? complete.targetUplcVersion : defaultUplcVersion; complete = { - ...productionOptions, + ...defaultOptions, ...complete }; + let uplcOptimizations = complete.uplcOptimizations as CompilerUplcOptimizations; + if( typeof options.uplcOptimizations === "boolean" ) + { + if( options.uplcOptimizations ) + { + uplcOptimizations = { + ...uplcOptimizations, + ...productionUplcOptimizations + } + } + else + { + uplcOptimizations = { + ...uplcOptimizations, + ...debugUplcOptimizations + } + } + } return { + targetUplcVersion, removeTraces: options.removeTraces ?? complete.removeTraces, - delayHoists: options.delayHoists ?? complete.delayHoists - } as CompilerOptions; + delayHoists: options.delayHoists ?? complete.delayHoists, + uplcOptimizations: completeUplcOptimizations( uplcOptimizations ), + addMarker: options.addMarker ?? complete.addMarker + }; } \ No newline at end of file diff --git a/packages/onchain/src/IR/toUPLC/__tests__/compileIR.natives.test.ts b/packages/onchain/src/IR/toUPLC/__tests__/compileIR.natives.test.ts index 96c0b904..817a8de3 100644 --- a/packages/onchain/src/IR/toUPLC/__tests__/compileIR.natives.test.ts +++ b/packages/onchain/src/IR/toUPLC/__tests__/compileIR.natives.test.ts @@ -1,6 +1,7 @@ -import { Application, Lambda, UPLCVar, showUPLC } from "@harmoniclabs/uplc"; +import { Application, Lambda, UPLCVar, prettyUPLC, showUPLC } from "@harmoniclabs/uplc"; import { IRNative } from "../../IRNodes/IRNative"; import { compileIRToUPLC } from "../compileIRToUPLC"; +import { debugOptions } from "../CompilerOptions"; describe("compileIRToUPLC", () => { @@ -11,7 +12,7 @@ describe("compileIRToUPLC", () => { const z = IRNative.z_comb; - const ir_zUPLC = compileIRToUPLC( z ); + const ir_zUPLC = compileIRToUPLC( z, debugOptions ); const innerZ = new Lambda( // toMakeRecursive new Application( @@ -35,13 +36,17 @@ describe("compileIRToUPLC", () => { ) ) - // // console.log( showUPLC( ir_zUPLC ) ) - // // console.log( showUPLC( ZUPLC ) ) + // console.log( prettyUPLC( ir_zUPLC ) ) + // console.log( prettyUPLC( ZUPLC ) ) expect( - ir_zUPLC + showUPLC( + ir_zUPLC + ) ).toEqual( - ZUPLC + showUPLC( + ZUPLC + ) ) }); diff --git a/packages/onchain/src/IR/toUPLC/compileIRToUPLC.ts b/packages/onchain/src/IR/toUPLC/compileIRToUPLC.ts index 87db4928..fba48c55 100644 --- a/packages/onchain/src/IR/toUPLC/compileIRToUPLC.ts +++ b/packages/onchain/src/IR/toUPLC/compileIRToUPLC.ts @@ -15,8 +15,9 @@ import { hoistForcedNatives } from "./subRoutines/hoistForcedNatives"; import { handleRecursiveTerms } from "./subRoutines/handleRecursiveTerms"; import { CompilerOptions, completeCompilerOptions } from "./CompilerOptions"; import { replaceHoistedWithLetted } from "./subRoutines/replaceHoistedWithLetted"; -import { IRNative } from "../IRNodes"; +import { IRApp, IRCase, IRConstr, IRNative, IRVar } from "../IRNodes"; import { replaceForcedNativesWithHoisted } from "./subRoutines/replaceForcedNativesWithHoisted"; +import { performUplcOptimizationsAndReturnRoot } from "./subRoutines/performUplcOptimizationsAndReturnRoot"; export function compileIRToUPLC( @@ -145,6 +146,27 @@ export function compileIRToUPLC( // will be re-hosited; causeing uselsess evaluations if( !options.delayHoists ) term = hoistForcedNatives( term ); + // at this point we expect the IR to be translable 1:1 to UPLC + + term = performUplcOptimizationsAndReturnRoot( term, options ); + + if( + options.addMarker && + options.targetUplcVersion.major >= 1 && + options.targetUplcVersion.minor >= 1 && + options.targetUplcVersion.patch >= 0 + ) + { + term = new IRCase( + new IRConstr( 0, [] ), + [ + term, + // never evaluated + IRConst.int( 42 ) + ] + ); + } + const srcmap = {}; const uplc = _irToUplc( term, srcmap ).term; diff --git a/packages/onchain/src/IR/toUPLC/subRoutines/handleLetted/__tests__/IR.compile.handleLetted.test.ts b/packages/onchain/src/IR/toUPLC/subRoutines/handleLetted/__tests__/IR.compile.handleLetted.test.ts index 7361e689..bfdf4d27 100644 --- a/packages/onchain/src/IR/toUPLC/subRoutines/handleLetted/__tests__/IR.compile.handleLetted.test.ts +++ b/packages/onchain/src/IR/toUPLC/subRoutines/handleLetted/__tests__/IR.compile.handleLetted.test.ts @@ -19,6 +19,7 @@ import { DataI } from "@harmoniclabs/plutus-data"; import { Machine } from "@harmoniclabs/plutus-machine"; import { pInt } from "../../../../../pluts/lib/std/int/pInt"; import { irHashToHex } from "../../../../IRHash"; +import { debugOptions, productionOptions } from "../../../CompilerOptions"; describe("handleLettedAndReturnRoot", () => { @@ -149,7 +150,7 @@ describe("handleLettedAndReturnRoot", () => { expect( getLettedTerms( root ).length ).toEqual( 2 ); - const compiled = compileIRToUPLC( root ); + const compiled = compileIRToUPLC( root, { ...productionOptions, addMarker: false } ); expect( showUPLC( compiled ) @@ -252,7 +253,7 @@ describe("handleLettedAndReturnRoot", () => { // logJson( root, 4 ) - const compiled = compileIRToUPLC( root ); + const compiled = compileIRToUPLC( root, debugOptions ); expect( showUPLC( compiled ) @@ -325,7 +326,7 @@ describe("handleLettedAndReturnRoot", () => { ) ); - const compiled = compileIRToUPLC( root ); + const compiled = compileIRToUPLC( root, { ...productionOptions, addMarker: false } ); expect( showUPLC( compiled ) ) .toEqual( @@ -355,10 +356,10 @@ describe("handleLettedAndReturnRoot", () => { ) ); - const compiled = compileIRToUPLC( root ); + const compiled = compileIRToUPLC( root, debugOptions ); expect( showUPLC( compiled ) ) - .toEqual("(lam a (lam b [(lam c [[(lam d (lam e [[(builtin addInteger) a] d])) c] c]) (con integer 2)]))"); + .toEqual("[(lam a (lam b (lam c [[(lam d (lam e [[(builtin addInteger) b] d])) a] a]))) (con integer 2)]"); // all inlined const expected = new IRFunc( 2, // a, b diff --git a/packages/onchain/src/IR/toUPLC/subRoutines/performUplcOptimizationsAndReturnRoot/__tests__/uplcOptimizations.test.ts b/packages/onchain/src/IR/toUPLC/subRoutines/performUplcOptimizationsAndReturnRoot/__tests__/uplcOptimizations.test.ts new file mode 100644 index 00000000..392afa34 --- /dev/null +++ b/packages/onchain/src/IR/toUPLC/subRoutines/performUplcOptimizationsAndReturnRoot/__tests__/uplcOptimizations.test.ts @@ -0,0 +1,145 @@ +import { showUPLC } from "@harmoniclabs/uplc"; +import { IRApp, IRCase, IRConst, IRConstr, IRFunc, IRNative, IRVar } from "../../../../IRNodes"; +import { _ir_apps } from "../../../../tree_utils/_ir_apps"; +import { performUplcOptimizationsAndReturnRoot } from ".."; +import { productionOptions } from "../../../CompilerOptions"; +import { _irToUplc } from "../../../_internal/_irToUplc"; +import { getExpandedIRFunc } from "../expandFuncsAndReturnRoot"; +import { Machine } from "@harmoniclabs/plutus-machine"; + +describe("uplc optimizations", () => { + + test("ifThenElse", () => { + + const original = _ir_apps( + IRNative.strictIfThenElse, + IRConst.bool(true), + IRConst.int( 1 ), + IRConst.int( 0 ) + ); + + const expected = new IRCase( + new IRConstr( 0, [ + IRConst.bool(true), + IRConst.int(1), + IRConst.int(0) + ]), + [ IRNative.strictIfThenElse ] + ); + + const a = showUPLC( _irToUplc( performUplcOptimizationsAndReturnRoot( original, productionOptions ) ).term ); + const b = showUPLC( _irToUplc( expected ).term ); + + // console.log( a ); + + expect( a ).toEqual( b ); + }); + + test("multi app",() => { + + const original = _ir_apps( + new IRFunc( 3, + _ir_apps( + IRNative.subtractInteger, + new IRVar( 0 ), + _ir_apps( + IRNative.addInteger, + new IRVar( 1 ), + new IRVar( 2 ) + ) + ) + ), + IRConst.int( 1 ), + IRConst.int( 2 ), + IRConst.int( 3 ) + ); + + const expected = new IRCase( + new IRConstr( 0, [ + IRConst.int( 1 ), + IRConst.int( 2 ), + IRConst.int( 3 ), + ]), + [ + getExpandedIRFunc( + _ir_apps( + IRNative.subtractInteger, + new IRVar( 0 ), + _ir_apps( + IRNative.addInteger, + new IRVar( 1 ), + new IRVar( 2 ) + ) + ), + 3 + ) + ] + ); + + const aUplc = _irToUplc( performUplcOptimizationsAndReturnRoot( original, productionOptions ) ).term; + + const a = showUPLC( aUplc ); + const b = showUPLC( _irToUplc( expected ).term ); + + console.log( a ); + + const originalUplc = _irToUplc( original ).term; + + const aRes = Machine.eval( aUplc ); + const originalRes = Machine.eval( originalUplc ); + + expect( a ).toEqual( b ); + + console.log( aRes.result, originalRes.result ); + console.log( aRes.budgetSpent.toJSON(), originalRes.budgetSpent.toJSON() ); + }); + + test.skip("letted", () => { + + const inner = _ir_apps( + IRNative.subtractInteger, + _ir_apps( + IRNative.addInteger, + new IRVar( 2 ), + new IRVar( 1 ), + ), + new IRVar( 0 ) + ) + + const original = new IRApp( + new IRFunc( 1, + new IRApp( + new IRFunc( 1, + new IRApp( + new IRFunc( 1, + inner.clone() + ), + IRConst.int( 3 ) + ) + ), + IRConst.int( 2 ) + ) + ), + IRConst.int( 1 ) + ); + + const expected = new IRCase( + new IRConstr( 0, [ IRConst.int(1), IRConst.int(2), IRConst.int(3) ] ), + [ + getExpandedIRFunc( + inner.clone(), + 3 + ) + ] + ); + + const aUplc = _irToUplc( performUplcOptimizationsAndReturnRoot( original, productionOptions ) ).term; + const bUplc = _irToUplc( expected ).term; + + const a = showUPLC( aUplc ); + + console.log( a ); + + expect( a ).toEqual( showUPLC( bUplc ) ); + }) +}); \ No newline at end of file diff --git a/packages/onchain/src/IR/toUPLC/subRoutines/performUplcOptimizationsAndReturnRoot/expandFuncsAndReturnRoot.ts b/packages/onchain/src/IR/toUPLC/subRoutines/performUplcOptimizationsAndReturnRoot/expandFuncsAndReturnRoot.ts new file mode 100644 index 00000000..05390077 --- /dev/null +++ b/packages/onchain/src/IR/toUPLC/subRoutines/performUplcOptimizationsAndReturnRoot/expandFuncsAndReturnRoot.ts @@ -0,0 +1,101 @@ +import { IRConstr } from "../../../IRNodes"; +import { IRApp } from "../../../IRNodes/IRApp"; +import { IRCase } from "../../../IRNodes/IRCase"; +import { IRDelayed } from "../../../IRNodes/IRDelayed"; +import { IRForced } from "../../../IRNodes/IRForced"; +import { IRFunc } from "../../../IRNodes/IRFunc"; +import { IRHoisted } from "../../../IRNodes/IRHoisted"; +import { IRLetted } from "../../../IRNodes/IRLetted"; +import { IRRecursive } from "../../../IRNodes/IRRecursive"; +import { IRSelfCall } from "../../../IRNodes/IRSelfCall"; +import { IRVar } from "../../../IRNodes/IRVar"; +import { IRTerm } from "../../../IRTerm"; +import { _modifyChildFromTo } from "../../_internal/_modifyChildFromTo"; + +export function getExpandedIRFunc( body: IRTerm, arity: number ): IRFunc +{ + body = new IRFunc( 1, body ); + while( --arity > 0 ) + { + body = new IRFunc( 1, body ); + } + return body as IRFunc; + // if( arity === 1 ) return new IRFunc( 1, body ); + // return new IRFunc( 1, getExpandedIRFunc( body, arity - 1 ) ); +} + +export function expandFuncsAndReturnRoot( root: IRTerm ): IRTerm +{ + const stack: IRTerm[] = [ root ]; + + while( stack.length > 0 ) + { + const t = stack.pop()!; + + if( t instanceof IRFunc ) + { + // whatever happens we continue from the body + stack.push( t.body ); + + // all good + if( t.arity <= 1 ) continue; + + const expanded = getExpandedIRFunc( t.body, t.arity ); + + if( t.parent ) + { + _modifyChildFromTo( t.parent, t, expanded ); + } + else + { + root = expanded; + } + + continue; + } + + if( t instanceof IRApp ) + { + stack.push( t.fn, t.arg ); + continue; + } + + if( t instanceof IRCase ) + { + stack.push( + t.constrTerm, + ...t.continuations + ); + continue; + } + if( t instanceof IRConstr ) + { + stack.push( ...t.fields ); + continue; + } + + if( t instanceof IRDelayed ) + { + stack.push( t.delayed ); + continue; + } + + if( t instanceof IRForced ) + { + stack.push( t.forced ); + continue; + } + + if( + t instanceof IRRecursive || + t instanceof IRHoisted || + t instanceof IRLetted || + t instanceof IRSelfCall + ) + { + throw new Error("Unexpected term while performing uplc optimizations"); + } + } + + return root; +} \ No newline at end of file diff --git a/packages/onchain/src/IR/toUPLC/subRoutines/performUplcOptimizationsAndReturnRoot/index.ts b/packages/onchain/src/IR/toUPLC/subRoutines/performUplcOptimizationsAndReturnRoot/index.ts new file mode 100644 index 00000000..0c8ebd2c --- /dev/null +++ b/packages/onchain/src/IR/toUPLC/subRoutines/performUplcOptimizationsAndReturnRoot/index.ts @@ -0,0 +1,266 @@ +import { IRConstr, IRNative } from "../../../IRNodes"; +import { IRApp } from "../../../IRNodes/IRApp"; +import { IRCase } from "../../../IRNodes/IRCase"; +import { IRDelayed } from "../../../IRNodes/IRDelayed"; +import { IRForced } from "../../../IRNodes/IRForced"; +import { IRFunc } from "../../../IRNodes/IRFunc"; +import { IRHoisted } from "../../../IRNodes/IRHoisted"; +import { IRLetted } from "../../../IRNodes/IRLetted"; +import { IRRecursive } from "../../../IRNodes/IRRecursive"; +import { IRSelfCall } from "../../../IRNodes/IRSelfCall"; +import { IRVar } from "../../../IRNodes/IRVar"; +import { IRTerm } from "../../../IRTerm"; +import { _modifyChildFromTo } from "../../_internal/_modifyChildFromTo"; +import { iterTree } from "../../_internal/iterTree"; +import { CompilerOptions, CompilerUplcOptimizations, isDebugUplcOptimizations } from "../../CompilerOptions"; +import { expandFuncsAndReturnRoot, getExpandedIRFunc } from "./expandFuncsAndReturnRoot"; + +export function performUplcOptimizationsAndReturnRoot( + root: IRTerm, + options: CompilerOptions +): IRTerm +{ + const opts = options.uplcOptimizations; + if( isDebugUplcOptimizations( opts ) ) return root; + + const { + groupApplications, + inlineSingleUse, + simplifyWrappedPartialFuncApps, + removeForceDelay + } = opts; + + root = expandFuncsAndReturnRoot( root ); + + const stack: IRTerm[] = [ root ]; + + while( stack.length > 0 ) + { + const t = stack.pop()!; + + if( t instanceof IRApp ) + { + if( isIdLike( t.fn ) ) + { + if( t.parent ) _modifyChildFromTo( t.parent, t, t.arg ); + else root = t.arg; + stack.push( t.arg ); + continue; + } + + if( !groupApplications ) + { + stack.push( t.fn, t.arg ) + continue; + } + + const [ args, body, arity ] = getMultiAppArgsAndBody( t ); + + if( + arity <= 2 || + args.length <= 2 + ) + { + stack.push( t.fn, t.arg ); + continue; + } + + const newNode = new IRCase( + new IRConstr( 0, args ), + [ + body + ] + ); + stack.push( body ); + + if( t.parent ) + { + _modifyChildFromTo( t.parent, t, newNode ); + } + else + { + root = newNode; + } + continue; + } + + if( t instanceof IRCase ) + { + stack.push( t.constrTerm, ...t.continuations ); + continue; + } + if( t instanceof IRConstr ) + { + stack.push( ...t.fields ); + continue; + } + + if( t instanceof IRDelayed ) + { + stack.push( t.delayed ); + continue; + } + + if( t instanceof IRForced ) + { + + stack.push( t.forced ); + continue; + } + + if( t instanceof IRFunc ) + { + stack.push( t.body ); + continue; + } + + if( + t instanceof IRRecursive || + t instanceof IRHoisted || + t instanceof IRLetted || + t instanceof IRSelfCall + ) + { + throw new Error("Unexpected term while performing uplc optimizations"); + } + } + + return root; +} + +function isAppLike( term: IRTerm ): term is IRApp | IRCase +{ + return ( + term instanceof IRApp || + isCaseConstrApp( term ) + ); +} + +function getMultiAppArgsAndBody( term: IRTerm ): [ args: IRTerm[], body: IRTerm, arity: number ] +{ + let args: IRTerm[] = []; + let body: IRTerm = term; + let arity: number = 0; + + /* + while( + term instanceof IRApp && + term.fn instanceof IRFunc && + term.fn.arity === 1 + ) + { + // letted terms + // [(lam a [(lam b [(lam c ... ))) c] b] a] :: [] + // [(lam b [(lam c ... ))) c] b] :: [a] + // [(lam c ... ) c] :: [a, b] + // ... :: [a, b, c] + + args.push( term.arg ); + term = term.fn.body as any; + // arity++; + body = term; + continue; + } + + arity = args.length; + + // if we started with letted or hoisted + // continue looking for consecutive applications or cases + if( arity > 0 ) + { + const [ nextArgs, nextBody, nextArity ] = getMultiAppArgsAndBody( body ); + return [ args.concat( nextArgs ), nextBody, arity + nextArity ]; + } + //*/ + + // else we look for consecutive applications or cases + while( term instanceof IRApp ) + { + /* + consecutive applications look like: + [ + [ + [ + (lam a (lam b (lam c ... ))) + a] + b] + c] + but the equivalent IRCase looks like: + (case + (constr 0 a b c) + (lam a (lam b (lam c ... ))) + ) + so we need to reverse the order of the args + since we start from the outermost application + (in order, we encounter from the top: c => b => a) + */ + args.unshift( term.arg ); + term = term.fn as any; + // arity++; + body = term; + }; + arity = args.length; + + if( arity === 0 ) return [ args, body, arity ]; + + const [ nextArgs, nextBody, nextArity ] = getMultiAppArgsAndBody( body ); + return [ args.concat( nextArgs ), nextBody, arity + nextArity ]; +} + +function isCaseConstrApp( term: IRTerm ): boolean +{ + return ( + term instanceof IRCase && + term.continuations.length === 1 && + term.constrTerm instanceof IRCase + ); +} + +function isIdLike( term: IRTerm ): boolean +{ + return ( + term instanceof IRFunc && + term.arity === 1 && + term.body instanceof IRVar && + Number( term.body.dbn ) === 0 + ); +} + +function getArityOfTerm( term: IRTerm ): number +{ + let arity = 0; + while( + term instanceof IRApp || + term instanceof IRFunc || + term instanceof IRNative || + term instanceof IRVar || + term instanceof IRForced || + term instanceof IRDelayed + ) + { + if( term instanceof IRForced ) + { + term = term.forced; + continue; + } + if( term instanceof IRDelayed ) + { + term = term.delayed; + continue; + } + + if( term instanceof IRApp ) + { + arity--; + term = term.fn; + continue; + } + if( term instanceof IRFunc ) + { + arity += term.arity; + term = term.body; + continue; + } + } + return arity; +} \ No newline at end of file diff --git a/packages/onchain/src/pluts/API/V1/Value/__tests__/PValue.evalScript.test.ts b/packages/onchain/src/pluts/API/V1/Value/__tests__/PValue.evalScript.test.ts index 486e6385..f69a68fe 100644 --- a/packages/onchain/src/pluts/API/V1/Value/__tests__/PValue.evalScript.test.ts +++ b/packages/onchain/src/pluts/API/V1/Value/__tests__/PValue.evalScript.test.ts @@ -1,5 +1,5 @@ import { CEKConst, Machine } from "@harmoniclabs/plutus-machine"; -import { UPLCTerm, ErrorUPLC } from "@harmoniclabs/uplc"; +import { UPLCTerm, ErrorUPLC, showUPLC } from "@harmoniclabs/uplc"; import { Term, pmatch, termTypeToString, typeExtends } from "../../../.."; import { compileIRToUPLC } from "../../../../../IR/toUPLC/compileIRToUPLC"; import { PMaybe, fromData, pBool, pByteString, pInt, pPair, pdelay, pfn, phoist, pif, plam, precursiveList, ptoData, toData } from "../../../../lib"; @@ -9,6 +9,7 @@ import { PCurrencySymbol } from "../PCurrencySymbol"; import { PTokenName } from "../PTokenName"; import { PAssetsEntry, PValue, PValueEntry } from "../PValue"; import { getFstT, getSndT } from "../../../../type_system/tyArgs"; +import { debugOptions } from "../../../../../IR/toUPLC/CompilerOptions"; const currSym = PCurrencySymbol.from( pByteString("ff".repeat(28)) ); const tn = PTokenName.from( pByteString("") ); @@ -291,15 +292,16 @@ describe("pvalueOf", () => { }) - test("token present", () => { + test.only("token present", () => { const term = pvalueOf.$( dynamicOneEntryValue ).$( currSym as any ).$( tn as any ); - const uplc = term.toUPLC(0); + const uplc = term.toUPLC(0, debugOptions); const expected = Machine.evalSimple( pInt( 1_000_000 ) ); const received = Machine.evalSimple( uplc ); + // console.log( showUPLC( uplc ) ); /* const compiled = UPLCEncoder.compile( new UPLCProgram([1,0,0], uplc.clone() ) ).toBuffer().buffer; diff --git a/packages/onchain/src/pluts/PTypes/PSoP/psop.ts b/packages/onchain/src/pluts/PTypes/PSoP/psop.ts index 770567d0..283703fc 100644 --- a/packages/onchain/src/pluts/PTypes/PSoP/psop.ts +++ b/packages/onchain/src/pluts/PTypes/PSoP/psop.ts @@ -241,9 +241,9 @@ export function psop< return addUtilityForType( thisSopType )( new Term( thisSopType, - dbn => new IRConstr( + (cfg, dbn) => new IRConstr( i, - ctorDefFieldsNames.map( fieldKey => jsSop[ fieldKey ].toIR( dbn ) ) + ctorDefFieldsNames.map( fieldKey => jsSop[ fieldKey ].toIR( cfg, dbn ) ) ) ) ) as any; diff --git a/packages/onchain/src/pluts/PTypes/PStruct/pstruct.ts b/packages/onchain/src/pluts/PTypes/PStruct/pstruct.ts index fe8fae9d..95bb3357 100644 --- a/packages/onchain/src/pluts/PTypes/PStruct/pstruct.ts +++ b/packages/onchain/src/pluts/PTypes/PStruct/pstruct.ts @@ -304,7 +304,7 @@ export function pstruct< { dataReprTerm = new Term( thisStructType, - _dbn => { + (cfg, _dbn) => { return IRConst.data( new DataConstr( i, @@ -324,7 +324,7 @@ export function pstruct< console.log( ctorDefFieldsNames ); console.log( fieldKey, termTypeToString( thisCtorDef[ fieldKey ] ) ); console.log( res ) - // console.log( showUPLC( _term.toIR( _dbn ) ) ) + // console.log( showUPLC( _term.toIR( cfg, _dbn ) ) ) throw res; } @@ -341,7 +341,7 @@ export function pstruct< { dataReprTerm = new Term( thisStructType, - dbn => { + (cfg, dbn) => { return new IRApp( new IRApp( @@ -357,7 +357,7 @@ export function pstruct< return res; } ) - ).toIR( dbn ) + ).toIR( cfg, dbn ) ) } ) diff --git a/packages/onchain/src/pluts/Script/__tests__/Script.compile.okScript.test.ts b/packages/onchain/src/pluts/Script/__tests__/Script.compile.okScript.test.ts index 69eb7ddd..aeb35dde 100644 --- a/packages/onchain/src/pluts/Script/__tests__/Script.compile.okScript.test.ts +++ b/packages/onchain/src/pluts/Script/__tests__/Script.compile.okScript.test.ts @@ -1,5 +1,6 @@ import { Lambda, UPLCConst } from "@harmoniclabs/uplc"; import { data, pfn, pmakeUnit, unit } from "../.."; +import { productionOptions } from "../../../IR/toUPLC/CompilerOptions"; test("okScript", () => { @@ -7,7 +8,7 @@ test("okScript", () => { (( d, r, c ) => pmakeUnit()); expect( - okScript.toUPLC(0) + okScript.toUPLC(0, { ...productionOptions, addMarker: false }) ).toEqual( new Lambda( new Lambda( diff --git a/packages/onchain/src/pluts/Term/index.ts b/packages/onchain/src/pluts/Term/index.ts index a1e219db..e4db4161 100644 --- a/packages/onchain/src/pluts/Term/index.ts +++ b/packages/onchain/src/pluts/Term/index.ts @@ -9,11 +9,12 @@ import { compileIRToUPLC } from "../../IR/toUPLC/compileIRToUPLC"; import { PType } from "../PType"; import { FromPType, GenericTermType, TermType, ToPType, isWellFormedGenericType, isWellFormedType, termTypeToString } from "../type_system"; import { cloneTermType } from "../type_system/cloneTermType"; -import { defineReadOnlyHiddenProperty } from "@harmoniclabs/obj-utils"; +import { defineReadOnlyHiddenProperty, isObject } from "@harmoniclabs/obj-utils"; import { Cloneable, isCloneable } from "../../utils/Cloneable"; import { assert } from "../../utils/assert"; import { IRVar } from "../../IR/IRNodes/IRVar"; import { IRSelfCall } from "../../IR/IRNodes/IRSelfCall"; +import { CompilerOptions, debugOptions, defaultOptions } from "../../IR/toUPLC/CompilerOptions"; export type UnTerm> = T extends Term ? PT : never; @@ -38,13 +39,17 @@ export class Term // typescript being silly here readonly type!: FromPType | TermType; - readonly toUPLC!: ( deBruijnLevel?: bigint | number ) => UPLCTerm + readonly toUPLC!: ( deBruijnLevel?: bigint | number, config?: CompilerOptions ) => UPLCTerm - readonly toIR!: ( deBruijnLevel?: bigint | number ) => IRTerm + readonly toIR!: ( config?: CompilerOptions, deBruijnLevel?: bigint | number ) => IRTerm readonly clone!: () => Term - constructor( type: FromPType | TermType | GenericTermType, _toIR: ( dbn: bigint ) => IRTerm, isConstant: boolean = false ) + constructor( + type: FromPType | TermType | GenericTermType, + _toIR: ( config: CompilerOptions, dbn: bigint ) => IRTerm, + isConstant: boolean = false + ) { assert( isWellFormedGenericType( type ) || @@ -71,15 +76,16 @@ export class Term Object.defineProperty( this, "toIR", { - value: ( deBruijnLevel: bigint | number = 0 ) => + value: ( config: CompilerOptions = defaultOptions, deBruijnLevel: bigint | number = 0 ) => { + if(!isObject( config )) config = defaultOptions; const dbnStr = deBruijnLevel.toString(); const _cacheHit = _IR_cache[ shouldHoist ? "hoisted" : dbnStr ]; if( _cacheHit ) return _cacheHit.clone(); if( typeof deBruijnLevel !== "bigint" ) deBruijnLevel = BigInt( deBruijnLevel ); - let ir = _toIR_( deBruijnLevel ); + let ir = _toIR_( config, deBruijnLevel ); if( shouldHoist ) { const res = new IRHoisted( ir ); @@ -100,7 +106,7 @@ export class Term // as for the current implementation we don't care // because we are going to re-assign the variable `ir` anyway // if this ever changes make sure to call `ir.clone()` - let uplc = compileIRToUPLC( ir/*.clone()*/ ); + let uplc = compileIRToUPLC( ir, debugOptions ); // console.log( showUPLC( uplc ) ) @@ -141,12 +147,12 @@ export class Term Object.defineProperty( this, "toUPLC", { - value: ( deBruijnLevel: bigint | number = 0 ) => + value: ( deBruijnLevel: bigint | number = 0, config = defaultOptions ) => { const key = shouldHoist ? "hoisted" : deBruijnLevel.toString(); const _cacheHit = _UPLC_cache[key]; if( _cacheHit ) return _cacheHit.clone() - const res = compileIRToUPLC( this.toIR( deBruijnLevel ) ); + const res = compileIRToUPLC( this.toIR( config, deBruijnLevel ), config ); _UPLC_cache[key] = res.clone(); return res; }, diff --git a/packages/onchain/src/pluts/lib/builtins/int/intBinOpToBool.ts b/packages/onchain/src/pluts/lib/builtins/int/intBinOpToBool.ts index 62ede7d3..e86764c8 100644 --- a/packages/onchain/src/pluts/lib/builtins/int/intBinOpToBool.ts +++ b/packages/onchain/src/pluts/lib/builtins/int/intBinOpToBool.ts @@ -55,10 +55,10 @@ export const plessEqInt = intBinOpToBool( IRNative.lessThanEqualInteger ); export const pgreaterInt = addApplications<[ PInt, PInt ], PBool>( new Term>>( fn([ int, int ], bool ), - _dbn => new IRHoisted( + (cfg, _dbn) => new IRHoisted( new IRApp( _pflipIR.clone(), - plessInt.toIR( 0 ) + plessInt.toIR( cfg, 0 ) ) ) ) @@ -67,10 +67,10 @@ export const pgreaterInt = addApplications<[ PInt, PInt ], PBool>( export const pgreaterEqInt = addApplications<[ PInt, PInt ], PBool>( new Term>>( fn([ int, int ], bool ), - _dbn => new IRHoisted( + (cfg, _dbn) => new IRHoisted( new IRApp( _pflipIR, - plessEqInt.toIR( 0 ) + plessEqInt.toIR( cfg, 0 ) ) ) ) diff --git a/packages/onchain/src/pluts/lib/papp.ts b/packages/onchain/src/pluts/lib/papp.ts index a9ace54d..0653eb07 100644 --- a/packages/onchain/src/pluts/lib/papp.ts +++ b/packages/onchain/src/pluts/lib/papp.ts @@ -109,7 +109,7 @@ export function papp( a: Term { + (cfg, dbn) => { let funcIR: IRTerm; @@ -117,18 +117,18 @@ export function papp( a: Term(toDelay: Term): Term< { return new Term( delayed( toDelay.type ), - (dbn) => { + (cfg, dbn) => { return new IRDelayed( - toDelay.toIR( dbn ) + toDelay.toIR( cfg, dbn ) ); } ); diff --git a/packages/onchain/src/pluts/lib/perror.ts b/packages/onchain/src/pluts/lib/perror.ts index 8fc8a365..6d9b40cd 100644 --- a/packages/onchain/src/pluts/lib/perror.ts +++ b/packages/onchain/src/pluts/lib/perror.ts @@ -11,7 +11,7 @@ export function perror( type: T , msg: string | undefined = { __original__: addInfos }; let src = new Error().stack?.split("\n")[2]; - src = src?.slice( src.indexOf("at ") + 3 ?? 0 ); + src = src?.slice( src.indexOf("at ") + 3 ); (addInfos as any).__src__ = src; diff --git a/packages/onchain/src/pluts/lib/pfn.ts b/packages/onchain/src/pluts/lib/pfn.ts index 54dcb8fa..a765219a 100644 --- a/packages/onchain/src/pluts/lib/pfn.ts +++ b/packages/onchain/src/pluts/lib/pfn.ts @@ -182,7 +182,7 @@ export function pfn>( fn( newInsTys as any, outputType ) as any, - dbn => { + (cfg, dbn) => { const thisLambdaPtr = dbn + BigInt( 1 ); const boundVars = inputsTypes.map( inT => { const boundVar = new Term( inT, - dbnAccessLevel => new IRVar( dbnAccessLevel - thisLambdaPtr ) + (cfg, dbnAccessLevel) => new IRVar( dbnAccessLevel - thisLambdaPtr ) ); defineReadOnlyHiddenProperty( @@ -217,7 +217,7 @@ export function pfn( toForce: Term { - const toForceUPLC = toForce.toIR( dbn ); + (cfg, dbn) => { + const toForceUPLC = toForce.toIR( cfg, dbn ); // if directly applying to Delay UPLC just remove the delay // example: diff --git a/packages/onchain/src/pluts/lib/pforce/minimal.ts b/packages/onchain/src/pluts/lib/pforce/minimal.ts index 84bc77ec..a1002b69 100644 --- a/packages/onchain/src/pluts/lib/pforce/minimal.ts +++ b/packages/onchain/src/pluts/lib/pforce/minimal.ts @@ -12,8 +12,8 @@ export function _pforce return new Term( outType as any, - (dbn) => { - const toForceUPLC = toForce.toIR( dbn ); + (cfg, dbn) => { + const toForceUPLC = toForce.toIR( cfg, dbn ); // if directly applying to Delay UPLC just remove the delay // example: diff --git a/packages/onchain/src/pluts/lib/plam.ts b/packages/onchain/src/pluts/lib/plam.ts index f5ad6a09..6ba265e2 100644 --- a/packages/onchain/src/pluts/lib/plam.ts +++ b/packages/onchain/src/pluts/lib/plam.ts @@ -33,18 +33,18 @@ return ( let lambdaTerm = new Term,ToPType>>( lam( inputType, outputType ) as any, - dbn => { + ( cfg, dbn ) => { const thisLambdaPtr = dbn + BigInt( 1 ); const boundVar = new Term>( inputType as any, - dbnAccessLevel => new IRVar( dbnAccessLevel - thisLambdaPtr ) + (cfg, dbnAccessLevel) => new IRVar( dbnAccessLevel - thisLambdaPtr ) ); const body = termFunc( addUtilityForType( inputType )( boundVar ) as any); // here the debruijn level is incremented - return new IRFunc( 1, body.toIR( thisLambdaPtr ), func_name ); + return new IRFunc( 1, body.toIR( cfg, thisLambdaPtr ), func_name ); } ); @@ -55,12 +55,12 @@ return ( inT, outputType ) as any, - dbn => { + (cfg, dbn) => { const thisLambdaPtr = dbn + BigInt( 1 ); const boundVar = new Term>( inT as any, - dbnAccessLevel => new IRVar( dbnAccessLevel - thisLambdaPtr ) + (cfg, dbnAccessLevel) => new IRVar( dbnAccessLevel - thisLambdaPtr ) ); const body = termFunc( @@ -74,7 +74,7 @@ return ( ); // here the debruijn level is incremented - return new IRFunc( 1, body.toIR( thisLambdaPtr ) ); + return new IRFunc( 1, body.toIR( cfg, thisLambdaPtr ) ); } ) ); diff --git a/packages/onchain/src/pluts/lib/plet/index.ts b/packages/onchain/src/pluts/lib/plet/index.ts index 6a639a8f..d9b5e06e 100644 --- a/packages/onchain/src/pluts/lib/plet/index.ts +++ b/packages/onchain/src/pluts/lib/plet/index.ts @@ -52,8 +52,8 @@ export function plet( const letted = new Term( type, - dbn => { - const ir = varValue.toIR( dbn ); + (cfg, dbn) => { + const ir = varValue.toIR( cfg, dbn ); // `compileIRToUPLC` can handle it even if this check is not present // but why spend useful tree iterations if we can avoid them here? @@ -92,10 +92,9 @@ export function plet( // return papp( plam( varValue.type, outType )( expr as any ), varValue as any ) as any; const term = new Term( outType, - dbn => { + (cfg, dbn) => { - - const arg = varValue.toIR( dbn ); + const arg = varValue.toIR( cfg, dbn ); if( // inline variables; no need to add an application since already in scope @@ -103,7 +102,7 @@ export function plet( arg instanceof IRSelfCall ) { - return expr( withUtility( varValue as any ) as any ).toIR( dbn ); + return expr( withUtility( varValue as any ) as any ).toIR( cfg, dbn ); } // if( @@ -111,7 +110,7 @@ export function plet( // arg instanceof IRLetted // ) // { - // return expr( withUtility( varValue as any ) as any ).toIR( dbn ); + // return expr( withUtility( varValue as any ) as any ).toIR( cfg, dbn ); // } return new IRApp( @@ -121,10 +120,10 @@ export function plet( withUtility( new Term( varValue.type, - varAccessDbn => new IRVar( varAccessDbn - ( dbn + BigInt(1) ) ) // point to the lambda generated here + ( cfg, varAccessDbn) => new IRVar( varAccessDbn - ( dbn + BigInt(1) ) ) // point to the lambda generated here ) as any ) as any - ).toIR( ( dbn + BigInt(1) ) ) + ).toIR( cfg, ( dbn + BigInt(1) ) ) ), arg, { __src__ } diff --git a/packages/onchain/src/pluts/lib/plet/minimal.ts b/packages/onchain/src/pluts/lib/plet/minimal.ts index d8787b63..f48f0c7b 100644 --- a/packages/onchain/src/pluts/lib/plet/minimal.ts +++ b/packages/onchain/src/pluts/lib/plet/minimal.ts @@ -10,9 +10,9 @@ export function _plet( varVal { return new Term( varValue.type, - dbn => { + (cfg, dbn) => { - const ir = varValue.toIR( dbn ); + const ir = varValue.toIR( cfg, dbn ); // `compileIRToUPLC` can handle it even if this check is not present // but why spend useful tree iterations if we can avoid them here? diff --git a/packages/onchain/src/pluts/lib/plet/old.ts b/packages/onchain/src/pluts/lib/plet/old.ts index a85d2359..d50f7258 100644 --- a/packages/onchain/src/pluts/lib/plet/old.ts +++ b/packages/onchain/src/pluts/lib/plet/old.ts @@ -26,10 +26,10 @@ export function _old_plet( va const letted = new Term( type, - dbn => + (cfg, dbn) => new IRLetted( Number( dbn ), - varValue.toIR( dbn ) + varValue.toIR( cfg, dbn ) ) ); @@ -50,8 +50,8 @@ export function _old_plet( va const term = addUtilityForType( outType )( new Term( outType, - dbn => { - const arg = varValue.toIR( dbn ); + (cfg, dbn) => { + const arg = varValue.toIR( cfg, dbn ); if( // inline variables; no need to add an application since already in scope @@ -59,7 +59,7 @@ export function _old_plet( va arg instanceof IRSelfCall ) { - return expr( withUtility( varValue as any ) as any ).toIR( dbn ); + return expr( withUtility( varValue as any ) as any ).toIR( cfg, dbn ); } return new IRApp( @@ -69,10 +69,10 @@ export function _old_plet( va withUtility( new Term( varValue.type, - varAccessDbn => new IRVar( varAccessDbn - ( dbn + BigInt(1) ) ) // point to the lambda generated here + (cfg, varAccessDbn) => new IRVar( varAccessDbn - ( dbn + BigInt(1) ) ) // point to the lambda generated here ) as any ) as any - ).toIR( ( dbn + BigInt(1) ) ) + ).toIR( cfg, dbn + BigInt(1) ) ), arg ) diff --git a/packages/onchain/src/pluts/lib/pmatch/getElemAtTerm.ts b/packages/onchain/src/pluts/lib/pmatch/getElemAtTerm.ts index e702b609..8165b91b 100644 --- a/packages/onchain/src/pluts/lib/pmatch/getElemAtTerm.ts +++ b/packages/onchain/src/pluts/lib/pmatch/getElemAtTerm.ts @@ -57,7 +57,7 @@ export function getElemAtTerm( n: number ): TermFn<[ PList ], PData > ( lst: Term>) => new Term( data, - dbn => new IRApp( uplc.clone(), lst.toIR(dbn) ) + (cfg, dbn) => new IRApp( uplc.clone(), lst.toIR( cfg, dbn) ) ) ); diff --git a/packages/onchain/src/pluts/lib/pmatch/pmatchSop.ts b/packages/onchain/src/pluts/lib/pmatch/pmatchSop.ts index 7e6312cd..2f0af7f6 100644 --- a/packages/onchain/src/pluts/lib/pmatch/pmatchSop.ts +++ b/packages/onchain/src/pluts/lib/pmatch/pmatchSop.ts @@ -75,9 +75,9 @@ export function pmatchSop( sopTerm: Term( returnT, - dbn => new IRCase( - sopTerm.toIR( dbn ), - continuationTerms.map( term => term.toIR( dbn ) ) + (cfg, dbn) => new IRCase( + sopTerm.toIR( cfg, dbn ), + continuationTerms.map( term => term.toIR( cfg, dbn ) ) ) ); @@ -126,9 +126,9 @@ export function pmatchSop( sopTerm: Term( returnT, - dbn => new IRCase( - sopTerm.toIR( dbn ), - continuationTerms.map( term => term.toIR( dbn ) ) + (cfg, dbn) => new IRCase( + sopTerm.toIR(cfg, dbn ), + continuationTerms.map( term => term.toIR( cfg, dbn ) ) ) );; } @@ -177,7 +177,7 @@ function makeConstrContinuationTerm( fields.map( f => ctorDef[f] ) as any, returnT ), - dbn => { + (cfg, dbn) => { const fstArgLambdaPtr = dbn + BigInt( 1 ); @@ -192,7 +192,7 @@ function makeConstrContinuationTerm( value: addUtilityForType( t )( new Term( t, - dbnAccessLevel => new IRVar( + (cfg, dbnAccessLevel) => new IRVar( dbnAccessLevel - (fstArgLambdaPtr + BigInt( i )) ) ) @@ -206,7 +206,7 @@ function makeConstrContinuationTerm( const body = cb( sInstance ); - return new IRFunc( nFields, body.toIR( dbn + BigInt( nFields ) ) ); + return new IRFunc( nFields, body.toIR( cfg, dbn + BigInt( nFields ) ) ); } ) } \ No newline at end of file diff --git a/packages/onchain/src/pluts/lib/precursive/minimal.ts b/packages/onchain/src/pluts/lib/precursive/minimal.ts index 68d4cc86..927a81fa 100644 --- a/packages/onchain/src/pluts/lib/precursive/minimal.ts +++ b/packages/onchain/src/pluts/lib/precursive/minimal.ts @@ -59,8 +59,8 @@ export function _precursive const recursiveFn = new Term( fnBody.type[2] as TermType, - dbn => { - const fnBodyIr = assertArity2AndRemoveFirst( fnBody.toIR( dbn ) ); + (cfg, dbn) => { + const fnBodyIr = assertArity2AndRemoveFirst( fnBody.toIR( cfg, dbn ) ); replaceSelfVars( fnBodyIr ); diff --git a/packages/onchain/src/pluts/lib/std/UtilityTerms/TermBool.ts b/packages/onchain/src/pluts/lib/std/UtilityTerms/TermBool.ts index 30864770..ac68536b 100644 --- a/packages/onchain/src/pluts/lib/std/UtilityTerms/TermBool.ts +++ b/packages/onchain/src/pluts/lib/std/UtilityTerms/TermBool.ts @@ -34,9 +34,9 @@ function pdelay(toDelay: Term): Term { + (cfg, dbn) => { return new IRDelayed( - toDelay.toIR( dbn ) + toDelay.toIR( cfg, dbn ) ); } ); diff --git a/packages/onchain/src/pluts/lib/std/UtilityTerms/TermList.ts b/packages/onchain/src/pluts/lib/std/UtilityTerms/TermList.ts index 9cc9e934..fd616091 100644 --- a/packages/onchain/src/pluts/lib/std/UtilityTerms/TermList.ts +++ b/packages/onchain/src/pluts/lib/std/UtilityTerms/TermList.ts @@ -203,7 +203,7 @@ export function addPListMethods( _lst: Term _lst.toIR( dbn ), + (cfg, dbn) => _lst.toIR( cfg, dbn ), (_lst as any).isConstant ) as any; diff --git a/packages/onchain/src/pluts/lib/std/UtilityTerms/TermStruct.ts b/packages/onchain/src/pluts/lib/std/UtilityTerms/TermStruct.ts index 9bf41f45..183e6cf5 100644 --- a/packages/onchain/src/pluts/lib/std/UtilityTerms/TermStruct.ts +++ b/packages/onchain/src/pluts/lib/std/UtilityTerms/TermStruct.ts @@ -94,11 +94,11 @@ export function addPStructMethods< const letted_fieldsListData = new Term>( list( data ), - dbn => new IRLetted( + (cfg, dbn) => new IRLetted( Number(dbn), new IRApp( hoisted_getFields.clone(), - struct.toIR( dbn ) + struct.toIR( cfg, dbn ) ) ) ); @@ -146,33 +146,33 @@ export function addPStructMethods< const letted_unconstred = new Term>>( pair( int, list( data )), - dbn => new IRLetted( + (cfg, dbn) => new IRLetted( Number(dbn), new IRApp( IRNative.unConstrData, - struct.toIR( dbn ) + struct.toIR( cfg, dbn ) ) ) ); const letted_ctorIdx = new Term( int, - dbn => new IRLetted( + (cfg, dbn) => new IRLetted( Number(dbn), new IRApp( IRNative.fstPair, - letted_unconstred.toIR( dbn ) + letted_unconstred.toIR( cfg, dbn ) ) ) ); const letted_rawFields = new Term>( list( data ), - dbn => new IRLetted( + (cfg, dbn) => new IRLetted( Number(dbn), new IRApp( IRNative.sndPair, - letted_unconstred.toIR( dbn ) + letted_unconstred.toIR( cfg, dbn ) ) ) ); diff --git a/packages/onchain/src/pluts/lib/std/UtilityTerms/mockUtilityTerms/mockPListMethods.ts b/packages/onchain/src/pluts/lib/std/UtilityTerms/mockUtilityTerms/mockPListMethods.ts index a587b837..feead018 100644 --- a/packages/onchain/src/pluts/lib/std/UtilityTerms/mockUtilityTerms/mockPListMethods.ts +++ b/packages/onchain/src/pluts/lib/std/UtilityTerms/mockUtilityTerms/mockPListMethods.ts @@ -27,7 +27,7 @@ export function mockPListMethods( lst: Term lst.toIR( dbn ), + (cfg, dbn) => lst.toIR( cfg, dbn ), (lst as any).isConstant ) as any; diff --git a/packages/onchain/src/pluts/lib/std/data/conversion/minimal_common.ts b/packages/onchain/src/pluts/lib/std/data/conversion/minimal_common.ts index 7021d25c..e1bb7d8c 100644 --- a/packages/onchain/src/pluts/lib/std/data/conversion/minimal_common.ts +++ b/packages/onchain/src/pluts/lib/std/data/conversion/minimal_common.ts @@ -17,9 +17,9 @@ export function _papp( a: Term new IRApp( - a.toIR(dbn), - b.toIR(dbn) + (cfg, dbn) => new IRApp( + a.toIR(cfg, dbn), + b.toIR(cfg, dbn) ) ) } @@ -34,18 +34,18 @@ export function _plam( inputType: A, ou ) => new Term,ToPType>>( lam( inputType, outputType ) as any, - dbn => { + (cfg, dbn) => { const thisLambdaPtr = dbn + BigInt( 1 ); const boundVar = new Term>( inputType as any, - dbnAccessLevel => new IRVar( dbnAccessLevel - thisLambdaPtr ) + (cfg, dbnAccessLevel) => new IRVar( dbnAccessLevel - thisLambdaPtr ) ); const body = termFunc( boundVar ); // here the debruijn level is incremented - return new IRFunc( 1, body.toIR( thisLambdaPtr ) ); + return new IRFunc( 1, body.toIR( cfg, thisLambdaPtr ) ); } ); } diff --git a/packages/onchain/src/pluts/lib/std/list/__tests__/list.const.pnil.test.ts b/packages/onchain/src/pluts/lib/std/list/__tests__/list.const.pnil.test.ts index 0204f9db..a5a6e856 100644 --- a/packages/onchain/src/pluts/lib/std/list/__tests__/list.const.pnil.test.ts +++ b/packages/onchain/src/pluts/lib/std/list/__tests__/list.const.pnil.test.ts @@ -1,13 +1,14 @@ import { Application, Builtin, UPLCConst, showUPLC } from "@harmoniclabs/uplc"; import { bs, data, int, pair } from "../../../../type_system" import { pnil } from "../const" +import { debugOptions } from "../../../../../IR/toUPLC/CompilerOptions"; describe("pnil", () => { test("just data", () => { const received = showUPLC( - pnil( data ).toUPLC(0) + pnil( data ).toUPLC(0, debugOptions) ); const expected = showUPLC( new Application( Builtin.mkNilData, UPLCConst.unit ) @@ -26,7 +27,7 @@ describe("pnil", () => { expect( showUPLC( - pnil( pair( data, data ) ).toUPLC(0) + pnil( pair( data, data ) ).toUPLC(0, debugOptions) ) ) .toEqual( @@ -41,7 +42,7 @@ describe("pnil", () => { expect( showUPLC( - pnil( pair( int, bs ) ).toUPLC(0) + pnil( pair( int, bs ) ).toUPLC(0, debugOptions) ) ) .toEqual( @@ -56,7 +57,7 @@ describe("pnil", () => { expect( showUPLC( - pnil( pair( data, data ) ).toUPLC(0) + pnil( pair( data, data ) ).toUPLC(0, debugOptions) ) ) .toEqual( diff --git a/packages/onchain/src/pluts/lib/std/list/const/index.ts b/packages/onchain/src/pluts/lib/std/list/const/index.ts index e27bbedf..77aa9768 100644 --- a/packages/onchain/src/pluts/lib/std/list/const/index.ts +++ b/packages/onchain/src/pluts/lib/std/list/const/index.ts @@ -73,7 +73,7 @@ export function pconstList( elemsT: ElemsT ): ( elems: return addPListMethods( new Term>>( list( elemsT ), - dbn => { + (cfg, dbn) => { return IRConst.listOf( elemsT ) ( elems.map(