#!/usr/bin/env node import * as minimist from 'minimist'; import * as fs from 'fs'; import * as path from 'path'; import Compiler from './compiler'; import { isError } from './error'; import { EnvError } from './env'; import Lexer, { LexerError } from './lexer'; import Parser, { ParserError } from './parser'; // import { inspect } from 'util'; // const print = (obj: any) => { // console.log(inspect(obj, { depth: null })); // }; const rawArgs = minimist(process.argv.slice(2)); const args = { eval: rawArgs.e || rawArgs.eval, file: rawArgs.f || rawArgs.file, help: rawArgs.h || rawArgs.help, output: rawArgs.o || rawArgs.output, pretty: rawArgs.p || rawArgs.pretty, }; const helpText = `Usage: moss [options] -e, --eval Evaluate a string of source code -f, --file Evaluate a file containing source code -h, --help Print this message -o, --output Write output to a file -p, --pretty Pretty print the output`; const moss = ( source: string, file?: string ): LexerError | ParserError | EnvError | string => { const lexer = new Lexer(source, file); const tokens = lexer.scan(); if (tokens instanceof LexerError) return tokens; const parser = new Parser(tokens); const tree = parser.parse(); // print(tree); if (tree instanceof ParserError) return tree; const compiler = new Compiler(tree, { prettyPrint: args.pretty }); return compiler.compile(); }; const run = () => { if (args.help) { return helpText; } else if (args.file) { const filepath = path.join(process.cwd(), args.file); if (filepath !== null) { const source = fs.readFileSync(filepath, 'utf-8'); return moss(source, args.file); } return ''; } else if (args.eval) { return moss(args.eval); } return helpText; }; const output = run(); if (isError(output)) { const moduleAndLine = `${output.module ? output.module : '-e'}:${ output.line }`; console.log(`Error ${moduleAndLine} ${output.message}`); } else { if (output.length) { if (args.output) { fs.writeFileSync(path.join(process.cwd(), args.output), output); } else { console.log(output); } } }