Added student test cases

master
Sanjar Ahmadov 3 years ago
parent ec9d922729
commit dddb026b51

@ -5,12 +5,14 @@
<br> <br>
## Passes: ## Passes:
- First Pass: Creates the symbol tables and adds all the elements of the program to the symbol table. The first step is creating the basic table symbol, which is the parent(root) of the symbol table structure(which forms a tree-like structure). Classes for Object, int, bool and str are added to this symbol table. This table contains the global declarations. At each level of scope, we create a symbol table which points to the parent symbol table. Variables, functions and classes are added to the appropriate symbol table according to the scope. - First Pass: Creates the symbol tables and adds all the elements of the program to the symbol table. The first step is creating the basic table symbol, which is the parent(root) of the symbol table structure(which forms a tree-like structure). Classes for Object, int, bool and str are added to this symbol table. This table contains the global declarations. At each level of scope, we create a symbol table which points to the parent symbol table. Variables, functions and classes are added to the appropriate symbol table according to the scope.
- Second Pass: At each node of the abstract syntax tree, the types are identified and populated. - Second Pass: At each node of the abstract syntax tree, the types are identified and populated.
## Recovery: ## Recovery:
- -
## Challenges: ## 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. - 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: ## Improvements:
- Added more tests to rigorously check program flow and indentation. - Added more tests to rigorously check program flow and indentation.

@ -1,14 +1,93 @@
x:int = 1 # class defs
x:int = 2 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: class B_CLASS(object):
if True: b_class_i:int = 0
if True:
return True
# All path should return, not just one
class C_CLASS(B_CLASS):
pass
fun_1() # 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
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
# Bad return
return a_i

@ -1,5 +1,111 @@
x:int = True # class defs
x + [1] 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 defs
class Foo(object): class A_CLASS(object):
x:int = 0 a_class_i:int = 0
def __init__(self:"A_CLASS", x:int):
def __init__(self:"Foo", x:int):
self.x = x self.x = x
def bar(y:int): def add(self:"A_CLASS", y:int) -> int:
print("Hello World!",self.x+y) y = y+self.x
y = 10 return y
def get_stones(name:str)->str: class B_CLASS(object):
def map_name(nm:str)->str: b_class_i:int = 0
return stones[color.index(nm)]
color=["Red","Blue"] class C_CLASS(B_CLASS):
stones=["Mind","Soul"] pass
return map_name(name)
# var defs
def funa(): a_s:str = "a_s"
def funb(): b_s:str = "b_s"
print("Hello") c_s:str = "c_s"
funb()
a_i:int = 0
def fund(): b_i:int = 0
def fune(): c_i:int = 0
print("Hello")
c = 4 + 5 a_b:bool = False
b_b:bool = False
def funf(): c_b:bool = False
def fung():
print("Hello") a_list:[int] = None
c = 6 b_list:[int] = None
c = 4 + 5 c_list:[int] = None
a_class:A_CLASS = None
if True: b_class:B_CLASS = None
if True: c_class:C_CLASS = None
if True:
print("Hello")
print("World") # fun defs
def f_1() -> object:
if True: def f_f_1() -> object:
if True: global a_s
if True: print(a_s)
print("Hello") pass
print("World") pass
if True: def f_2() -> object:
if True: f_a_s:str = "s"
if True: def f_f_2() -> object:
print("Hello") nonlocal f_a_s
print("World") print(f_a_s)
pass
if True: pass
if True:
if True: def f_3(x:int) -> int:
print("Hello") f_b_s:int = 3
else: return x*f_b_s
print("World")
# Declarations
if True: a_list = [1, 2, 3]
if True: b_list = [0, 0, 0]
if True: c_list = [-1, -2, -3]
print("Hello")
else: a_class = A_CLASS(5)
print("World") b_class = B_CLASS()
c_class = C_CLASS()
f = Foo(1) # POSITIVE TEST CASES
print(f.x)
f.bar(4) #-------------------
# String operations
a=[[[1],[2]],[[3],[4]]] # String addition and assignment operations
print(a[0][0][1]*a[1][1][0]) a_s = a_s + b_s
print(a_s)
multiline_string="Hi World,\
Here I am" # Assigning to a string with string indexing operation
c_s = a_s[0]
expr_precedence = -a + b * (c + d) print(c_s)
stone="Blue"
print(get_stones(stone)) # --------------------
# 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 "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 \ java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy --pass=sr \
${FILENAME} --out=${FILENAME}.ast.typed ${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 \ java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy \
--pass=ss --test ${FILENAME} --pass=ss --test ${FILENAME}

Loading…
Cancel
Save