Пример #1
0
def _process_quasiquote_list_item(obj):
    # TODO: could we invoke (list) directly?
    if is_list(obj) and first(obj) == Symbol('unquote'):
        return List([Symbol('list', ns='kaa.core'), first(rest(obj))])
    if is_list(obj) and first(obj) == Symbol('unquote-splice'):
        return first(rest(obj))
    return List([Symbol('list', ns='kaa.core'), _process_quasiquote(obj)])
Пример #2
0
    def _read_unquote(self, stream):
        if stream.peek_char() == '@':
            stream.pop_char()
            return List([Symbol('unquote-splice', meta={'source': stream.source_meta()}),
                         self.read_next(stream)])

        return List([Symbol('unquote', meta={'source': stream.source_meta()}),
                     self.read_next(stream)])
Пример #3
0
    def _read_symbol(self, s, meta):
        if any(special_form.name == s for special_form in SPECIAL_FORMS):
            return Symbol(s, None, meta)

        if '/' in s and s != '/':
            ns_name, sym_name = s.split('/', 1)
        else:
            ns_name, sym_name = None, s
        return self.ns.resolve(Symbol(sym_name, ns_name, meta))
Пример #4
0
def _process_quasiquote(obj):
    # `a -> 'a
    if not is_list(obj) or not obj:
        return List([Symbol('quote'), obj])
    # `~a -> a
    if first(obj) == Symbol('unquote'):
        return obj
    # `(a ~b ~@c) -> (concat (list 'a) (list b) c)
    # TODO: could we invoke (concat) directly?
    return List([Symbol('concat', ns='kaa.core')] +
                [_process_quasiquote_list_item(o) for o in obj])
Пример #5
0
 def import_ns(self, ns, symbol_names, alias=None):
     self.imported_namespaces[ns.name] = ns
     if symbol_names == '*' or symbol_names:
         importables = ns.exportables()
         imported_symbols = importables if symbol_names == '*' \
             else tuple(Symbol(name, ns.name) for name in symbol_names)
         for sym in imported_symbols:
             self.import_symbol(sym)
     if alias:
         self.ns_aliases[alias] = ns.name
Пример #6
0
 def import_module(self, mod, attrs=None, alias=None):
     self.imported_modules[mod.__name__] = mod
     if attrs == '*':
         raise NotImplementedError(
             '`import *` not yet implemented for modules')
     if attrs:
         for attr in attrs:
             self.import_symbol(Symbol(attr, mod.__name__))
     if alias:
         self.ns_aliases[alias] = mod.__name__
Пример #7
0
def parse_def(form):
    check(len(form) == 3, '`def` requires 2 args', form)
    _, sym, val = form
    check(is_symbol(sym), '`def` name must be a symbol', form)
    # If namespace `a` imports symbol `foo` from namespace `b`, then provides
    # `(def foo …)`, the reader resolves the symbol to `b/foo`, but the
    # intention is to define `a/foo`. To get that behaviour, we discard the
    # symbol namespace here.
    #
    # FIXME: this leads to confusing behaviour if a namespaced symbol is passed
    # to the reader. We should throw an error we read a qualified symbol that
    # resolves to another namespace, not silently rewrite it.
    sym = Symbol(sym.name, None, sym.meta)
    return Def(sym, val)
Пример #8
0
 def loop(self):
     self.ns[self.last_result_symbol] = None
     while True:
         try:
             exprs = self.read_exprs()
             if exprs and exprs[0] and is_list(exprs[0]) and \
                exprs[0][0] == Symbol('debug', '__kaa__'):
                 exprs = exprs[0][1:]
                 pdb.set_trace()
             result = Evaluator(self.ns).evaluate_all(exprs)
         except KeyboardInterrupt:
             # Ctrl-C; user wants to abandon current input
             print()
             continue
         except EOFError:
             # Ctrl-D; user wants to quit
             print()
             break
         except Exception:  # pylint: disable=broad-except
             traceback.print_exc()
             continue
         if result is not None:
             self.ns[self.last_result_symbol] = result
             print(serialize(result))
Пример #9
0
 def _read_quote(self, stream):
     return List([Symbol('quote', meta={'source': stream.source_meta()}),
                  self.read_next(stream)])
Пример #10
0
 def import_symbol(self, sym):
     # TODO: handle name not found in module
     # TODO: warn if symbol collision with self.defs
     self.imported_symbol_refs[Symbol(sym.name, self.name)] = sym
     self.imported_symbols.add(sym)
Пример #11
0
 def __setitem__(self, sym, value):
     assert isinstance(sym, Symbol), f'{sym} is not a Symbol'
     if sym.ns is None:
         sym = Symbol(sym.name, self.name, sym.meta)
     assert sym.ns == self.name, f'cannot define {sym} via namespace {self.name}'
     self.defs[sym] = value
Пример #12
0
def test_symbol_equality():
    assert Symbol('foo') == Symbol('foo')
    assert Symbol('foo') != Symbol('bar')
    assert Symbol('foo') != Symbol('foo', 'ns')
    assert Symbol('foo', 'ns1') != Symbol('foo', 'ns2')
    assert Symbol('foo', 'ns') == Symbol('foo', 'ns')
Пример #13
0
def test_read_special_form():
    assert read('def') == Symbol('def')
Пример #14
0
def test_read_list():
    obj = read('(foo 42 bar)')
    assert isinstance(obj, List)
    assert obj[0] == Symbol('foo', 'testing')
    assert obj[1] == 42
    assert obj[2] == Symbol('bar', 'testing')
Пример #15
0
def test_read_unqualified_symbol():
    assert read('foo-bar') == Symbol('foo-bar', 'testing')
Пример #16
0
def test_read_qualified_symbol():
    assert read('foo/bar') == Symbol('bar', 'foo')
Пример #17
0
def test_parse_lambda():
    parsed = parse_lambda(read('(lambda (foo) bar)'))
    assert isinstance(parsed, Lambda)
    assert isinstance(parsed.params, Params)
    assert tuple(parsed.body) == ((Symbol('bar', 'testing'), ))
Пример #18
0
 def __init__(self):
     self.ns = Namespace('repl')
     self.last_result_symbol = self.ns.resolve(Symbol('^'))
Пример #19
0
def test_resolve_qualified_with_alias():
    ns = Namespace('testing', import_core=False)
    core = ns.load_ns('kaa.core')
    ns.import_ns(core, (), 'core')
    sym = Symbol('asdfasdf', 'core')
    assert ns.resolve(sym) == sym.in_ns('kaa.core')
Пример #20
0
def test_define():
    ns = Namespace('testing', import_core=False)
    sym = Symbol('foo', 'testing')
    ns[sym] = 'bar'
    assert ns[sym] == 'bar'
Пример #21
0
def test_resolve_qualified_import_ref():
    ns = Namespace('testing', import_core=True)
    sym = Symbol('defun', 'kaa.core')
    assert ns.resolve(sym) == sym
Пример #22
0
def test_resolve_unqualified_def():
    ns = Namespace('testing', import_core=False)
    ns[Symbol('foo', 'testing')] = 'bar'
    sym = Symbol('foo')
    assert ns.resolve(sym) == sym.in_ns('testing')
Пример #23
0
def test_resolve_unqualified_unknown():
    ns = Namespace('testing', import_core=False)
    sym = Symbol('foo')
    assert ns.resolve(sym) == sym.in_ns('testing')
Пример #24
0
def test_resolve_qualified_with_unknown():
    ns = Namespace('testing', import_core=False)
    sym = Symbol('asfasdf', 'unknown')
    assert ns.resolve(sym) == sym
Пример #25
0
def _parse_except(form):
    check(
        is_list(form) and len(form) == 3 and form[0] == Symbol('except'),
        'invalid except form', form)
    return form[1:3]
Пример #26
0
def test_lookup():
    ns = Namespace('testing')
    ns[Symbol('x', 'testing')] = 42
    assert ns[Symbol('x', 'testing')] == 42
    assert ns[Symbol('defun', 'kaa.core')] is not None
Пример #27
0
    return Try(expr, (_parse_except(except_) for except_ in excepts))


def _parse_except(form):
    check(
        is_list(form) and len(form) == 3 and form[0] == Symbol('except'),
        'invalid except form', form)
    return form[1:3]


def raise_invalid_top_level_except(form):
    check(False, '`except` must appear within `try`', form)


SPECIAL_FORMS = {
    Symbol('def'):
    parse_def,
    Symbol('defmacro'):
    parse_defmacro,
    # Not invoked directly as a special form, but here so reader recognizes it
    # and doesn't attempt to resolve it as a normal symbol
    Symbol('except'):
    raise_invalid_top_level_except,
    Symbol('if'):
    parse_if,
    Symbol('import'):
    parse_import,
    Symbol('lambda'):
    parse_lambda,
    Symbol('raise'):
    parse_raise,