예제 #1
0
 def find(sym):
     from py.clojure.lang.namespace import find as findNamespace
     if sym.ns is None:
         raise InvalidArgumentException("Symbol must be namespace-qualified")
     ns = findNamespace(Symbol.intern(sym.ns))
     if ns is None:
         raise InvalidArgumentException("No such namespace " + str(sym.ns))
     return ns.findInternedVar(Symbol.intern(sym.name))
예제 #2
0
    def syntaxQuote(self, form):
        from py.clojure.lang.compiler import builtins as compilerbuiltins
        if form in compilerbuiltins:
            ret = RT.list(_QUOTE_, form)
        elif isinstance(form, Symbol):
            sym = form
            if sym.ns is None and sym.name.endswith("#"):
                gmap = GENSYM_ENV.deref()
                if gmap == None:
                    raise ReaderException("Gensym literal not in syntax-quote, before", self.rdr)
                gs = gmap[sym]
                if gs is None:
                    gs = Symbol.intern(None, sym.name[:-1] + "__" + str(RT.nextID()) + "__auto__")
                    GENSYM_ENV.set(gmap.assoc(sym, gs))
                sym = gs

            elif sym.ns is None and sym.name.endswith("."):
                ret = sym
            elif sym.ns is None and sym.name.startswith("."):
                ret = sym
            else:
                comp = currentCompiler.get(lambda: None)
                if comp is None:
                    raise IllegalStateException("No Compiler found in syntax quote!")
                ns = comp.getNS()
                if ns is None:
                    raise IllegalStateException("No ns in reader")
                sym = Symbol.intern(ns.__name__, sym.name)
            ret = RT.list(_QUOTE_, sym)
        else:
            if isUnquote(form):
                return form.next().first()
            elif isUnquoteSplicing(form):
                raise IllegalStateException("splice not in list")
            elif isinstance(form, IPersistentCollection):
                if isinstance(form, IPersistentMap):
                    keyvals = flattenMap(form)
                    ret = RT.list(_APPLY_, _HASHMAP_, RT.list(RT.cons(_CONCAT_, self.sqExpandList(keyvals.seq()))))
                elif isinstance(form, (IPersistentVector, IPersistentSet)):
                    ret = RT.list(_APPLY_, _VECTOR_, RT.list(_SEQ_, RT.cons(_CONCAT_, self.sqExpandList(form.seq()))))
                elif isinstance(form, (ISeq, IPersistentList)):
                    seq = form.seq()
                    if seq is None:
                        ret = RT.cons(_LIST_, None)
                    else:
                        ret = RT.list(_SEQ_, RT.cons(_CONCAT_, self.sqExpandList(seq)))
                else:
                    raise IllegalStateException("Unknown collection type")
            elif isinstance(form, (int, float, str, Keyword)):
                ret = form
            else:
                ret = RT.list(_QUOTE_, form)
        if hasattr(form, "meta") and form.meta() is not None:
            newMeta = form.meta().without(LINE_KEY)
            if len(newMeta) > 0:
                return RT.list(_WITH_META_, ret, self.syntaxQuote(form.meta()))
        return ret
예제 #3
0
 def find(self, *args):
     if len(args) == 1:
         if isinstance(args[0], Symbol):
             return interned.val()[args[0]]()
         if isinstance(args[0], str):
             return Keyword.find(Symbol.intern(args[0]))
     if len(args) == 2:
         return Keyword.find(Symbol.intern(*args))
     raise ArityException()
예제 #4
0
def compileFNStar(comp, form):
    haslocalcaptures = False
    if len(comp.locals) > 0: # we got a closure to deal with
        comp.pushLocalCaptures()
        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):
        comp.pushName(name)
        pushed = True
        name = Symbol.intern("fn" + str(RT.nextID()))
    else:
        form = form.next()

    if isinstance(form.first(), IPersistentVector):
        code = compileFn(comp, name, form, orgform)
    else:
        code = compileMultiFn(comp, name, form)



    if pushed:
        comp.popName()
    clist = comp.closureList()
    fcode = []


    if haslocalcaptures:
        comp.popLocalCaptures()

    if clist:
        for x in clist:
            fcode.extend(comp.compile(Symbol.intern(x)))
            fcode.append((STORE_DEREF, x))
            fcode.append((LOAD_CLOSURE, x))
        fcode.append((BUILD_TUPLE, len(clist)))
        fcode.extend(code)
        fcode.append((MAKE_CLOSURE, 0))
        code = fcode




    return code
예제 #5
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 = []
    args = []
    for x in argdefs:
        code.extend(x.code)
        for x in x.args:
            if x not in args:
                args.append(x)

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

    c = Code(code, comp.closureList(), ["__argsv__"], True, False, True, str(Symbol.intern(comp.getNS().__name__, name.name)), "./clj/clojure/core.clj", 0, None)

    fn = new.function(c.to_code(), comp.ns.__dict__, name.name)

    return [(LOAD_CONST, fn)]
예제 #6
0
def compileVector(comp, form):
    code = []
    code.extend(comp.compile(Symbol.intern("clojure.lang.rt.vector")))
    for x in form:
        code.extend(comp.compile(x))
    code.append((CALL_FUNCTION, len(form)))
    return code
예제 #7
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)]
    recurlabel = Label("recurLabel")
    recur = {"label": recurlabel,
             "args": 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: x.sym.name, comp.closureList())
    c = Code(code, clist, args, lastisargs, False, True, str(Symbol.intern(comp.getNS().__name__, name.name)), "./clj/clojure/core.clj", 0, None)
    if not clist:
        c = new.function(c.to_code(), comp.ns.__dict__, name.name)

    return [(LOAD_CONST, c)]
예제 #8
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.intern(comp.getNS().__name__, name.name)), "./clj/clojure/core.clj", 0, None)
    if not clist:
        c = new.function(c.to_code(), comp.ns.__dict__, name.name)

    return [(LOAD_CONST, c)]
예제 #9
0
 def executeCode(self, code):
     import sys
     if code == []:
         return None
     newcode = code[:]
     newcode.append((RETURN_VALUE, None))
     c = Code(newcode, [], [], False, False, False, str(Symbol.intern(self.getNS().__name__, "<string>")), "./clj/clojure/core.clj", 0, None)
     retval = eval(c.to_code(), self.getNS().__dict__)
     return retval
예제 #10
0
    def intern(*args):
        if len(args) == 1:
            if isinstance(args[0], Symbol):
                sym = args[0]
                if sym.meta() is not None:
                    sym = sym.withMeta(None)
                k = Keyword(sym)

                interned.mutate(lambda old: old if sym in old else old.assoc(sym,k))

                return interned.get()[sym]
            elif isinstance(args[0], str):
                return Keyword.intern(Symbol.intern(args[0]))
            else:
                raise InvalidArgumentException()
        elif len(args) == 2:
            return Keyword.intern(Symbol.intern(*args))
        else:
            raise ArityException()
예제 #11
0
def compileMap(comp, form):
    s = form.seq()
    c = 0
    code = []
    code.extend(comp.compile(Symbol.intern("clojure.lang.rt.map")))
    while s is not None:
        kvp = s.first()
        code.extend(comp.compile(kvp.getKey()))
        code.extend(comp.compile(kvp.getValue()))
        c += 2
        s = s.next()
    code.append([CALL_FUNCTION, c])
    return code
예제 #12
0
def compileFNStar(comp, form):
    haslocalcaptures = False
    aliases = []
    if len(comp.aliases) > 0: # we got a closure 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):
        comp.pushName(name)
        pushed = True
        name = Symbol.intern("fn" + str(RT.nextID()))
    else:
        form = form.next()

    if isinstance(form.first(), IPersistentVector):
        code = compileFn(comp, name, form, orgform)
    else:
        code = compileMultiFn(comp, name, form)



    if pushed:
        comp.popName()
    clist = comp.closureList()
    fcode = []


    if haslocalcaptures:
        comp.popAliases(aliases)

    if clist:
        for x in clist:
            fcode.extend(comp.getAlias(x.sym).compile(comp))  # Load our local version
            fcode.append((STORE_DEREF, x.sym.name))            # Store it in a Closure Cell
            fcode.append((LOAD_CLOSURE, x.sym.name))           # Push the cell on the stack
        fcode.append((BUILD_TUPLE, len(clist)))
        fcode.extend(code)
        fcode.append((MAKE_CLOSURE, 0))
        code = fcode
    return code
예제 #13
0
    def executeModule(self, code):
        code.append((RETURN_VALUE, None))
        c = Code(code, [], [], False, False, False, str(Symbol.intern(self.getNS().__name__, "<string>")), "./clj/clojure/core.clj", 0, None)
        import marshal
        import pickle
        import py_compile
        import time
        import dis

        dis.dis(c)
        codeobject = c.to_code()
        print codeobject.__class__ is compileDef.__class__

        with open('output.pyc', 'wb') as fc:
            fc.write(py_compile.MAGIC)
            py_compile.wr_long(fc, long(time.time()))
            marshal.dump(c, fc)
예제 #14
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.locals:
            newlocal = Symbol.intern(str(local)+"_"+str(RT.nextID()))
            code.extend(comp.compile(body))
            comp.locals[local] = comp.locals[local].cons(newlocal)
            args.append(local)
            local = newlocal
        else:
            comp.locals[local] = RT.list(local)
            args.append(local)
            code.extend(comp.compile(body))


        code.append((STORE_FAST, str(local)))

        idx += 1

    form = form.next()
    recurlabel = Label("recurLabel")
    recur = {"label": recurlabel,
             "args": map(lambda x: x.name, args)}
    code.append((recurlabel, None))
    comp.pushRecur(recur)
    code.extend(compileImplcitDo(comp, form))
    comp.popRecur()
    comp.popLocals(args)
    return code
예제 #15
0
def compileRecur(comp, form):
    s = form.next()
    idx = 0
    code = []
    locals = []
    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)
        local = comp.recurPoint.first()["args"][idx]
        local = comp.locals[Symbol.intern(local)].first()
        locals.append(local.name)
        idx += 1
        s = s.next()
    locals.reverse()
    code.extend(map(lambda x: (STORE_FAST, x), locals))
    code.append((JUMP_ABSOLUTE, comp.recurPoint.first()["label"]))
    return code
예제 #16
0
def matchSymbol(s):
    from py.clojure.lang.symbol import Symbol
    from py.clojure.lang.cljkeyword import Keyword
    m = symbolPat.match(s)
    if m is not None:
        ns = m.group(1)
        name = m.group(2)
        if ns is not None and ns.endswith(":/") or name.endswith(":")\
            or s.find("::") != -1:
                return None
        if s.startswith("::"):
            return "FIX"
        ns = ns if ns is None else ns[:-1]
        iskeyword = s.find(':') == 0
        sym = Symbol.intern(ns, name[(1 if iskeyword else 0):])
        if iskeyword:
            return Keyword.intern(s)
        else:
            return sym
    return None
예제 #17
0
def compileRecur(comp, form):
    s = form.next()
    idx = 0
    code = []
    locals = []
    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)
        local = comp.recurPoint.first()["args"][idx]
        local = comp.getAlias(Symbol.intern(local))
        if local is None:
            pass
        locals.append(local)
        idx += 1
        s = s.next()
    locals.reverse()
    for x in locals:
        code.extend(x.compileSet(comp))
    code.append((JUMP_ABSOLUTE, comp.recurPoint.first()["label"]))
    return code
예제 #18
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.intern(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
예제 #19
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
    code = []
    code.extend(comp.compile(value))
    code.append((DUP_TOP, 0))
    code.append((STORE_GLOBAL, sym.name))

    if sym.meta() is not None:
        code.extend(comp.compileAccessList(Symbol.intern("clojure.lang.rt.setMeta")))
        code.append((ROT_TWO, 0))
        code.append((LOAD_CONST, sym.meta()))
        code.append((CALL_FUNCTION, 2))
    return code
예제 #20
0
파일: clojure.py 프로젝트: janus/clojure-py
def main():
    requireClj("./clj/clojure/core.clj")

    RT.init()
    comp = Compiler()
    currentCompiler.set(comp)
    comp.setNS(Symbol.intern("user"))

    if not sys.argv[1:]:
        while True:
            try:
                line = raw_input(comp.getNS().__name__ + "=> ")
            except EOFError:
                break

            if not line:
                continue

            while unbalanced(line):
                try:
                    line += raw_input('.' * len(comp.getNS().__name__) + '.. ')
                except EOFError:
                    break

            # Propogate break from above loop.
            if unbalanced(line):
                break

            r = StringReader(line)
            s = read(r, True, None, True)

            try:
                res = comp.compile(s)
                print comp.executeCode(res)
            except Exception:
                import traceback; traceback.print_exc()
예제 #21
0
def garg(n):
    from symbol import Symbol
    return Symbol.intern(None,  "rest" if n == -1 else  ("p" + str(n)) + "__" + str(RT.nextID()) + "#")
예제 #22
0
 def pushLocalCaptures(self):
     for x in self.locals:
         self.locals[x] = self.locals[x].cons(Symbol.intern("__closure__" + self.locals[x].first().name))
     self.usedClosures = self.usedClosures.cons([])
예제 #23
0
파일: tests.py 프로젝트: janus/clojure-py
 def setUp(self):
     RT.init()
     self.comp = Compiler()
     currentCompiler.set(self.comp)
     self.comp.setNS(Symbol.intern('clojure.core'))
예제 #24
0
from py.clojure.lang.ipersistentvector import IPersistentVector
from py.clojure.lang.ipersistentmap import IPersistentMap
from py.clojure.lang.ipersistentlist import IPersistentList
from py.clojure.lang.var import Var
from py.clojure.util.byteplay import *
from py.clojure.lang.cljkeyword import Keyword
import new
import py.clojure.lang.rt as RT
from py.clojure.lang.lispreader import _AMP_
from py.clojure.lang.namespace import findItem
from py.clojure.lang.lispreader import LINE_KEY, garg
import re
import new


_MACRO_ = Keyword.intern(Symbol.intern(":macro"))



def compileNS(comp, form):
    rest = form.next()
    if len(rest) != 1:
        raise CompilerException("ns only supports one item", rest)
    comp.setNS(rest.first())
    return []

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
예제 #25
0
 def intern(ns, name):
     if isinstance(ns, Namespace):
         return ns.intern(name)
     ns = Namespace.findOrCreate(Symbol.intern(ns))
     return Var.intern(ns, name)
예제 #26
0
from py.clojure.lang.iref import IRef
from py.clojure.lang.ifn import IFn
from py.clojure.lang.settable import Settable
from py.clojure.lang.aref import ARef
from py.clojure.lang.cljexceptions import ArityException, InvalidArgumentException, IllegalStateException
from py.clojure.lang.persistenthashmap import EMPTY
from py.clojure.lang.threadutil import ThreadLocal, synchronized, currentThread
from py.clojure.lang.symbol import Symbol
from py.clojure.lang.cljkeyword import Keyword
from persistentarraymap import PersistentArrayMap

privateKey = Keyword.intern(Symbol.intern("private"))
macrokey = Keyword.intern(Symbol.intern(":macro"))
dvals = ThreadLocal()
privateMeta = PersistentArrayMap.create([privateKey, True])
UKNOWN = Symbol.intern("UNKNOWN")

def pushThreadBindings(bindings):
    f = dvals.get(lambda: Var.Frame())
    bmap = f.bindings
    bs = bindings.seq()
    while bs is not None:
        e = bs.first()
        v = e.getKey()
        if not v.dynamic:
            raise IllegalStateException("Can't dynamically bind non-dynamic var: " + str(v.ns) + "/" + str(v.sym))
        v.validate(v.getValidator(), e.getValue())
        v.threadBound = True
        bmap = bmap.assoc(v, Var.TBox(currentThread(), e.getValue()))
        bs = bs.next()
    dvals.set(Var.Frame(bmap, f))
예제 #27
0
    def compileSymbol(self, sym):


        if sym in self.locals or Symbol.intern("__closure__" + str(sym)) in self.locals:
            return self.compileLocal(sym)
        return self.compileAccessList(sym)
예제 #28
0
#from py.clojure.lang.gmp import Integer, Rational, Float
import py.clojure.lang.rt as RT
from py.clojure.lang.cljkeyword import LINE_KEY
from py.clojure.lang.symbol import Symbol
from py.clojure.lang.persistentvector import EMPTY as EMPTY_VECTOR
from py.clojure.lang.globals import currentCompiler
from py.clojure.lang.cljkeyword import Keyword
import re

def read1(rdr):
    rdr.next()
    if rdr is None:
        return ""
    return rdr.first()

_AMP_ = Symbol.intern("&")
_FN_ = Symbol.intern("fn")
_VAR_ = Symbol.intern("var")
_APPLY_ = Symbol.intern("apply")
_HASHMAP_ = Symbol.intern("clojure.core", "hashmap")
_CONCAT_ = Symbol.intern("clojure.core", "concat")
_LIST_ = Symbol.intern("clojure.core", "list")
_SEQ_ = Symbol.intern("clojure.core", "seq")
_VECTOR_ = Symbol.intern("clojure.core", "vector")
_QUOTE_ = Symbol.intern("quote")
_SYNTAX_QUOTE_ = Symbol.intern("`")
_UNQUOTE_ = Symbol.intern("~")
_UNQUOTE_SPLICING_ = Symbol.intern("~@")

ARG_ENV = Var.create(None).setDynamic()
GENSYM_ENV = Var.create(None).setDynamic()
예제 #29
0
 def internPrivate(nsName, sym):
     ns = Namespace.findOrCreate(Symbol.intern(nsName))
     ret = Var.intern(ns, Symbol.intern(sym))
     ret.setMeta(Var.privateMeta)
     return ret
예제 #30
0
 def __init__(self, sym, rest = None):
     AAlias.__init__(self, rest)
     self.sym = sym
     self.newsym = Symbol.intern(sym.name + str(RT.nextID()))