Merge pull request #5 from nyu-compiler-construction/sanjar/testing

Added student test cases
master
sunyinqi0508 4 years ago committed by GitHub
commit f1c13749a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -12,5 +12,7 @@
## Challenges:
- Nested structures were a challenge. A function inside a function needs to handle variable references as well as ensure function calls have appropriate scope.
- Testing various scenarious with similarly defined variables were time consuming. Instead, we defined certain set of variables in the begging of the student contributed test programs, and then used the same variables troughout the programs to cover various bad and good scenarious.
- Another challenge was to come up with good test cases to have a broader cover. Our approach to this issue was investigating Type Checking rules and writing adverse code to those rules to see if our analyzer can make correct inferences.
## Improvements:
- Added more tests to rigorously check program flow and indentation.

@ -1,14 +1,93 @@
x:int = 1
x:int = 2
# class defs
class A_CLASS(object):
a_class_i:int = 0
def __init__(self:"A_CLASS", x:int):
self.x = x
x
# Bad, self param is missing
def add(y:int) -> int:
y = y+self.x
return y
def fun_1() -> bool:
if True:
if True:
class B_CLASS(object):
b_class_i:int = 0
class C_CLASS(B_CLASS):
pass
# Bad, duplicate class def
class A_CLASS(object):
pass
# Bad, E_CLASS is not declared
class D_CLASS(E_CLASS):
pass
# var defs
a_s:str = "a_s"
b_s:str = "b_s"
c_s:str = "c_s"
a_i:int = 0
b_i:int = 0
c_i:int = 0
a_b:bool = False
b_b:bool = False
c_b:bool = False
a_list:[int] = None
b_list:[int] = None
c_list:[int] = None
a_class:A_CLASS = None
b_class:B_CLASS = None
c_class:C_CLASS = None
# fun defs
def f_1() -> object:
def f_f_1() -> object:
# a_s:int = 0 Fails if we uncomment this line
global a_s # Bad, duplicate declarion
print(a_s)
pass
pass
def f_2() -> object:
f_a_s:str = "s"
def f_f_2() -> object:
nonlocal f_a_s
print(f_a_s)
pass
pass
def f_3(x:int) -> bool:
f_b_s:int = 3
if (x + f_b_s > 3):
return True
# All path should return, not just one
elif (x + f_b_s == 3):
print("Equal") # Bad, this path should return
return False
def f_4() -> object:
f_a_i:int = 2
a_i = f_a_i + 1 # Bad, cant assign to a_i without declaring it as global or nonlocal
return f_a_i
# NEGATIVE TEST CASES - SEMANTIC
# Bad, f_2 cannot be redefined in the same scope
def f_2() -> object:
pass
# Bad, print cannot be redefined in the same scope
def print(val:object) -> object:
pass
# Bad, a_i cannot be redefined in the same scope
a_i:int = 2
fun_1()
# Bad return
return a_i

@ -1,5 +1,111 @@
x:int = True
x + [1]
# class defs
class A_CLASS(object):
a_class_i:int = 0
def __init__(self:"A_CLASS", x:int):
self.x = x
def add(self:"A_CLASS", y:int) -> int:
y = y+self.x
return y
class B_CLASS(object):
b_class_i:int = 0
class C_CLASS(B_CLASS):
pass
# var defs
a_s:str = "a_s"
b_s:str = "b_s"
c_s:str = "c_s"
a_i:int = 0
b_i:int = 0
c_i:int = 0
a_b:bool = False
b_b:bool = False
c_b:bool = False
a_list:[int] = None
b_list:[int] = None
c_list:[int] = None
a_class:A_CLASS = None
b_class:B_CLASS = None
c_class:C_CLASS = None
# fun defs
def f_1() -> object:
def f_f_1() -> object:
global a_s # Fails if we change it to z, which doesnt exist in global scope
pass
pass
def f_2() -> object:
f_a_s:str = "s"
def f_f_2() -> object:
nonlocal f_a_s # Fails if we change this to a_s which is in global scope but not in upper scope
pass
pass
def f_3(x:int) -> str:
f_b_s:int = 3
return x*f_b_s
# Declarations
a_list = [1, 2, 3]
b_list = [0, 0, 0]
c_list = [-1, -2, -3]
a_class = A_CLASS(5)
b_class = B_CLASS()
c_class = C_CLASS()
# NEGATIVE TEST CASES - TYPES
c_i = True
c_i + [1] # Bad, addint list to an int
a_i = a_b = z = "Error" # Bad, z is not defined and a_b is boolean
a_s = a_s + 1 # Bad, adding integer to a string
c_s = a_s[a_s] # Bad, indexing with a string variable
b_class.b_class_i = 2 # Bad, object attribute is not assignable
f_1 = 5 # Bad, function is not assignable
f_2 = f_1 # Bad, function is not storable
a_i = b_class.b_class_i = z = 5 # Bad, b_class.b_class_i is not assignable and z is not declared
x_i = "ss" # Bad assignment
a_s = a_i + b_i # Bad, assigning integer to a variable with string type
a_s = a_i == b_i and True # Bad, assigning boolean to a variable with string type
a_list = a_list + a_s # Bad, adding string and list
a_s = a_list[a_s] # Bad, indexing with a string variable and assigning int to str
a_list[1] = "a" # Bad, assigning str to int
a_i = f_3(3) + 5 # Bad, f_3 has string return type but it actually returns an int
f_1()
f_2()
a_i = a_class.add(a_s) # Bad, passing string where method expects int
y:bool = False
x = y = z = "Error"

@ -1,83 +1,109 @@
# Below this point we have all the same test cases from PA1 for validation purposes.
class Foo(object):
x:int = 0
def __init__(self:"Foo", x:int):
# class defs
class A_CLASS(object):
a_class_i:int = 0
def __init__(self:"A_CLASS", x:int):
self.x = x
def bar(y:int):
print("Hello World!",self.x+y)
y = 10
def get_stones(name:str)->str:
def map_name(nm:str)->str:
return stones[color.index(nm)]
color=["Red","Blue"]
stones=["Mind","Soul"]
return map_name(name)
def funa():
def funb():
print("Hello")
funb()
def fund():
def fune():
print("Hello")
c = 4 + 5
def funf():
def fung():
print("Hello")
c = 6
c = 4 + 5
if True:
if True:
if True:
print("Hello")
print("World")
if True:
if True:
if True:
print("Hello")
print("World")
if True:
if True:
if True:
print("Hello")
print("World")
if True:
if True:
if True:
print("Hello")
else:
print("World")
if True:
if True:
if True:
print("Hello")
else:
print("World")
f = Foo(1)
print(f.x)
f.bar(4)
a=[[[1],[2]],[[3],[4]]]
print(a[0][0][1]*a[1][1][0])
multiline_string="Hi World,\
Here I am"
expr_precedence = -a + b * (c + d)
stone="Blue"
print(get_stones(stone))
def add(self:"A_CLASS", y:int) -> int:
y = y+self.x
return y
class B_CLASS(object):
b_class_i:int = 0
class C_CLASS(B_CLASS):
pass
# var defs
a_s:str = "a_s"
b_s:str = "b_s"
c_s:str = "c_s"
a_i:int = 0
b_i:int = 0
c_i:int = 0
a_b:bool = False
b_b:bool = False
c_b:bool = False
a_list:[int] = None
b_list:[int] = None
c_list:[int] = None
a_class:A_CLASS = None
b_class:B_CLASS = None
c_class:C_CLASS = None
# fun defs
def f_1() -> object:
def f_f_1() -> object:
global a_s
print(a_s)
pass
pass
def f_2() -> object:
f_a_s:str = "s"
def f_f_2() -> object:
nonlocal f_a_s
print(f_a_s)
pass
pass
def f_3(x:int) -> int:
f_b_s:int = 3
return x*f_b_s
# Declarations
a_list = [1, 2, 3]
b_list = [0, 0, 0]
c_list = [-1, -2, -3]
a_class = A_CLASS(5)
b_class = B_CLASS()
c_class = C_CLASS()
# POSITIVE TEST CASES
#-------------------
# String operations
# String addition and assignment operations
a_s = a_s + b_s
print(a_s)
# Assigning to a string with string indexing operation
c_s = a_s[0]
print(c_s)
# --------------------
# Boolean operations
a_b = a_i == b_i and not b_b
print(a_b)
# --------------------
# List operations
a_list = a_list + b_list
c_i = a_list[0]
a_list[1] = 2
# --------------------
# function operations
a_i = f_3(3) + 5
f_1()
f_2()
# --------------------
# class operations
a_i = a_class.add(2)
print(a_i)
a_i = a_class.add(c_class.b_class_i)
print(a_i)

@ -9,8 +9,10 @@ fi
echo "Testing file ${FILENAME}"
echo "Generating .ast.typed file using student parser and reference analyzer"
java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy --pass=sr \
${FILENAME} --out=${FILENAME}.ast.typed
echo "Comparing the pervious output with student parser and student analyzer"
java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy \
--pass=ss --test ${FILENAME}

Loading…
Cancel
Save