bolt/src/bin/bolt.ts

124 lines
2.9 KiB
TypeScript
Raw Normal View History

2020-02-24 18:30:39 +01:00
#!/usr/bin/env node
2020-02-24 18:35:28 +01:00
import "source-map-support/register"
2020-02-24 18:30:39 +01:00
import * as fs from "fs"
import yargs from "yargs"
import { Scanner } from "../scanner"
2020-02-24 19:16:33 +01:00
import { Token, TextFile, SourceFile } from "../ast"
2020-02-24 18:30:39 +01:00
function toArray<T>(value: T): T extends Array<any> ? T : T[] {
if (Array.isArray(value)) {
return value as T[]
}
return value === null || value === undefined ? [] : [value]
}
function pushAll<T>(array: T[], elements: T[]) {
for (const element of elements) {
array.push(element);
}
}
function flatMap<T>(array: T[], proc: (element: T) => T[]) {
let out: T[] = []
for (const element of array) {
pushAll(out, proc(element));
}
return out
}
interface Hook {
timing: 'before' | 'after'
name: string
effects: string[]
}
function parseHook(str: string): Hook {
let timing: 'before' | 'after' = 'before';
if (str[0] === '+') {
str = str.substring(1)
timing = 'after';
}
const [name, rawEffects] = str.split('=');
return {
timing,
name,
effects: rawEffects.split(','),
}
}
yargs
.command(
'compile [files..]',
'Compile a set of source files',
yargs => yargs
.string('hook')
.describe('hook', 'Add a hook to a specific compile phase. See the manual for details.'),
args => {
const hooks: Hook[] = toArray(args.hook as string[] | string).map(parseHook);
2020-02-24 19:16:33 +01:00
const sourceFiles: SourceFile[] = [];
2020-02-24 18:30:39 +01:00
for (const filepath of toArray(args.files as string[] | string)) {
const file = new TextFile(filepath);
const content = fs.readFileSync(filepath, 'utf8')
const scanner = new Scanner(file, content)
for (const hook of hooks) {
if (hook.name === 'scan' && hook.timing === 'before') {
for (const effect of hook.effects) {
switch (effect) {
case 'abort':
process.exit(0);
break;
default:
throw new Error(`Could not execute hook effect '${effect}.`);
}
}
}
}
2020-02-24 19:16:33 +01:00
const sourceFile = scanner.scan();
// while (true) {
// const token = scanner.scanToken()
// if (token === null) {
// break;
// }
// tokens.push(token);
// }
2020-02-24 18:30:39 +01:00
for (const hook of hooks) {
if (hook.name === 'scan' && hook.timing == 'after') {
for (const effect of hook.effects) {
switch (effect) {
case 'dump':
2020-02-24 19:16:33 +01:00
console.log(JSON.stringify(sourceFile.toJSON(), undefined, 2));
2020-02-24 18:30:39 +01:00
break;
case 'abort':
process.exit(0);
break;
default:
throw new Error(`Could not execute hook effect '${effect}'.`)
}
}
}
}
2020-02-24 19:16:33 +01:00
sourceFiles.push(sourceFile);
2020-02-24 18:30:39 +01:00
}
2020-02-24 19:16:33 +01:00
2020-02-24 18:30:39 +01:00
})
.help()
.version()
.argv