import unittest as t
from lambdak import *

# A helper class to test attribute access.
class A: pass

class test_lambdak(t.TestCase):
  def test_init_k_x(self):
    args = (1, 2)
    lk = lambdak(*args)

    self.assertEqual((lk.k, lk.x), args)

  def test_init_k(self):
    lk = lambdak(1)

    self.assertEqual((lk.k, lk.x), (1, None))

class test_call_(t.TestCase):
  def test_call_none(self):
    self.assertEqual(call_(None), None)

  def test_call_func(self):
    val = 1
    def f(): return val

    self.assertEqual(call_(f), val)

class test_do_(t.TestCase):
  def test_do_1(self):
    a = A()
    val = 1

    do_(setattr(a, "x", val))()
    self.assertEqual(a.x, val)

  def test_do_2(self):
    a = A()
    (val1, val2) = (1, 2)

    do_(setattr(a, "x", val1), lambda:
    do_(setattr(a, "y", val2)))()
    self.assertEqual((a.x, a.y), (val1, val2))

class test_given_(t.TestCase):
  def test_given_id(self):
    val = 1
    f = given_(lambda x: x)

    self.assertEqual(f(val), val)

  def test_given_recursion(self):
    "Test that tail recursion doesn't stack overflow if it uses lambdak's trampoline system."
    f = given_(lambda x, acc:
      if_(x <= 1,
        lambda: lambda: acc,
        # This could also be written as
        #   lambda: functools.partial(f.k, x - 1, x * acc)
        # But trying to make the two branches of the `if_` look
        # consistent.
        lambda: lambda: f.k(x - 1, x * acc),
        lambda k: k()))

    try: f(1000, 1)
    except:
      self.assertTrue(False)
      return

    self.assertTrue(True)

class test_let_(t.TestCase):
  def test_let_val(self):
    val = 1
    test_l = let_(val, lambda x: x)

    self.assertEqual(test_l(), val)

class test_assert_(t.TestCase):
  def test_assert_succeed(self):
    try:
      assert_(True)()
      self.assertTrue(True)
    except:
      self.assertTrue(False)

  def test_assert_fail(self):
    try:
      assert_(False)()
      self.assertTrue(False)
    except:
      self.assertTrue(True)

class test_raise_(t.TestCase):
  def setUp(self): self.exn = Exception

  def test_raise_last(self):
    try: raise self.exn
    except: self.assertRaises(self.exn, raise_)

  def test_raise_exn_type(self):
    self.assertRaises(self.exn, raise_, self.exn)

  def test_raise_exn_val(self):
    e = Exception("Bad")
    self.assertRaises(self.exn, raise_, e)

  def test_raise_exn_type_val(self):
    msg = "Bad"
    e = Exception(msg)

    try: raise_(Exception, e)
    except Exception, ee:
      self.assertEqual(ee.message, msg)
      return

    self.assertTrue(False)

class test_if_(t.TestCase):
  def test_if_then(self):
    val = 1
    then_val = if_(True, lambda: val)

    self.assertEqual(then_val(), val)

  def test_if_else(self):
    val = 1
    else_val = if_(False, None, lambda: val)

    self.assertEqual(else_val(), val)

class test_cond_(t.TestCase):
  def test_cond_val(self):
    val = 1
    cond_val = cond_(
      [ (lambda: True, lambda: val),
        (lambda: False, lambda: 2) ])

    self.assertEqual(cond_val(), val)

  def test_cond_noval(self):
    cond_noval = cond_(
      [ (lambda: False, lambda: 1) ])

    self.assertEqual(cond_noval(), None)

class test_import_(t.TestCase):
  def test_import_math(self):
    "Math here is representative of the Python standard library."
    pi_floor = import_("math", lambda m: m.floor(m.pi))

    self.assertEqual(pi_floor(), 3)

class test_try_(t.TestCase):
  def test_try_exn(self):
    a = A()
    val = 1

    try_(lambda: 1 / 0, lambda: setattr(a, "x", val))()
    self.assertEqual(a.x, val)

  def test_try_noexn(self):
    a = A()
    val = 1
    a.x = val

    try_(lambda: 1, lambda: setattr(a, "x", 2))()
    self.assertEqual(a.x, val)

class test_for_(t.TestCase):
  def test_for_act(self):
    a = A()
    vals = (1, 2, 3)

    for_(range(1, 4), lambda x: setattr(a, "x%s" % x, x))()

    self.assertEqual((a.x1, a.x2, a.x3), vals)

class test_attr_accessors(t.TestCase):
  def test_setattr_(self):
    a = A()
    val = 1

    setattr_(a, "x", val)()
    self.assertEqual(a.x, val)

  def test_delattr_(self):
    a = A()
    attr_name = "x"
    a.x = 1

    delattr_(a, attr_name)()
    self.assertFalse(hasattr(a, attr_name))

if __name__ == "__main__":
  t.main()


@@ -1119,24 +1119,32 @@
 stem.%22%0A    f
+actorial
  = given_(la
@@ -1152,14 +1152,18 @@
 bda 
-x
+n
 , acc
+ = 1
 :%0A  
@@ -1170,17 +1170,17 @@
     if_(
-x
+n
  %3C= 1,%0A 
@@ -1219,51 +1219,15 @@
     
-# This could also be written as%0A        #  
+lambda:
  lam
@@ -1236,198 +1236,47 @@
 a: f
-unctools.partial(f.k, x
+actorial.k(n
  - 1, 
-x
+n
  * acc)
+,
 %0A
-  
       
-# But trying to make the two branches of the %60if_%60 look%0A        # consistent.%0A        lambda: lambda: f.k(x - 1, x * acc),%0A        lambda k: k()
+call_
 ))%0A%0A
@@ -1285,16 +1285,24 @@
   try: f
+actorial
 (1000, 1

Refactor recursion test