Skip to content

Commit

Permalink
Opt in support to return control flow separately from branch instruct…
Browse files Browse the repository at this point in the history
…ions (#43)

This gives access to the value even when branching multiple times
  • Loading branch information
swazrgb authored Apr 2, 2024
1 parent 93dfff9 commit 872d930
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 20 deletions.
28 changes: 19 additions & 9 deletions compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1895,7 +1895,8 @@ class Compiler {
}
let outDefs = typeof info.out === "number" ? [info.out] : info.out;
outDefs?.forEach((v, i) => {
args[v] = outs[i] || nilReg;
// First out is reserved for control value if executing branching instructions that opts into it
args[v] = outs[info.firstArgControlFlow ? i + 1 : i] || nilReg;
});

if (info.exec != null) {
Expand Down Expand Up @@ -2344,14 +2345,23 @@ class Compiler {
);
}
});

if (decl.initializer && ts.isCallExpression(decl.initializer)) {
return this.compileCall(decl.initializer, outs);
} else {
this.#error(
"only call expression are valid for array initializer",
decl,
);
if (decl.initializer) {
if (ts.isCallExpression(decl.initializer)) {
return this.compileCall(decl.initializer, outs);
} else if (ts.isPropertyAccessExpression(decl.initializer)) {
return this.compileResolvedCall(
decl,
decl.initializer.name.text,
decl.initializer.expression,
[],
outs,
);
} else {
this.#error(
"only call expression are valid for array initializer",
decl,
);
}
}
} else {
this.#error("Unable to bind object", decl);
Expand Down
38 changes: 27 additions & 11 deletions scripts/geninstr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ interface GenInfo {
inArgs: [number, ...ArgInfo][];
outArgs: [number, ...ArgInfo][];
execArgs: [number, ...ArgInfo][];
firstArgControlFlow?: boolean;
}

interface CompileInfo {
Expand All @@ -91,6 +92,7 @@ interface CompileInfo {
special?: "txt" | "bp";
c?: number;
bp?: boolean;
firstArgControlFlow?: boolean;
}

const instructions = gameData.instructions as unknown as {
Expand Down Expand Up @@ -232,6 +234,9 @@ function generateCompile(genInfo: GenInfo) {
if (genInfo.bp) {
info.bp = genInfo.bp;
}
if (genInfo.firstArgControlFlow) {
info.firstArgControlFlow = true;
}
compileInfos[genInfo.js] = info;
}

Expand Down Expand Up @@ -353,21 +358,30 @@ ${indent}`;
}

function makeConditionType(genInfo: GenInfo, returnType: string): string {
if (genInfo.outArgs.length > 0) {
return `${returnType} | undefined`;
}
const values = [...Object.values(genInfo.conditions!)];
let conditionType: string;
if (values.every((v) => typeof v == "boolean")) {
return "boolean";
conditionType = "boolean";
} else {
conditionType = values
.filter((v) => typeof v === "string")
.map((v) => `"${v}"`)
.join(" | ");
if (values.some((v) => typeof v !== "string")) {
conditionType = `${conditionType} | undefined`;
}
}
returnType = values
.filter((v) => typeof v === "string")
.map((v) => `"${v}"`)
.join(" | ");
if (values.some((v) => typeof v !== "string")) {
return `${returnType} | undefined`;

if (genInfo.outArgs.length > 0) {
if (genInfo.firstArgControlFlow) {
returnType = returnType.replace(/^\[|\]$/g, "");
return `[${conditionType}, ${returnType}]`;
} else {
return `${returnType} | undefined`;
}
} else {
return conditionType;
}
return returnType;
}

function uniqify(params: ParamInfo[]) {
Expand Down Expand Up @@ -427,6 +441,7 @@ fs.writeFileSync(
c?: number;
sub?: string;
bp?: boolean;
firstArgControlFlow?: boolean;
}
export const methods: { [key: string]: MethodInfo } = ${JSON.stringify(
compileInfos,
Expand Down Expand Up @@ -739,6 +754,7 @@ interface InstrInfo {
outArgs?: number[];
execArgs?: number[];
optional?: number;
firstArgControlFlow?: boolean;
}
export const instructions:{[key:string]:InstrInfo} = ${JSON.stringify(
decompileInfos,
Expand Down
5 changes: 5 additions & 0 deletions scripts/overrides.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@
"B": false
},
"outArgs": []
},
{
"js": "selectNearest",
"type": "function",
"firstArgControlFlow": true
}
],
"type": "operator"
Expand Down
19 changes: 19 additions & 0 deletions tests/__snapshots__/compile.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,25 @@ exports[`call_with_computation.ts 1`] = `
.ret "
`;

exports[`first_arg_control_flow.ts 1`] = `
"foo:
.name "foo"
.pname p1, "v"
select_nearest :l1, :l2, p1, signal, A
jump :l3
l1:
notify A, $txt="A is closest"
jump :l0
l2:
notify A, $txt="B is closest"
jump :l0
l3:
notify $txt="Default branch"
jump :l0
l0:
.ret "
`;

exports[`if_unit_type.ts 1`] = `
"test:
.name "test"
Expand Down
14 changes: 14 additions & 0 deletions tests/first_arg_control_flow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export function foo(v: Value) {
let [branch, nearest] = selectNearest(v, signal);
switch (branch) {
case "A":
notify("A is closest", nearest);
break;
case "B":
notify("B is closest", nearest);
break;
default:
notify("Default branch");
break;
}
}

0 comments on commit 872d930

Please sign in to comment.