Skip to content

Commit

Permalink
pass test simple uplc
Browse files Browse the repository at this point in the history
  • Loading branch information
michele-nuzzi committed Oct 29, 2024
1 parent 5ebfeed commit 2399478
Show file tree
Hide file tree
Showing 34 changed files with 778 additions and 122 deletions.
3 changes: 2 additions & 1 deletion packages/onchain/src/IR/interfaces/ToIR.ts
Original file line number Diff line number Diff line change
@@ -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
}
128 changes: 117 additions & 11 deletions packages/onchain/src/IR/toUPLC/CompilerOptions.ts
Original file line number Diff line number Diff line change
@@ -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<CompilerUplcOptimizations> = {}
): 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<CompilerUplcOptimizations>,
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
*
Expand All @@ -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<CompilerUplcOptimizations>;
/**
*
**/
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<CompilerOptions>,
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
};
}
17 changes: 11 additions & 6 deletions packages/onchain/src/IR/toUPLC/__tests__/compileIR.natives.test.ts
Original file line number Diff line number Diff line change
@@ -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", () => {
Expand All @@ -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(
Expand All @@ -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
)
)

});
Expand Down
24 changes: 23 additions & 1 deletion packages/onchain/src/IR/toUPLC/compileIRToUPLC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {

Expand Down Expand Up @@ -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 )
Expand Down Expand Up @@ -252,7 +253,7 @@ describe("handleLettedAndReturnRoot", () => {

// logJson( root, 4 )

const compiled = compileIRToUPLC( root );
const compiled = compileIRToUPLC( root, debugOptions );

expect(
showUPLC( compiled )
Expand Down Expand Up @@ -325,7 +326,7 @@ describe("handleLettedAndReturnRoot", () => {
)
);

const compiled = compileIRToUPLC( root );
const compiled = compileIRToUPLC( root, { ...productionOptions, addMarker: false } );

expect( showUPLC( compiled ) )
.toEqual(
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 2399478

Please sign in to comment.