def _new_var_entry(parent, var, full_entry=True): ############################################################################### """Create a variable sub-element of <parent> with information from <var>. If <full_entry> is False, only include standard name and intent. """ prop_list = ["intent"] if full_entry: prop_list.extend([ "allocatable", "active", "default_value", "diagnostic_name", "diagnostic_name_fixed", "kind", "persistence", "polymorphic", "protected", "state_variable", "type", "units" ]) prop_list.extend(Var.constituent_property_names()) # end if ventry = ET.SubElement(parent, "var") ventry.set("name", var.get_prop_value("standard_name")) for prop in prop_list: value = var.get_prop_value(prop) if value: ventry.set(prop, str(value)) # end if # end for if full_entry: dims = var.get_dimensions() if dims: dim_entry = ET.SubElement(ventry, "dimensions") dim_entry.text = " ".join(dims)
def _new_var(self, standard_name, units, dimensions, vtype, vkind=''): """Create and return a new Var object with the requested properties""" context = ParseContext(linenum=self.__linenum, filename="foo.meta") source = ParseSource("foo", "host", context) prop_dict = {'local_name' : f"foo{self.__linenum}", 'standard_name' : standard_name, 'units' : units, 'dimensions' : f"({', '.join(dimensions)})", 'type' : vtype, 'kind' : vkind} self.__linenum += 5 return Var(prop_dict, source, self.__run_env)
def add_constituent_vars(cap, host_model, suite_list, logger): ############################################################################### """Create a DDT library containing array reference variables for each constituent field for all suites in <suite_list>. Create and return a dictionary containing an index variable for each of the constituents as well as the variables from the DDT object. Also, write declarations for these variables to <cap>. Since the constituents are in a DDT (ccpp_constituent_properties_t), create a metadata table with the required information, then parse it to create the dictionary. """ # First create a MetadataTable for the constituents DDT stdname_layer = "ccpp_constituents_num_layer_consts" stdname_interface = "ccpp_constituents_num_interface_consts" stdname_2d = "ccpp_constituents_num_2d_consts" horiz_dim = "horizontal_dimension" vert_layer_dim = "vertical_layer_dimension" vert_interface_dim = "vertical_interface_dimension" array_layer = "vars_layer" array_interface = "vars_interface" array_2d = "vars_2d" # Table preamble (leave off ccpp-table-properties header) ddt_mdata = [ #"[ccpp-table-properties]", " name = {}".format(CONST_DDT_NAME), " type = ddt", "[ccpp-arg-table]", " name = {}".format(CONST_DDT_NAME), " type = ddt", "[ num_layer_vars ]", " standard_name = {}".format(stdname_layer), " units = count", " dimensions = ()", " type = integer", "[ num_interface_vars ]", " standard_name = {}".format(stdname_interface), " units = count", " dimensions = ()", " type = integer", "[ num_2d_vars ]", " standard_name = {}".format(stdname_2d), " units = count", " dimensions = ()", " type = integer", "[ {} ]".format(array_layer), " standard_name = ccpp_constituents_array_of_layer_consts", " units = none", " dimensions = ({}, {}, {})".format(horiz_dim, vert_layer_dim, stdname_layer), " type = real", " kind = kind_phys", "[ {} ]".format(array_interface), " standard_name = ccpp_constituents_array_of_interface_consts", " units = none", " dimensions = ({}, {}, {})".format(horiz_dim, vert_interface_dim, stdname_interface), " type = real", " kind = kind_phys", "[ {} ]".format(array_2d), " standard_name = ccpp_constituents_array_of_2d_consts", " units = none", " dimensions = ({}, {})".format(horiz_dim, stdname_2d), " type = real", " kind = kind_phys"] # Add entries for each constituent (once per standard name) const_stdnames = set() for suite in suite_list: if logger is not None: lmsg = "Adding constituents from {} to {}" logger.debug(lmsg.format(suite.name, host_model.name)) # end if scdict = suite.constituent_dictionary() for cvar in scdict.variable_list(): std_name = cvar.get_prop_value('standard_name') if std_name not in const_stdnames: # Add a metadata entry for this constituent # Check dimensions and figure vertical dimension # Currently, we only support variables with first dimension, # horizontal_dimension, and second (optional) dimension, # vertical_layer_dimension or vertical_interface_dimension dims = cvar.get_dimensions() if (len(dims) < 1) or (len(dims) > 2): emsg = "Unsupported constituent dimensions, '{}'" dimstr = "({})".format(", ".join(dims)) raise CCPPError(emsg.format(dimstr)) # end if hdim = dims[0].split(':')[-1] if hdim != 'horizontal_dimension': emsg = "Unsupported first constituent dimension, '{}', " emsg += "must be 'horizontal_dimension'" raise CCPPError(emsg.format(hdim)) # end if if len(dims) > 1: vdim = dims[1].split(':')[-1] if vdim == vert_layer_dim: cvar_array_name = array_layer elif vdim == vert_interface_dim: cvar_array_name = array_interface else: emsg = "Unsupported vertical constituent dimension, " emsg += "'{}', must be '{}' or '{}'" raise CCPPError(emsg.format(vdim, vert_layer_dim, vert_interface_dim)) # end if else: cvar_array_name = array_2d # end if # First, create an index variable for <cvar> ind_std_name = "index_of_{}".format(std_name) loc_name = "{}(:,:,{})".format(cvar_array_name, ind_std_name) ddt_mdata.append("[ {} ]".format(loc_name)) ddt_mdata.append(" standard_name = {}".format(std_name)) units = cvar.get_prop_value('units') ddt_mdata.append(" units = {}".format(units)) dimstr = "({})".format(", ".join(dims)) ddt_mdata.append(" dimensions = {}".format(dimstr)) vtype = cvar.get_prop_value('type') vkind = cvar.get_prop_value('kind') ddt_mdata.append(" type = {} | kind = {}".format(vtype, vkind)) const_stdnames.add(std_name) # end if # end for # end for # Parse this table using a fake filename parse_obj = ParseObject("{}_constituent_mod.meta".format(host_model.name), ddt_mdata) ddt_table = MetadataTable(parse_object=parse_obj, logger=logger) ddt_name = ddt_table.sections()[0].title ddt_lib = DDTLibrary('{}_constituent_ddtlib'.format(host_model.name), ddts=ddt_table.sections(), logger=logger) # A bit of cleanup del parse_obj del ddt_mdata # Now, create the "host constituent module" dictionary const_dict = VarDictionary("{}_constituents".format(host_model.name), parent_dict=host_model) # Add in the constituents object prop_dict = {'standard_name' : "ccpp_model_constituents_object", 'local_name' : constituent_model_object_name(host_model), 'dimensions' : '()', 'units' : "None", 'ddt_type' : ddt_name} const_var = Var(prop_dict, _API_SOURCE) const_var.write_def(cap, 1, const_dict) ddt_lib.collect_ddt_fields(const_dict, const_var) # Declare variable for the constituent standard names array max_csname = max([len(x) for x in const_stdnames]) if const_stdnames else 0 num_const_fields = len(const_stdnames) cs_stdname = constituent_model_const_stdnames(host_model) const_list = sorted(const_stdnames) if const_list: const_strs = ['"{}{}"'.format(x, ' '*(max_csname - len(x))) for x in const_list] cs_stdame_initstr = " = (/ " + ", ".join(const_strs) + " /)" else: cs_stdame_initstr = "" # end if cap.write("character(len={}) :: {}({}){}".format(max_csname, cs_stdname, num_const_fields, cs_stdame_initstr), 1) # Declare variable for the constituent standard names array array_name = constituent_model_const_indices(host_model) cap.write("integer :: {}({}) = -1".format(array_name, num_const_fields), 1) # Add individual variables for each index var to the const_dict for index, std_name in enumerate(const_list): ind_std_name = "index_of_{}".format(std_name) ind_loc_name = "{}({})".format(array_name, index + 1) prop_dict = {'standard_name' : ind_std_name, 'local_name' : ind_loc_name, 'dimensions' : '()', 'units' : 'index', 'protected' : "True", 'type' : 'integer', 'kind' : ''} ind_var = Var(prop_dict, _API_SOURCE) const_dict.add_variable(ind_var) # end for # Add vertical dimensions for DDT call strings pver = host_model.find_variable(standard_name=vert_layer_dim, any_scope=False) if pver is not None: prop_dict = {'standard_name' : vert_layer_dim, 'local_name' : pver.get_prop_value('local_name'), 'units' : 'count', 'type' : 'integer', 'protected' : 'True', 'dimensions' : '()'} if const_dict.find_variable(standard_name=vert_layer_dim, any_scope=False) is None: ind_var = Var(prop_dict, _API_SOURCE) const_dict.add_variable(ind_var) # end if # end if pver = host_model.find_variable(standard_name=vert_interface_dim, any_scope=False) if pver is not None: prop_dict = {'standard_name' : vert_interface_dim, 'local_name' : pver.get_prop_value('local_name'), 'units' : 'count', 'type' : 'integer', 'protected' : 'True', 'dimensions' : '()'} if const_dict.find_variable(standard_name=vert_interface_dim, any_scope=False) is None: ind_var = Var(prop_dict, _API_SOURCE) const_dict.add_variable(ind_var) # end if # end if return const_dict
_SUBHEAD = ''' subroutine {host_model}_ccpp_physics_{stage}({api_vars}) ''' _SUBFOOT = ''' end subroutine {host_model}_ccpp_physics_{stage} ''' _API_SRC_NAME = "CCPP_API" _API_SOURCE = ParseSource(_API_SRC_NAME, "MODULE", ParseContext(filename="host_cap.F90")) _SUITE_NAME_VAR = Var({'local_name':'suite_name', 'standard_name':'suite_name', 'intent':'in', 'type':'character', 'kind':'len=*', 'units':'', 'protected':'True', 'dimensions':'()'}, _API_SOURCE) _SUITE_PART_VAR = Var({'local_name':'suite_part', 'standard_name':'suite_part', 'intent':'in', 'type':'character', 'kind':'len=*', 'units':'', 'protected':'True', 'dimensions':'()'}, _API_SOURCE) # Used to prevent loop substitution lookups _BLANK_DICT = VarDictionary(_API_SRC_NAME) ############################################################################### def suite_part_list(suite, stage): ###############################################################################
def parse_fortran_var_decl(line, source, logger=None): ######################################################################## """Parse a Fortran variable declaration line and return a list of Var objects representing the variables declared on <line>. >>> _VAR_ID_RE.match('foo') #doctest: +ELLIPSIS <re.Match object; span=(0, 3), match='foo'> >>> _VAR_ID_RE.match("foo()") >>> _VAR_ID_RE.match('foo').group(1) 'foo' >>> _VAR_ID_RE.match('foo').group(2) >>> _VAR_ID_RE.match("foo(bar)").group(1) 'foo' >>> _VAR_ID_RE.match("foo(bar)").group(2) '(bar)' >>> _VAR_ID_RE.match("foo(bar)").group(2) '(bar)' >>> _VAR_ID_RE.match("foo(bar, baz)").group(2) '(bar, baz)' >>> _VAR_ID_RE.match("foo(bar : baz)").group(2) '(bar : baz)' >>> _VAR_ID_RE.match("foo(bar:)").group(2) '(bar:)' >>> _VAR_ID_RE.match("foo(: baz)").group(2) '(: baz)' >>> _VAR_ID_RE.match("foo(:, :,:)").group(2) '(:, :,:)' >>> _VAR_ID_RE.match("foo(8)").group(2) '(8)' >>> _VAR_ID_RE.match("foo(::,a:b,a:,:b)").group(2) '(::,a:b,a:,:b)' >>> parse_fortran_var_decl("integer :: foo", ParseSource('foo.F90', 'module', ParseContext()))[0].get_prop_value('local_name') 'foo' >>> parse_fortran_var_decl("integer :: foo = 0", ParseSource('foo.F90', 'module', ParseContext()))[0].get_prop_value('local_name') 'foo' >>> parse_fortran_var_decl("integer :: foo", ParseSource('foo.F90', 'module', ParseContext()))[0].get_prop_value('optional') >>> parse_fortran_var_decl("integer, optional :: foo", ParseSource('foo.F90', 'module', ParseContext()))[0].get_prop_value('optional') 'True' >>> parse_fortran_var_decl("integer, dimension(:) :: foo", ParseSource('foo.F90', 'module', ParseContext()))[0].get_prop_value('dimensions') '(:)' >>> parse_fortran_var_decl("integer, dimension(:) :: foo(bar)", ParseSource('foo.F90', 'module', ParseContext()))[0].get_prop_value('dimensions') '(bar)' >>> parse_fortran_var_decl("integer, dimension(:) :: foo(:,:), baz", ParseSource('foo.F90', 'module', ParseContext()))[0].get_prop_value('dimensions') '(:,:)' >>> parse_fortran_var_decl("integer, dimension(:) :: foo(:,:), baz", ParseSource('foo.F90', 'module', ParseContext()))[1].get_prop_value('dimensions') '(:)' >>> parse_fortran_var_decl("real (kind=kind_phys), pointer :: phii (:,:) => null() !< interface geopotential height", ParseSource('foo.F90', 'module', ParseContext()))[0].get_prop_value('dimensions') '(:,:)' >>> parse_fortran_var_decl("real(kind=kind_phys), dimension(im, levs, ntrac), intent(in) :: qgrs", ParseSource('foo.F90', 'scheme', ParseContext()))[0].get_prop_value('dimensions') '(im, levs, ntrac)' >>> parse_fortran_var_decl("character(len=*), intent(out) :: errmsg", ParseSource('foo.F90', 'scheme', ParseContext()))[0].get_prop_value('local_name') 'errmsg' >>> parse_fortran_var_decl("character(len=512), intent(out) :: errmsg", ParseSource('foo.F90', 'scheme', ParseContext()))[0].get_prop_value('kind') 'len=512' >>> parse_fortran_var_decl("real(kind_phys), intent(out) :: foo(8)", ParseSource('foo.F90', 'scheme', ParseContext()))[0].get_prop_value('dimensions') '(8)' >>> parse_fortran_var_decl("real(kind_phys), intent(out) :: foo(size(bar))", ParseSource('foo.F90', 'scheme', ParseContext()))[0].get_prop_value('dimensions') '(size(bar))' >>> parse_fortran_var_decl("real(kind_phys), intent(out) :: foo(8)", ParseSource('foo.F90', 'scheme', ParseContext()))[0].get_dimensions() ['8'] >>> parse_fortran_var_decl("character(len=*), intent(out) :: errmsg", ParseSource('foo.F90', 'module', ParseContext()))[0].get_prop_value('local_name') #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ParseSyntaxError: Invalid variable declaration, character(len=*), intent(out) :: errmsg, intent not allowed in module variable, in <standard input> """ context = source.context sline = line.strip() # Strip comments first if '!' in sline: sline = sline[0:sline.index('!')].rstrip() # end if tobject = ftype_factory(sline, context) newvars = list() if tobject is not None: varprops = sline[tobject.type_len:].strip() def_dims = None # Default dimensions intent = None dimensions = None if '::' in varprops: elements = varprops.split('::') varlist = elements[1].strip() varprops = Ftype.parse_attr_specs(elements[0].strip(), context) for prop in varprops: if prop[0:6] == 'intent': if source.type != 'scheme': typ = source.type errmsg = 'Invalid variable declaration, {}, intent' errmsg = errmsg + ' not allowed in {} variable' if logger is not None: ctx = context_string(context) errmsg = "WARNING: " + errmsg + "{}" logger.warning(errmsg.format(sline, typ, ctx)) else: raise ParseSyntaxError(errmsg.format(sline, typ), context=context) # end if else: intent = prop[6:].strip()[1:-1].strip() # end if elif prop[0:9:] == 'dimension': dimensions = prop[9:].strip() # end if # end for else: # No attr_specs varlist = varprops varprops = list() # end if # Create Vars from these pieces # We may need to reassemble multi-dimensional specs var_list = Ftype.reassemble_parens(varlist, 'variable_list', context) for var in var_list: prop_dict = {} if '=' in var: # We do not care about initializers var = var[0:var.rindex('=')].rstrip() # end if # Scan <var> and gather variable pieces inchar = None # Character context var_len = len(var) ploc = var.find('(') if ploc < 0: varname = var.strip() dimspec = None else: varname = var[0:ploc].strip() begin, end = check_balanced_paren(var) if (begin < 0) or (end < 0): if logger is not None: ctx = context_string(context) errmsg = "WARNING: Invalid variable declaration, {}{}" logger.warning(errmsg.format(var, ctx)) else: raise ParseSyntaxError('variable declaration', token=var, context=context) # end if else: dimspec = var[begin:end + 1] # end if # end if prop_dict['local_name'] = varname prop_dict['standard_name'] = unique_standard_name() prop_dict['units'] = '' if isinstance(tobject, FtypeTypeDecl): prop_dict['ddt_type'] = tobject.typestr else: prop_dict['type'] = tobject.typestr # end if if tobject.kind() is not None: prop_dict['kind'] = tobject.kind() # end if if 'optional' in varprops: prop_dict['optional'] = 'True' # end if if 'allocatable' in varprops: prop_dict['allocatable'] = 'True' # end if if intent is not None: prop_dict['intent'] = intent # end if if dimspec is not None: prop_dict['dimensions'] = dimspec elif dimensions is not None: prop_dict['dimensions'] = dimensions else: prop_dict['dimensions'] = '()' # end if # XXgoldyXX: I am nervous about allowing invalid Var objects here # Also, this tends to cause an exception that ends up back here # which is not a good idea. var = Var(prop_dict, source, invalid_ok=(logger is not None), logger=logger) newvars.append(var) # end for # No else (not a variable declaration) # end if return newvars
def parse_variable(self, curr_line): # The header line has the format [ <valid_fortran_symbol> ] # Parse header valid_line = (curr_line is not None) and ( not MetadataHeader.table_start(curr_line)) if valid_line: local_name = self.variable_start( curr_line) # caller handles exception else: local_name = None # End if if local_name is None: # This is not a valid variable line, punt (should be end of table) valid_line = False # End if # Parse lines until invalid line is found # NB: Header variables cannot have embedded blank lines if valid_line: var_props = {} var_props['local_name'] = local_name else: var_props = None # End if while valid_line: curr_line, curr_line_num = self._pobj.next_line() valid_line = ((curr_line is not None) and (not MetadataHeader.is_blank(curr_line)) and (not MetadataHeader.table_start(curr_line)) and (self.variable_start(curr_line) is None)) # A valid line may have multiple properties (separated by '|') if valid_line: properties = self.parse_config_line(curr_line) for property in properties: try: pname = property[0].strip() pval_str = property[1].strip() # Make sure this is a match hp = Var.get_prop(pname) if hp is not None: pval = hp.valid_value(pval_str) else: raise ParseSyntaxError("variable property name", token=pname, context=self._pobj) # End if if pval is None: raise ParseSyntaxError( "'{}' property value".format(pname), token=pval_str, context=self._pobj) # End if except ParseSyntaxError as p: raise p # If we get this far, we have a valid property. var_props[pname] = pval # End for # End if # End while if var_props is None: return None, curr_line else: try: newvar = Var(var_props, source=self) except CCPPError as ve: raise ParseSyntaxError(ve, context=self._pobj) return newvar, curr_line
def parse_fortran_var_decl(line, source, logger=None): ######################################################################## """Parse a Fortran variable declaration line and return a list of Var objects representing the variables declared on <line>. >>> _var_id_re_.match('foo') #doctest: +ELLIPSIS <_sre.SRE_Match object at 0x...> >>> _var_id_re_.match("foo()") >>> _var_id_re_.match('foo').group(1) 'foo' >>> _var_id_re_.match('foo').group(2) >>> _var_id_re_.match("foo(bar)").group(1) 'foo' >>> _var_id_re_.match("foo(bar)").group(2) '(bar)' >>> _var_id_re_.match("foo(bar)").group(2) '(bar)' >>> _var_id_re_.match("foo(bar, baz)").group(2) '(bar, baz)' >>> _var_id_re_.match("foo(bar : baz)").group(2) '(bar : baz)' >>> _var_id_re_.match("foo(bar:)").group(2) '(bar:)' >>> _var_id_re_.match("foo(: baz)").group(2) '(: baz)' >>> _var_id_re_.match("foo(:, :,:)").group(2) '(:, :,:)' >>> _var_id_re_.match("foo(8)").group(2) '(8)' >>> _var_id_re_.match("foo(::,a:b,a:,:b)").group(2) '(::,a:b,a:,:b)' >>> parse_fortran_var_decl("integer :: foo", ParseSource('foo.F90', 'MODULE', ParseContext()))[0].get_prop_value('local_name') 'foo' >>> parse_fortran_var_decl("integer :: foo = 0", ParseSource('foo.F90', 'MODULE', ParseContext()))[0].get_prop_value('local_name') 'foo' >>> parse_fortran_var_decl("integer :: foo", ParseSource('foo.F90', 'MODULE', ParseContext()))[0].get_prop_value('optional') False >>> parse_fortran_var_decl("integer, optional :: foo", ParseSource('foo.F90', 'MODULE', ParseContext()))[0].get_prop_value('optional') 'True' >>> parse_fortran_var_decl("integer, dimension(:) :: foo", ParseSource('foo.F90', 'MODULE', ParseContext()))[0].get_prop_value('dimensions') '(:)' >>> parse_fortran_var_decl("integer, dimension(:) :: foo(bar)", ParseSource('foo.F90', 'MODULE', ParseContext()))[0].get_prop_value('dimensions') '(bar)' >>> parse_fortran_var_decl("integer, dimension(:) :: foo(:,:), baz", ParseSource('foo.F90', 'MODULE', ParseContext()))[0].get_prop_value('dimensions') '(:,:)' >>> parse_fortran_var_decl("integer, dimension(:) :: foo(:,:), baz", ParseSource('foo.F90', 'MODULE', ParseContext()))[1].get_prop_value('dimensions') '(:)' >>> parse_fortran_var_decl("real (kind=kind_phys), pointer :: phii (:,:) => null() !< interface geopotential height", ParseSource('foo.F90', 'MODULE', ParseContext()))[0].get_prop_value('dimensions') '(:,:)' >>> parse_fortran_var_decl("real(kind=kind_phys), dimension(im, levs, ntrac), intent(in) :: qgrs", ParseSource('foo.F90', 'MODULE', ParseContext()))[0].get_prop_value('dimensions') '(im, levs, ntrac)' >>> parse_fortran_var_decl("character(len=*), intent(out) :: errmsg", ParseSource('foo.F90', 'MODULE', ParseContext()))[0].get_prop_value('local_name') 'errmsg' """ context = source.context sline = line.strip() # Strip comments first if '!' in sline: sline = sline[0:sline.index('!')].rstrip() # End if tobject = Ftype_factory(sline, context) newvars = list() if tobject is not None: varprops = sline[tobject.type_len:].strip() def_dims = None # Default dimensions intent = None dimensions = None if '::' in varprops: elements = varprops.split('::') varlist = elements[1].strip() varprops = Ftype.parse_attr_specs(elements[0].strip(), context) for prop in varprops: if prop[0:6] == 'intent': intent = prop[6:].strip()[1:-1].strip() elif prop[0:9:] == 'dimension': dimensions = prop[9:].strip() # End if # End for else: # No attr_specs varlist = varprops varprops = list() # End if # Create Vars from these pieces # We may need to reassemble multi-dimensional specs vars = Ftype.reassemble_parens(varlist, 'variable_list', context) for var in vars: prop_dict = {} if '=' in var: # We do not care about initializers var = var[0:var.rindex('=')].rstrip() # End if # Scan <var> and gather variable pieces inchar = None # Character context var_len = len(var) ploc = var.find('(') if ploc < 0: varname = var.strip() dimspec = None else: varname = var[0:ploc].strip() begin, end = check_balanced_paren(var) if (begin < 0) or (end < 0): if logger is not None: ctx = context_string(context) logger.warning( "WARNING: Invalid variable declaration, {}{}". format(var, ctx)) else: raise ParseSyntaxError('variable declaration', token=var, context=context) # End if else: dimspec = var[begin:end + 1] # End if # End if prop_dict['local_name'] = varname prop_dict['standard_name'] = Ftype.unique_standard_name() prop_dict['units'] = '' prop_dict['type'] = tobject.typestr if tobject.kind is not None: prop_dict['kind'] = tobject.kind # End if if 'optional' in varprops: prop_dict['optional'] = 'True' # End if if 'allocatable' in varprops: prop_dict['allocatable'] = 'True' # End if if intent is not None: prop_dict['intent'] = intent # End if if dimspec is not None: prop_dict['dimensions'] = dimspec elif dimensions is not None: prop_dict['dimensions'] = dimensions else: prop_dict['dimensions'] = '()' # End if # XXgoldyXX: I am nervous about allowing invalid Var objects here newvars.append( Var(prop_dict, source, invalid_ok=(logger is not None), logger=logger)) # End for # No else (not a variable declaration) # End if return newvars