-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.ts
103 lines (90 loc) · 3.18 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { readdirSync, readFileSync } from "fs";
import { join } from "path";
import { isLeft } from "fp-ts/lib/Either";
import yargs from "yargs";
import { runProgram } from "./full_pipeline";
import { NativeFunctionImplementations } from "./evaluator";
import { clock, defineReadString, parseNum, print } from "./main_native_implementations";
// async wrapper to allow using await; top-level await requires ES Modules, which ts-jest 26 doesn't support
(async () => {
const rawArgs = process.argv.slice(2); // ignore "node", JS filename
// use Promise.resolve() to convert T | Promise<T> into a Promise<T>
const processedArgs = await Promise.resolve(
yargs(rawArgs)
.options({
files: { alias: "f", type: "array" },
args: { alias: "a", type: "array" },
})
.demandOption("files").argv,
);
const stringifiedArgs = {
files: processedArgs.files.map((fileName) => fileName.toString()),
args: processedArgs.args?.map((arg) => arg.toString()),
};
const createArgsText = (args: Array<string> | undefined): Array<string> => {
const modulePrologue = `
module Args
{
import LinkedList from StdCollections;
let args = LinkedList();
`;
const argInitializationText: Array<string> = [];
args?.forEach((arg) => {
argInitializationText.push(`
args.pushEnd("${arg}");
`);
});
const moduleEpilogue = `
}
export args;
`;
return [modulePrologue + argInitializationText.join("\n") + moduleEpilogue];
};
try {
const stdlibTexts = readdirSync(join(__dirname, "..", "wheel_stdlib")).map((filename) =>
readFileSync(join(__dirname, "..", "wheel_stdlib", filename), "utf8"),
);
const userProgramTexts = stringifiedArgs.files.map((filename) => readFileSync(filename, "utf8"));
const argsText = createArgsText(stringifiedArgs.args);
const programTexts = stdlibTexts.concat(argsText).concat(userProgramTexts);
const implementations: NativeFunctionImplementations = {
clock,
print,
parseNum,
readString: defineReadString(),
};
const runResult = runProgram(implementations)(programTexts);
if (isLeft(runResult)) {
switch (runResult.left.pipelineErrorKind) {
case "scan":
console.log("Scan error(s). Invalid lexeme(s):");
runResult.left.scanErrors.forEach((scanErr) => console.log(scanErr.invalidLexeme));
break;
case "parse":
console.log("Parse error(s):");
runResult.left.parseErrors.forEach((parseErr) => console.log(parseErr.message));
break;
case "circularDep":
console.log("Circular dependencies detected");
break;
case "evaluation":
console.log("Evaluation error:");
console.log(runResult.left.evalError);
break;
}
} else {
console.log("Successful evaluation.");
switch (runResult.right.valueKind) {
case "number":
console.log(`Result: ${runResult.right.value}`);
break;
case "closure":
console.log("Result: <closure>");
}
}
} catch (err) {
console.error(`Error reading files`);
console.error(err);
process.exit(2);
}
})();