"""
ArithmeticGenerator.py
Author: Mike Lynch
Date: 12-19-06
COMS-W4115: Prof. Edwards

Generates a source file designed to do exhaustive testing of every combination
of ways in which to perform arithmetic on operators when the operators are
being accessed in different ways (as constants, atomic variables, elements of
an array)
"""

import os

codeLines = []

typeInt = {"max": 2147483647, "min": -2147483648, "array_size": 4,
           "name": "int", "signed": True, "prefix": "i",
           "hasArray": True, "decimal": False, "print": "%d"}
typeUint = {"max": 4294967295, "min": 0, "array_size": 4,
            "name": "uint", "signed": False, "prefix": "ui",
            "hasArray": True, "decimal": False, "print": "%4u"}
typeByte = {"max": 127, "min": -127, "array_size": 16,
            "name": "byte", "signed": True, "prefix": "b",
             "hasArray": True, "decimal": False, "print": "%d"}
typeUbyte = {"max": 255, "min": 0, "array_size": 16,
             "name": "ubyte", "signed": False, "prefix": "ub",
             "hasArray": False, "decimal": False, "print": "%1u"}
typeFloat = {"max": 34875302984.5, "min": -6456873543.4, "array_size": 4,
             "name": "float", "signed": True, "prefix": "f",
             "hasArray": True, "decimal": True, "print": "%f"}
       
types = (typeInt, typeUint, typeByte, typeUbyte, typeFloat)

header = \
"""
/*
 * This class tests different ways of loading values for arithmetic
 *  operations
 *@generated by utils\ArithmeticGenerator.py
 */
 
"""

codeLines.append(header)

declarations = []
numVars = 3
for t in types:
    for i in range(numVars):
        declarations.append("%s %s%d;" % (t["name"], t["prefix"], i + 1))
        if t["hasArray"]:
            declarations.append("%s_array[%d] %sA%d;" % (t["name"], t["array_size"], t["prefix"], i + 1))

declarations.sort();
for d in declarations:
    codeLines.append(d)

#print ""

codeLines.append("")

addition = {"symbol": "+",
            "vals":[(84, 19),]}
subtraction = {"symbol": "-",
            "vals":[(54, 8),]}
multiplication = {"symbol": "*",
            "vals":[(18, 5),]}
division = {"symbol": "/",
            "vals":[(80, 8),]}

operations = (addition, subtraction, multiplication, division)

def generateOperations(operation, varType):
    operations = []
    for valuePair in operation["vals"]:
        v1, v2 = valuePair
        if varType["decimal"]:
            v1 = "%s.0" % str(v1)
            v2 = "%s.0" % str(v2)
        #arithmetic on constants
        operations.append("//arithmetic on two constants")
        operations.append("%s3 = %s %s %s;" % \
                          (varType["prefix"], v1, operation["symbol"],\
                           v2))
        operations.append("ccall printf(\"%s3 = %s\\n\", %s3);" % (varType["prefix"], varType["print"],
                                                                     varType["prefix"]))
        #arithmetic on constants stored in an array
        if varType["hasArray"]:
            operations.append("%sA3[0] = %s %s %s;" % \
                              (varType["prefix"], v1, operation["symbol"],\
                               v2))
            operations.append("ccall printf(\"%sA3[0] = %s\\n\", %sA3[0]);" % (varType["prefix"], varType["print"],
                                                                         varType["prefix"]))

        operations.append("")

        #arithmetic drawing one value from a variable stored in a variable
        operations.append("//arithmetic on one constant and one variable")
        operations.append("%s1 = %s;" % (varType["prefix"], v1))
        operations.append("%s2 = %s;" % (varType["prefix"], v2))
        operations.append("%s3 = %s1 %s %s;" % (varType["prefix"], varType["prefix"], operation["symbol"],
                                                v2))
        operations.append("ccall printf(\"%s3 = %s\\n\", %s3);" % (varType["prefix"], varType["print"],
                                                                   varType["prefix"]))

        operations.append("%s3 = %s %s %s2;" % (varType["prefix"], v1,  \
                                                operation["symbol"], varType["prefix"]))
        operations.append("ccall printf(\"%s3 = %s\\n\", %s3);" % (varType["prefix"], varType["print"],
                                                                     varType["prefix"]))
        #arithmetic drawing one value from a variable stored in an array
        if varType["hasArray"]:
            operations.append("%sA3[0] = %s1 %s %s;" % (varType["prefix"], varType["prefix"], operation["symbol"],
                                                    v2))
            operations.append("ccall printf(\"%sA3[0] = %s\\n\", %sA3[0]);" % (varType["prefix"], varType["print"],
                                                                               varType["prefix"]))

            operations.append("%sA3[0] = %s %s %s2;" % (varType["prefix"], v1,  \
                                                    operation["symbol"], varType["prefix"]))
            operations.append("ccall printf(\"%sA3[0] = %s\\n\", %sA3[0]);" % (varType["prefix"], varType["print"],
                                                                                 varType["prefix"]))

        operations.append("")

        #arithmetic on two variables stored in a variable
        operations.append("//arithmetic on two variables")
        operations.append("%s3 = %s1 %s %s2;" % (varType["prefix"], varType["prefix"], operation["symbol"],
                                                 varType["prefix"]))
        operations.append("ccall printf(\"%s3 = %s\\n\", %s3);" % (varType["prefix"], varType["print"],
                                                                   varType["prefix"]))
        #arithmetic on two variables stored in an array
        if varType["hasArray"]:
            operations.append("%sA3[0] = %s1 %s %s2;" % (varType["prefix"], varType["prefix"], operation["symbol"],
                                                     varType["prefix"]))
            operations.append("ccall printf(\"%sA3[0] = %s\\n\", %sA3[0]);" % (varType["prefix"],
                                                                               varType["print"], varType["prefix"]))
        operations.append("")
            
        if varType["hasArray"]:
            #arithmetic drawing one value from an array
            operations.append("//arithmetic on one constant and one array value")
            operations.append("%sA1[0] = %s;" % (varType["prefix"], v1))
            operations.append("%sA2[0] = %s;" % (varType["prefix"], v2))
            operations.append("%s3 = %sA1[0] %s %s;" % (varType["prefix"], varType["prefix"], operation["symbol"],
                                                    v2))
            operations.append("ccall printf(\"%s3 = %s\\n\", %s3);" % (varType["prefix"], varType["print"],
                                                                       varType["prefix"]))

            operations.append("%s3 = %s %s %sA2[0];" % (varType["prefix"], v1,  \
                                                    operation["symbol"], varType["prefix"]))
            operations.append("ccall printf(\"%s3 = %s\\n\", %s3);" % (varType["prefix"], varType["print"],
                                                                         varType["prefix"]))
            operations.append("%sA3[0] = %sA1[0] %s %s;" % (varType["prefix"], varType["prefix"], operation["symbol"],
                                                    v2))
            operations.append("ccall printf(\"%sA3[0] = %s\\n\", %sA3[0]);" % (varType["prefix"], varType["print"],
                                                                       varType["prefix"]))

            operations.append("%sA3[0] = %s %s %sA2[0];" % (varType["prefix"], v1,  \
                                                    operation["symbol"], varType["prefix"]))
            operations.append("ccall printf(\"%sA3[0] = %s\\n\", %sA3[0]);" % (varType["prefix"], varType["print"],
                                                                         varType["prefix"]))

            operations.append("")

            #arithmetic on two array values
            operations.append("//arithmetic on two array values")
            operations.append("%s3 = %sA1[0] %s %sA2[0];" % (varType["prefix"], varType["prefix"], operation["symbol"],
                                                     varType["prefix"]))
            operations.append("ccall printf(\"%s3 = %s\\n\", %s3);" % (varType["prefix"], varType["print"],
                                                                         varType["prefix"]))
            operations.append("%sA3[0] = %sA1[0] %s %sA2[0];" % (varType["prefix"], varType["prefix"], operation["symbol"],
                                                     varType["prefix"]))
            operations.append("ccall printf(\"%sA3[0] = %s\\n\", %sA3[0]);\n" % (varType["prefix"], varType["print"],
                                                                         varType["prefix"]))
            operations.append("")

            #arithmetic on one array value, one variable value
            operations.append("//arithmetic on one array value, one variable value")
            operations.append("%s3 = %sA1[0] %s %s2;" % (varType["prefix"], varType["prefix"], operation["symbol"],
                                                     varType["prefix"]))
            operations.append("ccall printf(\"%s3 = %s\\n\", %s3);" % (varType["prefix"], varType["print"],
                                                                         varType["prefix"]))
            operations.append("%sA3[0] = %sA1[0] %s %s2;" % (varType["prefix"], varType["prefix"], operation["symbol"],
                                                     varType["prefix"]))
            operations.append("ccall printf(\"%sA3[0] = %s\\n\", %sA3[0]);" % (varType["prefix"], varType["print"],
                                                                         varType["prefix"]))

            operations.append("%s3 = %s1 %s %sA2[0];" % (varType["prefix"], varType["prefix"], operation["symbol"],
                                                     varType["prefix"]))
            operations.append("ccall printf(\"%s3 = %s\\n\", %s3);" % (varType["prefix"], varType["print"],
                                                                         varType["prefix"]))
            operations.append("%sA3[0] = %s1 %s %sA2[0];" % (varType["prefix"], varType["prefix"], operation["symbol"],
                                                     varType["prefix"]))
            operations.append("ccall printf(\"%sA3[0] = %s\\n\", %sA3[0]);" % (varType["prefix"], varType["print"],
                                                                         varType["prefix"]))
    #for o in operations:
    #    print o
    return operations

for t in types:
    testHeader = \
"""
/************************************
*       TEST FOR %s VALUES          *
*************************************/
""" % (t["name"]).upper()
    codeLines.append(testHeader)
    #print testHeader
    for op in operations:
        for codeLine in generateOperations(op, t):
            codeLines.append(codeLine)

f = open("testcases%sassignment5.dspl" % (os.path.sep), "w")
for line in codeLines:
    f.write("%s\n" % line)
    #print line
f.close()


def dsplToC(line):
    line = line.replace("_array", "")
    line = line.replace("uint", "unsigned int")
    line = line.replace("ubyte", "unsigned byte")
    line = line.replace("ccall ", "")
    line = line.replace("byte", "char")
    if (line.find("[16]") >= 0):
        line = line.replace("[16]", "")
        line = line.replace(";", "[16];")
    if (line.find("[4]") >= 0):
        line = line.replace("[4]", "")
        line = line.replace(";", "[4];")
    return line


"""
Generate the equivalent C code and use to generate the correct expected output
"""
f = open("utils%s_assignment5.c" % (os.path.sep), "w")
f.write("#include <stdio.h>\n\n")
f.write("int main(char** argv, int argc) {\n")
for line in codeLines:
    f.write("\t%s\n" % dsplToC(line))
f.write("\treturn 0;\n");
f.write("}\n")
f.close()

output = os.popen4("gcc -o utils%s_assignment5.o utils%s_assignment5.c" % (os.path.sep, os.path.sep))[1]
for line in output:
    print line
output = os.popen4("utils%s_assignment5.o > testcases%scorrect%sassignment5.out" % (os.path.sep, os.path.sep, os.path.sep))[1]
for line in output:
    print line
print "Finished!"                      
