Commit 7bbce441 authored by Sergio Costas's avatar Sergio Costas

Moved the loop outside the function that checks the current statement. This...

Moved the loop outside the function that checks the current statement. This allows to fully remove all recursion, thus preventing failures in case of too much deep recursion.
parent c2310236
......@@ -429,7 +429,7 @@ class crusty(object):
options = self._eval_assignment(assignment.child2,var_container,function_container)
newoptions = []
for option in options:
retval = self._check_assignment(var_defined,[option],varname,assignment.child1[0],None,0,function_container)
retval = self._check_assignment(var_defined,option,varname,assignment.child1[0],None,function_container)
newoptions.append( (option[0],retval,option[2],option[3]) )
return newoptions
else:
......@@ -560,7 +560,7 @@ class crusty(object):
self._process_block(node.child1,tmpvars, function_container)
def _check_assignment(self,var_defined,options,varname,node,tree,counter,function_container):
def _check_assignment(self,var_defined,option,varname,node,tree,function_container):
this_is_crust = self.TYPE_CRUST if self._check_variable_properties(var_defined, self.PROPERTY_CRUST_VARIABLE) else self.TYPE_NO_CRUST
if self._check_variable_properties(var_defined,self.PROPERTY_ARRAY):
......@@ -568,16 +568,9 @@ class crusty(object):
if self._check_variable_properties(var_defined,self.PROPERTY_STRUCT) and (node.right is not None):
this_is_crust = self.TYPE_NO_MATTER
error_list = []
if len(options) > 1:
for option in options[1:]:
# create a new "execution thread" for each possible assignment value
if (option[2] != self.TYPE_NO_MATTER) and (this_is_crust != self.TYPE_NO_MATTER) and (option[2] != this_is_crust):
error_list.append( (this_is_crust,option[3],varname,node.line) )
newvar_container = option[1]
self._set_var_value(newvar_container,varname,option[0],node.line)
self._process_block(tree[counter+1:],newvar_container,function_container)
if (options[0][2] != self.TYPE_NO_MATTER) and (this_is_crust != self.TYPE_NO_MATTER) and (options[0][2] != this_is_crust):
error_list.append( (this_is_crust,options[0][3],varname,node.line) )
if (option[2] != self.TYPE_NO_MATTER) and (this_is_crust != self.TYPE_NO_MATTER) and (option[2] != this_is_crust):
error_list.append( (this_is_crust,option[3],varname,node.line) )
for error_element in error_list:
if error_element[0] == self.TYPE_CRUST:
if error_element[1] is None:
......@@ -585,69 +578,98 @@ class crusty(object):
else:
self._add_error(self.MSG_CRITICAL,"Assigning the non-crust variable '{:s}' to the crust variable '{:s}' at line {:d}",error_element[1],error_element[2],error_element[3])
else:
if options[0][3] is None:
if option[3] is None:
self._add_error(self.MSG_CRITICAL,"Assigning a crust pointer to the non-crust variable '{:s}' at line {:d}",error_element[2],error_element[3])
else:
self._add_error(self.MSG_CRITICAL,"Assigning the crust pointer '{:s}' to the non-crust variable '{:s}' at line {:d}",error_element[1],error_element[2],error_element[3])
var_container = options[0][1]
self._set_var_value(var_container,varname,options[0][0],node.line)
var_container = option[1]
self._set_var_value(var_container,varname,option[0],node.line)
return var_container
def _check_return_block(self,tree,var_container):
if len(tree) == 0:
return [(None,None)]
else:
return [(tree,var_container)]
def _process_block(self, tree, var_container, function_container):
for counter in range(len(tree)):
node = tree[counter]
if (node.type == "TYPE_SPECIFIER"):
if (node.enum_data is not None):
self._process_enum(node,var_container)
continue
if node.type == "CRUSTY_DEBUG":
print("Debug: '{:s}'".format(str(var_container)))
continue
if node.type == "START_BLOCK":
# append a new block for the variables created inside this block
var_container.insert(0,{})
continue
if node.type == "END_BLOCK":
# remove the last block of variables
var_container = var_container[1:]
continue
if node.type == "EMPTY_DECLARATOR":
continue
if node.type == "VARIABLE_DEFINITION":
if not node.t_typedef:
varname = node.name
var_defined = {"properties":self._get_variable_properties(node,False), "status":crusty.STATUS_UNINITIALIZED, "init_line": None, "pointer": node.pointer, "enum": False }
var_container[0][node.name] = var_defined
if node.assignment is not None:
var_defined["init_line"] = node.line
options = self._eval_assignment(node.assignment,var_container,function_container)
var_container = self._check_assignment(var_defined,options,varname,node,tree,counter,function_container)
continue
if node.type == "=":
varname = node.child1[0].name
var_defined = self._find_variable(var_container,varname,node.line)
options = self._eval_assignment(node.child2,var_container,function_container)
var_container = self._check_assignment(var_defined,options,varname,node.child1[0],tree,counter,function_container)
continue
if node.type == "FUNCTION_CALL":
function_params = self._find_function(function_container,node.name,node.line)
if ((function_params[0][0] & self.PROPERTY_CRUST_VARIABLE) != 0) and (function_params[0][1] == 1):
self._add_error(self.MSG_ERROR,"Calling the function '{:s}' at line {:d}, but ignoring the crust-type return value",node.name,node.line)
options = self._eval_function_call(node,var_container,function_container)
if len(options) > 1:
for option in options[1:]:
self._process_block(tree[counter+1:],option[1],function_container)
var_container = options[0][1]
continue
# if node.type == "FOR":
# print("Tipo: {:s}; Nombre: {:s}".format(str(node.type),str(node.name)))
# b1,b2 = lib.get_next_block(tree[counter+1:])
# process_nodes(b1,False,var_container,function_container, tabs+1)
# print()
# print()
# process_nodes(b2,False,var_container,function_container, tabs)
#
# break
print("Tipo: {:s}; Nombre: {:s}".format(str(node.type),str(node.name)))
blocks = [ (tree,var_container) ]
while len(blocks) > 0:
current_block = blocks[0]
blocks = blocks[1:]
if current_block[0] is not None:
retval = self._process_block2(current_block[0],current_block[1],function_container)
blocks += retval
def _process_block2(self, tree, var_container, function_container):
node = tree[0]
if (node.type == "TYPE_SPECIFIER"):
if (node.enum_data is not None):
self._process_enum(node,var_container)
return self._check_return_block(tree[1:],var_container)
if node.type == "CRUSTY_DEBUG":
print("Debug: '{:s}'".format(str(var_container)))
return self._check_return_block(tree[1:],var_container)
if node.type == "START_BLOCK":
# append a new block for the variables created inside this block
var_container.insert(0,{})
return self._check_return_block(tree[1:],var_container)
if node.type == "END_BLOCK":
# remove the last block of variables
var_container = var_container[1:]
return self._check_return_block(tree[1:],var_container)
if node.type == "EMPTY_DECLARATOR":
return self._check_return_block(tree[1:],var_container)
if node.type == "VARIABLE_DEFINITION":
if not node.t_typedef:
varname = node.name
var_defined = {"properties":self._get_variable_properties(node,False), "status":crusty.STATUS_UNINITIALIZED, "init_line": None, "pointer": node.pointer, "enum": False }
var_container[0][node.name] = var_defined
if node.assignment is not None:
var_defined["init_line"] = node.line
options = self._eval_assignment(node.assignment,var_container,function_container)
retvals = []
for option in options:
new_var_container = self._check_assignment(var_defined,option,varname,node,tree,function_container)
retvals += self._check_return_block(tree[1:],new_var_container)
return retvals
else:
return self._check_return_block(tree[1:],var_container)
if node.type == "=":
varname = node.child1[0].name
var_defined = self._find_variable(var_container,varname,node.line)
options = self._eval_assignment(node.child2,var_container,function_container)
retvals = []
for option in options:
new_var_container = self._check_assignment(var_defined,option,varname,node.child1[0],tree,function_container)
retvals += self._check_return_block(tree[1:],new_var_container)
return retvals
if node.type == "FUNCTION_CALL":
function_params = self._find_function(function_container,node.name,node.line)
if ((function_params[0][0] & self.PROPERTY_CRUST_VARIABLE) != 0) and (function_params[0][1] == 1):
self._add_error(self.MSG_ERROR,"Calling the function '{:s}' at line {:d}, but ignoring the crust-type return value",node.name,node.line)
options = self._eval_function_call(node,var_container,function_container)
retvals = []
for option in options:
retvals += self._check_return_block(tree[1:],option[1])
return retvals
#if node.type == "IF":
#retvals = self._eval_condition(node.condition,var_container,function_container)
#continue
# if node.type == "FOR":
# print("Tipo: {:s}; Nombre: {:s}".format(str(node.type),str(node.name)))
# b1,b2 = lib.get_next_block(tree[counter+1:])
# process_nodes(b1,False,var_container,function_container, tabs+1)
# print()
# print()
# process_nodes(b2,False,var_container,function_container, tabs)
#
# break
print("Tipo: {:s}; Nombre: {:s}".format(str(node.type),str(node.name)))
return self._check_return_block(tree[1:],var_container)
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