Пример #1
0
    def trace_map(self):
        from pixie.vm.string import String
        from pixie.vm.keyword import keyword

        tm = {keyword(u"type") : keyword(u"pixie")}
        tm[keyword(u"name")] = String(self._name)
        return tm
Пример #2
0
    def fqd(self, itm):
        ns_alias = rt.namespace(itm)
        current_nms = rt.ns.deref()

        if ns_alias is None:
            return keyword(rt.name(itm), rt.name(current_nms))
        else:
            ns_fqd = current_nms.resolve_ns(ns_alias)
            return keyword(rt.name(itm), rt.name(ns_fqd))
Пример #3
0
    def trace_map(self):
        from pixie.vm.string import String
        from pixie.vm.keyword import keyword

        tp = self._tp
        assert isinstance(tp, Type)
        tm = {keyword(u"type") : keyword(u"polymorphic")}
        tm[keyword(u"name")] = String(self._name)
        tm[keyword(u"tp")] = String(tp._name)
        return tm
Пример #4
0
    def trace_map(self):
        import pixie.vm.rt as rt
        from pixie.vm.keyword import keyword

        tm = {keyword(u"type"): keyword(u"extra"),
              keyword(u"msg"): rt.wrap(self._str)}

        if self._data:
            tm[keyword(u"data")] = self._data

        return tm
Пример #5
0
    def trace_map(self):
        import pixie.vm.rt as rt
        from pixie.vm.keyword import keyword

        tm = {keyword(u"type"): keyword(u"extra"),
              keyword(u"msg"): rt.wrap(self._str)}

        if self._data:
            tm[keyword(u"data")] = self._data

        return tm
Пример #6
0
def _throw(ex):
    from pixie.vm.keyword import keyword
    if isinstance(ex, RuntimeException):
        raise WrappedException(ex)
    if rt._satisfies_QMARK_(IVector, ex):
        data = rt.nth(ex, rt.wrap(0))
        msg = rt.nth(ex, rt.wrap(1))
    elif rt._satisfies_QMARK_(ILookup, ex):
        data = rt._val_at(ex, keyword(u"data"), nil)
        msg = rt._val_at(ex, keyword(u"msg"), nil)
    else:
        affirm(False, u"Can only throw vectors, maps and exceptions")
        return nil
    raise WrappedException(RuntimeException(msg, data))
Пример #7
0
def _throw(ex):
    from pixie.vm.keyword import keyword
    if isinstance(ex, RuntimeException):
        raise WrappedException(ex)
    if rt._satisfies_QMARK_(IVector, ex):
        data = rt.nth(ex, rt.wrap(0))
        msg = rt.nth(ex, rt.wrap(1))
    elif rt._satisfies_QMARK_(ILookup, ex):
        data = rt._val_at(ex, keyword(u"data"), nil)
        msg = rt._val_at(ex, keyword(u"msg"), nil)
    else:
        affirm(False, u"Can only throw vectors, maps and exceptions")
        return nil
    raise WrappedException(RuntimeException(msg, data))
Пример #8
0
def affirm(val, msg):
    """Works a lot like assert except it throws RuntimeExceptions"""
    assert isinstance(msg, unicode)
    if not val:
        import pixie.vm.rt as rt
        from pixie.vm.keyword import keyword
        raise WrappedException(RuntimeException(rt.wrap(msg), keyword(u"pixie.stdlib/AssertionException")))
Пример #9
0
    def inner_invoke(self, args):
        from pixie.vm.keyword import keyword
        import pixie.vm.rt as rt
        from pixie.vm.string import String
        import pixie.vm.persistent_vector as vector

        with with_ns(u"user"):
            NS_VAR.deref().include_stdlib()

        acc = vector.EMPTY
        for x in self._argv:
            acc = rt.conj(acc, rt.wrap(x))

        PROGRAM_ARGUMENTS.set_root(acc)


        rdr = MetaDataReader(PromptReader())
        with with_ns(u"user"):
            while True:
                try:
                    val = read(rdr, False)
                    if val is eof:
                        break
                    val = interpret(compile(val))
                except WrappedException as ex:
                    print "Error: ", ex._ex.__repr__()
                    rdr.reset_line()
                    continue
                if val is keyword(u"exit-repl"):
                    break
                val = rt.str(val)
                assert isinstance(val, String), "str should always return a string"
                print val._str
Пример #10
0
    def invoke(self, rdr, ch):
        nms = u""
        ch = rdr.read()
        if ch == u":":
            itm = read_inner(rdr, True)
            nms = rt.name(rt.ns.deref())
        else:
            rdr.unread()
            itm = read_inner(rdr, True)

        affirm(isinstance(itm, Symbol), u"Can't keyword quote a non-symbol")
        if nms:
            affirm(rt.namespace(itm) is None, u"Kewyword cannot have two namespaces")
            return keyword(rt.name(itm), nms)
        else:
            return keyword(rt.name(itm), rt.namespace(itm))
Пример #11
0
 def invoke(self, rdr, ch):
     ch = rdr.read()
     if ch == u":":
         itm = read_inner(rdr, True)
         return self.fqd(itm)
     else:
         rdr.unread()
         itm = read_inner(rdr, True)
         return keyword(rt.name(itm), rt.namespace(itm))
Пример #12
0
    def invoke(self, rdr, ch):
        nms = u""
        ch = rdr.read()
        if ch == u":":
            itm = read_inner(rdr, True)
            nms = rt.name(rt.ns.deref())
        else:
            rdr.unread()
            itm = read_inner(rdr, True)

        affirm(isinstance(itm, Symbol), u"Can't keyword quote a non-symbol")
        if nms:
            affirm(
                rt.namespace(itm) is None,
                u"Kewyword cannot have two namespaces")
            return keyword(rt.name(itm), nms)
        else:
            return keyword(rt.name(itm), rt.namespace(itm))
Пример #13
0
    def invoke(self, rdr, ch):
        ch = rdr.read()
        if ch == u":":
            ch = rdr.read()
            itm = read_symbol(rdr, ch, False)
            return self.fqd(itm)
        else:
            itm = read_symbol(rdr, ch, False)

            return keyword(rt.name(itm), rt.namespace(itm))
Пример #14
0
def _seq(self):
    import pixie.vm.persistent_vector as vector
    import pixie.vm.persistent_hash_map as hmap
    from pixie.vm.keyword import keyword
    assert isinstance(self, RuntimeException)
    trace = vector.EMPTY
    trace_element = rt.hashmap(keyword(u"type"), keyword(u"runtime"))
    trace_element = rt.assoc(trace_element, keyword(u"data"), rt.wrap(self._data))
    trace = rt.conj(trace, trace_element)
    for x in self._trace:
        tmap = x.trace_map()
        trace_element = hmap.EMPTY
        for key in tmap:
            val = tmap[key]
            trace_element = rt.assoc(trace_element, key, val)

        trace = rt.conj(trace, trace_element)

    return rt._seq(trace)
Пример #15
0
def _seq(self):
    import pixie.vm.persistent_vector as vector
    import pixie.vm.persistent_hash_map as hmap
    from pixie.vm.keyword import keyword
    assert isinstance(self, RuntimeException)
    trace = vector.EMPTY
    trace_element = rt.hashmap(keyword(u"type"), keyword(u"runtime"))
    trace_element = rt.assoc(trace_element, keyword(u"data"),
                             rt.wrap(self._data))
    trace = rt.conj(trace, trace_element)
    for x in self._trace:
        tmap = x.trace_map()
        trace_element = hmap.EMPTY
        for key in tmap:
            val = tmap[key]
            trace_element = rt.assoc(trace_element, key, val)

        trace = rt.conj(trace, trace_element)

    return rt._seq(trace)
Пример #16
0
def maybe_oop_invoke(form):
    head = rt.first(form)
    if isinstance(rt.first(form), symbol.Symbol) and rt.name(head).startswith(".-"):
        postfix = rt.next(form)
        affirm(rt.count(postfix) == 1, u" Attribute lookups must only have one argument")
        subject = rt.first(postfix)
        kw = keyword(rt.name(head)[2:])
        fn = symbol.symbol(u"pixie.stdlib/-get-attr")
        return create_from_list([fn, subject, kw])

    elif isinstance(rt.first(form), symbol.Symbol) and rt.name(head).startswith("."):
        subject = rt.first(rt.next(form))
        postfix = rt.next(rt.next(form))
        form = cons(keyword(rt.name(head)[1:]), postfix)
        form = cons(subject, form)
        form = cons(symbol.symbol(u"pixie.stdlib/-call-method"), form)
        return form

    else:
        return form
Пример #17
0
def _try_catch(main_fn, catch_fn, final):
    from pixie.vm.keyword import keyword

    try:
        return main_fn.invoke([])
    except Exception as ex:
        if not isinstance(ex, WrappedException):
            if isinstance(ex, Exception):
                if not we_are_translated():
                    print "Python Error Info: ", ex.__dict__, ex
                    raise
                ex = RuntimeException(
                    rt.wrap(u"Internal error: " + unicode(str(ex))), keyword(u"pixie.stdlib/InternalError")
                )
            else:
                ex = RuntimeException(u"No available message", keyword(u"pixie.stdlib/UnknownInternalError"))
            return catch_fn.invoke([ex])
        else:
            return catch_fn.invoke([ex._ex])
    finally:
        if final is not nil:
            final.invoke([])
Пример #18
0
def _try_catch(main_fn, catch_fn, final):
    from pixie.vm.keyword import keyword
    try:
        return main_fn.invoke([])
    except Exception as ex:
        if not isinstance(ex, WrappedException):
            if isinstance(ex, Exception):
                if not we_are_translated():
                    print "Python Error Info: ", ex.__dict__, ex
                    raise
                ex = RuntimeException(
                    rt.wrap(u"Internal error: " + unicode(str(ex))),
                    keyword(u"pixie.stdlib/InternalError"))
            else:
                ex = RuntimeException(
                    u"No available message",
                    keyword(u"pixie.stdlib/UnknownInternalError"))
            return catch_fn.invoke([ex])
        else:
            return catch_fn.invoke([ex._ex])
    finally:
        if final is not nil:
            final.invoke([])
Пример #19
0
    def invoke(self, rdr, ch):
        meta = read_inner(rdr, True)
        obj = read_inner(rdr, True)

        if isinstance(meta, Keyword):
            meta = rt.hashmap(meta, true)

        if isinstance(meta, Symbol):
            meta = rt.hashmap(keyword(u"tag"), meta)

        if rt._satisfies_QMARK_(rt.IMeta.deref(), obj):
            return rt.with_meta(obj, rt.merge(meta, rt.meta(obj)))

        return obj
Пример #20
0
def maybe_oop_invoke(form):
    head = rt.first(form)
    if isinstance(rt.first(form),
                  symbol.Symbol) and rt.name(head).startswith(".-"):
        postfix = rt.next(form)
        affirm(
            rt.count(postfix) == 1,
            u" Attribute lookups must only have one argument")
        subject = rt.first(postfix)
        kw = keyword(rt.name(head)[2:])
        fn = symbol.symbol(u"pixie.stdlib/-get-attr")
        return create_from_list([fn, subject, kw])

    elif isinstance(rt.first(form),
                    symbol.Symbol) and rt.name(head).startswith("."):
        subject = rt.first(rt.next(form))
        postfix = rt.next(rt.next(form))
        form = cons(keyword(rt.name(head)[1:]), postfix)
        form = cons(subject, form)
        form = cons(symbol.symbol(u"pixie.stdlib/-call-method"), form)
        return form

    else:
        return form
Пример #21
0
    def trace_map(self):
        from pixie.vm.string import String
        from pixie.vm.numbers import Integer
        from pixie.vm.keyword import keyword

        tm = {keyword(u"type") : keyword(u"interpreter")}
        tm[keyword(u"line")] = String(self._line.__repr__())
        tm[keyword(u"line-number")] = Integer(self._line_number)
        tm[keyword(u"column-number")] = Integer(self._column_number)
        tm[keyword(u"file")] = String(self._file)
        return tm
Пример #22
0
    def trace_map(self):
        from pixie.vm.string import String
        from pixie.vm.numbers import Integer
        from pixie.vm.keyword import keyword

        tm = {keyword(u"type"): keyword(u"interpreter")}
        tm[keyword(u"line")] = String(self._line.__repr__())
        tm[keyword(u"line-number")] = Integer(self._line_number)
        tm[keyword(u"column-number")] = Integer(self._column_number)
        tm[keyword(u"file")] = String(self._file)
        return tm
Пример #23
0
def repl():
    from pixie.vm.keyword import keyword
    import pixie.vm.rt as rt
    from pixie.vm.string import String

    with with_ns(u"user"):
        NS_VAR.deref().include_stdlib()

    rdr = PromptReader()
    while True:
        with with_ns(u"user"):
            try:
                val = interpret(compile(read(rdr, True)))
            except WrappedException as ex:
                print "Error: ", ex._ex.__repr__()
                continue
            if val is keyword(u"exit-repl"):
                break
            val = rt.str(val)
            assert isinstance(val, String), "str should always return a string"
            print val._str
Пример #24
0
    def inner_invoke(self, args):
        from pixie.vm.keyword import keyword
        import pixie.vm.rt as rt
        from pixie.vm.string import String
        import pixie.vm.persistent_vector as vector

        print "Pixie 0.1 - Interactive REPL"
        print "(" + platform.name + ", " + platform.cc + ")"
        print ":exit-repl or Ctrl-D to quit"
        print "----------------------------"

        with with_ns(u"user"):
            NS_VAR.deref().include_stdlib()

        acc = vector.EMPTY
        for x in self._argv:
            acc = rt.conj(acc, rt.wrap(x))

        PROGRAM_ARGUMENTS.set_root(acc)

        rdr = MetaDataReader(PromptReader())
        with with_ns(u"user"):
            while True:
                try:
                    val = read(rdr, False)
                    if val is eof:
                        break
                    val = interpret(compile(val))
                    self.set_recent_vars(val)
                except WrappedException as ex:
                    print "Error: ", ex._ex.__repr__()
                    rdr.reset_line()
                    self.set_error_var(ex._ex)
                    continue
                if val is keyword(u"exit-repl"):
                    break
                val = rt._repr(val)
                assert isinstance(val,
                                  String), "str should always return a string"
                print unicode_to_utf8(val._str)
Пример #25
0
    def inner_invoke(self, args):
        from pixie.vm.keyword import keyword
        import pixie.vm.rt as rt
        from pixie.vm.string import String
        import pixie.vm.persistent_vector as vector

        print "Pixie 0.1 - Interactive REPL"
        print "(" + platform.name + ", " + platform.cc + ")"
        print ":exit-repl or Ctrl-D to quit"
        print "----------------------------"

        with with_ns(u"user"):
            NS_VAR.deref().include_stdlib()

        acc = vector.EMPTY
        for x in self._argv:
            acc = rt.conj(acc, rt.wrap(x))

        PROGRAM_ARGUMENTS.set_root(acc)

        rdr = MetaDataReader(PromptReader())
        with with_ns(u"user"):
            while True:
                try:
                    val = read(rdr, False)
                    if val is eof:
                        break
                    val = interpret(compile(val))
                    self.set_recent_vars(val)
                except WrappedException as ex:
                    print "Error: ", ex._ex.__repr__()
                    rdr.reset_line()
                    self.set_error_var(ex._ex)
                    continue
                if val is keyword(u"exit-repl"):
                    break
                val = rt._repr(val)
                assert isinstance(val, String), "str should always return a string"
                print unicode_to_utf8(val._str)
Пример #26
0
def runtime_error(msg, data=None):
    import pixie.vm.rt as rt
    from pixie.vm.keyword import keyword
    if data is None:
        data = u"pixie.stdlib/AssertionException"
    raise WrappedException(RuntimeException(rt.wrap(msg), keyword(data)))
Пример #27
0
    def invoke(self, rdr, ch):
        itm = read(rdr, True)
        affirm(isinstance(itm, Symbol), u"Can't keyword quote a non-symbol")

        return keyword(itm._str)
Пример #28
0
from pixie.vm.cons import cons
from pixie.vm.symbol import symbol, Symbol
from pixie.vm.keyword import keyword, Keyword
import pixie.vm.rt as rt
from pixie.vm.persistent_vector import EMPTY as EMPTY_VECTOR
from pixie.vm.libs.readline import _readline
from pixie.vm.string import Character, String
from pixie.vm.code import wrap_fn, extend
from pixie.vm.persistent_hash_map import EMPTY as EMPTY_MAP
from pixie.vm.persistent_hash_set import EMPTY as EMPTY_SET
import pixie.vm.stdlib as proto
import pixie.vm.compiler as compiler

from rpython.rlib.rsre import rsre_re as re

LINE_NUMBER_KW = keyword(u"line-number")
COLUMN_NUMBER_KW = keyword(u"column-number")
LINE_KW = keyword(u"line")
FILE_KW = keyword(u"file")

GEN_SYM_ENV = code.intern_var(u"pixie.stdlib.reader", u"*gen-sym-env*")
GEN_SYM_ENV.set_dynamic()
GEN_SYM_ENV.set_value(EMPTY_MAP)

class PlatformReader(object.Object):
    _type = object.Type(u"PlatformReader")

    def read(self):
        assert False

    def unread(self, ch):
Пример #29
0
def read_obj(rdr):
    tag = read_tag(rdr)

    if tag == INT:
        return Integer(intmask(read_raw_integer(rdr)))
    elif tag == BIGINT:
        return BigInteger(read_raw_bigint(rdr))
    elif tag == CODE:
        return read_code(rdr)
    elif tag == NIL:
        return nil
    elif tag == VAR:
        return read_var(rdr)
    elif tag == STRING:
        return String(read_raw_string(rdr))
    elif tag == KEYWORD:
        return keyword(read_raw_string(rdr))
    elif tag == SYMBOL:
        return symbol(read_raw_string(rdr))
    elif tag == LINE_PROMISE:
        lp = LinePromise()
        lp._chrs = None
        lp._str = read_raw_string(rdr)
        return lp
    elif tag == MAP:
        return read_map(rdr)
    elif tag == TRUE:
        return true
    elif tag == FALSE:
        return false
    elif tag == NIL:
        return nil
    elif tag == VECTOR:
        return read_vector(rdr)
    elif tag == SEQ:
        return read_seq(rdr)
    elif tag == FLOAT:
        return read_float(rdr)
    elif tag == NAMESPACE:
        return read_namespace(rdr)
    elif tag == INT_STRING:
        return Integer(int(read_raw_string(rdr)))
    elif tag == BIGINT_STRING:
        return BigInteger(rbigint.fromstr(str(read_raw_string(rdr))))

    elif tag == NEW_CACHED_OBJ:
        return rdr.read_and_cache()
    elif tag == CACHED_OBJ:
        return rdr.read_cached_obj()

    elif tag == EOF:
        from pixie.vm.reader import eof

        return eof

    elif tag == CODE_INFO:
        return read_interpreter_code_info(rdr)

    elif tag == TAGGED:
        tp_name = read_raw_string(rdr)
        tp = get_type_by_name(tp_name)
        handler = read_handlers.get(tp, None)
        if handler is None:
            runtime_error(u"No type handler for " + tp_name)

        obj = read_obj(rdr)
        return handler.invoke([obj])
    else:
        runtime_error(u"No dispatch for bytecode: " + unicode(tag_name[tag]))

    return nil
Пример #30
0
    def invoke(self, rdr, ch):
        itm = read(rdr, True)
        affirm(isinstance(itm, Symbol), u"Can't keyword quote a non-symbol")

        return keyword(rt.name(itm))
Пример #31
0
from pixie.vm.libs.libedit import _readline
from pixie.vm.string import Character
from pixie.vm.code import wrap_fn
from pixie.vm.persistent_hash_map import EMPTY as EMPTY_MAP
from pixie.vm.persistent_hash_set import EMPTY as EMPTY_SET
from pixie.vm.persistent_list import EmptyList
import pixie.vm.compiler as compiler

from rpython.rlib.rbigint import rbigint
from rpython.rlib.rsre import rsre_re as re

READING_FORM_VAR = code.intern_var(u"pixie.stdlib", u"*reading-form*")
READING_FORM_VAR.set_dynamic()
READING_FORM_VAR.set_root(false)

LINE_NUMBER_KW = keyword(u"line-number")
COLUMN_NUMBER_KW = keyword(u"column-number")
LINE_KW = keyword(u"line")
FILE_KW = keyword(u"file")

GEN_SYM_ENV = code.intern_var(u"pixie.stdlib.reader", u"*gen-sym-env*")
GEN_SYM_ENV.set_dynamic()
GEN_SYM_ENV.set_root(EMPTY_MAP)

ARG_AMP = symbol(u"&")
ARG_MAX = keyword(u"max-arg")
ARG_ENV = code.intern_var(u"pixie.stdlib.reader", u"*arg-env*")
ARG_ENV.set_dynamic()
ARG_ENV.set_root(nil)

class PlatformReader(object.Object):
Пример #32
0
from pixie.vm.string import Character, String
from pixie.vm.atom import Atom
from rpython.rlib.rarithmetic import r_uint, intmask
from pixie.vm.persistent_list import EmptyList
from pixie.vm.cons import cons
from pixie.vm.persistent_list import create_from_list

import pixie.vm.rt as rt

NS_VAR = code.intern_var(u"pixie.stdlib", u"*ns*")
NS_VAR.set_dynamic()

FN_NAME = code.intern_var(u"pixie.stdlib", u"*fn-name*")
FN_NAME.set_dynamic()

DYNAMIC_KW = keyword(u"dynamic")

gensym_id = Atom(numbers.zero_int)


def gensym1():
    return gensym2(rt.wrap(u"gensym_"))


def gensym2(prefix):
    rt.reset_BANG_(gensym_id, rt._add(rt.deref(gensym_id), rt.wrap(1)))
    i = rt.deref(gensym_id)

    return rt.symbol(rt.str(prefix, i))

Пример #33
0
def read_obj(rdr):
    tag = read_tag(rdr)

    if tag == INT:
        return Integer(intmask(read_raw_integer(rdr)))
    elif tag == CODE:
        return read_code(rdr)
    elif tag == NIL:
        return nil
    elif tag == VAR:
        return read_var(rdr)
    elif tag == STRING:
        return String(read_raw_string(rdr))
    elif tag == KEYWORD:
        return keyword(read_raw_string(rdr))
    elif tag == SYMBOL:
        return symbol(read_raw_string(rdr))
    elif tag == LINE_PROMISE:
        lp = LinePromise()
        lp._str = read_raw_string(rdr)
        return lp
    elif tag == MAP:
        return read_map(rdr)
    elif tag == TRUE:
        return true
    elif tag == FALSE:
        return false
    elif tag == NIL:
        return nil
    elif tag == VECTOR:
        return read_vector(rdr)
    elif tag == SEQ:
        return read_seq(rdr)
    elif tag == FLOAT:
        return read_float(rdr)
    elif tag == NAMESPACE:
        return read_namespace(rdr)
    elif tag == INT_STRING:
        return Integer(int(read_raw_string(rdr)))

    elif tag == NEW_CACHED_OBJ:
        return rdr.read_and_cache()
    elif tag == CACHED_OBJ:
        return rdr.read_cached_obj()

    elif tag == EOF:
        from pixie.vm.reader import eof
        return eof

    elif tag == CODE_INFO:
        return read_interpreter_code_info(rdr)

    elif tag == TAGGED:
        tp_name = read_raw_string(rdr)
        tp = get_type_by_name(tp_name)
        handler = read_handlers.get(tp, None)
        if handler is None:
            runtime_error(u"No type handler for " + tp_name)

        obj = read_obj(rdr)
        return handler.invoke([obj])
    else:
        runtime_error(u"No dispatch for bytecode: " + unicode(tag_name[tag]))

    return nil
Пример #34
0
import pixie.vm.code as code
from pixie.vm.keyword import Keyword, keyword
from pixie.vm.string import Character, String
from pixie.vm.atom import Atom
from rpython.rlib.rarithmetic import r_uint, intmask
from pixie.vm.persistent_list import EmptyList

import pixie.vm.rt as rt

NS_VAR = code.intern_var(u"pixie.stdlib", u"*ns*")
NS_VAR.set_dynamic()

FN_NAME = code.intern_var(u"pixie.stdlib", u"*fn-name*")
FN_NAME.set_dynamic()

DYNAMIC_KW = keyword(u"dynamic")

gensym_id = Atom(numbers.zero_int)

def gensym1():
    return gensym2(rt.wrap(u"gensym_"))

def gensym2(prefix):
    rt.reset_BANG_(gensym_id, rt._add(rt.deref(gensym_id), rt.wrap(1)))
    i = rt.deref(gensym_id)

    return rt.symbol(rt.str(prefix, i))

gensym = code.intern_var(u"pixie.stdlib", u"gensym")
gensym.set_root(code.MultiArityFn(u"gensym", {0: code.wrap_fn(gensym1), 1: code.wrap_fn(gensym2)}))
Пример #35
0
import pixie.vm.stdlib as proto
from pixie.vm.keyword import keyword
from rpython.rlib.clibffi import get_libc_name
import os
import pixie.vm.rt as rt

class FileList(Object):
    _type = Type(u"pixie.path.FileList")

    def type(self):
        return FileList._type

    def __init__(self, top):
        self._top = rt.name(top)

KW_DIR = keyword(u"dir")
KW_FILE = keyword(u"file")

@extend(proto._reduce, FileList)
def _reduce(self, f, init):
    assert isinstance(self, FileList)
    for dirpath, dirnames, filenames in os.walk(str(self._top)):
        for dirname in dirnames:
            init = f.invoke([init, rt.vector(rt.wrap(dirpath), KW_DIR, rt.wrap(dirname))])
            if rt.reduced_QMARK_(init):
                return rt.deref(init)

        for filename in filenames:
            init = f.invoke([init, rt.vector(rt.wrap(dirpath), KW_FILE, rt.wrap(filename))])
            if rt.reduced_QMARK_(init):
                return rt.deref(init)