def primToC(self, exp, assignTo, indent=0): if self.isIBPrimitive(exp.funcExp): setvar = self.setIntVar primFormat = self.ibprimFormat.format('{0}', '{1}', '{2}', op=self.ibprimitives[exp.funcExp.name]) nary = 2 elif self.isIUPrimitive(exp.funcExp): setvar = self.setIntVar primFormat = self.iuprimFormat.format('{0}', '{1}', op=self.iuprimitives[exp.funcExp.name]) nary = 1 else: setvar = self.sprimrts[exp.funcExp.name] primFormat = self.sprimitives[exp.funcExp.name] nary = 2 tmp = gensym('_') setvar(tmp) code = ' ' * indent + dedent('''\ std::unique_ptr<schemetype_t*> {0} (new schemetype_t); {1} ''').format( tmp.name, primFormat.format(tmp.name, *[self.toC(arg, None) for arg in exp.argExps]) ).replace('\n', '\n' + ' ' * indent) cont = AppExp(exp.argExps[-1], tmp) return code + self.toC(cont, assignTo, indent)
def atmToC(self, exp, assignTo=None, indent=0): if assignTo is None: code = ' ' * indent if isinstance(exp, BoolExp): code += 'true' if exp.val else 'false' elif isinstance(exp, NumExp): code += str(exp.val) elif isinstance(exp, VarExp): code += exp.name elif isinstance(exp, StrExp): tmp = gensym('_') self.declareVar(tmp, val) code += tmp.name else: raise RuntimeError('unhandled AtomicExp in atmToC()') return code else: self.declareVar(assignTo) if isinstance(exp, VarExp): return ' ' * indent + '{0} = {1};\n'.format(assignTo.name, exp.name) #~ return dedent('''\ #~ {0}.intVal = {1}.intVal; #~ strcpy({0}.strVal, {1}.strVal); #~ {0}.label = {1}.label; #~ ''').format(assignTo.name, exp.name) elif isinstance(exp, StrExp): #~ self.setStrVar(assignTo) return self.setStr(assignTo, exp, indent) else: #~ self.setIntVar(assignTo) #~ if assignTo in self.svars: #~ self.svars.remove(assignTo) return self.setInt(assignTo, exp, indent)
def __init__(self): self.lambdaBindings = {} self.rv = VarExp('returnValue') self.rvtype = 0 self.ivars = set() self.svars = set() self.fvars = set() self.ibprimitives = { '+': '+', '-': '-', '*': '*', '=': '==' } self.ibprimFormat = '{0}->_num = {1}->_num {op} {2}->_num;\n' self.iuprimitives = { 'zero?': '== 0' } self.iuprimFormat = '{0}->_num = {1}->_num {op};\n' self.tmpvar = gensym('_') self.sprimitives = { 'string-append': '{0}->_str.append({1}->_str);', 'string=?': '{0}->_num = 1 - abs(strcmp({1}->_str, {2}->_str));\n' } self.sprimrts = { 'string-append': self.setStrVar, 'string=?': self.setIntVar } self.primops = ( self.ibprimitives.keys() | self.iuprimitives.keys() | self.sprimitives.keys() ) self.retExp = LamExp([self.rv], self.rv) self.declareCode = '' self.argVars = [VarExp('_args[{0}]'.format(i)) for i in range(10)] self.ivars.update(self.argVars) self.lam_holes = {}
def to_cpp(exp): code = None decls = [] if isinstance(exp, VarExp): code = exp.name elif isinstance(exp, (NumExp, BoolExp, StrExp)): if isinstance(exp, NumExp): val = str(exp.val) sym = "_num" typ = NUM elif isinstance(exp, BoolExp): val = "1" if exp.val else "0" sym = "_bool" typ = NUM elif isinstance(exp, StrExp): val = '"{0}"'.format(exp.val) sym = "_str" typ = STR else: assert 0 tmp = gensym(sym) decl = ( declare(tmp), dedent( """\ {var}->type = {typ}; {var}->{loc} = {val};""" ).format(var=tmp.name, loc=typ.lower(), val=val, typ=typ.upper()), ) decls.append(decl) code = tmp.name elif isinstance(exp, VoidExp): unimplemented(exp) elif isinstance(exp, LamExp): cls = lambda_gen[exp] # instantiate a temporary to fill with our lambda tmp = gensym("_lam") decl = ( declare(tmp), dedent( """\ {var}->type = {LAM}; {var}->lam = lambda_t(new {cls}({holes}));""" ).format(var=tmp.name, cls=cls, holes=", ".join(hole.name for hole in holes[exp]), LAM=LAM), ) decls.append(decl) code = tmp.name elif isinstance(exp, AppExp): for arg in exp.argExps: decls.extend(arg.decls) decls.extend(exp.funcExp.decls) tmp = gensym("_ret") func = str(exp.funcExp) if is_primop(func): prim = gensym("_prim") typ, body = gen_primop(func, prim, *[str(arg) for arg in exp.argExps[:-1]]) decl = ( declare(prim) + "\nschemetype_t {0};".format(tmp.name), dedent( """\ {prim}->type = {typ}; {body} {func}->lam->args({prim}); {var} = {func};""" ).format(prim=prim.name, body=body, typ=typ, var=tmp.name, func=str(exp.argExps[-1]), LAM=LAM), ) decls.append(decl) elif exp.funcExp.typ == VarExp: decl = ( "schemetype_t {0};".format(tmp.name), dedent( """\ {func}->lam->args({args}); {var} = {func};""" ).format( func=str(exp.funcExp), args=", ".join(str(arg) for arg in exp.argExps), var=tmp.name, LAM=LAM ), ) decls.append(decl) else: raise RuntimeError("AppExp unimplemented for funcExp of type: {0}".format(str(exp.funcExp.typ))) code = tmp.name elif isinstance(exp, IfExp): decls.extend(exp.condExp.decls) then_decls, then_ops = exp.thenExp.decls_ops else_decls, else_ops = exp.elseExp.decls_ops tmp = gensym("_ret") decl = ( "schemetype_t {0};".format(tmp.name), dedent( """\ if ({cond}->num) {{ {then_decls} {then_ops} {var} = std::move({then}); }} else {{ {else_decls} {else_ops} {var} = std::move({else_}); }}""" ).format( var=tmp.name, cond=str(exp.condExp), then_decls=then_decls, then_ops=then_ops, then=str(exp.thenExp), else_decls=else_decls, else_ops=else_ops, else_=str(exp.elseExp), ), ) decls.append(decl) code = tmp.name elif isinstance(exp, LetRecExp): for var, body in exp.bindings: decls.extend(body.decls) decl = ( declare(var), dedent( """\ {var}->type = {LAM}; {var}->lam = {body}->lam;""" ).format(var=str(var), body=str(body), LAM=LAM), ) decls.append(decl) decls.extend(exp.bodyExp.decls) code = str(exp.bodyExp) elif isinstance(exp, BeginExp): unimplemented(exp) elif isinstance(exp, SetExp): unimplemented(exp) elif isinstance(exp, SetThenExp): unimplemented(exp) elif isinstance(exp, CppCode): return exp else: unimplemented(exp) return CppCode(type(exp), code, decls)
def gen_cpp(exp): exp = sanitize(exp) # compute the holes at each LamExp holes = compute_holes(exp) lambda_gen = LamGenCpp(exp) # map function def to_cpp(exp): code = None decls = [] if isinstance(exp, VarExp): code = exp.name elif isinstance(exp, (NumExp, BoolExp, StrExp)): if isinstance(exp, NumExp): val = str(exp.val) sym = "_num" typ = NUM elif isinstance(exp, BoolExp): val = "1" if exp.val else "0" sym = "_bool" typ = NUM elif isinstance(exp, StrExp): val = '"{0}"'.format(exp.val) sym = "_str" typ = STR else: assert 0 tmp = gensym(sym) decl = ( declare(tmp), dedent( """\ {var}->type = {typ}; {var}->{loc} = {val};""" ).format(var=tmp.name, loc=typ.lower(), val=val, typ=typ.upper()), ) decls.append(decl) code = tmp.name elif isinstance(exp, VoidExp): unimplemented(exp) elif isinstance(exp, LamExp): cls = lambda_gen[exp] # instantiate a temporary to fill with our lambda tmp = gensym("_lam") decl = ( declare(tmp), dedent( """\ {var}->type = {LAM}; {var}->lam = lambda_t(new {cls}({holes}));""" ).format(var=tmp.name, cls=cls, holes=", ".join(hole.name for hole in holes[exp]), LAM=LAM), ) decls.append(decl) code = tmp.name elif isinstance(exp, AppExp): for arg in exp.argExps: decls.extend(arg.decls) decls.extend(exp.funcExp.decls) tmp = gensym("_ret") func = str(exp.funcExp) if is_primop(func): prim = gensym("_prim") typ, body = gen_primop(func, prim, *[str(arg) for arg in exp.argExps[:-1]]) decl = ( declare(prim) + "\nschemetype_t {0};".format(tmp.name), dedent( """\ {prim}->type = {typ}; {body} {func}->lam->args({prim}); {var} = {func};""" ).format(prim=prim.name, body=body, typ=typ, var=tmp.name, func=str(exp.argExps[-1]), LAM=LAM), ) decls.append(decl) elif exp.funcExp.typ == VarExp: decl = ( "schemetype_t {0};".format(tmp.name), dedent( """\ {func}->lam->args({args}); {var} = {func};""" ).format( func=str(exp.funcExp), args=", ".join(str(arg) for arg in exp.argExps), var=tmp.name, LAM=LAM ), ) decls.append(decl) else: raise RuntimeError("AppExp unimplemented for funcExp of type: {0}".format(str(exp.funcExp.typ))) code = tmp.name elif isinstance(exp, IfExp): decls.extend(exp.condExp.decls) then_decls, then_ops = exp.thenExp.decls_ops else_decls, else_ops = exp.elseExp.decls_ops tmp = gensym("_ret") decl = ( "schemetype_t {0};".format(tmp.name), dedent( """\ if ({cond}->num) {{ {then_decls} {then_ops} {var} = std::move({then}); }} else {{ {else_decls} {else_ops} {var} = std::move({else_}); }}""" ).format( var=tmp.name, cond=str(exp.condExp), then_decls=then_decls, then_ops=then_ops, then=str(exp.thenExp), else_decls=else_decls, else_ops=else_ops, else_=str(exp.elseExp), ), ) decls.append(decl) code = tmp.name elif isinstance(exp, LetRecExp): for var, body in exp.bindings: decls.extend(body.decls) decl = ( declare(var), dedent( """\ {var}->type = {LAM}; {var}->lam = {body}->lam;""" ).format(var=str(var), body=str(body), LAM=LAM), ) decls.append(decl) decls.extend(exp.bodyExp.decls) code = str(exp.bodyExp) elif isinstance(exp, BeginExp): unimplemented(exp) elif isinstance(exp, SetExp): unimplemented(exp) elif isinstance(exp, SetThenExp): unimplemented(exp) elif isinstance(exp, CppCode): return exp else: unimplemented(exp) return CppCode(type(exp), code, decls) body = exp.map(to_cpp) main_decls, main_ops = body.decls_ops lambda_decls, lambda_ops = lambda_gen.decls_ops next = gensym("_trampoline") # generate some C code! code = dedent( """\ #include <cstdio> #include <cstdlib> #include <memory> #include <string> enum type_t {{ {types} }}; // forward decls ----------------------------------------------------------------------------------- class lambda; class schemetype; typedef std::shared_ptr<lambda> lambda_t; typedef std::shared_ptr<schemetype> schemetype_t; // lambda decl ------------------------------------------------------------------------------------- {lambda_decls} // schemetype decl --------------------------------------------------------------------------------- class schemetype {{ public: union {{ lambda_t lam; long num; std::shared_ptr<std::string> str; }}; type_t type; schemetype(); ~schemetype(); }}; // lambda impl ------------------------------------------------------------------------------------- {lambda_ops} // schemetype impl --------------------------------------------------------------------------------- schemetype::schemetype() : lam(lambda_t()) {{ }} schemetype::~schemetype() {{ if (type == {LAM}) {{ lam.reset(); }} else if (type == {STR}) {{ str.reset(); }} }} // main -------------------------------------------------------------------------------------------- int main() {{ {main_decls} {next_decl} {main_ops} {next} = {body}; // trampoline while ({next}->type == {LAM}) {{ if (*({next}->lam)) {{ {next} = std::move((*({next}->lam))()); }} else {{ printf("error: lambda called before providing arguments!\\n"); exit(-1); }} }} if ({next}->type != {NUM}) {{ printf("error: non-number type in return value\\n"); return -1; }} return {next}->num; }} """ ).format( types=", ".join(TYPES), lambda_decls=lambda_decls, lambda_ops=lambda_ops, main_decls=main_decls, next_decl=declare(next, False), next=next.name, main_ops=main_ops, body=str(body), LAM=LAM, NUM=NUM, STR=STR, ) return code