refactor file loading

This commit is contained in:
nora 2023-08-02 15:01:52 +02:00
parent beb0321382
commit 7eeaf548d0
9 changed files with 236 additions and 193 deletions

View file

@ -1,16 +1,16 @@
import { CompilerError, Span, withErrorPrinter } from "./error";
import { LoadedFile, withErrorPrinter } from "./error";
import { isValidIdent, tokenize } from "./lexer";
import { lower as lowerToWasm } from "./lower";
import { parse } from "./parser";
import { ParseState, parse } from "./parser";
import { printAst } from "./printer";
import { resolve } from "./resolve";
import { typeck } from "./typeck";
import { writeModuleWatToString } from "./wasm/wat";
import fs from "fs";
import path from "path";
import { exec } from "child_process";
import { Crate, Built, Typecked, DepCrate } from "./ast";
import { GlobalContext, CrateLoader } from "./context";
import { Crate, Built, Typecked } from "./ast";
import { GlobalContext, parseArgs } from "./context";
import { loadCrate } from "./loader";
const INPUT = `
extern mod std;
@ -33,70 +33,9 @@ function linkStd() = (
);
`;
type Config = {
input: string;
filename: string;
packageName: string;
debug: Set<string>;
noOutput: boolean;
};
function parseArgs(): Config {
let filename: string;
let input: string;
let packageName: string;
let debug = new Set<string>();
let noOutput = false;
if (process.argv.length > 2) {
filename = process.argv[2];
if (path.extname(filename) !== ".nil") {
console.error(process.argv);
console.error(
`error: filename must have \`.nil\` extension: \`${filename}\``
);
process.exit(1);
}
input = fs.readFileSync(filename, { encoding: "utf-8" });
packageName = path.basename(filename, ".nil");
const debugArg = process.argv.find((arg) => arg.startsWith("--debug="));
if (debugArg !== undefined) {
const debugs = debugArg.slice("--debug=".length);
debug = new Set(debugs.split(","));
}
if (process.argv.some((arg) => arg === "--no-output")) {
noOutput = true;
}
} else {
filename = "<hardcoded>";
input = INPUT;
packageName = "test";
debug = new Set([
"tokens",
"parsed",
"resolved",
"typecked",
"wat",
"wasm-validate",
]);
}
return {
filename,
input,
packageName,
debug,
noOutput,
};
}
function main() {
const config = parseArgs();
const { filename, packageName, input, debug } = config;
const opts = parseArgs(INPUT);
const { filename, packageName, input, debug } = opts;
if (!isValidIdent(packageName)) {
console.error(
@ -105,22 +44,24 @@ function main() {
process.exit(1);
}
const gcx = new GlobalContext(loadCrate);
const file: LoadedFile = { path: filename, content: input };
const gcx = new GlobalContext(opts, loadCrate);
const mainCrate = gcx.crateId.next();
withErrorPrinter(
input,
filename,
() => {
const start = Date.now();
const tokens = tokenize(input);
const tokens = tokenize(file);
if (debug.has("tokens")) {
console.log("-----TOKENS------------");
console.log(tokens);
}
const ast: Crate<Built> = parse(packageName, tokens, mainCrate);
const parseState: ParseState = { tokens, file };
const ast: Crate<Built> = parse(packageName, parseState, mainCrate);
if (debug.has("ast")) {
console.log("-----AST---------------");
@ -160,7 +101,7 @@ function main() {
console.log(moduleStringColor);
}
if (!config.noOutput) {
if (!opts.noOutput) {
fs.writeFileSync("out.wat", moduleString);
}
@ -189,62 +130,4 @@ function main() {
);
}
const loadCrate: CrateLoader = (
gcx: GlobalContext,
name: string,
span: Span
): DepCrate => {
// We really, really want a good algorithm for finding crates.
// But right now we just look for files in the CWD.
const existing = gcx.depCrates.find((crate) => crate.packageName === name);
if (existing) {
return existing;
}
const options = [`${name}.nil`, `${name}/${name}.mod.nil`];
let input: string | undefined = undefined;
let filename: string | undefined = undefined;
options.forEach((tryName) => {
try {
input = fs.readFileSync(tryName, { encoding: "utf-8" });
filename = tryName;
} catch (e) {}
});
if (input === undefined || filename === undefined) {
throw new CompilerError(
`failed to load ${name}, could not find ${options.join(" or ")}`,
span
);
}
const inputString: string = input;
return withErrorPrinter(
inputString,
filename,
(): DepCrate => {
const crateId = gcx.crateId.next();
const tokens = tokenize(inputString);
const ast = parse(name, tokens, crateId);
const resolved = resolve(gcx, ast);
console.log(resolved);
const typecked = typeck(gcx, resolved);
gcx.depCrates.push(typecked);
return typecked;
},
() => {
throw new CompilerError(
`failed to load crate ${name}: crate contains errors`,
span
);
}
);
};
main();