示例#1
0
    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)
示例#2
0
 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)
示例#3
0
 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 = {}
示例#4
0
    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)
示例#5
0
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