예제 #1
0
    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)
예제 #2
0
    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())
예제 #3
0
    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())
예제 #4
0
    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)
예제 #5
0
    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)))
예제 #6
0
    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))
예제 #7
0
    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))
예제 #8
0
    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))
예제 #9
0
    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))
예제 #10
0
    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))
예제 #11
0
    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))
예제 #12
0
    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))
예제 #13
0
    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))
예제 #14
0
    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)
예제 #15
0
    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)
예제 #16
0
    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))
예제 #17
0
    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)
예제 #18
0
    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)
예제 #19
0
    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))
예제 #20
0
    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)
예제 #21
0
 def test_quasi(self):
     src = """
     `bar
     """
     col = parse_source(src)
     self.assertEqual(col, cons(symbol("quasiquote"),
                                symbol("bar"),
                                nil))
예제 #22
0
    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)
예제 #23
0
 def test_quote_symbol(self):
     src = """
     'foo
     """
     col = parse_source(src)
     self.assertEqual(col, cons(symbol("quote"),
                                symbol("foo"),
                                nil))
예제 #24
0
    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))
예제 #25
0
    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))
예제 #26
0
    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)
예제 #27
0
    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))
예제 #28
0
 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))
예제 #29
0
    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))
예제 #30
0
    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)
예제 #31
0
    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)
예제 #32
0
    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)
예제 #33
0
    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))
예제 #34
0
    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)
예제 #35
0
    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)
예제 #36
0
    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))
예제 #37
0
    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)
예제 #38
0
    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)
예제 #39
0
    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))
예제 #40
0
    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))
예제 #41
0
    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)
예제 #42
0
    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))
예제 #43
0
    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)
예제 #44
0
    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")))
예제 #45
0
    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))
예제 #46
0
 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))
예제 #47
0
 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))
예제 #48
0
    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")))
예제 #49
0
    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)
예제 #50
0
    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)
예제 #51
0
    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))
예제 #52
0
    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))
예제 #53
0
    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)
예제 #54
0
    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)
예제 #55
0
    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)
예제 #56
0
    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)
예제 #57
0
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)
예제 #58
0
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)
예제 #59
0
 def expander():
     expanded = cons(found.expand(), params)
     expanded.set_position(source_obj.get_position())
     return expanded
예제 #60
0
 def test_cons(self):
     src = "(cons 1 2 3 nil)"
     stmt, env = compile_expr(src)
     self.assertEqual(stmt(), cons(1, 2, 3, nil))