def run(prog, macro_lookup): """ PROG => (e (com (q . PROG) (mac)) ARGS) The result can be evaluated with the stage_com eval function. """ args = TOP.as_path() mac = quote(macro_lookup) return eval(prog.to([b"com", prog, mac]), args)
def build_macro_lookup_program(macro_lookup, macros, run_program): macro_lookup_program = macro_lookup.to([QUOTE_KW, macro_lookup]) for macro in macros: macro_lookup_program = eval( macro_lookup.to([ b"opt", [ b"com", [QUOTE_KW, [CONS_KW, macro, macro_lookup_program]], macro_lookup_program ] ]), TOP.as_path()) macro_lookup_program = optimize_sexp(macro_lookup_program, run_program) return macro_lookup_program
def build_macro_lookup_program(macro_lookup, macros, run_program): macro_lookup_program = macro_lookup.to(quote(macro_lookup)) for macro in macros: macro_lookup_program = eval( macro_lookup.to([ b"opt", [ b"com", quote([CONS_ATOM, macro, macro_lookup_program]), macro_lookup_program ] ]), TOP.as_path()) macro_lookup_program = optimize_sexp(macro_lookup_program, run_program) return macro_lookup_program
def do_com_prog(prog, macro_lookup, symbol_table, run_program): """ Turn the given program `prog` into a clvm program using the macros to do transformation. prog is an uncompiled s-expression. Return a new expanded s-expression PROG_EXP that is equivalent by rewriting based upon the operator, where "equivalent" means (a (com (q PROG) (MACROS)) ARGS) == (a (q PROG_EXP) ARGS) for all ARGS. Also, (opt (com (q PROG) (MACROS))) == (opt (com (q PROG_EXP) (MACROS))) """ # lower "quote" to "q" prog = lower_quote(prog, macro_lookup, symbol_table, run_program) # quote atoms if prog.nullp() or not prog.listp(): atom = prog.as_atom() if atom == b"@": return prog.to(TOP.as_path()) for pair in symbol_table.as_iter(): symbol, value = pair.first(), pair.rest().first() if symbol == atom: return prog.to(value) return prog.to(quote(prog)) operator = prog.first() if operator.listp(): # (com ((OP) . RIGHT)) => (a (com (q OP)) 1) inner_exp = eval( prog.to([ b"com", quote(operator), quote(macro_lookup), quote(symbol_table) ]), TOP.as_path()) return prog.to([inner_exp]) as_atom = operator.as_atom() for macro_pair in macro_lookup.as_iter(): macro_name = macro_pair.first().as_atom() if macro_name == as_atom: macro_code = macro_pair.rest().first() post_prog = brun(macro_code, prog.rest()) return eval( post_prog.to([ b"com", post_prog, quote(macro_lookup), quote(symbol_table) ]), TOP.as_short_path()) if as_atom in COMPILE_BINDINGS: f = COMPILE_BINDINGS[as_atom] post_prog = f(prog.rest(), macro_lookup, symbol_table, run_program) return eval(prog.to(quote(post_prog)), TOP.as_path()) if operator == QUOTE_ATOM: return prog compiled_args = [ do_com_prog(_, macro_lookup, symbol_table, run_program) for _ in prog.rest().as_iter() ] r = prog.to([operator] + compiled_args) if as_atom in PASS_THROUGH_OPERATORS or as_atom.startswith(b"_"): return r for (symbol, value) in symbol_table.as_python(): if symbol == b"*": return r if symbol == as_atom: new_args = eval( prog.to([ b"opt", [ b"com", quote([b"list"] + list(prog.rest().as_iter())), quote(macro_lookup), quote(symbol_table) ] ]), TOP.as_path()) r = prog.to( [APPLY_ATOM, value, [CONS_ATOM, LEFT.as_path(), new_args]]) return r raise SyntaxError("can't compile %s, unknown operator" % disassemble(prog))