import unittest
from compyler.test.util import eval_code

deffunc = """

def foo(a):
    print a

foo('Im so awesome')

print 'aaa'
"""

funcResults = """Im so awesome
aaa
"""

defclass = """

class foo:
    def bar(self,a):
        print a

a = foo()
a.bar("Im still awesome")
#

"""

returnVal = """

def bar():
    return 1

def foo():
    print "!!!" , bar()
    return 1 + bar()

print foo()

"""

default = """

def foo(a, b=1):
    print 2,1,a,b

foo("this is a test")


"""

some_defaults = """

def bar(a=1,b=2,c=3,d=4):
    print a,b,c,d

bar(4,3)
bar(a=4,c=4)

"""

# this was causing a crash
other_defaults = """

def bar(x,y):
    z,foo = 1,2
    print x,y,z,foo

bar(3,4)    
    

"""

def simpleFunction(*args):
    print args

class test_opcodes_functions(unittest.TestCase):
    def test_functions(self):
        #self.failUnlessEqual(self.eval_code("simplerFunction()"),"")
        self.failUnless(eval_code("simpleFunction('AAAA','BBBB','CCCC')","('AAAA', 'BBBB', 'CCCC')\n",title='test_opcodes_functions: 1'))
        self.failUnless(eval_code("simpleKwFunction('AAAA','BBBB','CCCC',foo=1,bar=2)",
                                  "('AAAA', 'BBBB', 'CCCC')\n{'foo': 1, 'bar': 2}\n",title='test_opcodes_functions: 2'))
        self.failUnless(eval_code("a={'a':1,'b':2};simpleKwFunction('AAAA','BBBB','CCCC',foo=1,bar=2,**a)",
                                  "('AAAA', 'BBBB', 'CCCC')\n{'a': 1, 'b': 2, 'bar': 2, 'foo': 1}\n",title='test_opcodes_functions: 3'))
        self.failUnless(eval_code("a=(1,2,3,4);simpleFunction(1,*a)",
                                  "(1, 1, 2, 3, 4)\n",title='test_opcodes_functions: 4'))
        self.failUnless(eval_code("a={'a':1,'b':2};b=(4,5,6);simpleKwFunction('AAAA','BBBB','CCCC',foo=1,bar=2,*b,**a)",
                                  "('AAAA', 'BBBB', 'CCCC', 4, 5, 6)\n{'a': 1, 'b': 2, 'bar': 2, 'foo': 1}\n",title='test_opcodes_functions: 5'))

    def test_make_function(self):
        self.failUnless(eval_code(deffunc, funcResults, 'exec',title='test_opcodes_functions: 6'))

    def test_make_class(self):
        self.failUnless(eval_code(defclass, "Im still awesome\n", 'exec',title='test_opcodes_functions: 7'))

    def test_default_args(self):
        self.failUnless(eval_code(default, "2 1 this is a test 1\n",'exec'
                                  ,title='test_opcodes_functions: 8'))
        self.failUnless(eval_code(some_defaults, "4 3 3 4\n4 2 4 4\n",
                                  'exec',title='test_opcodes_functions: 8'))
        self.failUnless(eval_code(other_defaults, "3 4 1 2\n",
                                  'exec',title='test_opcodes_functions: 8'))

    def test_return_val(self):
        self.failUnless(eval_code(returnVal,"!!! 1\n2\n",'exec',title='test_opcodes_functions: 9'))
        
if __name__ == "__main__":
    unittest.main()

