Commits

Jürgen Bömmels  committed 62cfba5

Implement "append" & "append!"

  • Participants
  • Parent commits b27460b

Comments (0)

Files changed (2)

File scheme/procedure.py

         w_pair.cdr = w_obj
         return w_undefined
 
+class Append(W_Procedure):
+    _symbol_name = "append"
+
+    def procedure(self, ctx, lst):
+        w_lol = plst2lst(lst)
+        w_lol = Reverse().procedure(ctx,[w_lol])
+        
+        w_result = w_nil
+        while w_lol is not w_nil:
+            assert isinstance(w_lol, W_Pair)
+            w_list = w_lol.car
+            w_lol = w_lol.cdr
+            if w_list is w_nil:
+                continue
+            if not isinstance(w_list, W_Pair):
+                raise WrongArgType(w_list, "List")
+            w_head = W_Pair(w_list.car, w_undefined)
+            w_tail = w_head
+            w_list = w_list.cdr
+            while w_list is not w_nil:
+                if not isinstance (w_list, W_Pair):
+                    raise WrongArgType(w_list, "List")
+                assert isinstance(w_tail, W_Pair)
+                w_tail.cdr = W_Pair(w_list.car, w_undefined)
+                w_tail = w_tail.cdr
+                w_list = w_list.cdr
+
+            assert isinstance(w_tail, W_Pair)
+            w_tail.cdr = w_result
+            w_result = w_head
+
+        return w_result
+
+class AppendE(W_Procedure):
+    _symbol_name = "append!"
+
+    def procedure(self, ctx, lst):
+        if len(lst) == 0:
+            return w_nil
+
+        w_head = w_nil
+        w_prev_tail = w_nil
+        for w_list in lst:
+            if w_list is w_nil:
+                continue
+            if w_head is w_nil:
+                w_head = w_list
+            if w_prev_tail is not w_nil:
+                assert isinstance(w_prev_tail, W_Pair)
+                w_prev_tail.cdr = w_list
+            if not isinstance(w_list, W_Pair):
+                raise WrongArgType(w_list, "List")
+            while w_list.cdr is not w_nil:
+                w_list = w_list.cdr
+                if not isinstance(w_list, W_Pair):
+                    raise WrongArgType(w_list, "List")        
+            w_prev_tail = w_list
+
+        return w_head
+
 class Apply(W_Procedure):
     _symbol_name = "apply"
 

File scheme/test/test_eval.py

 def eval_noctx(expr):
     return parse(expr)[0].eval(ExecutionContext())
 
+def parse_(expr):
+    return parse(expr)[0]
+
 def test_numerical():
     w_num = eval_noctx("(+)")
     assert w_num.to_number() == 0
     py.test.raises(WrongArgsNumber, eval_, ctx, "(apply 1)")
     py.test.raises(WrongArgType, eval_, ctx, "(apply 1 '(1))")
     py.test.raises(WrongArgType, eval_, ctx, "(apply + 42)")
+
+def test_append():
+    ctx = ExecutionContext()
+    eval_(ctx, "(define lst-a (list 'a 'b 'c))")
+
+    w_res = eval_(ctx, "(append '(1 2 3) lst-a)")
+    assert w_res.equal(parse_("(1 2 3 a b c)"))
+
+    w_res = eval_(ctx, "(append lst-a lst-a '() '(1 2 3))")
+    w_lst_a = eval_(ctx, "lst-a")
+    assert w_res.equal(parse_("(a b c a b c 1 2 3)"))
+    assert w_lst_a.equal(parse_("(a b c)"))
+
+    w_res = eval_(ctx, "(append '(1 2 3) '(4 (5 6) 7) '(8) '((9)))")
+    assert w_res.equal(parse_("(1 2 3 4 (5 6) 7 8 (9))"))
+
+    w_res = eval_(ctx, "(append)")
+    assert w_res.eq(w_nil)
+
+    w_res = eval_(ctx, "(append!)")
+    assert w_res.eq(w_nil)
+
+    w_res = eval_(ctx, "(append! (list 1 2 3) lst-a)")
+    w_lst_a = eval_(ctx, "lst-a")
+    assert w_res.equal(parse_("(1 2 3 a b c)"))
+    assert w_lst_a.equal(parse_("(a b c)"))
+
+    w_res = eval_(ctx, "(append! lst-a '(1 2 3))")
+    w_lst_a = eval_(ctx, "lst-a")
+    assert w_res.equal(parse_("(a b c 1 2 3)"))
+    assert w_lst_a.equal(parse_("(a b c 1 2 3)"))
+
+    py.test.raises(WrongArgType, eval_, ctx, "(append 'a '())")
+    py.test.raises(WrongArgType, eval_, ctx, "(append 1 2 3)")
+    py.test.raises(WrongArgType, eval_, ctx, "(append! (cons 1 2) '(3 4))")