#!/usr/bin/env node import "source-map-support/register" import * as fs from "fs" import yargs from "yargs" import { Scanner } from "../scanner" import { Token, TextFile, SourceFile } from "../ast" function toArray(value: T): T extends Array ? T : T[] { if (Array.isArray(value)) { return value as T[] } return value === null || value === undefined ? [] : [value] } function pushAll(array: T[], elements: T[]) { for (const element of elements) { array.push(element); } } function flatMap(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); const sourceFiles: SourceFile[] = []; 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}.`); } } } } const sourceFile = scanner.scan(); // while (true) { // const token = scanner.scanToken() // if (token === null) { // break; // } // tokens.push(token); // } for (const hook of hooks) { if (hook.name === 'scan' && hook.timing == 'after') { for (const effect of hook.effects) { switch (effect) { case 'dump': console.log(JSON.stringify(sourceFile.toJSON(), undefined, 2)); break; case 'abort': process.exit(0); break; default: throw new Error(`Could not execute hook effect '${effect}'.`) } } } } sourceFiles.push(sourceFile); } }) .help() .version() .argv