def generate_spec(self): assert self.fspec.targetlang == "python", "Wrong target language for this" " call" assert self.fspec.varspecs != {}, "varspecs attribute must be defined" specnames_unsorted = list(self.fspec.varspecs.keys()) _vbfs_inv = invertMap(self.fspec._varsbyforspec) # Process state variable specifications if len(_vbfs_inv) > 0: specname_vars = [] specname_auxvars = [] for varname in self.fspec.vars: # check if varname belongs to a for macro grouping in # self.fspec.varspecs if varname not in specname_vars: specname_vars.append(varname) for varname in self.fspec.auxvars: # check if varname belongs to a for macro grouping in # self.fspec.varspecs if varname not in specname_auxvars: specname_auxvars.append(varname) else: specname_vars = intersect(self.fspec.vars, specnames_unsorted) specname_auxvars = intersect(self.fspec.auxvars, specnames_unsorted) specname_vars.sort() for vn, vs in list(self.fspec.varspecs.items()): if any([pt in vs for pt in ("^", "**")]): self.fspec.varspecs[vn] = convertPowers(vs, "pow") self.fspec.vars.sort() reusestr, specupdated = self._processReusedPy(specname_vars, self.fspec.varspecs) self.fspec.varspecs.update(specupdated) temp = self._specStrParse(specname_vars, self.fspec.varspecs, "xnew") specstr_py = self._generate_fun("_specfn", reusestr + temp, "xnew", specname_vars, docodeinserts=True) # Process auxiliary variable specifications specname_auxvars.sort() assert self.fspec.auxvars == specname_auxvars, ( "Mismatch between declared auxiliary" " variable names and varspecs keys" ) reusestraux, specupdated = self._processReusedPy(specname_auxvars, self.fspec.varspecs) self.fspec.varspecs.update(specupdated) tempaux = self._specStrParse(specname_auxvars, self.fspec.varspecs, "auxvals") auxspecstr_py = self._generate_fun( "_auxspecfn", reusestraux + tempaux, "auxvals", specname_auxvars, docodeinserts=True ) try: spec_info = makeUniqueFn(specstr_py) except SyntaxError: print("Syntax error in specification:\n" + specstr_py) raise try: auxspec_info = makeUniqueFn(auxspecstr_py) except SyntaxError: print("Syntax error in auxiliary spec:\n" + auxspecstr_py) raise self.fspec.spec = spec_info self.fspec.auxspec = auxspec_info
def generate_spec(self): assert self.fspec.targetlang == 'python', ( 'Wrong target language for this' ' call') assert self.fspec.varspecs != {}, 'varspecs attribute must be defined' specnames_unsorted = list(self.fspec.varspecs.keys()) _vbfs_inv = invertMap(self.fspec._varsbyforspec) # Process state variable specifications if len(_vbfs_inv) > 0: specname_vars = [] specname_auxvars = [] for varname in self.fspec.vars: # check if varname belongs to a for macro grouping in # self.fspec.varspecs if varname not in specname_vars: specname_vars.append(varname) for varname in self.fspec.auxvars: # check if varname belongs to a for macro grouping in # self.fspec.varspecs if varname not in specname_auxvars: specname_auxvars.append(varname) else: specname_vars = intersect(self.fspec.vars, specnames_unsorted) specname_auxvars = intersect(self.fspec.auxvars, specnames_unsorted) specname_vars.sort() for vn, vs in list(self.fspec.varspecs.items()): if any([pt in vs for pt in ('^', '**')]): self.fspec.varspecs[vn] = convertPowers(vs, 'pow') self.fspec.vars.sort() reusestr, specupdated = self._processReusedPy(specname_vars, self.fspec.varspecs) self.fspec.varspecs.update(specupdated) temp = self._specStrParse(specname_vars, self.fspec.varspecs, 'xnew') specstr_py = self._generate_fun('_specfn', reusestr + temp, 'xnew', specname_vars, docodeinserts=True) # Process auxiliary variable specifications specname_auxvars.sort() assert self.fspec.auxvars == specname_auxvars, \ ('Mismatch between declared auxiliary' ' variable names and varspecs keys') reusestraux, specupdated = self._processReusedPy( specname_auxvars, self.fspec.varspecs) self.fspec.varspecs.update(specupdated) tempaux = self._specStrParse(specname_auxvars, self.fspec.varspecs, 'auxvals') auxspecstr_py = self._generate_fun('_auxspecfn', reusestraux + tempaux, 'auxvals', specname_auxvars, docodeinserts=True) try: spec_info = makeUniqueFn(specstr_py) except SyntaxError: print("Syntax error in specification:\n" + specstr_py) raise try: auxspec_info = makeUniqueFn(auxspecstr_py) except SyntaxError: print("Syntax error in auxiliary spec:\n" + auxspecstr_py) raise self.fspec.spec = spec_info self.fspec.auxspec = auxspec_info
def generate_spec(self): assert self.fspec.targetlang == "c", "Wrong target language for this" " call" assert self.fspec.varspecs != {}, "varspecs attribute must be defined" specnames_unsorted = list(self.fspec.varspecs.keys()) _vbfs_inv = invertMap(self.fspec._varsbyforspec) # Process state variable specifications if len(_vbfs_inv) > 0: specname_vars = [] specname_auxvars = [] for varname in self.fspec.vars: # check if varname belongs to a for macro grouping in # self.fspec.varspecs if varname not in specname_vars: specname_vars.append(varname) for varname in self.fspec.auxvars: # check if varname belongs to a for macro grouping in # self.fspec.varspecs if varname not in specname_auxvars: specname_auxvars.append(varname) else: specname_vars = intersect(self.fspec.vars, specnames_unsorted) specname_auxvars = intersect(self.fspec.auxvars, specnames_unsorted) specname_vars.sort() # sorted version of var and par names pnames = self.fspec.pars inames = self.fspec.inputs pnames.sort() inames.sort() pardefines = "" vardefines = "" inpdefines = "" parundefines = "" varundefines = "" inpundefines = "" # produce vector field specification assert self.fspec.vars == specname_vars, ( "Mismatch between declared " " variable names and varspecs keys" ) valid_depTargNames = self.fspec.inputs + self.fspec.vars + self.fspec.auxvars for specname, specstr in self.fspec.varspecs.items(): assert type(specstr) == str, ( "Specification for %s was not a string" % specname ) if any([pt in specstr for pt in ("^", "**")]): self.fspec.varspecs[specname] = convertPowers(specstr, "pow") # pre-process reused sub-expression dictionary to adapt for # known calling sequence in C reusestr, specupdated = self._processReusedC(specname_vars, self.fspec.varspecs) self.fspec.varspecs.update(specupdated) specstr_C = self._generate_fun( "vfieldfunc", reusestr, specname_vars, pardefines, vardefines, inpdefines, parundefines, varundefines, inpundefines, True, ) self.fspec.spec = specstr_C # produce auxiliary variables specification specname_auxvars.sort() assert self.fspec.auxvars == specname_auxvars, ( "Mismatch between declared auxiliary" " variable names and varspecs keys" ) if self.fspec.auxvars != []: reusestraux, specupdated = self._processReusedC( specname_auxvars, self.fspec.varspecs ) self.fspec.varspecs.update(specupdated) if self.fspec.auxvars == []: auxspecstr_C = self._generate_fun( "auxvars", "", specname_auxvars, "", "", "", "", "", "", False ) else: auxspecstr_C = self._generate_fun( "auxvars", reusestraux, specname_auxvars, pardefines, vardefines, inpdefines, parundefines, varundefines, inpundefines, False, ) self.fspec.auxspec = auxspecstr_C
def test_invertMap_for_dict(): assert {'x': 'x', 'y': 'y'} == invertMap({'x': ['x'], 'y': ['y']})
def _processReused(specnames, specdict, reuseterms, indentstr='', typestr='', endstatementchar='', parseFunc=idfn): """Process substitutions of reused terms.""" seenrepterms = [] # for new protected names (global to all spec names) reused = {}.fromkeys(specnames) reuseterms_inv = invertMap(reuseterms) # establish order for reusable terms, in case of inter-dependencies are_dependent = [] deps = {} for origterm, rterm in reuseterms.items(): for _, rt in reuseterms.items(): if proper_match(origterm, rt): if rterm not in are_dependent: are_dependent.append(rterm) try: deps[rterm].append(rt) except KeyError: # new list deps[rterm] = [rt] order = remain(sorted(reuseterms.values()), are_dependent) + are_dependent for specname in specnames: reused[specname] = [] specstr = specdict[specname] repeatkeys = [] for origterm, repterm in reuseterms.items(): # only add definitions if string found if proper_match(specstr, origterm): specstr = specstr.replace(origterm, repterm) if repterm not in seenrepterms: reused[specname].append([ indentstr, typestr + ' ' * (len(typestr) > 0), repterm, " = ", parseFunc(origterm), endstatementchar, "\n" ]) seenrepterms.append(repterm) else: # look for this term on second pass repeatkeys.append(origterm) if len(seenrepterms) > 0: # don't bother with a second pass if specstr has not changed for origterm in repeatkeys: # second pass repterm = reuseterms[origterm] if proper_match(specstr, origterm): specstr = specstr.replace(origterm, repterm) if repterm not in seenrepterms: seenrepterms.append(repterm) reused[specname].append([ indentstr, typestr + ' ' * (len(typestr) > 0), repterm, " = ", parseFunc(origterm), endstatementchar, "\n" ]) # if replacement terms have already been used in the specifications # and there are no occurrences of the terms meant to be replaced then # just log the definitions that will be needed without replacing # any strings. if reused[specname] == [] and len(reuseterms) > 0: for origterm, repterm in reuseterms.items(): # add definition if *replacement* string found in specs if proper_match(specstr, repterm) and repterm not in seenrepterms: reused[specname].append([ indentstr, typestr + ' ' * (len(typestr) > 0), repterm, " = ", parseFunc(origterm), endstatementchar, "\n" ]) seenrepterms.append(repterm) specdict[specname] = specstr # add any dependencies for repeated terms to those that will get # defined when functions are instantiated for r in seenrepterms: if r in are_dependent: for repterm in deps[r]: if repterm not in seenrepterms: reused[specname].append([ indentstr, typestr + ' ' * (len(typestr) > 0), repterm, " = ", parseFunc(reuseterms_inv[repterm]), endstatementchar, "\n" ]) seenrepterms.append(repterm) # reuseterms may be automatically provided for a range of definitions # that may or may not contain instances, and it's too inefficient to # check in advance, so we'll not cause an error here if none show up. # if len(seenrepterms) == 0 and len(reuseterms) > 0: # print("Reuse terms expected:%r" % reuseterms) # info(specdict) # raise RuntimeError("Declared reusable term definitions did not match" # " any occurrences in the specifications") return (reused, specdict, seenrepterms, order)
def generate_spec(self): assert self.fspec.targetlang == 'c', ('Wrong target language for this' ' call') assert self.fspec.varspecs != {}, 'varspecs attribute must be defined' specnames_unsorted = list(self.fspec.varspecs.keys()) _vbfs_inv = invertMap(self.fspec._varsbyforspec) # Process state variable specifications if len(_vbfs_inv) > 0: specname_vars = [] specname_auxvars = [] for varname in self.fspec.vars: # check if varname belongs to a for macro grouping in # self.fspec.varspecs if varname not in specname_vars: specname_vars.append(varname) for varname in self.fspec.auxvars: # check if varname belongs to a for macro grouping in # self.fspec.varspecs if varname not in specname_auxvars: specname_auxvars.append(varname) else: specname_vars = intersect(self.fspec.vars, specnames_unsorted) specname_auxvars = intersect(self.fspec.auxvars, specnames_unsorted) specname_vars.sort() # sorted version of var and par names pnames = self.fspec.pars inames = self.fspec.inputs pnames.sort() inames.sort() pardefines = "" vardefines = "" inpdefines = "" parundefines = "" varundefines = "" inpundefines = "" # produce vector field specification assert self.fspec.vars == specname_vars, ('Mismatch between declared ' ' variable names and varspecs keys') valid_depTargNames = self.fspec.inputs + self.fspec.vars + self.fspec.auxvars for specname, specstr in self.fspec.varspecs.items(): assert type( specstr) == str, "Specification for %s was not a string" % specname if any([pt in specstr for pt in ('^', '**')]): self.fspec.varspecs[specname] = convertPowers(specstr, 'pow') # pre-process reused sub-expression dictionary to adapt for # known calling sequence in C reusestr, specupdated = self._processReusedC(specname_vars, self.fspec.varspecs) self.fspec.varspecs.update(specupdated) specstr_C = self._generate_fun( 'vfieldfunc', reusestr, specname_vars, pardefines, vardefines, inpdefines, parundefines, varundefines, inpundefines, True) self.fspec.spec = specstr_C # produce auxiliary variables specification specname_auxvars.sort() assert self.fspec.auxvars == specname_auxvars, \ ('Mismatch between declared auxiliary' ' variable names and varspecs keys') if self.fspec.auxvars != []: reusestraux, specupdated = self._processReusedC( specname_auxvars, self.fspec.varspecs) self.fspec.varspecs.update(specupdated) if self.fspec.auxvars == []: auxspecstr_C = self._generate_fun('auxvars', '', specname_auxvars, '', '', '', '', '', '', False) else: auxspecstr_C = self._generate_fun('auxvars', reusestraux, specname_auxvars, pardefines, vardefines, inpdefines, parundefines, varundefines, inpundefines, False) self.fspec.auxspec = auxspecstr_C
def _processReused(specnames, specdict, reuseterms, indentstr='', typestr='', endstatementchar='', parseFunc=idfn): """Process substitutions of reused terms.""" seenrepterms = [] # for new protected names (global to all spec names) reused = {}.fromkeys(specnames) reuseterms_inv = invertMap(reuseterms) # establish order for reusable terms, in case of inter-dependencies are_dependent = [] deps = {} for origterm, rterm in reuseterms.iteritems(): for _, rt in reuseterms.iteritems(): if proper_match(origterm, rt): if rterm not in are_dependent: are_dependent.append(rterm) try: deps[rterm].append(rt) except KeyError: # new list deps[rterm] = [rt] order = remain(reuseterms.values(), are_dependent) + are_dependent for specname in specnames: reused[specname] = [] specstr = specdict[specname] repeatkeys = [] for origterm, repterm in reuseterms.iteritems(): # only add definitions if string found if proper_match(specstr, origterm): specstr = specstr.replace(origterm, repterm) if repterm not in seenrepterms: reused[specname].append([indentstr, typestr + ' ' * (len(typestr) > 0), repterm, " = ", parseFunc(origterm), endstatementchar, "\n"]) seenrepterms.append(repterm) else: # look for this term on second pass repeatkeys.append(origterm) if len(seenrepterms) > 0: # don't bother with a second pass if specstr has not changed for origterm in repeatkeys: # second pass repterm = reuseterms[origterm] if proper_match(specstr, origterm): specstr = specstr.replace(origterm, repterm) if repterm not in seenrepterms: seenrepterms.append(repterm) reused[specname].append([indentstr, typestr + ' ' * (len(typestr) > 0), repterm, " = ", parseFunc(origterm), endstatementchar, "\n"]) # if replacement terms have already been used in the specifications # and there are no occurrences of the terms meant to be replaced then # just log the definitions that will be needed without replacing # any strings. if reused[specname] == [] and len(reuseterms) > 0: for origterm, repterm in reuseterms.iteritems(): # add definition if *replacement* string found in specs if proper_match(specstr, repterm) and repterm not in seenrepterms: reused[specname].append([indentstr, typestr + ' ' * (len(typestr) > 0), repterm, " = ", parseFunc(origterm), endstatementchar, "\n"]) seenrepterms.append(repterm) specdict[specname] = specstr # add any dependencies for repeated terms to those that will get # defined when functions are instantiated for r in seenrepterms: if r in are_dependent: for repterm in deps[r]: if repterm not in seenrepterms: reused[specname].append([indentstr, typestr + ' ' * (len(typestr) > 0), repterm, " = ", parseFunc( reuseterms_inv[repterm]), endstatementchar, "\n"]) seenrepterms.append(repterm) # reuseterms may be automatically provided for a range of definitions # that may or may not contain instances, and it's too inefficient to # check in advance, so we'll not cause an error here if none show up. # if len(seenrepterms) == 0 and len(reuseterms) > 0: # print "Reuse terms expected:", reuseterms # info(specdict) # raise RuntimeError("Declared reusable term definitions did not match" # " any occurrences in the specifications") return (reused, specdict, seenrepterms, order)