Beispiel #1
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 = internVar(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
Beispiel #2
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
Beispiel #3
0
def compileFn(comp, name, form, orgform):
    locals, args, lastisargs, argsname = unpackArgs(form.first())

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

    if orgform.meta() is not None:
        line = orgform.meta()[LINE_KEY]
    else:
        line = 0
    code = [(SetLineno,line if line is not None else 0)]
    if lastisargs:
        code.extend(cleanRest(argsname.name))

    recurlabel = Label("recurLabel")

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

    code.append((recurlabel, None))
    comp.pushRecur(recur)
    code.extend(compileImplcitDo(comp, form.next()))
    comp.popRecur()
    code.append((RETURN_VALUE,None))
    comp.popAliases(locals)

    clist = map(lambda x: RT.name(x.sym), comp.closureList())
    code = expandMetas(code, comp)
    c = Code(code, clist, args, lastisargs, False, True, str(symbol(comp.getNS().__name__, name.name)), comp.filename, 0, None)
    if not clist:
        c = types.FunctionType(c.to_code(), comp.ns.__dict__, name.name)

    return [(LOAD_CONST, c)], c
Beispiel #4
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: RT.name(x.sym), comp.closureList())
    code = expandMetas(code, comp)
    c = Code(code, clist, argslist, hasvararg, False, True, str(symbol(comp.getNS().__name__, name.name)), comp.filename, 0, None)
    if not clist:
        c = types.FunctionType(c.to_code(), comp.ns.__dict__, name.name)
    return [(LOAD_CONST, c)], c
Beispiel #5
0
    def extendForType(self, tp, mp):
        """Extends this protocol for the given type and the given map of methods
           mp should be a map of methodnames: functions"""
       
        for x in mp:
            name =  RT.name(x.sym)
            if name not in self.protofns:
                raise ProtocolException("No Method found for name " + x)
            
            fn = self.protofns[name]
            fn.extend(tp, mp[x])

        self.markImplementor(tp)
Beispiel #6
0
    def extendForType(self, tp, mp):
        """Extends this protocol for the given type and the given map of methods
           mp should be a map of methodnames: functions"""

        for x in mp:
            name = RT.name(x.sym)
            if name not in self.protofns:
                raise ProtocolException("No Method found for name " + x)

            fn = self.protofns[name]
            fn.extend(tp, mp[x])

        self.markImplementor(tp)
Beispiel #7
0
    def getAccessCode(self, sym):
        print sym
        if (sym.ns is not None and sym.ns == self.nsString) \
           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 '{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 maybeDeref(self.ns, self.nsString, RT.name(sym), self.nsString)

        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 = findNamespace(sym.ns)
            if not hasattr(module, RT.name(sym)):
                raise CompilerException(
                    "{0} does not define {1}".format(module, RT.name(sym)),
                    None)

            return getAttrChain(sym.getNamespace() + "." + sym.getName())

        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
Beispiel #8
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 = []
    i = getAttrChain("clojure.lang.var.intern")
    v = tr.Call(i, tr.Const(comp.getNS().__name__), tr.Const(sym.getName()))

    # We just wrote some treadle code to define a var, but
    # the compiler won't see that yet, so let's re-define the var now
    # so that the compiler can pick it up

    internVar(comp.getNS().__name__, sym.getName())

    #v.setDynamic(True)
    if len(form) == 3:
        code = tr.Call(tr.Attr(v, "bindRoot"),
                           comp.compile(value))


    else:
        code = v

    with Quoted(comp):
        code = tr.Call(tr.Attr(code, "setMeta"), comp.compile(sym.meta()))
    #v.setMeta(sym.meta())
    comp.popName()
    return code
Beispiel #9
0
def compileFn(comp, name, form, orgform):
    locals, args, lastisargs, argsname = unpackArgs(form.first())

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

    if orgform.meta() is not None:
        line = orgform.meta()[LINE_KEY]
    else:
        line = 0
    code = [(SetLineno, line if line is not None else 0)]
    if lastisargs:
        code.extend(cleanRest(argsname.name))

    recurlabel = Label("recurLabel")

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

    code.append((recurlabel, None))
    comp.pushRecur(recur)
    code.extend(compileImplcitDo(comp, form.next()))
    comp.popRecur()
    code.append((RETURN_VALUE, None))
    comp.popAliases(locals)

    clist = map(lambda x: RT.name(x.sym), comp.closureList())
    code = expandMetas(code, comp)
    c = Code(code, clist, args, lastisargs, False, True,
             str(Symbol(comp.getNS().__name__, name.name)), comp.filename, 0,
             None)
    if not clist:
        c = types.FunctionType(c.to_code(), comp.ns.__dict__, name.name)

    return [(LOAD_CONST, c)], c
Beispiel #10
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: RT.name(x.sym), comp.closureList())
    code = expandMetas(code, comp)
    c = Code(code, clist, argslist, hasvararg, False, True,
             str(Symbol(comp.getNS().__name__, name.name)), comp.filename, 0,
             None)
    if not clist:
        c = types.FunctionType(c.to_code(), comp.ns.__dict__, name.name)
    return [(LOAD_CONST, c)], c
Beispiel #11
0
 def test_named(self):
     self.assertEqual(RT.name(RT.symbol(u"foo")), u"foo")
     self.assertEqual(RT.namespace(RT.symbol(u"foo", u"bar")), u"foo")
Beispiel #12
0
 def compile(self, comp):
     self.isused = True
     return [(LOAD_DEREF, RT.name(self.sym))]
Beispiel #13
0
 def compileSet(self, comp):
     return [(STORE_DEREF, RT.name(self.sym))]
Beispiel #14
0
    def compileAccessList(self, sym):
        if sym.ns == 'py':
            return [(LOAD_CONST, getBuiltin(RT.name(sym)))]

        code = self.getAccessCode(sym)
        return code
Beispiel #15
0
 def compile(self, comp):
     self.isused = True
     return [(LOAD_DEREF, RT.name(self.sym))]
Beispiel #16
0
 def compile(self, comp):
     return [(LOAD_FAST, RT.name(self.newsym))]
Beispiel #17
0
    def compileAccessList(self, sym):
        if sym.ns == 'py':
            return [(LOAD_CONST, getBuiltin(RT.name(sym)))]

        code = self.getAccessCode(sym)
        return code
Beispiel #18
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
Beispiel #19
0
 def __init__(self, sym, rest=None):
     AAlias.__init__(self, rest)
     self.sym = sym
     self.newsym = Symbol(RT.name(sym) + str(RT.nextID()))
Beispiel #20
0
def compileFNStar(comp, form):
    haslocalcaptures = False
    aliases = []
    if len(comp.aliases) > 0: # we might have closures to deal with
        for x in comp.aliases:

            comp.pushAlias(x, Closure(x))
            aliases.append(x)
        haslocalcaptures = True

    orgform = form
    if len(form) < 2:
        raise CompilerException("2 or more arguments to fn* required", form)
    form = form.next()
    name = form.first()
    pushed = False

    if not isinstance(name, Symbol):
        name = comp.getNamesString() + "_auto_"
    else:
        comp.pushName(name.name)
        pushed = True
        form = form.next()

    name = symbol(name)

    # This is fun stuff here. The idea is that we want closures to be able
    # to call themselves. But we can't get a pointer to a closure until after
    # it's created, which is when we actually run this code. So, we're going to
    # create a tmp local that is None at first, then pass that in as a possible
    # closure cell. Then after we create the closure with MAKE_CLOSURE we'll
    # populate this var with the correct value

    selfalias = Closure(name)
    comp.pushAlias(name, selfalias)

    # form = ([x] x)
    if isinstance(form.first(), IPersistentVector):
        code, ptr = compileFn(comp, name, form, orgform)
    # form = (([x] x))
    elif len(form) == 1:
        code, ptr = compileFn(comp, name, RT.list(*form.first()), orgform)
    # form = (([x] x) ([x y] x))
    else:
        code, ptr = compileMultiFn(comp, name, form)

    if pushed:
        comp.popName()

    clist = comp.closureList()
    fcode = []

    if haslocalcaptures:
        comp.popAliases(aliases)

    if clist:
        for x in clist:
            if x is not selfalias:   #we'll populate selfalias later
                fcode.extend(comp.getAlias(x.sym).compile(comp))  # Load our local version
                fcode.append((STORE_DEREF, RT.name(x.sym)))            # Store it in a Closure Cell
            fcode.append((LOAD_CLOSURE, RT.name(x.sym)))           # Push the cell on the stack
        fcode.append((BUILD_TUPLE, len(clist)))
        fcode.extend(code)
        fcode.append((MAKE_CLOSURE, 0))
        code = fcode

    if selfalias in clist:
        prefix = []
        prefix.append((LOAD_CONST, None))
        prefix.extend(selfalias.compileSet(comp))
        prefix.extend(code)
        code = prefix
        code.append((DUP_TOP, None))
        code.extend(selfalias.compileSet(comp))

    comp.popAlias(symbol(name)) #closure
    return code
Beispiel #21
0
 def compileSet(self, comp):
     return [(STORE_FAST, RT.name(self.newsym))]
Beispiel #22
0
 def test_named(self):
     self.assertEqual(RT.name(RT.symbol(u"foo")), u"foo")
     self.assertEqual(RT.namespace(RT.symbol(u"foo", u"bar")), u"foo")
Beispiel #23
0
 def compileSet(self, comp):
     return [(STORE_DEREF, RT.name(self.sym))]
Beispiel #24
0
 def __init__(self, sym, rest = None):
     AAlias.__init__(self, rest)
     self.sym = sym
     self.newsym = symbol(RT.name(sym) + str(RT.nextID()))
Beispiel #25
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
Beispiel #26
0
 def compile(self, comp):
     return [(LOAD_FAST, RT.name(self.newsym))]
Beispiel #27
0
 def compileSet(self, comp):
     return [(STORE_FAST, RT.name(self.newsym))]
Beispiel #28
0
    def compileAccessList(self, sym):
        if sym.ns == 'py':
            return getBuiltin(RT.name(sym))

        code = self.getAccessCode(sym)
        return code
Beispiel #29
0
def compileFNStar(comp, form):
    haslocalcaptures = False
    aliases = []
    if len(comp.aliases) > 0:  # we might have closures to deal with
        for x in comp.aliases:

            comp.pushAlias(x, Closure(x))
            aliases.append(x)
        haslocalcaptures = True

    orgform = form
    if len(form) < 2:
        raise CompilerException("2 or more arguments to fn* required", form)
    form = form.next()
    name = form.first()
    pushed = False

    if not isinstance(name, Symbol):
        name = comp.getNamesString() + "_auto_"
    else:
        comp.pushName(name.name)
        pushed = True
        form = form.next()

    name = Symbol(name)

    # This is fun stuff here. The idea is that we want closures to be able
    # to call themselves. But we can't get a pointer to a closure until after
    # it's created, which is when we actually run this code. So, we're going to
    # create a tmp local that is None at first, then pass that in as a possible
    # closure cell. Then after we create the closure with MAKE_CLOSURE we'll
    # populate this var with the correct value

    selfalias = Closure(name)
    comp.pushAlias(name, selfalias)

    # form = ([x] x)
    if isinstance(form.first(), IPersistentVector):
        code, ptr = compileFn(comp, name, form, orgform)
    # form = (([x] x))
    elif len(form) == 1:
        code, ptr = compileFn(comp, name, RT.list(*form.first()), orgform)
    # form = (([x] x) ([x y] x))
    else:
        code, ptr = compileMultiFn(comp, name, form)

    if pushed:
        comp.popName()

    clist = comp.closureList()
    fcode = []

    if haslocalcaptures:
        comp.popAliases(aliases)

    if clist:
        for x in clist:
            if x is not selfalias:  #we'll populate selfalias later
                fcode.extend(comp.getAlias(
                    x.sym).compile(comp))  # Load our local version
                fcode.append((STORE_DEREF,
                              RT.name(x.sym)))  # Store it in a Closure Cell
            fcode.append(
                (LOAD_CLOSURE, RT.name(x.sym)))  # Push the cell on the stack
        fcode.append((BUILD_TUPLE, len(clist)))
        fcode.extend(code)
        fcode.append((MAKE_CLOSURE, 0))
        code = fcode

    if selfalias in clist:
        prefix = []
        prefix.append((LOAD_CONST, None))
        prefix.extend(selfalias.compileSet(comp))
        prefix.extend(code)
        code = prefix
        code.append((DUP_TOP, None))
        code.extend(selfalias.compileSet(comp))

    comp.popAlias(Symbol(name))  #closure
    return code
Beispiel #30
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