예제 #1
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(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
            elif sym.ns is not None:
                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(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
예제 #2
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(sym.ns))
    if ns is None:
        raise InvalidArgumentException("No such namespace " + str(sym.ns))
    return ns.findInternedVar(symbol(sym.name))
예제 #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(args[0]))
    if len(args) == 2:
        return Keyword.find(symbol(*args))
    raise ArityException()
예제 #4
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": 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(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)]
예제 #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 = []
    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)]
예제 #6
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 = []
    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("clojure.lang.rt.setMeta")))
        code.append((ROT_TWO, 0))
        code.append((LOAD_CONST, sym.meta()))
        code.append((CALL_FUNCTION, 2))

    comp.popName()
    return code
예제 #7
0
def compileVector(comp, form):
    code = []
    code.extend(comp.compile(symbol("clojure.lang.rt.vector")))
    for x in form:
        code.extend(comp.compile(x))
    code.append((CALL_FUNCTION, len(form)))
    return code
예제 #8
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(self.getNS().__name__, "<string>")), self.filename, 0, None)
     retval = eval(c.to_code(), self.getNS().__dict__)
     return retval
예제 #9
0
def keyword(*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(symbol(args[0]))
        else:
            raise InvalidArgumentException()
    elif len(args) == 2:
        return keyword(symbol(*args))
    else:
        raise ArityException()
예제 #10
0
def compileMap(comp, form):
    s = form.seq()
    c = 0
    code = []
    code.extend(comp.compile(symbol("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
예제 #11
0
    def executeModule(self, code):
        code.append((RETURN_VALUE, None))
        c = Code(code, [], [], False, False, False, str(symbol(self.getNS().__name__, "<string>")), self.filename, 0, None)
        import marshal
        import pickle
        import py_compile
        import time
        import dis

        dis.dis(c)
        codeobject = c.to_code()

        with open('output.pyc', 'wb') as fc:
            fc.write(py_compile.MAGIC)
            py_compile.wr_long(fc, long(time.time()))
            marshal.dump(c, fc)
예제 #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: x.name, args)}
    code.append((recurlabel, None))
    comp.pushRecur(recur)
    code.extend(compileImplcitDo(comp, form))
    comp.popRecur()
    comp.popAliases(args)
    return code
예제 #13
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(ns, name[(1 if iskeyword else 0):])
        if iskeyword:
            return keyword(s)
        else:
            return sym
    return None
예제 #14
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(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
예제 #15
0
def main():
    requireClj(os.path.dirname(__file__) + "/clj/clojure/core.clj")

    RT.init()
    comp = Compiler()
    currentCompiler.set(comp)
    comp.setNS(symbol("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:
                traceback.print_exc()
    else:
        for x in sys.argv[1:]:
            requireClj(x)
예제 #16
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
예제 #17
0
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 *
import py.clojure.util.byteplay as byteplay
from py.clojure.lang.cljkeyword import Keyword, 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
import sys

_MACRO_ = keyword(symbol(":macro"))
version = (sys.version_info[0] * 10) + sys.version_info[1]

def emitJump(label):
    if version == 26:
        return [(JUMP_IF_FALSE, label),
                (POP_TOP, None)]
    else:
        return [(POP_JUMP_IF_FALSE, label)]

def emitLanding(label):
    if version == 26:
        return [(label, None),
                (POP_TOP, None)]
    else:
        return [(label, None)]
예제 #18
0
 def __init__(self, sym, rest = None):
     AAlias.__init__(self, rest)
     self.sym = sym
     self.newsym = symbol(sym.name + str(RT.nextID()))
예제 #19
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):
        name = comp.getNamesString()
    else:
        comp.pushName(name.name)
        pushed = True
        form = form.next()

    name = symbol(name)
    gensym = symbol("_"+name.name + str(RT.nextID()))

    if haslocalcaptures:
        comp.pushAlias(name, LocalMacro(name, gensym))

    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.popAlias(name)

    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

    if haslocalcaptures:
        code.append((DUP_TOP, None))
        code.append((STORE_GLOBAL, gensym.name))

    return code
예제 #20
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, currentThread
from py.clojure.lang.symbol import symbol
from py.clojure.lang.cljkeyword import keyword
import persistentarraymap

privateKey = keyword(symbol("private"))
macrokey = keyword(symbol(":macro"))
dvals = ThreadLocal()
privateMeta = persistentarraymap.create([privateKey, True])
UKNOWN = symbol("UNKNOWN")


def pushThreadBindings(bindings):
    f = dvals.get(lambda: 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))
예제 #21
0
def intern(ns, name):
    if isinstance(ns, Namespace):
        return ns.intern(name)
    ns = Namespace.findOrCreate(symbol(ns))
    return intern(ns, name)
예제 #22
0
def internPrivate(nsName, sym):
    ns = Namespace.findOrCreate(symbol(nsName))
    ret = intern(ns, symbol(sym))
    ret.setMeta(Var.privateMeta)
    return ret
예제 #23
0
from py.clojure.lang.cljexceptions import ReaderException, IllegalStateException
import py.clojure.lang.rt as RT
from py.clojure.lang.cljkeyword import LINE_KEY
from py.clojure.lang.symbol import Symbol, 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, keyword
import re

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

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

ARG_ENV = var(None).setDynamic()
GENSYM_ENV = var(None).setDynamic()
예제 #24
0
 def setUp(self):
     RT.init()
     self.comp = Compiler()
     currentCompiler.set(self.comp)
     self.comp.setNS(symbol("clojure.core"))
예제 #25
0
def garg(n):
    from symbol import Symbol
    return symbol(None,  "rest" if n == -1 else  ("p" + str(n)) + "__" + str(RT.nextID()) + "#")