Skip to content

Commit

Permalink
Temp interpreter (#263)
Browse files Browse the repository at this point in the history
* add text language

* lint

* add hardcode plugin

* use compilationOptions func

* ensure names are preserved

* cleanup

* implement no:hardcode test flag
  • Loading branch information
MichalMarsalek authored Nov 13, 2023
1 parent 1bfaed1 commit 01923e4
Show file tree
Hide file tree
Showing 17 changed files with 192 additions and 12 deletions.
22 changes: 18 additions & 4 deletions src/common/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
} from "./objective";
import { readsFromArgv, readsFromStdin } from "./symbols";
import { PolygolfError } from "./errors";
import { getOutput } from "../interpreter";

export type OptimisationLevel = "nogolf" | "simple" | "full";
export interface CompilationOptions {
Expand All @@ -25,6 +26,7 @@ export interface CompilationOptions {
skipTypecheck: boolean;
restrictFrontend: boolean;
codepointRange: [number, number];
skipPlugins: string[];
}

export function compilationOptions(
Expand All @@ -37,6 +39,7 @@ export function compilationOptions(
skipTypecheck: partial.skipTypecheck ?? false,
restrictFrontend: partial.restrictFrontend ?? true,
codepointRange: partial.codepointRange ?? [1, Infinity],
skipPlugins: [],
};
}

Expand Down Expand Up @@ -257,6 +260,10 @@ export function compileVariant(
options: CompilationOptions,
language: Language,
): CompilationResult {
if (options.level !== "nogolf")
try {
getOutput(program); // precompute output
} catch {}
const obj = getObjectiveFunc(options);
let best = compileVariantNoPacking(program, options, language);
const packers = language.packers ?? [];
Expand Down Expand Up @@ -307,8 +314,15 @@ export function compileVariantNoPacking(
options: CompilationOptions,
language: Language,
): CompilationResult {
const phases = language.phases;
if (options.level === "nogolf" || options.level === "simple") {
const phases = language.phases.map((x) => ({
mode: x.mode,
plugins: x.plugins.filter((x) => !options.skipPlugins.includes(x.name)),
}));
if (
phases.length < 1 ||
options.level === "nogolf" ||
options.level === "simple"
) {
try {
const warnings: Error[] = [];
const addWarning = (x: Error) => warnings.push(x);
Expand Down Expand Up @@ -383,7 +397,7 @@ export function compileVariantNoPacking(
history: [number, string][],
warnings: Error[],
) {
if (startPhase >= language.phases.length) return;
if (startPhase >= phases.length) return;
if (latestPhaseWeSawTheProg.size > 200) return;
const stringified = stringify(program);
const latestSeen = latestPhaseWeSawTheProg.get(stringified);
Expand Down Expand Up @@ -414,7 +428,7 @@ export function compileVariantNoPacking(

while (!queue.isEmpty()) {
const state = queue.dequeue();
const phase = language.phases[state.startPhase];
const phase = phases[state.startPhase];
const warnings = [...state.warnings];

function addWarning(x: Error, isGlobal: boolean) {
Expand Down
86 changes: 86 additions & 0 deletions src/interpreter/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { programToSpine } from "../common/Spine";
import {
type Node,
block,
functionCall,
isBuiltinIdent,
isOfKind,
} from "../IR";
import { readsFromInput } from "../common/symbols";
import { PolygolfError } from "../common/errors";
import { compilationOptions, compileVariant } from "../common/compile";
import javascriptLanguage from "../languages/javascript";
import { required } from "../common/Language";
import { addVarDeclarations } from "../plugins/block";

const javascriptForInterpreting = {
...javascriptLanguage,
phases: [
...javascriptLanguage.phases,
required(addVarDeclarations, {
name: "instrument",
visit(node, spine) {
const parent = spine.parent?.node;
if (
parent !== undefined &&
spine.pathFragment === "body" &&
isOfKind("While", "ForEach", "ForEachKey", "ForCLike")(parent) &&
(node.kind !== "Block" ||
node.children[0].kind !== "FunctionCall" ||
!isBuiltinIdent("instrument")(node.children[0].func))
) {
return block([functionCall("instrument"), node]);
}
},
}),
],
};

const outputCache = new Map<Node, unknown>();

export function getOutput(program: Node) {
if (!outputCache.has(program)) {
try {
outputCache.set(program, _getOutput(program));
} catch (e) {
outputCache.set(program, e);
}
}
const res = outputCache.get(program);
if (typeof res === "string") return res;
throw res;
}

function _getOutput(program: Node): string {
const spine = programToSpine(program);
if (spine.someNode(readsFromInput))
throw new PolygolfError("Program reads from input.");
const jsCode = compileVariant(
program,
compilationOptions({ level: "nogolf" }),
javascriptForInterpreting,
);
if (typeof jsCode.result !== "string") {
throw jsCode.result;
}
let output = "";
function print(x: string) {
output += x + "\n";
}
function write(x: string) {
output += x;
}
const start = Date.now();
function instrument() {
if (Date.now() - start > 500)
throw new PolygolfError("Program took too long to interpret.");
}
/* eslint-disable */
new Function("print", "write", "instrument", jsCode.result)(
print,
write,
instrument,
);
/* eslint-enable */
return output;
}
2 changes: 2 additions & 0 deletions src/languages/golfscript/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,14 @@ import {
replaceToSplitAndJoin,
} from "../../plugins/textOps";
import { inlineVariables } from "../../plugins/block";
import { hardcode } from "../../plugins/static";

const golfscriptLanguage: Language = {
name: "Golfscript",
extension: "gs",
emitter: emitProgram,
phases: [
search(hardcode()),
required(printIntToPrint),
search(
flipBinaryOps,
Expand Down
2 changes: 2 additions & 0 deletions src/languages/javascript/emit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ export default function emitProgram(
const prec = precedence(expr);
function emitNoParens(e: IR.Node): TokenTree {
switch (e.kind) {
case "VarDeclarationWithAssignment":
return ["let", emit(e.assignment)];
case "Block":
return expr === program
? joinNodes("\n", e.children)
Expand Down
3 changes: 2 additions & 1 deletion src/languages/javascript/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
forRangeToForCLike,
forRangeToForEach,
} from "../../plugins/loops";
import { golfStringListLiteral } from "../../plugins/static";
import { golfStringListLiteral, hardcode } from "../../plugins/static";
import { golfLastPrint, implicitlyConvertPrintArg } from "../../plugins/print";
import {
useDecimalConstantPackedPrinter,
Expand Down Expand Up @@ -68,6 +68,7 @@ const javascriptLanguage: Language = {
extension: "js",
emitter: emitProgram,
phases: [
search(hardcode()),
required(printIntToPrint),
search(
golfStringListLiteral(),
Expand Down
2 changes: 2 additions & 0 deletions src/languages/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import pythonLanguage from "./python";
import swiftLanguage from "./swift";
import golfscriptLanguage from "./golfscript";
import javascriptLanguage from "./javascript";
import textLanguage from "./text";

const languages = [
golfscriptLanguage,
Expand All @@ -15,6 +16,7 @@ const languages = [
swiftLanguage,
polygolfLanguage,
javascriptLanguage,
textLanguage,
];

export default languages;
Expand Down
3 changes: 2 additions & 1 deletion src/languages/lua/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,15 @@ import {
pickAnyInt,
useIntegerTruthiness,
} from "../../plugins/arithmetic";
import { listOpsToTextOps } from "../../plugins/static";
import { hardcode, listOpsToTextOps } from "../../plugins/static";
import { base10DecompositionToFloatLiteralAsBuiltin } from "./plugins";

const luaLanguage: Language = {
name: "Lua",
extension: "lua",
emitter: emitProgram,
phases: [
search(hardcode()),
required(printIntToPrint),
search(
flipBinaryOps,
Expand Down
7 changes: 6 additions & 1 deletion src/languages/nim/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ import {
removeUnusedForVar,
shiftRangeOneUp,
} from "../../plugins/loops";
import { golfStringListLiteral, listOpsToTextOps } from "../../plugins/static";
import {
golfStringListLiteral,
hardcode,
listOpsToTextOps,
} from "../../plugins/static";
import { golfLastPrint, implicitlyConvertPrintArg } from "../../plugins/print";
import {
useDecimalConstantPackedPrinter,
Expand Down Expand Up @@ -78,6 +82,7 @@ const nimLanguage: Language = {
extension: "nim",
emitter: emitProgram,
phases: [
search(hardcode()),
required(printIntToPrint),
search(
flipBinaryOps,
Expand Down
4 changes: 2 additions & 2 deletions src/languages/nim/nim.test.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ b or b
## Misc

```polygolf
print (list_get (text_split "abc" "b") 0);
println (list_get (text_split "abc" "b") 0);
```

```nim
```nim nogolf
include re
"abc".split"b"[0].echo
```
Expand Down
7 changes: 6 additions & 1 deletion src/languages/python/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ import {
forRangeToForRangeOneStep,
removeUnusedForVar,
} from "../../plugins/loops";
import { golfStringListLiteral, listOpsToTextOps } from "../../plugins/static";
import {
golfStringListLiteral,
hardcode,
listOpsToTextOps,
} from "../../plugins/static";
import { golfLastPrint, implicitlyConvertPrintArg } from "../../plugins/print";
import {
packSource2to1,
Expand Down Expand Up @@ -77,6 +81,7 @@ const pythonLanguage: Language = {
extension: "py",
emitter: emitProgram,
phases: [
search(hardcode()),
required(printIntToPrint),
search(
golfStringListLiteral(),
Expand Down
2 changes: 1 addition & 1 deletion src/languages/python/python.test.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ if ($a != 0) {
$a <- 1;
```

```python
```python no:hardcode
a=1
if a:print(a)
a=1
Expand Down
7 changes: 6 additions & 1 deletion src/languages/swift/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ import {
printIntToPrint,
} from "../../plugins/ops";
import { alias, renameIdents } from "../../plugins/idents";
import { golfStringListLiteral, listOpsToTextOps } from "../../plugins/static";
import {
golfStringListLiteral,
hardcode,
listOpsToTextOps,
} from "../../plugins/static";
import { golfLastPrint, implicitlyConvertPrintArg } from "../../plugins/print";
import { assertInt64 } from "../../plugins/types";
import {
Expand Down Expand Up @@ -66,6 +70,7 @@ const swiftLanguage: Language = {
extension: "swift",
emitter: emitProgram,
phases: [
search(hardcode()),
required(printIntToPrint),
search(
flipBinaryOps,
Expand Down
11 changes: 11 additions & 0 deletions src/languages/text/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { getOutput } from "../../interpreter";
import type { Language } from "../../common/Language";

const textLanguage: Language = {
name: "Text",
extension: "txt",
phases: [],
emitter: getOutput,
};

export default textLanguage;
25 changes: 25 additions & 0 deletions src/languages/text/text.test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Text

```polygolf
% Printing
println "Hello, World!";
% Looping
for $i 0 10 {
println_int $i;
};
```

```txt
Hello, World!
0
1
2
3
4
5
6
7
8
9
```
2 changes: 2 additions & 0 deletions src/markdown-tests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const keywords = [
"restrictFrontend",
"1..127",
"32..127",
"no:hardcode",
] as const;

export function compilationOptionsFromKeywords(
Expand All @@ -40,6 +41,7 @@ export function compilationOptionsFromKeywords(
getAllVariants: is("allVariants"),
restrictFrontend: is("restrictFrontend"),
skipTypecheck: isLangTest ? is("skipTypecheck") : !is("typecheck"),
skipPlugins: is("no:hardcode") ? ["hardcode"] : [],
};
}

Expand Down
4 changes: 4 additions & 0 deletions src/plugins/idents.test.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ println_int 12345;
println_int 12345;
println_int 12345;
println "text";
println (argv_get 0);
```

<!-- alias plugin cannot be tested directly yet, so we test it on Python -->

```py
import sys
p=print
t="text"
a=12345
Expand All @@ -37,4 +40,5 @@ p(a)
p(a)
p(a)
p(t)
p(sys.argv[1])
```
Loading

0 comments on commit 01923e4

Please sign in to comment.