Refactored ASTGenerator #3
|
@ -170,7 +170,7 @@ class AstGenerator:
|
|||
if return_value is None:
|
||||
self.generate_expression(return_type)
|
||||
else:
|
||||
self.current_ast_element.append(self.make_literal(return_type, return_value))
|
||||
self.generate_literal(return_type, return_value)
|
||||
|
||||
# return to the parent
|
||||
self.current_ast_element = parent
|
||||
|
@ -377,6 +377,13 @@ class AstGenerator:
|
|||
pass
|
||||
|
||||
def generate_conditional(self):
|
||||
"""
|
||||
@brief generate a conditional statement
|
||||
|
||||
@effects: modifies the current_ast_element
|
||||
|
||||
@return: None
|
||||
"""
|
||||
if self.current_control_flow_nesting_depth >= self.settings['generation-options']['max-nesting-depth']:
|
||||
return
|
||||
|
||||
|
@ -384,24 +391,25 @@ class AstGenerator:
|
|||
'block-termination-probability']:
|
||||
return
|
||||
|
||||
element = build_xml_element([], name=GAZ_IF_TAG)
|
||||
self.current_ast_element.append(element)
|
||||
parent = self.current_ast_element
|
||||
self.current_ast_element = element
|
||||
|
||||
self.make_scoped_element(GAZ_IF_TAG, [])
|
||||
self.current_control_flow_nesting_depth += 1
|
||||
|
||||
self.push_scope()
|
||||
|
||||
self.generate_expression(GAZ_BOOL_KEY)
|
||||
|
||||
self.generate_block(tag=[("type", GAZ_TRUE_BLOCK_TAG)])
|
||||
self.generate_block(tag=[("type", GAZ_TRUE_BLOCK_TAG)]) # FIXME this inhibits elif blocks
|
||||
self.generate_block(tag=[("type", GAZ_FALSE_BLOCK_TAG)])
|
||||
|
||||
self.pop_scope()
|
||||
self.current_ast_element = parent
|
||||
self.current_control_flow_nesting_depth -= 1
|
||||
self.exit_scoped_element(parent)
|
||||
|
||||
def generate_loop(self): # fixme generation of infinite loops happens too often...
|
||||
def generate_loop(self):
|
||||
"""
|
||||
@brief generate a loop
|
||||
|
||||
@return: None
|
||||
"""
|
||||
# FIXME make sure that loop conditions are evaluated at least once (assert true or make a config param)
|
||||
if self.current_control_flow_nesting_depth >= self.settings['generation-options']['max-nesting-depth']:
|
||||
return
|
||||
|
@ -412,35 +420,44 @@ class AstGenerator:
|
|||
|
||||
init_var = self.generate_zero_declaration()
|
||||
parent = self.current_ast_element
|
||||
element = build_xml_element([], name=GAZ_LOOP_TAG)
|
||||
self.current_ast_element.append(element)
|
||||
self.current_ast_element = element
|
||||
|
||||
self.make_scoped_element(GAZ_LOOP_TAG, [])
|
||||
self.current_control_flow_nesting_depth += 1
|
||||
self.push_scope()
|
||||
self.generate_expression(GAZ_BOOL_KEY)
|
||||
|
||||
self.generate_expression(GAZ_BOOL_KEY) # the loop entry condition #TODO force true
|
||||
self.generate_block(block_type=GAZ_LOOP_TAG,
|
||||
loop_var=init_var) # append a variable increment and prepend a break statement if var is > max loop iterations
|
||||
self.pop_scope()
|
||||
self.current_ast_element = parent
|
||||
|
||||
self.current_control_flow_nesting_depth -= 1
|
||||
self.exit_scoped_element(parent)
|
||||
|
||||
def generate_zero_declaration(self):
|
||||
"""
|
||||
@brief generate a declaration int a = 0 for some a
|
||||
|
||||
@return: None
|
||||
"""
|
||||
parent = self.current_ast_element
|
||||
element = build_xml_element([], name=GAZ_DECLARATION_TAG)
|
||||
|
||||
self.current_ast_element.append(element)
|
||||
self.current_ast_element = element
|
||||
self.make_element(GAZ_DECLARATION_TAG, [])
|
||||
|
||||
# Initialize variable
|
||||
variable = self.generate_variable(GAZ_INT_KEY, 'var')
|
||||
self.current_ast_element.append(variable.xml)
|
||||
self.current_scope.append(variable.name, variable)
|
||||
|
||||
self.generate_xhs(GAZ_RHS_TAG, variable.type, is_zero=True)
|
||||
|
||||
self.current_ast_element = parent
|
||||
|
||||
return variable
|
||||
|
||||
def generate_assignment(self):
|
||||
"""
|
||||
@brief generate an assignment
|
||||
|
||||
@return: None
|
||||
"""
|
||||
possible_vars = self.current_scope.get_all_defined_mutable_vars()
|
||||
if len(possible_vars) == 0:
|
||||
raise ValueError("No possible variables to assign to!")
|
||||
|
@ -448,9 +465,7 @@ class AstGenerator:
|
|||
# same structure as a declaration
|
||||
parent = self.current_ast_element
|
||||
|
||||
element = build_xml_element([], name=GAZ_ASSIGNMENT_TAG)
|
||||
self.current_ast_element.append(element)
|
||||
self.current_ast_element = element
|
||||
self.make_element(GAZ_ASSIGNMENT_TAG, [])
|
||||
|
||||
variable = random.choice(possible_vars)
|
||||
|
||||
|
@ -466,29 +481,48 @@ class AstGenerator:
|
|||
self.generate_stream(GAZ_IN_STREAM)
|
||||
|
||||
def generate_stream(self, stream_type):
|
||||
"""
|
||||
@brief generate a stream statment from a stream type
|
||||
|
||||
@param stream_type: whether the stream is an input or output
|
||||
@return:
|
||||
"""
|
||||
parent = self.current_ast_element
|
||||
|
||||
args = [
|
||||
("type", stream_type),
|
||||
]
|
||||
element = build_xml_element(args, name=GAZ_STREAM_TAG)
|
||||
self.current_ast_element.append(element)
|
||||
self.current_ast_element = element
|
||||
|
||||
self.make_element(GAZ_STREAM_TAG, args)
|
||||
self.generate_expression(ANY_TYPE)
|
||||
|
||||
self.current_ast_element = parent
|
||||
|
||||
def generate_variable(self, var_type: str, mut=None):
|
||||
"""
|
||||
@brief generate a variable
|
||||
|
||||
@param var_type: they type of the variable
|
||||
@param mut: mutability of the variable
|
||||
@return: None
|
||||
"""
|
||||
if mut is None:
|
||||
return Variable(self.get_name(GAZ_VAR_TAG), var_type, self.get_qualifier())
|
||||
else:
|
||||
return Variable(self.get_name(GAZ_VAR_TAG), var_type, mut)
|
||||
|
||||
def generate_literal(self, var_type: str, value=None):
|
||||
"""
|
||||
@brief generate a literal
|
||||
|
||||
@param var_type: Type of the literal
|
||||
@param value: optional value of the literal
|
||||
@return: None
|
||||
"""
|
||||
if value is None:
|
||||
value = self.get_value(var_type)
|
||||
else:
|
||||
value = value
|
||||
|
||||
args = [
|
||||
("type", var_type),
|
||||
("value", str(value)),
|
||||
|
@ -496,7 +530,7 @@ class AstGenerator:
|
|||
element = build_xml_element(args, name=GAZ_LIT_TAG)
|
||||
self.current_ast_element.append(element)
|
||||
|
||||
def make_literal(self, type, value):
|
||||
def make_literal(self, type, value): # TODO eliminate this function
|
||||
args = [
|
||||
("type", type),
|
||||
("value", value),
|
||||
|
@ -505,6 +539,11 @@ class AstGenerator:
|
|||
return element
|
||||
|
||||
def generate_global(self):
|
||||
"""
|
||||
@brief generate a global const declaration
|
||||
|
||||
@return: None
|
||||
"""
|
||||
current_scope = self.current_scope
|
||||
current_element = self.current_ast_element
|
||||
|
||||
|
@ -517,6 +556,13 @@ class AstGenerator:
|
|||
self.current_ast_element = current_element
|
||||
|
||||
def generate_expression(self, expr_type: str, is_zero=False):
|
||||
"""
|
||||
@brief generate an expression
|
||||
|
||||
@param expr_type: the type of the expression
|
||||
@param is_zero: if the expression should eval to 0
|
||||
@return: None
|
||||
"""
|
||||
if is_zero:
|
||||
self.generate_literal(expr_type, value=0)
|
||||
return
|
||||
|
@ -530,11 +576,17 @@ class AstGenerator:
|
|||
elif expr_type == GAZ_CHAR_KEY:
|
||||
self.generate_char_expr()
|
||||
elif expr_type == ANY_TYPE: # TODO implement the choice of any type
|
||||
self.generate_int_expr()
|
||||
ty = self.get_type(GAZ_RHS_TAG)
|
||||
self.generate_expression(ty)
|
||||
else:
|
||||
raise NotImplementedError(f"Expression type {expr_type} not implemented")
|
||||
|
||||
def generate_routine_args(self):
|
||||
def generate_routine_args(self) -> list[Argument]:
|
||||
"""
|
||||
@brief generate a list of arguments for a routine
|
||||
|
||||
@return: a list of arguments
|
||||
"""
|
||||
number = random.randint(self.settings['properties']['number-of-arguments']['min'],
|
||||
self.settings['properties']['number-of-arguments']['max'])
|
||||
args = []
|
||||
|
@ -701,7 +753,7 @@ class AstGenerator:
|
|||
# add the check 'if loop_var >= self.settings['generation_options']['max-loop-iterations']: break'
|
||||
operation = build_xml_element([("op", ">=")], name=GAZ_OPERATOR_TAG)
|
||||
rhs = self._loop_heloper(loop_var, operation)
|
||||
rhs.append(
|
||||
rhs.append( # TODO refactor this to use generate_literal instead of make_literal
|
||||
self.make_literal(GAZ_INT_KEY, "'" + str(self.settings['generation-options']['max-loop-iterations']) + "'"))
|
||||
|
||||
true_block = build_xml_element([], name=GAZ_BLOCK_TAG)
|
||||
|
@ -742,7 +794,7 @@ class AstGenerator:
|
|||
|
||||
operation = build_xml_element([("op", "+")], name=GAZ_OPERATOR_TAG)
|
||||
rhs = self._loop_heloper(loop_var, operation)
|
||||
rhs.append(self.make_literal(GAZ_INT_KEY, '1'))
|
||||
rhs.append(self.make_literal(GAZ_INT_KEY, '1')) # TODO refactor this to use generate_literal instead of make_literal
|
||||
|
||||
# return everything to normalcy
|
||||
self.current_ast_element = parent
|
||||
|
@ -814,4 +866,3 @@ class AstGenerator:
|
|||
self.generate_binary(op, random.choice([GAZ_INT_KEY, GAZ_FLOAT_KEY]))
|
||||
else:
|
||||
self.generate_binary(op, random.choice(expr_type))
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
import random
|
||||
import sys
|
||||
import warnings
|
||||
from contextlib import redirect_stdout
|
||||
|
||||
|
@ -30,10 +31,11 @@ class Fuzzer():
|
|||
os.mkdir("fuzzer")
|
||||
os.mkdir("fuzzer/input")
|
||||
os.mkdir("fuzzer/debug")
|
||||
os.mkdir("fuzzer/debug/ast")
|
||||
os.mkdir("fuzzer/debug/ast_err")
|
||||
os.mkdir("fuzzer/instream")
|
||||
os.mkdir("fuzzer/outputs")
|
||||
os.mkdir("fuzzer/ground_truth")
|
||||
os.system("cp tester_config.json fuzzer/tester_config.json")
|
||||
for i in range(self.batch):
|
||||
try:
|
||||
self.fuzzer.fuzz()
|
||||
|
@ -42,7 +44,7 @@ class Fuzzer():
|
|||
warnings.warn("None Tag Exception encountered, writing stack trace and xml to debug/ast/{}.xml\n"
|
||||
"Look for a top-level <argument> tag or send it to Ayrton and I'll see what I can see"
|
||||
"".format(r))
|
||||
with open("fuzzer/debug/ast/{}.xml".format(r), 'w') as f:
|
||||
with open("fuzzer/debug/ast_err/{}.xml".format(r), 'w') as f:
|
||||
f.write(xml.dom.minidom.parseString(ET.tostring(self.fuzzer.ast).decode('utf-8')).toprettyxml())
|
||||
continue
|
||||
dom = xml.dom.minidom.parseString(ET.tostring(self.fuzzer.ast).decode('utf-8'))
|
||||
|
@ -58,9 +60,16 @@ class Fuzzer():
|
|||
except (OverflowError, ZeroDivisionError, ValueError):
|
||||
os.system("rm -f fuzzer/ground_truth/{}_{}.py".format(self.file_name, i))
|
||||
continue
|
||||
except KeyboardInterrupt:
|
||||
r = random.randint(0, 1000000)
|
||||
warnings.warn("Execution halted, result written to debug/ast/{}.xml\n"
|
||||
"".format(r))
|
||||
with open("fuzzer/debug/ast_err/{}.xml".format(r), 'w') as f:
|
||||
f.write(xml.dom.minidom.parseString(ET.tostring(self.fuzzer.ast).decode('utf-8')).toprettyxml())
|
||||
sys.exit(1)
|
||||
with open("fuzzer/input/{}_{}.in".format(self.file_name, i), 'w') as f:
|
||||
f.write(self.fuzzer.source)
|
||||
with open("fuzzer/debug/{}_{}.out".format(self.file_name, i), 'w') as f:
|
||||
with open("fuzzer/debug/{}_{}.xml".format(self.file_name, i), 'w') as f:
|
||||
f.write(pretty)
|
||||
# y.write(self.fuzzer.out)
|
||||
# with open("fuzzer/instream/{}.in".format(i), 'w') as f:
|
||||
|
|
36
tester_config.json
Normal file
36
tester_config.json
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"inDir": "<inDir>",
|
||||
"outDir": "<outDir>",
|
||||
"inStrDir": "<inStrDir>",
|
||||
"testedExecutablePaths": {
|
||||
"<team id>": "<path_to_gazc_exe>"
|
||||
},
|
||||
"runtimes": {
|
||||
"<team id>": "<path_to_libgazrt.so>"
|
||||
},
|
||||
"toolchains": {
|
||||
"gazprea": [
|
||||
{
|
||||
"stepName": "gazc",
|
||||
"executablePath": "$EXE",
|
||||
"arguments": [
|
||||
"$INPUT",
|
||||
"$OUTPUT"
|
||||
],
|
||||
"output": "gazc.ll",
|
||||
"allowError": true
|
||||
},
|
||||
{
|
||||
"stepName": "lli",
|
||||
"executablePath": "/cshome/cmput415/415-resources/llvm-project/build/bin/lli",
|
||||
"arguments": [
|
||||
"$INPUT"
|
||||
],
|
||||
"output": "-",
|
||||
"usesRuntime": true,
|
||||
"usesInStr": true,
|
||||
"allowError": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue