def test_recursive_cons(self): a = cons(1, 2, 3, recursive=True) self.assertTrue(a.is_proper()) self.assertTrue(a.is_recursive()) self.assertTrue(is_pair(a)) self.assertTrue(is_proper(a)) self.assertEqual(a.length(), 3) self.assertEqual(car(a), car(cdr(cdr(cdr(a))))) self.assertEqual(str(a), "(1 2 3 ...)") self.assertEqual(repr(a), "cons(1, 2, 3, recursive=True)") b = pair(0, a) c = pair(0, a) self.assertEqual(b, c) self.assertNotEqual(a, b) self.assertNotEqual(a, c) z = cons(1, cons(2, cons(3, nil))) setcdr(cdr(cdr(z)), z) self.assertEqual(a, z) self.assertEqual(z, a)
def test_nil(self): # singleton nil check Nil = type(nil) self.assertEqual(id(nil), id(Nil())) self.assertEqual(id(Nil()), id(Nil())) self.assertTrue(nil is Nil()) # behavior self.assertIsInstance(nil, pair) self.assertTrue(is_pair(nil)) self.assertTrue(is_nil(nil)) self.assertTrue(is_proper(nil)) self.assertFalse(nil) self.assertTrue(not nil) self.assertEqual(str(nil), "nil") self.assertEqual(repr(nil), "nil") self.assertEqual(nil, nil) self.assertNotEqual(nil, cons(1, nil)) self.assertNotEqual(cons(1, nil), nil) with self.assertRaises(TypeError): car(nil) with self.assertRaises(TypeError): cdr(nil) self.assertEqual(list(nil), list()) self.assertEqual(tuple(nil), tuple())
def test_nil(self): # singleton nil check Nil = type(nil) self.assertEqual(id(nil), id(Nil())) self.assertEqual(id(Nil()), id(Nil())) self.assertTrue(nil is Nil()) # behavior self.assertIsInstance(nil, pair) self.assertTrue(is_pair(nil)) self.assertTrue(is_nil(nil)) self.assertTrue(is_proper(nil)) self.assertFalse(nil) self.assertTrue(not nil) self.assertEqual(str(nil), "nil") self.assertEqual(repr(nil), "nil") self.assertEqual(nil, nil) self.assertNotEqual(nil, cons(1, nil)) self.assertNotEqual(cons(1, nil), nil) with self.assertRaises(TypeError): car(nil) with self.assertRaises(TypeError): cdr(nil) self.assertEqual(list(nil), list()) self.assertEqual(tuple(nil), tuple())
def test_recursive_cons(self): a = cons(1, 2, 3, recursive=True) self.assertTrue(a.is_proper()) self.assertTrue(a.is_recursive()) self.assertTrue(is_pair(a)) self.assertTrue(is_proper(a)) self.assertEqual(a.length(), 3) self.assertEqual(car(a), car(cdr(cdr(cdr(a))))) self.assertEqual(str(a), "(1 2 3 ...)") self.assertEqual(repr(a), "cons(1, 2, 3, recursive=True)") b = pair(0, a) c = pair(0, a) self.assertEqual(b, c) self.assertNotEqual(a, b) self.assertNotEqual(a, c) z = cons(1, cons(2, cons(3, nil))) setcdr(cdr(cdr(z)), z) self.assertEqual(a, z) self.assertEqual(z, a)
def test_simple(self): self.qq("`1", 1) self.qq("`,1", 1) self.qq("`tacos", symbol("tacos")) self.qq("`:tacos", keyword("tacos")) self.qq("`nil", symbol("nil")) self.qq("`()", nil) self.qq("`(1 2 3 ,4 ,5)", cons(1, 2, 3, 4, 5, nil)) self.qq("`(1 2 3 ,A ,B Z)", cons(1, 2, 3, 4, 5, symbol("Z"), nil), A=4, B=5) self.qq("`(1 2 ,(foo 3 6))", cons(1, 2, [3, 4, 5], nil), foo=lambda a, b: list(range(a,b)))
def test_setf_cdr(self): src = """ (begin (setf (cdr o) 9) o) """ stmt, env = compile_expr(src, o=cons(1, 2)) res = stmt() self.assertEqual(res, cons(1, 9))
def test_setf_cdr(self): src = """ (begin (setf (cdr o) 9) o) """ stmt, env = compile_expr(src, o=cons(1, 2)) res = stmt() self.assertEqual(res, cons(1, 9))
def test_decimal(self): src = "1.5d" col = parse_source(src) self.assertEqual(col, cons(symbol("decimal"), (0, (1, 5), -1), nil)) src = ".5d" col = parse_source(src) self.assertEqual(col, cons(symbol("decimal"), (0, (5, ), -1), nil)) src = "1.d" col = parse_source(src) self.assertEqual(col, cons(symbol("decimal"), (0, (1, ), 0), nil))
def test_fraction(self): src = "1/2/3" self.assertRaises(SyntaxError, parse_source, src) src = "1/2" col = parse_source(src) self.assertEqual(col, cons(symbol("fraction"), 1, 2, nil)) src = "-1/2" col = parse_source(src) self.assertEqual(col, cons(symbol("fraction"), -1, 2, nil))
def test_quote_list(self): src = "'()" stmt, env = compile_expr(src) self.assertEqual(stmt(), nil) src = "'(())" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(nil, nil)) src = "'(1 2 3)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1, 2, 3, nil))
def test_quote_list(self): src = "'()" stmt, env = compile_expr(src) self.assertEqual(stmt(), nil) src = "'(())" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(nil, nil)) src = "'(1 2 3)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1, 2, 3, nil))
def test_fraction(self): src = "1/2/3" self.assertRaises(SyntaxError, parse_source, src) src = "1/2" col = parse_source(src) self.assertEqual(col, cons(symbol("fraction"), 1, 2, nil)) src = "-1/2" col = parse_source(src) self.assertEqual(col, cons(symbol("fraction"), -1, 2, nil))
def test_decimal(self): src = "1.5d" col = parse_source(src) self.assertEqual(col, cons(symbol("decimal"), "1.5", nil)) src = ".5d" col = parse_source(src) self.assertEqual(col, cons(symbol("decimal"), ".5", nil)) src = "1.d" col = parse_source(src) self.assertEqual(col, cons(symbol("decimal"), "1.", nil))
def test_list(self): src = "(testing a thing)" col = parse_source(src) exp = cons(symbol("testing"), symbol("a"), symbol("thing"), nil) self.assertEqual(col, exp) src = "[testing a thing]" col = parse_source(src) self.assertEqual(col, exp) with self.assertRaises(SyntaxError): src = "(no way]" col = parse_source(src) with self.assertRaises(SyntaxError): src = "[no way)" col = parse_source(src) with self.assertRaises(SyntaxError): src = "{no way]" col = parse_source(src) with self.assertRaises(SyntaxError): src = "[no way}" col = parse_source(src) with self.assertRaises(SyntaxError): src = "{no way)" col = parse_source(src) with self.assertRaises(SyntaxError): src = "(no way}" col = parse_source(src)
def compile_keyword(self, kwd: keyword, tc, cont): """ Compile a keyword expression """ source = cons(_symbol_keyword, str(kwd), nil) return tcf(self.compile, source, False, cont)
def test_let(self): src = "(let ((tacos 1) (beer 2)) (cons tacos beer))" stmt, env = compile_expr(src, tacos=5) self.assertEqual(stmt(), cons(1, 2)) src = "(let ((tacos 1) (beer 2)) (cons tacos beer nil))" stmt, env = compile_expr(src, tacos=5) self.assertEqual(stmt(), cons(1, 2, nil)) src = "(let () (cons tacos beer nil))" stmt, env = compile_expr(src, tacos=5, beer=9) self.assertEqual(stmt(), cons(5, 9, nil)) src = "(let ((tacos 1)) (cons tacos beer))" stmt, env = compile_expr(src, tacos=5, beer=9) self.assertEqual(stmt(), cons(1, 9))
def compile_keyword(self, kwd: keyword, tc, cont): """ Compile a keyword expression """ source = cons(_symbol_keyword, str(kwd), nil) return tcf(self.compile, source, False, cont)
def test_dict(self): src = """ #{} """ stmt, env = compile_expr(src) res = stmt() self.assertTrue(type(res) is dict) self.assertEqual(res, {}) src = """ #{foo: 1 bar: 2 baz: 3} """ stmt, env = compile_expr(src) res = stmt() self.assertTrue(type(res) is dict) self.assertEqual(res, dict(foo=1, bar=2, baz=3)) src = """ #{["foo" 1] ["bar" 2] ["baz" 3]} """ stmt, env = compile_expr(src) res = stmt() self.assertTrue(type(res) is dict) self.assertEqual(res, dict(foo=1, bar=2, baz=3)) src = """ #{["foo" . 1] ("bar" . 2) baz: 3} """ stmt, env = compile_expr(src) res = stmt() self.assertTrue(type(res) is dict) self.assertEqual(res, dict(foo=1, bar=2, baz=3)) src = """ #{["foo" 1] bar baz: 3} """ stmt, env = compile_expr(src, bar=["bar", 2]) res = stmt() self.assertTrue(type(res) is dict) self.assertEqual(res, dict(foo=1, bar=2, baz=3)) src = """ #{["foo" 1] bar baz: 3} """ stmt, env = compile_expr(src, bar=cons("bar", 2)) res = stmt() self.assertTrue(type(res) is dict) self.assertEqual(res, dict(foo=1, bar=2, baz=3)) src = """ #{foo: 1 ["bar" 2]} """ self.assertRaises(SibilantSyntaxError, compile_expr, src)
def test_improper_cons(self): z = cons(1, 2) self.assertEqual(z.length(), 2) self.assertFalse(z.is_proper()) self.assertEqual(car(z), 1) self.assertEqual(cdr(z), 2) self.assertEqual(str(z), "(1 . 2)") self.assertEqual(repr(z), "cons(1, 2)") self.assertTrue(is_pair(z)) self.assertFalse(is_proper(z)) self.assertNotEqual(z, None) self.assertNotEqual(z, nil) self.assertNotEqual(z, cons(1, nil)) self.assertNotEqual(z, cons(1, 3)) self.assertNotEqual(z, cons(1, 3, nil))
def test_eval_pair(self): data = cons(symbol("+"), 1, 2, symbol("tacos"), nil) src = """ (eval source_obj) """ stmt, env = compile_expr(src, source_obj=data, tacos=5) self.assertEqual(stmt(), 8)
def test_quasi(self): src = """ `bar """ col = parse_source(src) self.assertEqual(col, cons(symbol("quasiquote"), symbol("bar"), nil))
def test_eval_pair(self): data = cons(symbol("+"), 1, 2, symbol("tacos"), nil) src = """ (eval source_obj) """ stmt, env = compile_expr(src, source_obj=data, tacos=5) self.assertEqual(stmt(), 8)
def test_quote_symbol(self): src = """ 'foo """ col = parse_source(src) self.assertEqual(col, cons(symbol("quote"), symbol("foo"), nil))
def test_implicit_begin(self): src = "{testing a thing}" col = parse_source(src) self.assertEqual( col, cons(symbol("begin"), symbol("testing"), symbol("a"), symbol("thing"), nil))
def test_improper_cons(self): z = cons(1, 2) self.assertEqual(z.length(), 2) self.assertFalse(z.is_proper()) self.assertEqual(car(z), 1) self.assertEqual(cdr(z), 2) self.assertEqual(str(z), "(1 . 2)") self.assertEqual(repr(z), "cons(1, 2)") self.assertTrue(is_pair(z)) self.assertFalse(is_proper(z)) self.assertNotEqual(z, None) self.assertNotEqual(z, nil) self.assertNotEqual(z, cons(1, nil)) self.assertNotEqual(z, cons(1, 3)) self.assertNotEqual(z, cons(1, 3, nil))
def test_quote_unquote_splice(self): src = """ `(,@foo) """ col = parse_source(src) exp = cons(symbol("quasiquote"), cons(cons(symbol("unquote-splicing"), symbol("foo"), nil), nil), nil) self.assertEqual(col, exp) src = """ `(,@(foo bar)) """ col = parse_source(src) exp = cons(symbol("quasiquote"), cons(cons(symbol("unquote-splicing"), cons(symbol("foo"), symbol("bar"), nil), nil), nil), nil) self.assertEqual(col, exp)
def test_implicit_begin(self): src = "{testing a thing}" col = parse_source(src) self.assertEqual(col, cons(symbol("begin"), symbol("testing"), symbol("a"), symbol("thing"), nil))
def test_1(self): src = """ (lambda (a b) (lambda (x) (cons (+ a x) b))) """ stmt, env = compile_expr(src) fun = stmt() funx = fun(1, 9) self.assertTrue(funx(2), cons(3, 9))
def test_quote_list(self): src = """ '(foo bar) """ col = parse_source(src) self.assertEqual( col, cons(symbol("quote"), cons(symbol("foo"), symbol("bar"), nil), nil)) src = """ \n'(foo\n bar\n) """ col = parse_source(src) self.assertEqual( col, cons(symbol("quote"), cons(symbol("foo"), symbol("bar"), nil), nil))
def test_compile_pair(self): data = cons(symbol("+"), 1, 2, symbol("tacos"), nil) src = """ (compile source_obj) """ stmt, env = compile_expr(src, source_obj=data, tacos=5) res = stmt() self.assertIs(type(res), CodeType) self.assertEqual(eval(res, {"tacos": 5}), 8)
def test_compile_pair(self): data = cons(symbol("+"), 1, 2, symbol("tacos"), nil) src = """ (compile source_obj) """ stmt, env = compile_expr(src, source_obj=data, tacos=5) res = stmt() self.assertIs(type(res), CodeType) self.assertEqual(eval(res, {"tacos": 5}), 8)
def test_newline(self): src = """ ( this is a test ) """ col = parse_source(src) exp = cons(symbol("this"), symbol("is"), symbol("a"), symbol("test"), nil) self.assertEqual(col, exp)
def test_quote_list(self): src = """ '(foo bar) """ col = parse_source(src) self.assertEqual(col, cons(symbol("quote"), cons(symbol("foo"), symbol("bar"), nil), nil)) src = """ \n'(foo\n bar\n) """ col = parse_source(src) self.assertEqual(col, cons(symbol("quote"), cons(symbol("foo"), symbol("bar"), nil), nil))
def test_macro_let(self): src = """ (macro-let [[swap_test (a b c) (cons c b a '())]] (swap_test 'world 'hello cons)) """ stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(symbol("hello"), symbol("world"))) self.assertFalse("swap_test" in env)
def test_comments(self): src = """ ; Let's check out the comments ( this is ; well it's something a test ) ; this ought to work """ col = parse_source(src) exp = cons(symbol("this"), symbol("is"), symbol("a"), symbol("test"), nil) self.assertEqual(col, exp)
def test_dot(self): src = "'(1.4)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1.4, nil)) src = "'(1. 4)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1.0, 4, nil)) src = "'(1 .4)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1, 0.4, nil)) src = "'(1 . 4)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1, 4)) src = "'(1. . .4)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1.0, 0.4))
def compile(self, compiler, source_obj, tc, cont): expanded = self.expand() expanded = _symbol_None if expanded is None else expanded if is_pair(source_obj): called_by, source = source_obj res = cons(expanded, source) fill_position(res, source_obj.get_position()) expanded = res return tcf(cont, expanded, tc)
def compile(self, compiler, source_obj, tc, cont): expanded = self.expand() expanded = _symbol_None if expanded is None else expanded if is_pair(source_obj): called_by, source = source_obj res = cons(expanded, source) fill_position(res, source_obj.get_position()) expanded = res return tcf(cont, expanded, tc)
def test_dot(self): src = "'(1.4)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1.4, nil)) src = "'(1. 4)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1.0, 4, nil)) src = "'(1 .4)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1, 0.4, nil)) src = "'(1 . 4)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1, 4)) src = "'(1. . .4)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1.0, 0.4))
def test_4(self): src = """ (lambda (a b) (setq a ((lambda (x) (+ a x)) 9)) (cons a b)) """ stmt, env = compile_expr(src) fun = stmt() res = fun(100, 200) self.assertTrue(res, cons(109, 200)) src = """ (lambda (a b) (setq b ((lambda (x) (+ b x)) 9)) (cons a b)) """ stmt, env = compile_expr(src) fun = stmt() res = fun(100, 200) self.assertTrue(res, cons(100, 209)) src = """ (lambda (a b) (setq a ((lambda (x) (+ b x)) 9)) (cons a b)) """ stmt, env = compile_expr(src) fun = stmt() res = fun(100, 200) self.assertTrue(res, cons(209, 200)) src = """ (lambda (a b) (setq b ((lambda (x) (+ a x)) 9)) (cons a b)) """ stmt, env = compile_expr(src) fun = stmt() res = fun(100, 200) self.assertTrue(res, cons(100, 109))
def test_newline(self): src = """ ( this is a test ) """ col = parse_source(src) exp = cons(symbol("this"), symbol("is"), symbol("a"), symbol("test"), nil) self.assertEqual(col, exp)
def test_multi(self): src = """ 1.0 "2" (3) """ strm = source_str(src, "<unittest>") read = default_reader.read a = read(strm) b = read(strm) c = read(strm) self.assertEqual(a, 1.0) self.assertEqual(b, "2") self.assertEqual(c, cons(3, nil))
def test_comments(self): src = """ ; Let's check out the comments ( this is ; well it's something a test ) ; this ought to work """ col = parse_source(src) exp = cons(symbol("this"), symbol("is"), symbol("a"), symbol("test"), nil) self.assertEqual(col, exp)
def test_defmacro(self): src = """ (defmacro swap_test (a b c) (cons c b a '())) """ stmt, env = compile_expr(src) self.assertEqual(stmt(), None) swap_test = env["swap_test"] self.assertTrue(isinstance(swap_test, Macro)) self.assertTrue(is_macro(swap_test)) self.assertEqual(swap_test.__name__, "swap_test") self.assertRaises(TypeError, swap_test, 1, 2, 3) self.assertEqual(swap_test.expand(1, 2, 3), cons(3, 2, 1, nil)) src = """ (swap_test 'world 'hello cons) """ # compiles to equivalent of (cons 'hello 'world) stmt, env = compile_expr(src, swap_test=swap_test) self.assertEqual(stmt(), cons(symbol("hello"), symbol("world")))
def test_multi(self): src = """ 1.0 "2" (3) """ strm = source_str(src, "<unittest>") read = default_reader.read a = read(strm) b = read(strm) c = read(strm) self.assertEqual(a, 1.0) self.assertEqual(b, "2") self.assertEqual(c, cons(3, nil))
def test_good_iterable(self): # an iterable is fine self.assertEqual(b_u_p(range(0, 0)), nil) self.assertEqual(b_u_p(range(0, 3)), cons(0, 1, 2)) self.assertEqual(b_u_p(range(0, 3), nil), cons(0, 1, 2, nil)) self.assertEqual(b_u_p(range(0, 3), [3]), cons(0, 1, 2, 3)) self.assertEqual(b_u_p(range(0, 3), [3, nil]), cons(0, 1, 2, 3, nil)) self.assertEqual(b_u_p([0], range(1, 4)), cons(0, 1, 2, 3)) self.assertEqual(b_u_p([0], range(1, 4), nil), cons(0, 1, 2, 3, nil))
def test_good_iterable(self): # an iterable is fine self.assertEqual(b_u_p(range(0, 0)), nil) self.assertEqual(b_u_p(range(0, 3)), cons(0, 1, 2)) self.assertEqual(b_u_p(range(0, 3), nil), cons(0, 1, 2, nil)) self.assertEqual(b_u_p(range(0, 3), [3]), cons(0, 1, 2, 3)) self.assertEqual(b_u_p(range(0, 3), [3, nil]), cons(0, 1, 2, 3, nil)) self.assertEqual(b_u_p([0], range(1, 4)), cons(0, 1, 2, 3)) self.assertEqual(b_u_p([0], range(1, 4), nil), cons(0, 1, 2, 3, nil))
def test_defmacro(self): src = """ (defmacro swap_test (a b c) (cons c b a '())) """ stmt, env = compile_expr(src) self.assertEqual(stmt(), None) swap_test = env["swap_test"] self.assertTrue(isinstance(swap_test, Macro)) self.assertTrue(is_macro(swap_test)) self.assertEqual(swap_test.__name__, "swap_test") self.assertRaises(TypeError, swap_test, 1, 2, 3) self.assertEqual(swap_test.expand(1, 2, 3), cons(3, 2, 1, nil)) src = """ (swap_test 'world 'hello cons) """ # compiles to equivalent of (cons 'hello 'world) stmt, env = compile_expr(src, swap_test=swap_test) self.assertEqual(stmt(), cons(symbol("hello"), symbol("world")))
def test_let_star_values(self): src = """ (let*-values [[(a (b c)) (#tuple 1 (#tuple 2 3))] [(d e) `(,(+ a b) ,(+ a c))]] `(,d . ,e)) """ stmt, env = compile_expr(src) res = stmt() self.assertEqual(res, cons(3, 4, nil)) src = """ (let*-values [[(d e) `(,(+ a b) ,(+ a c))] [(a (b c)) (#tuple 1 (#tuple 2 3))]] `(,d . ,e)) """ stmt, env = compile_expr(src) self.assertRaises(NameError, stmt)
def test_let_star_values(self): src = """ (let*-values [[(a (b c)) (#tuple 1 (#tuple 2 3))] [(d e) `(,(+ a b) ,(+ a c))]] `(,d . ,e)) """ stmt, env = compile_expr(src) res = stmt() self.assertEqual(res, cons(3, 4, nil)) src = """ (let*-values [[(d e) `(,(+ a b) ,(+ a c))] [(a (b c)) (#tuple 1 (#tuple 2 3))]] `(,d . ,e)) """ stmt, env = compile_expr(src) self.assertRaises(NameError, stmt)
def test_improper(self): self.qq("`(1 . 2)", cons(1, 2)) self.qq("`(1 . (2 3))", cons(1, 2, 3, nil)) self.qq("`(1 . ,'(2 . 3))", cons(1, 2, 3)) self.qq("`(1 . ,A)", cons(1, 2), A=2) self.qq("`(1 . ,A)", cons(1, 2, nil), A=cons(2, nil)) self.qq("`(1 . ,A)", cons(1, 2, 3), A=cons(2, 3))
def test_splice(self): self.qq("`(1 2 ,@A)", cons(1, 2, 3, 4, 5, nil), A=range(3, 6)) self.qq("`(1 2 ,@A ,B)", cons(1, 2, 3, 4, 5, nil), A=cons(3, 4, nil), B=5) self.qq("`(1 2 ,@(range 3 6))", cons(1, 2, 3, 4, 5, nil)) self.qq("`(,@foo)", cons(1, 2, 3, nil), foo=cons(1, 2, 3, nil))
def compile_symbol(self, sym: Symbol, tc, cont): """ Compile a symbol expression. This can result in a constant for certain specialty Python values (None, True, False, and ...) Dotted symbols will be compiled into attr calls. Non-dotted symbols will be compiled into variable references. If a symbol correlates to an Alias in the module namespace, then that alias will be expanded and compilation will continue from the expanded form. """ comp = self.find_compiled(sym) if comp and is_alias(comp): return tcf(comp.compile, self, sym, tc, cont) elif sym is _symbol_None: return tcf(self.compile_constant, None, tc, cont) elif sym is _symbol_True: return tcf(self.compile_constant, True, tc, cont) elif sym is _symbol_False: return tcf(self.compile_constant, False, tc, cont) elif sym is _symbol_ellipsis: return tcf(self.compile_constant, ..., tc, cont) elif is_lazygensym(sym): return tcf(cont, self.pseudop_get_var(sym), tc) else: ex = sym.rsplit(".", 1) if len(ex) == 1: return tcf(cont, self.pseudop_get_var(sym), None) else: source = cons(_symbol_attr, *ex, nil) return tcf(self.compile, source, tc, cont)
def compile_tcr_apply(self, source_obj: pair, tc, cont): assert tc # print("compiling a tcr apply", source_obj) pos = source_obj.get_position() maybe = self.helper_inline_tcr(source_obj) if maybe: fun, args = source_obj return tcf(self.complete_apply, args, pos, True, cont) else: def ccp(done_source, tc): assert done_source is None return tcf(self.complete_tcr_apply, cont) tcr_source = cons(self.self_ref, source_obj) tcr_source.set_position(pos) self.pseudop_get_global(_symbol_tcr_frame) return tcf(self.complete_apply, tcr_source, pos, False, ccp)
def compile_symbol(self, sym: Symbol, tc, cont): """ Compile a symbol expression. This can result in a constant for certain specialty Python values (None, True, False, and ...) Dotted symbols will be compiled into attr calls. Non-dotted symbols will be compiled into variable references. If a symbol correlates to an Alias in the module namespace, then that alias will be expanded and compilation will continue from the expanded form. """ comp = self.find_compiled(sym) if comp and is_alias(comp): return tcf(comp.compile, self, sym, tc, cont) elif sym is _symbol_None: return tcf(self.compile_constant, None, tc, cont) elif sym is _symbol_True: return tcf(self.compile_constant, True, tc, cont) elif sym is _symbol_False: return tcf(self.compile_constant, False, tc, cont) elif sym is _symbol_ellipsis: return tcf(self.compile_constant, ..., tc, cont) elif is_lazygensym(sym): return tcf(cont, self.pseudop_get_var(sym), tc) else: ex = sym.rsplit(".", 1) if len(ex) == 1: return tcf(cont, self.pseudop_get_var(sym), None) else: source = cons(_symbol_attr, *ex, nil) return tcf(self.compile, source, tc, cont)
def test_list(self): src = "(testing a thing)" col = parse_source(src) exp = cons(symbol("testing"), symbol("a"), symbol("thing"), nil) self.assertEqual(col, exp) src = "[testing a thing]" col = parse_source(src) self.assertEqual(col, exp) with self.assertRaises(SyntaxError): src = "(no way]" col = parse_source(src) with self.assertRaises(SyntaxError): src = "[no way)" col = parse_source(src) with self.assertRaises(SyntaxError): src = "{no way]" col = parse_source(src) with self.assertRaises(SyntaxError): src = "[no way}" col = parse_source(src) with self.assertRaises(SyntaxError): src = "{no way)" col = parse_source(src) with self.assertRaises(SyntaxError): src = "(no way}" col = parse_source(src)
def gather_formals(args, declared_at=None, filename=None): """ parses formals pair args into five values: (positional, keywords, defaults, stararg, starstararg) - positional is a list of symbols defining positional arguments - defaults is a list of keywords and expr pairs defining keyword arguments and their default value expression - kwonly is a list of keywords and expr pairs which are keyword-only arguments and theid default value expression - stararg is a symbol for variadic positional arguments - starstararg is a symbol for variadic keyword arguments """ undefined = object() err = partial(SibilantSyntaxError, location=declared_at, filename=filename) if is_symbol(args): return ((), (), (), args, None) elif isinstance(args, (list, tuple)): improper = False args = cons(*args, nil) elif is_proper(args): improper = False elif is_pair(args): improper = True else: raise err("formals must be symbol or pair, not %r" % args) positional = [] iargs = iter(args.unpack()) for arg in iargs: if is_keyword(arg): if improper: raise err("cannot mix improper formal with keywords") else: break elif is_symbol(arg) or is_lazygensym(arg): positional.append(arg) else: raise err("positional formals must be symbols, nor %r" % arg) else: # handled all of args, done deal. if improper: return (positional[:-1], (), (), positional[-1], None) else: return (positional, (), (), None, None) defaults = [] kwonly = [] while arg not in (_keyword_star, _keyword_starstar): value = next(iargs, undefined) if value is undefined: raise err("missing value for keyword formal %s" % args) else: defaults.append((arg, value)) arg = next(iargs, undefined) if arg is undefined: break elif is_keyword(arg): continue else: raise err("keyword formals must be alternating keywords and" " values, not %r" % arg) star = None starstar = None if arg is undefined: return (positional, defaults, kwonly, None, None) if arg is _keyword_star: star = next(iargs, undefined) if star is undefined: raise err("* keyword requires symbol binding") elif star is nil: # nil means an ignored star arg, this is allowed. pass elif not (is_symbol(star) or is_lazygensym(star)): raise err("* keyword requires symbol binding, not %r" % star) arg = next(iargs, undefined) if arg is undefined: return (positional, defaults, kwonly, star, starstar) # while is_symbol(arg): # kwonly.append(arg) # arg = next(iargs, undefined) # # if arg is undefined: # return (positional, defaults, kwonly, star, starstar) if not is_keyword(arg): raise err("expected keyword in formals, got %r" % arg) # keyword formals after *: are considered keyword-only while arg not in (_keyword_star, _keyword_starstar): value = next(iargs, undefined) if value is undefined: raise err("missing value for keyword-only formal %s" % arg) else: kwonly.append((arg, value)) arg = next(iargs, undefined) if arg is undefined: break elif is_keyword(arg): continue else: raise err("keyword-only formals must be alternating keywords" " and values, not %r" % arg) if arg is _keyword_starstar: starstar = next(iargs, undefined) if starstar is undefined: raise err("** keyword requires symbol binding") elif not (is_symbol(starstar) or is_lazygensym(starstar)): raise err("** keyword requires symbol binding, not %r" % star) arg = next(iargs, undefined) if arg is not undefined: raise err("leftover formals %r" % arg) return (positional, defaults, kwonly, star, starstar)
def gather_parameters(args, declared_at=None, filename=None): """ parses parameter args into five values: (positional, keywords, values, stararg, starstararg) - positional is a list of expressions for positional arguments - keywords is a list of keywords defining keyword arguments - values is a list of expressions defining values for keywords - stararg is a symbol for variadic positional expression - starstararg is a symbol for variadic keyword expression """ undefined = object() def err(msg): return SibilantSyntaxError(msg, location=declared_at, filename=filename) if is_symbol(args) or is_lazygensym(args): return ((), (), (), args, None) elif isinstance(args, (list, tuple)): improper = False args = cons(*args, nil) if args else nil elif is_proper(args): improper = False elif is_pair(args): improper = True else: raise err("parameters must be symbol or pair, not %r" % args) positional = [] iargs = iter(args.unpack()) for arg in iargs: if is_keyword(arg): break else: positional.append(arg) else: # handled all of args, done deal. if improper: return (positional[:-1], (), (), positional[-1], None) else: return (positional, (), (), None, None) keywords = [] defaults = [] while arg not in (_keyword_star, _keyword_starstar): keywords.append(arg) value = next(iargs, undefined) if value is undefined: raise err("missing value for keyword parameter %s" % arg) else: defaults.append(value) arg = next(iargs, undefined) if arg is undefined: break elif is_keyword(arg): continue else: raise err("keyword parameters must be alternating keywords and" " values, not %r" % arg) star = None starstar = None if arg is undefined: return (positional, keywords, defaults, None, None) if arg is _keyword_star: star = next(iargs, undefined) if star is undefined: raise err("* keyword parameter needs value") arg = next(iargs, undefined) if arg is _keyword_starstar: starstar = next(iargs, undefined) if starstar is undefined: raise err("** keyword parameter needs value") arg = next(iargs, undefined) if arg is not undefined: raise err("leftover parameters %r" % arg) return (positional, keywords, defaults, star, starstar)
def expander(): expanded = cons(found.expand(), params) expanded.set_position(source_obj.get_position()) return expanded
def test_cons(self): src = "(cons 1 2 3 nil)" stmt, env = compile_expr(src) self.assertEqual(stmt(), cons(1, 2, 3, nil))