import getopt import sys import juic.parser import juic.eval import juic.builtins USAGE_STRING = """ usage: juic [OPTIONS] INPUT JustUI high-level description compiler. Options: --debug=lexer Dump the lexer output and stop =parser Dump the parser output and stop --unit-tests Check unit tests specified by "//^" comments """.strip() def usage(exitcode=None): print(USAGE_STRING, file=sys.stderr) if exitcode is not None: sys.exit(exitcode) def main(argv): # Read command-line arguments try: opts, args = getopt.gnu_getopt(argv[1:], "", ["help", "debug=", "unit-tests"]) opts = dict(opts) if len(argv) == 1 or "-h" in opts or "--help" in opts: usage(0) if len(args) < 1: usage(1) if len(args) > 1: raise getopt.GetoptError("only one input file can be specified") except getopt.GetoptError as e: print("error:", e, file=sys.stderr) print("Try '{} --help' for details.".format(argv[0]), file=sys.stderr) sys.exit(1) #--- with open(args[0], "r") as fp: source = fp.read() try: lexer = juic.parser.JuiLexer(source, args[0], keepUnitTests="--unit-tests" in opts) if opts.get("--debug") == "lexer": lexer.dump() return 0 parser = juic.parser.JuiParser(lexer) ast = parser.scope() if opts.get("--debug") == "parser": for node in ast.args: node.dump() print("---") return 0 except juic.parser.SyntaxError as e: print(e.loc, ": ", "\x1b[31merror:\x1b[0m ", e.message, sep="", file=sys.stdout) return 1 ctx = juic.eval.Context(juic.builtins.builtinClosure) if "--unit-tests" in opts: for node in ast.args: ctx.execStmt(node) return 0 for node in ast.args: v = ctx.execStmt(node) if node.ctor == juic.parser.Node.T.SCOPE_EXPR: v = ctx.force(v) print(">>>>>>>", juic.eval.juiValueString(v)) ctx.currentScope.dump() ctx.currentClosure.dump() print("TODO: Codegen not implemented yet o(x_x)o") return 1 sys.exit(main(sys.argv))