Rename directory "engines" to "languages"

This commit is contained in:
Nilay Majorwar
2022-01-30 20:47:33 +05:30
parent 0bf7c0de3a
commit e3be5a8a83
82 changed files with 27 additions and 21 deletions

View File

@ -0,0 +1,8 @@
# Deadfish
## Allowed symbols
- `i`: Increment value by 1
- `d`: Decrement value by 1
- `s`: Square the value
- `o`: Output the value

View File

@ -0,0 +1,45 @@
import { MonacoTokensProvider } from "../types";
export type DFRS = {
value: number;
};
export enum DF_OP {
INCR = "i",
DECR = "d",
SQ = "s",
OUT = "o",
}
/** A single element of the program's AST */
export type DFAstStep = {
instr: DF_OP;
location: { line: number; char: number };
};
/** Sample program printing "Hello world" */
export const sampleProgram = [
"iisiiiisiiiiiiiio",
"iiiiiiiiiiiiiiiiiiiiiiiiiiiiio",
"iiiiiiioo",
"iiio",
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddo",
"dddddddddddddddddddddsddo",
"ddddddddo",
"iiio",
"ddddddo",
"ddddddddo",
].join("\n");
/** Tokens provider */
export const editorTokensProvider: MonacoTokensProvider = {
tokenizer: {
root: [
[/i/, "orange"],
[/d/, "red"],
[/s/, "blue"],
[/o/, "green"],
],
},
defaultToken: "comment",
};

View File

@ -0,0 +1,4 @@
import { setupWorker } from "../setup-worker";
import DeadfishLanguageEngine from "./runtime";
setupWorker(new DeadfishLanguageEngine());

View File

@ -0,0 +1,11 @@
import { Renderer } from "./renderer";
import { LanguageProvider } from "../types";
import { DFRS, sampleProgram, editorTokensProvider } from "./constants";
const provider: LanguageProvider<DFRS> = {
Renderer,
sampleProgram,
editorTokensProvider,
};
export default provider;

View File

@ -0,0 +1,24 @@
import { RendererProps } from "../types";
import { DFRS } from "./constants";
const styles = {
container: {
width: "100%",
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
},
text: {
fontSize: "4em",
},
};
export const Renderer = ({ state }: RendererProps<DFRS>) => {
const value = state == null ? 0 : state.value;
return (
<div style={styles.container}>
<h1 style={styles.text}>{value}</h1>
</div>
);
};

View File

@ -0,0 +1,88 @@
import { DocumentRange, LanguageEngine, StepExecutionResult } from "../types";
import { DFAstStep, DFRS, DF_OP } from "./constants";
// Default values for internal states
// Factories are used to create new objects on reset
const DEFAULT_AST = (): DFAstStep[] => [];
const DEFAULT_PC = -1;
const DEFAULT_VALUE = 0;
// Instruction characters
const OP_CHARS = Object.values(DF_OP);
export default class DeadfishLanguageEngine implements LanguageEngine<DFRS> {
private _ast: DFAstStep[] = DEFAULT_AST();
private _value: number = DEFAULT_VALUE;
private _pc: number = DEFAULT_PC;
resetState() {
this._ast = DEFAULT_AST();
this._value = DEFAULT_VALUE;
this._pc = DEFAULT_PC;
}
validateCode(code: string) {
this.parseCode(code);
}
prepare(code: string, _input: string) {
this._ast = this.parseCode(code);
}
executeStep(): StepExecutionResult<DFRS> {
// Execute and update program counter
let output: string | undefined = undefined;
if (this._pc !== -1) {
const astStep = this._ast[this._pc];
output = this.processOp(astStep.instr);
}
this._pc += 1;
// Prepare location of next step
let nextStepLocation: DocumentRange | null = null;
if (this._pc < this._ast.length) {
const { line, char } = this._ast[this._pc].location;
const charRange = { start: char, end: char + 1 };
nextStepLocation = { line, charRange };
}
// Prepare and return execution result
const rendererState = { value: this._value };
return { rendererState, nextStepLocation, output };
}
private parseCode(code: string) {
const ast: DFAstStep[] = [];
// For each line...
code.split("\n").forEach((line, lIdx) => {
// For each character of this line...
line.split("").forEach((char, cIdx) => {
if (OP_CHARS.includes(char as DF_OP)) {
ast.push({
instr: char as DF_OP,
location: { line: lIdx, char: cIdx },
});
}
});
});
return ast;
}
/**
* Process the given instruction and return string to push to output if any.
*
* @param instr Instruction to apply
* @returns String to append to output, if any
*/
private processOp(instr: DF_OP): string | undefined {
if (instr === DF_OP.INCR) ++this._value;
else if (instr === DF_OP.DECR) --this._value;
else if (instr === DF_OP.SQ) this._value = this._value * this._value;
else if (instr === DF_OP.OUT) return this._value.toString();
else throw new Error("Invalid instruction");
if (this._value === -1 || this._value === 256) this._value = 0;
}
}

View File

@ -0,0 +1 @@
diissisdo

View File

@ -0,0 +1,3 @@
iisiiiisiiiiiiiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiooiiio
dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddo
dddddddddddddddddddddsddoddddddddoiiioddddddoddddddddo

View File

@ -0,0 +1,40 @@
import { readTestProgram, executeProgram } from "../../test-utils";
import Engine from "../runtime";
/**
* All test programs are picked up from https://esolangs.org/wiki/Deadfish.
*/
describe("Test programs", () => {
// Standard hello-world program
test("hello world", async () => {
const code = readTestProgram(__dirname, "helloworld");
const result = await executeProgram(new Engine(), code);
expect(result.output).toBe("7210110810811132119111114108100");
expect(result.rendererState.value).toBe(100);
});
// Test program 1, output 0
test("output zero (1)", async () => {
const code = readTestProgram(__dirname, "zero1");
const result = await executeProgram(new Engine(), code);
expect(result.output).toBe("0");
expect(result.rendererState.value).toBe(0);
});
// Test program 2, output 0
test("output zero (2)", async () => {
const code = readTestProgram(__dirname, "zero2");
const result = await executeProgram(new Engine(), code);
expect(result.output).toBe("0");
expect(result.rendererState.value).toBe(0);
});
// Test program 3, output 288
test("output 288", async () => {
const code = readTestProgram(__dirname, "288");
const result = await executeProgram(new Engine(), code);
expect(result.output).toBe("288");
expect(result.rendererState.value).toBe(288);
});
});

View File

@ -0,0 +1 @@
iissso

View File

@ -0,0 +1 @@
iissisdddddddddddddddddddddddddddddddddo