From 94b3304a77956bdeb3840eecba4be78d398c88b3 Mon Sep 17 00:00:00 2001 From: ignis Date: Sun, 28 Apr 2019 01:10:57 +0900 Subject: [PATCH] extract pass1 and pass2 sets --- code/code_gen/code_gen.py | 294 ++++++++++++++++++++++++++++++-------- code/code_gen/terms.input | 4 +- 2 files changed, 236 insertions(+), 62 deletions(-) diff --git a/code/code_gen/code_gen.py b/code/code_gen/code_gen.py index 2f14efa..ddcbf88 100644 --- a/code/code_gen/code_gen.py +++ b/code/code_gen/code_gen.py @@ -2,7 +2,7 @@ # This example shows how to write a basic calculator with variables. # -from lark import Lark, Transformer, v_args +from lark import Lark, Visitor, Transformer, v_args, Token try: @@ -18,7 +18,7 @@ calc_grammar = """ ?start: statement* ?statement: NAME "=" sum -> assign_var - | avg "{" [sum ("," sum)*] "}" -> assign_avg_var + | avg "{" [NAME ("," NAME)*] "}" -> assign_avg_var | varlist ?sum: product @@ -96,70 +96,32 @@ avg_array_divide = "{0} = {0} / denum {1}" real_array_diff = "call {0[0]} ( {0[0]}_{0[1]}, {0[1]} )" @v_args(inline=True) # Affects the signatures of the methods -class CalculateTree(Transformer): +class ToFortran(Transformer): - def __init__(self): - self.primary = [] - self.derived = {} - self.averaged = {} + def __init__(self, primary_set): + self.primary = primary_set self.derivatives = {} self.dependency = {} - def varlist(self, *args): - for arg in args: - self.primary.append(arg.value) - return self.primary - - def assign_var(self, name, (value, dep)): - self.derived[name.value] = value - self.dependency[name.value] = dep - return "{} = {}".format(name, value) - - def assign_avg_var(self, weight, *args): #name, (value, dep)): - - fmt = "avg_{}" - if weight is not None: - wvalue, wdep = self.var(weight) - self.averaged[fmt.format(weight)] = wvalue, None - self.dependency[fmt.format(weight)] = wdep - fmt = weight + "_" + fmt - - for i, (value, dep) in enumerate(args): - self.averaged[fmt.format(i)] = value, weight - self.dependency[fmt.format(i)] = dep + (wdep if weight is not None else []) - - return "" - - def avg(self, *args): - try: - return args[0] - except IndexError: - return None - def number(self, numeral): - return (numeral, []) - - def var(self, name): - dep = [] - if name not in self.primary: - dep.append(name.value) - return (name + "(i,j,k)", dep) - - def fluc(self, name): - dep = [] - if name not in self.primary: - dep.append(name.value) - fmt = "({0}(i,j,k) - avg_{0}(i))" - return (fmt.format(name) , dep) + return (str(float(numeral)), []) def env(self, name): - return (name, []) + return (name.value, []) + + def var(self, name): + return (name + "(i,j,k)", + [name.value] if name.value not in self.primary else []) + + def fluc(self, name): + fmt = "({0}(i,j,k) - {{}}avg_{0}(i))" + return (fmt.format(name), + [name.value] if name.value not in self.primary else []) def dnx (self, partial, b): signature = "{}_{}".format(partial.data, b) self.derivatives[signature] = (partial.data, b.value) - self.dependency[signature] = [b.value] return (signature + "(i,j,k)", [signature]) @@ -203,6 +165,97 @@ class CalculateTree(Transformer): sqrt = lambda self : "sqrt" rxn_rate = lambda self : "rxn_rate" +class CheckPass(Visitor): + + def __init__(self): + self.hasFluc = False + + @classmethod + def check(cls, tree): + self = cls() + return self(tree) + + def __call__(self, tree): + self.visit(tree) + return self.hasFluc + + def fluc(self, tree): + self.hasFluc = True + + +@v_args(inline=True) # Affects the signatures of the methods +class CalculateTree(Transformer): + + def __init__(self): + self.primary = [] + self.derived = {} + self.averaged = {} + self.derivatives = {} + self.dependency = {} + self.definitions = {} + self.exp_parser = ToFortran([]) + + def varlist(self, *args): + + for arg in args: + self.primary.append(arg.value) + self.dependency[arg.value] = [] + # return self.primary + + return "" + + def assign_var(self, *args): # name, (value, dep)): + + vname, vdef = args + self.definitions[vname.value] = vdef + + code, dep = self.exp_parser.transform(vdef) + self.dependency[vname.value] = dep + + return "" + + def assign_avg_var(self, *args): # weight, *args): #name, (value, dep)): + + weight = args[0] + vlist = args[1:] + self.averaged[str(weight)] = map(str, vlist) + + w = str(weight) + for v in vlist: + avg_var = ( "" if w == str(None) else w + "_" ) + "avg_" + v + self.dependency[avg_var] = [str(v)] + # average_names.append(avg_var) + # self.depsDict[avg_var] = [v] + # self.flucDict[avg_var] = False + + ''' + fmt = "avg_{}" + if weight is not None: + wvalue, wdep = self.var(weight) + self.averaged[fmt.format(weight)] = wvalue, None + self.dependency[fmt.format(weight)] = wdep + fmt = weight + "_" + fmt + + for i, (value, dep) in enumerate(args): + self.averaged[fmt.format(i)] = value, weight + self.dependency[fmt.format(i)] = dep + (wdep if weight is not None else []) + + ''' + return "" + + + def avg(self, *args): + try: + return args[0] + except IndexError: + return None + + def dep_graph (self): + return dict( + self.dependency.items() + + self.exp_parser.dependency.items() + ) + def array_decl (self): f_code = "" @@ -315,11 +368,84 @@ class CalculateTree(Transformer): tf=CalculateTree() -calc_parser = Lark(calc_grammar, parser='lalr' , transformer=tf) +ft=ToFortran(['u','v','w','y']) + + +calc_parser = Lark(calc_grammar, parser='lalr' ) # , transformer=tf) calc = calc_parser.parse import sys +import pprint + +pp = pprint.PrettyPrinter() + + +class FortranProgram: + + def __init__ (self, terms_input): + + self.tree_parser = Lark(calc_grammar, parser='lalr' ) + + self.parser = CalculateTree() + + tree = self.tree_parser.parse(terms_input) + + self.parser.transform(tree) + + + dg = self.parser.dep_graph() + fd = {} + for v in dg.iterkeys(): + fd[v] = False + + for n, d in (self.parser.definitions.iteritems()): + fd[n] = CheckPass.check(d) + + average_names = [] + for w, vlist in self.parser.averaged.iteritems(): + for v in vlist: + avg_var = ( "" if w == "None" else w + "_" ) + "avg_" + v + average_names.append(avg_var) + + def isFluc (a): + for x in dg[a]: + fd[a] = fd[a] or isFluc(x) + + return fd[a] + + pass1var = filter(lambda x: not isFluc(x), average_names) + + pass2var = filter(isFluc, average_names) + + def dep_set (varset): + c = set([]) + + for var in varset: + c.update(dg[var]) + + return c + + def dep_closer (s): + c = set(s) + + while len(dep_set(s)) > 0: + s = dep_set(s) + c.update(s) + + return c + + self.pass1set = dep_closer(set(pass1var)) + + self.pass2set = dep_closer(set(pass2var)) + + print self.pass1set + + print self.pass2set + + + + def main(): while True: try: @@ -335,15 +461,61 @@ def test(): mod_form = template_file.read() with open("terms.input") as inputfile: - (calc(inputfile.read())) + terms_raw = ((inputfile.read())) + parsed_tree = (calc(terms_raw)) - print mod_form.format(tf.module_dict()) + ''' + tf.transform(parsed_tree) - print "! ", tf.derived - print "! ", tf.derivatives - print "! ", tf.dependency + namelist, deflist = zip(*list(tf.definitions.iteritems())) - print "! ", tf.sort_vars() + hasFluc = dict([ (n, hf) for n, hf in zip(namelist, map(CheckPass.check, deflist)) ]) + + codes, deps = zip(*map ( ft.transform, deflist )) + + depsDict = dict(zip(namelist, deps)) + + visited = {n: False for n in namelist} + + def isFluc (a, graph, visit, hf): + try: + if visit[a]: + pass + elif len(graph[a]) < 1: + visit[a] = True + else: + hf[a] = any([hf[a]] + [isFluc(x, graph, visit, hf) for x in graph[a]]) + visit[a] = True + + return hf[a] + except KeyError: + return False + + flucDict = {n: isFluc(n, depsDict, visited, hasFluc) for n in namelist} + ''' + + + FortranProgram(terms_raw) + + + ''' + for f, ts in zip(namelist, deps): + for t in ts: + print "{} -> {}".format(f, t) + + for d, (op, phi) in ft.derivatives.iteritems(): + print "{} -> {}".format(d, phi) + + print tf.averaged + ''' + + #print mod_form.format(tf.module_dict()) + + #print "! ", tf.derived + #print "! ", tf.derivatives + #print "! ", tf.dependency + + #print "! ", tf.sort_vars() if __name__ == '__main__': test() diff --git a/code/code_gen/terms.input b/code/code_gen/terms.input index 94d44bf..42e4e8b 100644 --- a/code/code_gen/terms.input +++ b/code/code_gen/terms.input @@ -8,10 +8,12 @@ k = (sqr(u')+sqr(v')+sqr(w'))/2.0 tflux = u' * c_auto' -avg { u, v, w, c_auto } +avg { u, v, w, c_auto, tflux } avg c_auto { u, v, w } avg y { u, v, w } avg fsd_auto { u } + +avg temp { }