示例#1
0
def compileBytecode(comp, form):
    codename = form.first().name
    if not hasattr(byteplay, codename):
        raise CompilerException("bytecode {0} unknown".format(codename), form)
    bc = getattr(byteplay, codename)
    hasarg = bc in byteplay.hasarg
    form = form.next()
    arg = None
    if hasarg:
        arg = form.first()
        if not isinstance(arg, (int, str, unicode)) and bc is not LOAD_CONST:
            raise CompilerException(
                "first argument to {0} must be int, unicode, or str".format(
                    codename), form)

        arg = evalForm(arg, comp.getNS())
        form = form.next()

    se = byteplay.getse(bc, arg)
    if form != None and se[0] != 0 and (se[0] != len(form) or se[1] > 1):
        raise CompilerException(
            "literal bytecode {0} not supported".format(codename), form)
    s = form
    code = []
    while s is not None:
        code.extend(comp.compile(s.first()))
        s = s.next()
    code.append((bc, arg))
    if se[1] == 0:
        code.append((LOAD_CONST, None))
    return code
示例#2
0
    def getAccessCode(self, sym):
        if (sym.ns is not None and sym.ns == self.getNS().__name__) \
           or sym.ns is None:
            if self.getNS() is None:
                raise CompilerException("no namespace has been defined", None)
            if not hasattr(self.getNS(), RT.name(sym)):
                raise CompilerException("could not resolve '" + str(sym) + "', '" \
                                        + RT.name(sym) + "' not found in " + self.getNS().__name__ +
                                        " reference " + str(self.getNamesString(False)), None)
            var = getattr(self.getNS(), RT.name(sym))
            return [GlobalPtr(self.getNS(), RT.name(sym))]

        if hasattr(self.getNS(), "__aliases__") and \
            symbol(sym.ns) in self.getNS().__aliases__:
            sym = symbol(self.getNS().__aliases__[symbol(sym.ns)].__name__,
                         RT.name(sym))

        splt = []
        if sym.ns is not None:
            module = findNamespace(sym.ns)
            if not hasattr(module, RT.name(sym)):
                raise CompilerException(
                    str(module) + " does not define " + RT.name(sym), None)
            return [GlobalPtr(module, RT.name(sym))]

        code = LOAD_ATTR if sym.ns else LOAD_GLOBAL
        #if not sym.ns and RT.name(sym).find(".") != -1 and RT.name(sym) != "..":
        raise CompilerException(
            "unqualified dotted forms not supported: " + str(sym), sym)

        if len(RT.name(sym).replace(".", "")):
            splt.extend((code, attr) for attr in RT.name(sym).split("."))
        else:
            splt.append((code, RT.name(sym)))
        return splt
示例#3
0
def compileLetMacro(comp, form):
    if len(form) < 3:
        raise CompilerException("alias-properties takes at least two args",
                                form)

    form = form.next()

    s = RT.seq(form.first())
    syms = []
    while s is not None:
        sym = s.first()
        syms.append(sym)
        s = s.next()
        if s is None:
            raise CompilerException(
                "let-macro takes a even number of bindings")
        macro = s.first()

        comp.pushAlias(sym, LocalMacro(sym, macro))

        s = s.next()

    body = form.next()

    code = compileImplcitDo(comp, body)

    comp.popAliases(syms)
    return code
示例#4
0
def compileDot(comp, form):
    if len(form) != 3:
        raise CompilerException(". form must have two arguments", form)
    clss = form.next().first()
    member = form.next().next().first()

    if isinstance(member, Symbol):
        attr = member.name
        args = []
    elif isinstance(member, ISeq):
        if not isinstance(member.first(), Symbol):
            raise CompilerException("Member name must be symbol", form)
        attr = member.first().name
        args = []
        if len(member) > 1:
            f = member.next()
            while f is not None:
                args.append(comp.compile(f.first()))
                f = f.next()

    alias = comp.getAlias(clss)
    if alias:
        code = alias.compile(comp)
        code.append((LOAD_ATTR, attr))
    else:
        code = comp.compile(Symbol(clss, attr))

    for x in args:
        code.extend(x)
    code.append((CALL_FUNCTION, len(args)))
    return code
示例#5
0
def compileLetStar(comp, form):
    if len(form) < 2:
        raise CompilerException("let* takes at least two args", form)
    form = form.next()
    if not isinstance(form.first(), IPersistentVector):
        raise CompilerException("let* takes a vector as it's first argument",
                                form)
    bindings = RT.seq(form.first())
    args = []
    code = []
    if bindings and len(bindings) % 2:
        raise CompilerException("let* takes a even number of bindings", form)
    while bindings:
        local, bindings = bindings.first(), bindings.next()
        body, bindings = bindings.first(), bindings.next()
        if not isinstance(local, Symbol) or local.ns is not None:
            raise CompilerException("bindings must be non-namespaced symbols",
                                    form)
        code.extend(comp.compile(body))
        alias = RenamedLocal(
            Symbol("{0}_{1}".format(local, RT.nextID())) if comp.
            getAlias(local) else local)
        comp.pushAlias(local, alias)
        args.append(local)
        code.extend(alias.compileSet(comp))
    form = form.next()
    code.extend(compileImplcitDo(comp, form))
    comp.popAliases(args)
    return code
示例#6
0
    def __init__(self, comp, form):
        form = RT.seq(form)
        if len(form) < 2:
            raise CompilerException("FN defs must have at least two vars",
                                    form)
        argv = form.first()
        if not isinstance(argv, PersistentVector):
            raise CompilerException("FN arg list must be a vector", form)
        body = form.next()

        self.locals, self.args, self.lastisargs, self.argsname = unpackArgs(
            argv)
        endLabel = Label("endLabel")
        argcode = [(LOAD_CONST, len), (LOAD_FAST, '__argsv__'),
                   (CALL_FUNCTION, 1),
                   (LOAD_CONST,
                    len(self.args) - (1 if self.lastisargs else 0)),
                   (COMPARE_OP, ">=" if self.lastisargs else "==")]
        argcode.extend(emitJump(endLabel))
        for x in range(len(self.args)):
            if self.lastisargs and x == len(self.args) - 1:
                offset = len(self.args) - 1
                argcode.extend([(LOAD_FAST, '__argsv__'), (LOAD_CONST, offset),
                                (SLICE_1, None),
                                (STORE_FAST, self.argsname.name)])
                argcode.extend(cleanRest(self.argsname.name))
            else:
                argcode.extend([(LOAD_FAST, '__argsv__'), (LOAD_CONST, x),
                                (BINARY_SUBSCR, None),
                                (STORE_FAST, self.args[x])])

        for x in self.locals:
            comp.pushAlias(x, FnArgument(x))

        recurlabel = Label("recurLabel")

        recur = {
            "label":
            recurlabel,
            "args":
            map(lambda x: comp.getAlias(symbol(x)).compileSet(comp), self.args)
        }

        bodycode = [(recurlabel, None)]
        comp.pushRecur(recur)
        bodycode.extend(compileImplcitDo(comp, body))
        bodycode.append((RETURN_VALUE, None))
        bodycode.extend(emitLanding(endLabel))
        comp.popRecur()
        comp.popAliases(self.locals)

        self.argcode = argcode
        self.bodycode = bodycode
示例#7
0
def compileIf(comp, form):
    if len(form) != 3 and len(form) != 4:
        raise CompilerException("if takes 2 or 3 args", form)
    cmp = comp.compile(form.next().first())
    body = comp.compile(form.next().next().first())
    if len(form) == 3:
        body2 = [(LOAD_CONST, None)]
    else:
        body2 = comp.compile(form.next().next().next().first())

    elseLabel = Label("IfElse")
    endlabel = Label("IfEnd")
    condition_name = garg(0).name
    code = cmp
    code.append((STORE_FAST, condition_name))
    code.append((LOAD_FAST, condition_name))
    code.append((LOAD_CONST, None))
    code.append((COMPARE_OP, 'is not'))
    code.extend(emitJump(elseLabel))
    code.append((LOAD_FAST, condition_name))
    code.append((LOAD_CONST, False))
    code.append((COMPARE_OP, '!='))
    code.extend(emitJump(elseLabel))
    code.extend(body)
    code.append((JUMP_ABSOLUTE, endlabel))
    code.extend(emitLanding(elseLabel))
    code.extend(body2)
    code.append((endlabel, None))
    return code
示例#8
0
def compileIfStar(comp, form):
    """
    Compiles the form (if* pred val else?).
    """
    if len(form) != 3 and len(form) != 4:
        raise CompilerException("if takes 2 or 3 args", form)
    cmp = comp.compile(form.next().first())
    body = comp.compile(form.next().next().first())
    if len(form) == 3:
        body2 = [(LOAD_CONST, None)]
    else:
        body2 = comp.compile(form.next().next().next().first())

    elseLabel = Label("IfElse")
    endlabel = Label("IfEnd")
    condition_name = garg(0).name
    code = cmp
    code.append((STORE_FAST, condition_name))
    code.append((LOAD_FAST, condition_name))
    code.append((LOAD_CONST, None))
    code.append((COMPARE_OP, 'is not'))
    code.extend(emitJump(elseLabel))
    code.append((LOAD_FAST, condition_name))
    code.append((LOAD_CONST, False))
    code.append((COMPARE_OP, 'is not'))
    # Use is not instead of != as bool is a subclass of int, and
    # therefore False == 0
    code.extend(emitJump(elseLabel))
    code.extend(body)
    code.append((JUMP_ABSOLUTE, endlabel))
    code.extend(emitLanding(elseLabel))
    code.extend(body2)
    code.append((endlabel, None))
    return code
示例#9
0
def compileDef(comp, form):
    if len(form) not in [2, 3]:
        raise CompilerException("Only 2 or 3 arguments allowed to def", form)
    sym = form.next().first()
    value = None
    if len(form) == 3:
        value = form.next().next().first()
    if sym.ns is None:
        ns = comp.getNS()
    else:
        ns = sym.ns

    comp.pushName(sym.name)

    code = []
    v = internVar(comp.getNS(), sym)
    v.setDynamic(True)
    v.setMeta(sym.meta())
    code.append((LOAD_CONST, v))
    code.append((LOAD_ATTR, "bindRoot"))
    code.extend(comp.compile(value))
    code.append((CALL_FUNCTION, 1))
    code.append((LOAD_CONST, v.setDynamic))
    code.append((LOAD_CONST, False))
    code.append((CALL_FUNCTION, 1))
    code.append((POP_TOP, None))

    comp.popName()
    return code
示例#10
0
def compileDef(comp, form):
    if len(form) not in [2, 3]:
        raise CompilerException("Only 2 or 3 arguments allowed to def", form)
    sym = form.next().first()
    value = None
    if len(form) == 3:
        value = form.next().next().first()
    if sym.ns is None:
        ns = comp.getNS()
    else:
        ns = sym.ns

    comp.pushName(RT.name(sym))
    code = []
    v = intern(comp.getNS(), sym)

    v.setDynamic(True)
    if len(form) == 3:
        code.append((LOAD_CONST, v))
        code.append((LOAD_ATTR, "bindRoot"))
        compiledValue = comp.compile(value)
        if isinstance(value, ISeq) \
           and value.first().getName() == 'fn' \
           and sym.meta() is not None:
            try:
                compiledValue[0][1].__doc__ = sym.meta()[Keyword('doc')]
            except AttributeError:
                pass
        code.extend(compiledValue)
        code.append((CALL_FUNCTION, 1))
    else:
        code.append((LOAD_CONST, v))
    v.setMeta(sym.meta())
    comp.popName()
    return code
示例#11
0
 def compilePropertyAccess(self, form):
     attrname = form.first().name[2:]
     if len(form) != 2:
         raise CompilerException(
             "Property access must have at only one argument", form)
     c = self.compile(form.next().first())
     c.append((LOAD_ATTR, attrname))
     return c
示例#12
0
def compileLoopStar(comp, form):
    if len(form) < 3:
        raise CompilerException("loop* takes at least two args")
    form = form.next()
    if not isinstance(form.first(), PersistentVector):
        raise CompilerException("loop* takes a vector as it's first argument")
    s = form.first()
    args = []
    code = []
    idx = 0
    while idx < len(s):
        if len(s) - idx < 2:
            raise CompilerException("loop* takes a even number of bindings")
        local = s[idx]
        if not isinstance(local, Symbol) or local.ns is not None:
            raise CompilerException("bindings must be non-namespaced symbols")

        idx += 1

        body = s[idx]
        if local in comp.aliases:
            newlocal = symbol(str(local) + "_" + str(RT.nextID()))
            code.extend(comp.compile(body))
            comp.pushAlias(local, RenamedLocal(newlocal))
            args.append(local)
        else:
            comp.pushAlias(local, RenamedLocal(local))
            args.append(local)
            code.extend(comp.compile(body))

        code.extend(comp.getAlias(local).compileSet(comp))

        idx += 1

    form = form.next()
    recurlabel = Label("recurLabel")
    recur = {
        "label": recurlabel,
        "args": map(lambda x: comp.getAlias(x).compileSet(comp), args)
    }
    code.append((recurlabel, None))
    comp.pushRecur(recur)
    code.extend(compileImplcitDo(comp, form))
    comp.popRecur()
    comp.popAliases(args)
    return code
示例#13
0
def compileIs(comp, form):
    if len(form) != 3:
        raise CompilerException("is? requires 2 arguments", form)
    fst = form.next().first()
    itm = form.next().next().first()
    code = comp.compile(fst)
    code.extend(comp.compile(itm))
    code.append((COMPARE_OP, "is"))
    return code
示例#14
0
def unpackArgs(form):
    locals = {}
    args = []
    lastisargs = False
    argsname = None
    for x in form:
        if x == _AMP_:
            lastisargs = True
            continue
        if lastisargs and argsname is not None:
            raise CompilerException(
                "variable length argument must be the last in the function")
        if lastisargs:
            argsname = x
        if not isinstance(x, Symbol) or x.ns is not None:
            raise CompilerException(
                "fn* arguments must be non namespaced symbols " + " got " +
                str(form) + " instead", form)
        locals[x] = RT.list(x)
        args.append(x.name)
    return locals, args, lastisargs, argsname
示例#15
0
    def getAccessCode(self, sym):
        if (sym.ns is not None and sym.ns == self.getNS().__name__) \
           or sym.ns is None:
            if not hasattr(self.getNS(), sym.name):
                raise CompilerException("could not resolve " + str(sym) + " " \
                                        + sym.name + " not found in " + self.getNS().__name__, sym)
            var = getattr(self.getNS(), sym.name)
            if isinstance(var, Var):
                if (var.isDynamic()):
                    return [(LOAD_CONST, var.deref), (CALL_FUNCTION, 0)]
                else:
                    return [(LOAD_CONST, var.deref())]
            return [(LOAD_GLOBAL, sym.name)]

        splt = []
        if sym.ns is not None:
            module = findNamespace(sym.ns)
            if not hasattr(module, sym.name):
                raise CompilerException(
                    str(module) + " does not define " + sym.name, None)
            attr = getattr(module, sym.name)
            if isinstance(attr, Var):
                splt.append((LOAD_CONST, attr.deref))
                splt.append((CALL_FUNCTION, 0))
            else:
                splt.append((LOAD_CONST, module))
                splt.append((LOAD_ATTR, sym.name))
            return splt

        code = LOAD_ATTR if sym.ns else LOAD_GLOBAL
        if not sym.ns and sym.name.find(".") != -1 and sym.name != "..":
            raise CompilerException(
                "unqualified dotted forms not supported: " + str(sym), sym)

        if len(sym.name.replace(".", "")):
            splt.extend((code, attr) for attr in sym.name.split("."))
        else:
            splt.append((code, sym.name))
        return splt
示例#16
0
 def compileMethodAccess(self, form):
     attrname = form.first().name[1:]
     if len(form) < 2:
         raise CompilerException(
             "Method access must have at least one argument", form)
     c = self.compile(form.next().first())
     c.append((LOAD_ATTR, attrname))
     s = form.next().next()
     while s is not None:
         c.extend(self.compile(s.first()))
         s = s.next()
     c.append((CALL_FUNCTION, (len(form) - 2)))
     return c
示例#17
0
def compileLetStar(comp, form):
    if len(form) < 3:
        raise CompilerException("let* takes at least two args")
    form = form.next()
    if not isinstance(form.first(), PersistentVector):
        raise CompilerException("let* takes a vector as it's first argument")
    s = form.first()
    args = []
    code = []
    idx = 0
    while idx < len(s):
        if len(s) - idx < 2:
            raise CompilerException("let* takes a even number of bindings")
        local = s[idx]
        if not isinstance(local, Symbol) or local.ns is not None:
            raise CompilerException("bindings must be non-namespaced symbols")

        idx += 1

        body = s[idx]
        if comp.getAlias(local) is not None:
            code.extend(comp.compile(body))
            newlocal = symbol(str(local) + "_" + str(RT.nextID()))
            comp.pushAlias(local, RenamedLocal(newlocal))
            args.append(local)
        else:
            code.extend(comp.compile(body))
            comp.pushAlias(local, RenamedLocal(local))
            args.append(local)

        code.extend(comp.getAlias(local).compileSet(comp))

        idx += 1

    form = form.next()

    code.extend(compileImplcitDo(comp, form))
    comp.popAliases(args)
    return code
示例#18
0
def compileRecur(comp, form):
    s = form.next() or []
    code = []
    if len(s) > len(comp.recurPoint.first()["args"]):
        raise CompilerException("too many arguments to recur", form)
    for recur_val in s:
        code.extend(comp.compile(recur_val))
    sets = comp.recurPoint.first()["args"][:]
    sets.reverse()
    for x in sets:
        code.extend(x)
    code.append((JUMP_ABSOLUTE, comp.recurPoint.first()["label"]))
    return code
示例#19
0
    def compile(self, itm):
        try:
            c = []
            lineset = False
            if getattr(itm, "meta", lambda: None)() is not None:
                line = itm.meta()[LINE_KEY]
                if line is not None and line > self.lastlineno:
                    lineset = True
                    self.lastlineno = line
                    c.append([SetLineno, line])

            if isinstance(itm, Symbol):
                c.extend(self.compileSymbol(itm))
            elif isinstance(itm, PersistentList) or isinstance(itm, Cons):
                c.extend(self.compileForm(itm))
            elif itm is None:
                c.extend(self.compileNone(itm))
            elif type(itm) in [str, int, types.ClassType, type, Var]:
                c.extend([(LOAD_CONST, itm)])
            elif isinstance(itm, IPersistentVector):
                c.extend(compileVector(self, itm))
            elif isinstance(itm, IPersistentMap):
                c.extend(compileMap(self, itm))
            elif isinstance(itm, Keyword):
                c.extend(compileKeyword(self, itm))
            elif isinstance(itm, bool):
                c.extend(compileBool(self, itm))
            elif isinstance(itm, EmptyList):
                c.append((LOAD_CONST, itm))
            elif isinstance(itm, unicode):
                c.append((LOAD_CONST, itm))
            elif isinstance(itm, float):
                c.append((LOAD_CONST, itm))
            elif isinstance(itm, long):
                c.append((LOAD_CONST, itm))
            elif isinstance(itm, fractions.Fraction):
                c.append((LOAD_CONST, itm))
            elif isinstance(itm, IPersistentSet):
                c.append((LOAD_CONST, itm))
            elif isinstance(itm, type(re.compile(""))):
                c.append((LOAD_CONST, itm))
            else:
                raise CompilerException(
                    " don't know how to compile {0}".format(type(itm)), None)

            if len(c) < 2 and lineset:
                return []
            return c
        except:
            print "Compiling {0}".format(itm)
            raise
示例#20
0
    def getAccessCode(self, sym):
        if sym.ns is None or sym.ns == self.getNS().__name__:
            if self.getNS() is None:
                raise CompilerException("no namespace has been defined", None)
            if not hasattr(self.getNS(), RT.name(sym)):
                raise CompilerException(
                    "could not resolve '{0}', '{1}' not found in {2} reference {3}"
                    .format(sym, RT.name(sym),
                            self.getNS().__name__,
                            self.getNamesString(False)), None)
            var = getattr(self.getNS(), RT.name(sym))
            return [GlobalPtr(self.getNS(), RT.name(sym))]

        if Symbol(sym.ns) in getattr(self.getNS(), "__aliases__", {}):
            sym = Symbol(self.getNS().__aliases__[Symbol(sym.ns)].__name__,
                         RT.name(sym))

        splt = []
        if sym.ns is not None:
            module = findNS(sym.ns)
            if not hasattr(module, RT.name(sym)):
                raise CompilerException(
                    "{0} does not define {1}".format(module, RT.name(sym)),
                    None)
            return [GlobalPtr(module, RT.name(sym))]

        code = LOAD_ATTR if sym.ns else LOAD_GLOBAL
        #if not sym.ns and RT.name(sym).find(".") != -1 and RT.name(sym) != "..":
        raise CompilerException(
            "unqualified dotted forms not supported: {0}".format(sym), sym)

        if len(RT.name(sym).replace(".", "")):
            splt.extend((code, attr) for attr in RT.name(sym).split("."))
        else:
            splt.append((code, RT.name(sym)))
        return splt
示例#21
0
    def emit(self, comp, mode):
        module = self.ns
        val = getattr(module, self.name)

        if isinstance(val, Var):
            if not val.isDynamic():
                val = val.deref()
                return [(LOAD_CONST, val)]
            else:
                if mode is PTR_MODE_DEREF:
                    return [(LOAD_CONST, val), (LOAD_ATTR, "deref"),
                            (CALL_FUNCTION, 0)]
                else:
                    raise CompilerException("Invalid deref mode", mode)

        return [(LOAD_CONST, module), (LOAD_ATTR, self.name)]
示例#22
0
def compileNS(comp, form):
    rest = form.next()
    if len(rest) != 1:
        raise CompilerException("in-ns only supports one item", rest)
    ns = rest.first()
    code = [(LOAD_CONST, comp), (LOAD_ATTR, "setNS")]
    if isinstance(ns, Symbol):
        code.append((LOAD_CONST, ns))
    else:
        code.extend(comp.compile(ns))
    code.append((CALL_FUNCTION, 1))
    set_NS_ = [(LOAD_CONST, comp), (LOAD_ATTR, "_NS_"), (LOAD_ATTR, "set"),
               (LOAD_CONST, comp), (LOAD_ATTR, "ns"), (CALL_FUNCTION, 1),
               (LOAD_CONST, comp), (LOAD_ATTR, "ns")]
    code.extend(set_NS_)
    return code
示例#23
0
def compileRecur(comp, form):
    s = form.next()
    idx = 0
    code = []
    while s is not None:
        code.extend(comp.compile(s.first()))
        if idx >= len(comp.recurPoint.first()["args"]):
            raise CompilerException("to many arguments to recur", form)

        idx += 1
        s = s.next()

    sets = comp.recurPoint.first()["args"][:]
    sets.reverse()
    for x in sets:
        code.extend(x)
    code.append((JUMP_ABSOLUTE, comp.recurPoint.first()["label"]))
    return code
示例#24
0
def compilePyIf(comp, form):
    if len(form) != 3 and len(form) != 4:
        raise CompilerException("if takes 2 or 3 args", form)
    cmp = comp.compile(form.next().first())
    body = comp.compile(form.next().next().first())
    if len(form) == 3:
        body2 = [(LOAD_CONST, None)]
    else:
        body2 = comp.compile(form.next().next().next().first())

    elseLabel = Label("IfElse")
    endlabel = Label("IfEnd")
    code = cmp
    code.extend(emitJump(elseLabel))
    code.extend(body)
    code.append((JUMP_ABSOLUTE, endlabel))
    code.extend(emitLanding(elseLabel))
    code.extend(body2)
    code.append((endlabel, None))
    return code
示例#25
0
    def compile(self, itm):
        from clojure.lang.persistentlist import PersistentList, EmptyList
        from clojure.lang.cons import Cons
        c = []
        lineset = False
        if hasattr(itm, "meta") and itm.meta() is not None:
            line = itm.meta()[LINE_KEY]
            if line is not None and line > self.lastlineno:
                lineset = True
                self.lastlineno = line
                c.append([SetLineno, line])

        if isinstance(itm, Symbol):
            c.extend(self.compileSymbol(itm))
        elif isinstance(itm, PersistentList) or isinstance(itm, Cons):
            c.extend(self.compileForm(itm))
        elif itm is None:
            c.extend(self.compileNone(itm))
        elif type(itm) in [str, int, new.classobj, type]:
            c.extend([(LOAD_CONST, itm)])
        elif isinstance(itm, IPersistentVector):
            c.extend(compileVector(self, itm))
        elif isinstance(itm, IPersistentMap):
            c.extend(compileMap(self, itm))
        elif isinstance(itm, Keyword):
            c.extend(compileKeyword(self, itm))
        elif isinstance(itm, bool):
            c.extend(compileBool(self, itm))
        elif isinstance(itm, EmptyList):
            c.append((LOAD_CONST, itm))
        elif isinstance(itm, unicode):
            c.append((LOAD_CONST, itm))
        else:
            raise CompilerException(
                "Don't know how to compile" + str(type(itm)), None)

        if len(c) < 2 and lineset:
            return []
        return c
示例#26
0
def compileKWApply(comp, form):
    if len(form) < 3:
        raise CompilerException("at least two arguments required to kwapply",
                                form)

    form = form.next()
    fn = form.first()
    form = form.next()
    kws = form.first()
    args = form.next()
    code = []

    s = args
    code.extend(comp.compile(fn))
    while s is not None:
        code.extend(comp.compile(s.first()))
        s = s.next()
    code.extend(comp.compile(kws))
    code.append((LOAD_ATTR, "toDict"))
    code.append((CALL_FUNCTION, 0))
    code.append((CALL_FUNCTION_KW, 0 if args is None else len(args)))
    return code
示例#27
0
def compileMultiFn(comp, name, form):
    s = form
    argdefs = []

    while s is not None:
        argdefs.append(MultiFn(comp, s.first()))
        s = s.next()
    argdefs = sorted(argdefs, lambda x, y: len(x.args) < len(y.args))
    if len(filter(lambda x: x.lastisargs, argdefs)) > 1:
        raise CompilerException(
            "Only one function overload may have variable number of arguments",
            form)

    code = []
    if len(argdefs) == 1 and not argdefs[0].lastisargs:
        hasvararg = False
        argslist = argdefs[0].args
        code.extend(argdefs[0].bodycode)
    else:
        hasvararg = True
        argslist = ["__argsv__"]
        for x in argdefs:
            code.extend(x.argcode)
            code.extend(x.bodycode)

        code.append((LOAD_CONST, Exception))
        code.append((CALL_FUNCTION, 0))
        code.append((RAISE_VARARGS, 1))

    clist = map(lambda x: x.sym.name, comp.closureList())
    c = Code(code, clist, argslist, hasvararg, False, True,
             str(symbol(comp.getNS().__name__, name.name)), comp.filename, 0,
             None)

    if not clist:
        c = new.function(c.to_code(), comp.ns.__dict__, name.name)

    return [(LOAD_CONST, c)], c
示例#28
0
def compileTry(comp, form):
    """
    Compiles the try macro.
    """
    assert form.first() == Symbol("try")
    form = form.next()

    if not form:
        # I don't like this, but (try) == nil
        return [(LOAD_CONST, None)]

    # Keep a list of compiled might-throw statements in
    # implicit-do try body
    body = comp.compile(form.first())
    form = form.next()

    if not form:
        # If there are no further body statements, or
        # catch/finally/else etc statements, just
        # compile the body
        return body

    catch = []
    els = None
    fin = None
    for subform in form:
        try:
            name = subform.first()
        except AttributeError:
            name = None
        if name in (Symbol("catch"), Symbol("except")):
            name = subform.first()
            if len(subform) != 4:
                raise CompilerException(
                    "try {0} blocks must be 4 items long".format(name), form)

            # Exception is second, val is third
            exception = subform.next().first()
            if not isinstance(exception, Symbol):
                raise CompilerException(
                    "exception passed to {0} block must be a symbol".format(
                        name), form)
            for ex, _, _ in catch:
                if ex == exception:
                    raise CompilerException(
                        "try cannot catch duplicate exceptions", form)

            var = subform.next().next().first()
            if not isinstance(var, Symbol):
                raise CompilerException(
                    "variable name for {0} block must be a symbol".format(
                        name), form)
            val = subform.next().next().next().first()
            catch.append((exception, var, val))
        elif name == Symbol("else"):
            if len(subform) != 2:
                raise CompilerException("try else blocks must be 2 items",
                                        form)
            elif els:
                raise CompilerException("try cannot have multiple els blocks",
                                        form)
            els = subform.next().first()
        elif name == Symbol("finally"):
            if len(subform) != 2:
                raise CompilerException("try finally blocks must be 2 items",
                                        form)
            elif fin:
                raise CompilerException(
                    "try cannot have multiple finally blocks", form)
            fin = subform.next().first()
        else:
            # Append to implicit do
            body.append((POP_TOP, None))
            body.extend(comp.compile(subform))

    if fin and not catch and not els:
        return compileTryFinally(body, comp.compile(fin))
    elif catch and not fin and not els:
        return compileTryCatch(comp, body, catch)
    elif not fin and not catch and els:
        raise CompilerException(
            "try does not accept else statements on their own", form)

    if fin and catch and not els:
        return compileTryCatchFinally(comp, body, catch, comp.compile(fin))

    if not fin and not catch and not els:
        # No other statements, return compiled body
        return body
示例#29
0
def getBuiltin(name):
    if hasattr(__builtin__, name):
        return getattr(__builtin__, name)
    raise CompilerException("Python builtin {0} not found".format(name), name)
示例#30
0
def compileBuiltin(comp, form):
    if len(form) != 2:
        raise CompilerException("throw requires two arguments", form)
    name = str(form.next().first())
    return [(LOAD_CONST, getBuiltin(name))]