Commit 313c3bc5 authored by Sergio Costas's avatar Sergio Costas

Added WHILE support and one test

parent e816ecca
......@@ -212,7 +212,7 @@ class crust(object):
def _copy_container(self,container):
""" Fully copies a var_container to allow several parallel emulations """
retval = {"debug_level": container["debug_level"], "variables": []}
retval = {"debug_level": container["debug_level"], "loop_level": container["loop_level"], "variables": []}
for element in container["variables"]:
vargroup = {}
for varname in element:
......@@ -798,7 +798,7 @@ class crust(object):
def process_tree(self,tree):
""" Process the main tree with the global variables and the function definitions and declarations """
var_container = { "variables": [ {} ], "debug_level": 0}
var_container = { "variables": [ {} ], "debug_level": 0, "loop_level": 0}
# First fill all the global variables and the function declarations
for node in tree:
if (node.type == "TYPE_SPECIFIER"):
......@@ -874,6 +874,7 @@ class crust(object):
def _process_block(self, tree, var_container):
var_container["debug_level"] = 0
var_container["loop_level"] = 0
if tree[0].type == "START_BLOCK":
tree = tree[1:] # the variable block has been already added
blocks = [ (tree,var_container) ]
......@@ -1025,5 +1026,73 @@ class crust(object):
var_container["variables"] = var_container["variables"][1:]
return [(None,None)]
if node.type == "BREAK":
if var_container["loop_level"] == 0:
self._add_error(var_container,self.MSG_CRITICAL,"Break not in a loop at line {:d}",node.line)
return [(None,None)]
while(tree[0].type != "ENDLOOP"):
tree = tree[1:]
return [self._check_return_block(tree,var_container)]
if node.type == "END_LOOP":
var_container["loop_level"] -= 1
return [self._check_return_block(tree[1:],var_container)]
if node.type == "WHILE":
var_container["loop_level"] += 1
condition = node.condition[0]
wblock, other_block = self._get_next_block(tree[1:])
retvals = []
if not node.t_crust_no_zero:
# loop executed zero times
retvals += self._check_return_block([self._new_eval_false(condition)] + other_block[:], self._copy_container(var_container) )
# loop executed one time
retvals += self._check_return_block([self._new_start_block(), self._new_eval_true(condition)] + wblock[1:-1] + [self._new_eval_false(condition), self._new_end_block(), self._new_end_loop()] + other_block[:], self._copy_container(var_container))
# loop executed two times
retvals += self._check_return_block([self._new_start_block(), self._new_eval_true(condition)] + wblock[1:-1] + [self._new_eval_true(condition)] + wblock[1:-1] + [self._new_eval_false(condition), self._new_end_block(), self._new_end_loop()] + other_block[:], self._copy_container(var_container))
return retvals
if (node.type == "EVAL_TRUE") or (node.type == "EVAL_FALSE"):
values = self._eval_assignment(node.condition,var_container,True)
retvals = []
for value in values:
if (node.type == "EVAL_TRUE") and (value[4] == self.CONDITION_FALSE):
continue
if (node.type == "EVAL_FALSE") and (value[4] == self.CONDITION_TRUE):
continue
retvals += self._check_return_block(tree[1:],self._copy_container(value[1]))
if len(retvals) == 0:
return [(None,None)]
else:
return retvals
print("Tipo: {:s}; Nombre: {:s}; Linea: {:s}".format(str(node.type),str(node.name),str(node.line)))
return self._check_return_block(tree[1:],var_container)
def _new_start_block(self):
node = self.AST_node()
node.type = "START_BLOCK"
return node
def _new_end_block(self):
node = self.AST_node()
node.type = "END_BLOCK"
return node
def _new_end_loop(self):
node = self.AST_node()
node.type = "END_LOOP"
return node
def _new_eval_false(self,condition):
node = self.AST_node()
node.type = "EVAL_FALSE"
node.condition = condition.copy()
return node
def _new_eval_true(self,condition):
node = self.AST_node()
node.type = "EVAL_TRUE"
node.condition = condition.copy()
return node
......@@ -54,7 +54,6 @@ void add_type_element(char *);
%token START_BLOCK
%token END_BLOCK
%token TYPENAME_IDENTIFIER
%token ENDLOOP
//%start translation_unit
%start start_unit
......@@ -801,22 +800,19 @@ iteration_statement
: while_statement '(' expression ')' statement { $$ = $1;
$$->condition = $3;
append_next_with_blocks($$,$5);
append_next_leaf($$,ENDLOOP,-1);
free_tree($2);
free_tree($4); }
| DO statement WHILE '(' expression ')' ';' { $$ = $1;
$$->condition = $5;
append_next_with_blocks($$,$2);
append_next_leaf($$,ENDLOOP,-1);
free_tree($3);
free_tree($4);
free_tree($6);
free_tree($7); }
| for_statement '(' expression_statement expression_statement ')' statement { $$ = $1;
| for_statement '(' expression_statement expression_statement ')' statement { $$ = $1;
$$->for_ch1 = $3;
$$->for_ch2 = $4;
append_next_with_blocks($$,$6);
append_next_leaf($$,ENDLOOP,-1);
free_tree($2);
free_tree($5); }
| for_statement '(' expression_statement expression_statement expression ')' statement { $$ = $1;
......@@ -824,22 +820,19 @@ iteration_statement
$$->for_ch2 = $4;
$$->for_ch3 = $5;
append_next_with_blocks($$,$7);
append_next_leaf($$,ENDLOOP,-1);
free_tree($2);
free_tree($6); }
| for_statement '(' declaration expression_statement ')' statement { $$ = $1;
| for_statement '(' declaration expression_statement ')' statement { $$ = $1;
$$->for_ch1 = $3;
$$->for_ch2 = $4;
append_next_with_blocks($$,$6);
append_next_leaf($$,ENDLOOP,-1);
free_tree($2);
free_tree($5); }
| for_statement '(' declaration expression_statement expression ')' statement { $$ = $1;
| for_statement '(' declaration expression_statement expression ')' statement { $$ = $1;
$$->for_ch1 = $3;
$$->for_ch2 = $4;
$$->for_ch3 = $5;
append_next_with_blocks($$,$7);
append_next_leaf($$,ENDLOOP,-1);
free_tree($2);
free_tree($6); }
;
......
......@@ -383,5 +383,11 @@ class Test(unittest.TestCase):
def testFunctionPointerReturnsCrust2(self):
self._generic_test("unitest/test95.c",[ (crust.crust.MSG_ERROR,"Calling the function '{:s}' at line {:d}, but ignoring the crust-type return value","test1",9) ])
def testBreakOutsideLoop(self):
self._generic_test("unitest/test96.c",[ (crust.crust.MSG_CRITICAL,"Break not in a loop at line {:d}",2) ])
def testWhileFreesTwice(self):
self._generic_test("unitest/test97.c",[ (crust.crust.MSG_ERROR,"Parameter {:d} when calling function '{:s}' at line {:d} was freed at line {:d}",1,"main",10,10) ])
if __name__ == '__main__':
unittest.main()
void main() {
break;
}
typedef __crust_t__ unsigned char *crust_t;
#define NULL ((void *)0)
void main(crust_t param) {
int b = 0;
while(b == 0) {
main(param);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment