Source code for pycropml.transpiler.generators.fortranGenerator

# coding: utf8
from pycropml.transpiler.pseudo_tree import Node
from pycropml.transpiler.codeGenerator import CodeGenerator
from pycropml.transpiler.rules.fortranRules import FortranRules
from pycropml.transpiler.interface import middleware
from pycropml.transpiler.generators.docGenerator import DocGenerator
from pycropml.transpiler import lib
from pycropml.transpiler.preprocessing import check_range_function
import os
from path import Path
#from pycropml.transpiler.Parser import parser
#from pycropml.transpiler.ast_transform import AstTransformer, transform_to_syntax_tree
import shutil


# get the path of fortran subroutine list_sub
# This subroutine is used to hnndle dynamic arrays


  
#f_src = open(list_path, 'rb')

#file_dest = dir_lib  
#f_dest = open(file_dest, 'wb')

#shutil.copyfileobj(f_src, f_dest) 


[docs] def transf_var_name(name): #if var_name starts with "_" we replace it by "cy_" if name.startswith("_"): name = "cy_" + name[1:] return name
[docs] class FortranGenerator(CodeGenerator, FortranRules): """ This class contains the specific properties of fortran language and use the NodeVisitor to generate a fortran code source from a well formed syntax tree. Args: CodeGenerator (CodeGeneration): Common code generation class FortranRules (FortranRules): Transformation rules """ def __init__(self, tree, model=None, name = None): CodeGenerator.__init__(self) FortranRules.__init__(self) self.tree = tree self.indent_with=' '*4 self.model=model # crop2ml models self.name = name self.initialValue=[] #self.z = middleware(self.tree) #self.z.transform(self.tree) self.mod_parameters=[] self.parameters=[] self.node_params=[] self.index=[] self.params=[] self.recursive=False self.allocatable = {} self.privates = [p.name for p in model.inputs if "parametercategory" in dir(p) and p.parametercategory=="private" and "ARRAY" in p.datatype ] self.states_arr = [p.name for p in model.inputs if "variablecategory" in dir(p) and p.variablecategory=="state" and "ARRAY" in p.datatype ] if self.model: self.doc= DocGenerator(model, '!') self.funcname = "" dir_lib = Path(os.path.dirname(lib.__file__)) self.f_src=dir_lib/"f90"/"list_sub.f90" if self.model: pkg = self.model.path.split(os.path.sep)[-1] self.f_dest = os.path.join(self.model.path,"src","f90",pkg,"list_sub.f90")
[docs] def visit_notAnumber(self, node): pass
[docs] def visit_comparison(self, node): if node.op == "is": if node.right.type == "none": self.write("NULL(") self.visit(node.left) self.write(")") else: self.visit_binary_op(node)
[docs] def visit_local(self, node): self.write(transf_var_name(node.name))
# self.write("(%s - 1)"%node.name) if node.name in self.index else self.write(node.name)
[docs] def visit_binary_op(self, node): op = node.op prec = self.binop_precedence.get(op, 0) self.operator_enter(prec) if node.op not in ["is_not"]: self.visit(node.left) self.write(u" %s " % self.binary_op[op].replace('_', ' ')) if "type" in dir(node.right): if node.right.type=="binary_op" and self.binop_precedence.get(str(node.right.op), 0) >= prec: # and node.right.op not in ("+","-") : self.write("(") self.visit(node.right) self.write(")") else: self.visit(node.right) else: self.visit(node.right) else: self.write("ALLOCATED(") self.visit(node.left) self.write(")") self.operator_exit()
[docs] def visit_unary_op(self, node): op = node.operator prec = self.unop_precedence[op] self.operator_enter(prec) self.write(u"%s" % self.unary_op[op]) self.visit(node.value) self.operator_exit()
[docs] def body(self, statements): self.new_line = True self.indentation += 1 if isinstance(statements, list): for stmt in statements: if stmt.type!="declaration": self.visit(stmt) else: self.visit(statements) self.indentation -= 1
'''https://rosettacode.org/wiki/Operator_precedence#Fortran''' binop_precedence = { 'or': 1, 'and': 2, # unary: 'not': 3, '!': 3, 'in': 4, 'not_in': 4, 'is': 4, 'is_not': 4, '<': 4, '<=': 4, '>': 4, '>=': 4, '!=': 4, '==': 4, '|': 5, '^': 6, '&': 7, '<<': 8, '>>': 8, '+': 9, '-': 9, '*': 11, '@': 11, '/': 11, '//': 11, '%': 11, # unary: '+': 11, '-': 11, '~': 11 '**': 12, } unop_precedence = { 'not': 3, '!': 3, '+': 10, '-': 10, '~': 10, }
[docs] def visit_import(self, node): pass
[docs] def visit_assignment(self, node): if node.value.type=="none": pass elif node.value.type=="cond_expr_node": self.visit_cond_expr_node(node) elif node.value.type=="local" and isinstance(node.value.pseudo_type, list) and node.value.pseudo_type[0]=="array" \ and node.target.type=="local" and isinstance(node.target.pseudo_type, list) and node.target.pseudo_type[0]=="array": self.newline(node) self.write(f"IF (ALLOCATED({node.value.name})) THEN") self.newline(node) self.write(f" ALLOCATE({node.target.name}(SIZE({node.value.name})))") self.newline(node) self.write(f" {node.target.name} = {node.value.name}") self.newline(node) if node.value.name not in self.parameters: self.write(f" DEALLOCATE({node.value.name})") self.newline(node) self.write("END IF") self.newline(node) elif node.value.type == "standard_call" and node.value.function=="integr": self.newline(node) self.write("%s = %s"%(node.target.name,node.value.args[0].name)) self.newline(node) self.write("call Add(%s,"%node.target.name) self.visit( node.value.args[1]) self.write(")") elif (node.target.type=="tuple" and node.value.type == "custom_call") or (node.value.type == "custom_call" and not self.recursive and node.value.pseudo_type=="tuple") or (node.value.type == "custom_call" and node.value.function.startswith('model_')): self.newline(node) node =Node("subroutine", receiver = node.target,function=node.value.function, args=node.value.args ) self.write('call ') self.visit(node) elif node.value.type =="list" and not node.value.elements: self.write("\n deallocate(%s)\n"%transf_var_name(node.target.name)) elif node.value.type == "notAnumber": self.visit_notAnumber(node) elif node.target.type=="local" and node.value.type=="array" and "elements" in dir(node.value) and node.value.elements.type == "binary_op" and node.value.elements.op=="*" and node.value.elements.left.type=="list": self.newline(node) self.write(f"ALLOCATE({node.target.name}(") self.visit(node.value.elements.right) self.write("))") self.newline(node) self.write(f"{node.target.name} = ") self.visit(node.value.elements.left.elements[0]) else: self.newline(node) self.visit(node.target) self.write(' = ') if node.value.type=="binary_op" and isinstance(node.value.left.pseudo_type, list) and not isinstance(node.value.right.pseudo_type, list): self.visit(node.value.left.elements[0]) else: self.visit(node.value)
[docs] def visit_tuple(self,node): pass
[docs] def visit_tab(self, node): self.write("[") self.visit(node.receiver) self.write("(:") self.visit(node.index) self.write("-1),") self.visit(node.receiver) self.write("(") self.visit(node.index) self.write("+1:)]")
[docs] def visit_cond_expr_node(self, node): self.newline(node) self.write(u"IF (") self.visit(node.value.test) self.write(') THEN') self.newline(node) self.indentation+=1 self.visit(node.target) self.write("=") self.visit(node.value.true_val) self.newline(node) self.indentation-=1 self.write(u"ELSE ") self.newline(node) self.indentation+=1 self.visit(node.target) self.write("=") self.visit(node.value.false_val) self.newline(node) self.indentation-=1 self.write(u"END IF ")
[docs] def visit_if_statement(self, node): self.newline(node) self.write('IF(') self.visit(node.test) self.write(') THEN') self.newline(node) self.body(node.block) self.newline(node) while True: else_ = node.otherwise if len(else_) == 0: self.newline(node) self.write(u"END IF") break elif len(else_) == 1 and else_[0].type=='elseif_statement': self.visit(else_[0]) self.newline(node) self.write(u"END IF") else: self.visit(else_) self.newline(node) self.write(u"END IF") break break
[docs] def visit_elseif_statement(self, node): self.newline() self.write('ELSE IF ( ') self.visit(node.test) self.write(') THEN') self.newline(node) self.body(node.block) self.newline(node)
[docs] def visit_else_statement(self, node): self.newline() self.write('ELSE') self.newline(node) self.body(node.block) self.newline(node)
[docs] def visit_float(self, node): self.write(node.value)
[docs] def visit_int(self, node): self.write(str(node.value))
[docs] def visit_bool(self, node): self.write(".TRUE.") if node.value=="true" else self.write(".FALSE.")
[docs] def visit_str(self, node): if node.value==b'': self.write ('""') else: self.emit_string(node)
[docs] def visit_pair(self, node): self.visit(node.key) self.write(u": ") self.visit(node.value)
[docs] def visit_ExprStatNode(self, node): self.newline(node) self.visit(node.expr)
[docs] def visit_list(self, node): self.write(u'(/') self.comma_separated_list(node.elements) self.write(u'/)')
[docs] def visit_array(self, node): if "type" in dir(node.elements) and node.elements.type != "list": if node.elements.type == "standard_call" and node.elements.function=="range": self.write(u'(/(i_cyml_r,') if len(node.elements.args)==1: self.write(u' i_cyml_r=0,') self.comma_separated_list(node.elements.args) self.write(u'-1)/)') elif len(node.elements.args)>1: self.write(u' i_cyml_r=') self.visit(node.elements.args[0]) self.write(u' ,') self.visit(node.elements.args[1]) self.write(u'-1') if len(node.elements.args)==3: self.write(u' ,') self.visit(node.elements.args[2]) self.write(u')/)') else: self.visit(node.elements.left.elements[0]) else: self.write(u'(/') self.comma_separated_list(node.elements) self.write(u'/)')
[docs] def visit_standard_method_call(self, node): l = node.receiver.pseudo_type if isinstance(l, list): l = l[0] z = self.methods[l][node.message] if callable(z): self.visit(z(node)) else: if not node.args: self.write(z) self.write('(') self.visit(node.receiver) self.write(')') else: "%s.%s"%(self.visit(node.receiver),self.write(z)) self.write("(") self.comma_separated_list(node.args) self.write(")")
[docs] def visit_method_call(self, node): "%s.%s"%(self.visit(node.receiver),self.write(node.message))
[docs] def visit_index(self, node): if "sequence" not in dir(node.sequence): # x[i] -> index self.visit(node.sequence) self.write(u"(") if isinstance(node.index.type, tuple): self.emit_sequence(node.index) else: if node.index.type=='standard_method_call': self.visit(node.index) if node.index.message=="index" : self.write(u")") elif node.index.type=="int": z=int(node.index.value)+1 if z!=0: self.write(str(z)) if int(node.index.value)<0: if z!=0: self.write("%z +") self.write(" SIZE(%s)"%node.sequence.name) self.write(u")") else: self.visit(node.index) self.write("+1)") else: self.visit(node.sequence.sequence) self.write(u"(") self.visit(node.sequence.index) self.write(" ,") self.visit(node.index) self.write(" )")
[docs] def visit_sliceindex(self, node): self.visit(node.receiver) self.write(u"(") if node.message=="sliceindex_from": self.write("(") self.visit(node.args) self.write(u" + 1):") if node.message=="sliceindex_to": self.write(u":") if node.args.type=="binary_op": self.write("(") self.visit(node.args) self.write(")") else: self.visit(node.args) if node.message=="sliceindex": self.write("(") self.visit(node.args[0]) self.write(u" + 1):") if node.args[1].type=="binary_op": self.write("(") self.visit(node.args[1]) self.write(")") else: self.visit(node.args[1]) self.write(u")")
[docs] def visit_continuestatnode(self, node): self.newline(node) self.write('continue')
[docs] def visit_breakstatnode(self, node): self.newline(node) self.write('exit')
"""def visit_module(self, node): self.visit(node.body)"""
[docs] def visit_module(self, node): self.nb=0 self.zmod = middleware(node) self.zmod.transform(node) self.totfunctions = self.zmod.functions for f in self.totfunctions: r = middleware(f) r.transform(f) self.allocatable[f.name] = r.allocated_var if self.model is not None: self.write("MODULE %smod"%self.model.name.capitalize()) else: self.write("Module %s"%self.name) if self.name else self.write("Module Test") self.newline(node) self.indentation += 1 self.newline(node) if "list" in self.zmod.dependencies : self.write("USE list_sub") self.newline(node) if self.model: try: shutil.copyfile(self.f_src, self.f_dest) except: from urllib.request import urlopen file = urlopen(url = "https://raw.githubusercontent.com/AgriculturalModelExchangeInitiative/PyCrop2ML/master/src/pycropml/transpiler/lib/f90/list_sub.f90") g = file.read().decode("utf-8") with open(self.f_dest, "w") as f: f.write(g) for dependency in self.zmod.dependencies: if dependency!="list" and dependency.split("_")[0]=="model": self.write("USE %smod" %dependency.split("model_")[1].capitalize()) self.newline(node) self.write("IMPLICIT NONE") self.newline(node) self.indentation -= 1 self.write("CONTAINS") self.newline(node) self.indentation += 1 self.visit(node.body) self.newline(extra=1) self.indentation -= 1 self.newline(node) self.write("END MODULE")
[docs] def visit_function(self, node): self.newline(extra=1) self.write("RECURSIVE FUNCTION %s"%(node.name)) if node.recursive else self.write("FUNCTION %s"%(node.name)) self.write("(") parameters=[] node_params=[] for pa in node.params: if pa.name not in self.mod_parameters: parameters.append(pa.name) pa.feat="IN" node_params.append(pa) self.write(', &\n '.join(parameters)) if len(self.z.returns)==1 and "name" in dir(self.z.returns[0].value) and self.z.returns[0].value.name not in parameters: self.write(') RESULT(%s)'%(','.join(self.transform_return(node)[0])) ) elif len(self.z.returns)==1 and "name" in dir(self.z.returns[0].value) and self.z.returns[0].value.name in parameters: self.write(') RESULT(res_cyml)') elif len(self.z.returns)>1 or "name" not in dir(self.z.returns[0].value) : self.write(') RESULT(res_cyml)') else: self.write(') RESULT(%s)'%(','.join(self.transform_return(node)[0])) ) self.indentation += 1 self.initialValue=[] newNode = self.add_features(node) self.newline(node) self.write("IMPLICIT NONE") self.newline(node) pnames = [e.name for e in node_params] self.visit_declaration(node_params) #self.visit_decl(node) rname = self.transform_return(node)[0] if rname and rname[0] not in pnames: self.visit_declaration(self.transform_return(node)[1]) var_range = check_range_function() var_range.process(node) if var_range.res : self.visit_declaration([Node(type="int", name="i_cyml_r", pseudo_type="int")]) interVar = [i for i in newNode if "feat" not in dir(i)] self.visit_declaration(interVar) if len(self.z.returns)>=1 or "name" not in dir(self.z.returns[0].value): self.visit_declaration([Node(type="local", name="res_cyml", pseudo_type=node.return_type)]) elif len(self.z.returns)==1 and "name" in dir(self.z.returns[0].value) and self.z.returns[0].value.name in parameters: self.visit_declaration([Node(type="local", name="res_cyml", pseudo_type=node.return_type)]) if self.initialValue: for n in self.initialValue: if n.name in self.z.allocated_var and "elts" in dir(n): self.write(f"ALLOCATE({n.name}(") self.visit(n.elts) self.write("))") self.newline(node) elif not isinstance(n.value, list) and isinstance(n.value, Node): self.write("%s = " %str(n.name)) self.visit(n.value) self.newline(node) elif isinstance(n.pseudo_type, list) and len(n.value)>=1 and n.pseudo_type[0] in ("list","array"): self.write("%s = " %n.name) self.write(u'(/') self.comma_separated_list(n.value) self.write(u'/)') self.newline(node) elif isinstance(n.pseudo_type, str): if n.value==b'': self.write('%s = ""' %(n.name)) else: if n.value=="false": n.value=".FALSE." elif n.value=="true": n.value=".TRUE." self.write("%s = %s" %(n.name, n.value)) self.newline(node) self.indentation -=1 self.newline(node) self.body(node.block) self.newline(node) self.write("END FUNCTION %s"%node.name)
[docs] def visit_function_definition(self, node): self.newline(node) self.nb=0 self.funcname = node.name self.recursive = node.recursive self.z = middleware(node, alloc = self.allocatable) self.z.transform(node) self.parameters=[] self.node_params=[] for pa in node.params: if pa.name not in self.mod_parameters: self.parameters.append(pa.name) self.node_params.append(pa) test = False for f in self.z.returns: if "name" in dir(f.value) and f.value.name in self.parameters: test = True break if node.name.startswith("model_") or node.name.startswith("init_") :node.type="subroutine_def" elif node.name == "main": node.type = "program" elif node.recursive or self.z.returns[0].value.type!="tuple": node.type="function" else: node.type="subroutine_def" self.visit(node)
[docs] def visit_subroutine_def(self, node): self.newline(extra=1) self.write("SUBROUTINE ") self.write("%s("%node.name) self.parameters=[] self.node_params=[] for pa in node.params: if pa.name not in self.mod_parameters: self.parameters.append(pa.name) self.node_params.append(pa) return_params = self.transform_return(node)[0] parameters = self.parameters+[e for e in return_params if e not in self.parameters] self.write(', &\n '.join(parameters)) self.write(')') self.indentation += 1 self.newline(node) self.write("IMPLICIT NONE") self.initialValue=[] newNode = self.add_features(node) if check_range_function().process(node): self.visit_declaration([Node(type="int", name="i_cyml_r", pseudo_type="int")]) self.visit_declaration(newNode) #self.visit_decl(node) if self.initialValue: for n in self.initialValue: if n.name in self.z.allocated_var and "elts" in dir(n): self.write(f"ALLOCATE({n.name}(") self.visit(n.elts) self.write("))") self.newline(node) elif "value" in dir(n) and not isinstance(n.value, list) and isinstance(n.value, Node): self.write("%s = " %str(n.name)) self.visit(n.value) self.newline(node) elif "value" in dir(n) and len(n.value)>=1 and (isinstance(n.pseudo_type, list) and n.pseudo_type[0] in ("list", "array")): self.write("%s = " %n.name) self.write(u'(/') self.comma_separated_list(n.value) self.write(u'/)') self.newline(node) elif "value" in dir(n) and isinstance(n.pseudo_type, str): if n.value==b'': self.write('%s = ""' %(n.name)) else: if n.value=="false": n.value=".FALSE." elif n.value=="true": n.value=".TRUE." self.write("%s = %s" %(n.name, n.value)) self.newline(node) self.indentation -=1 self.newline(node) if self.model and node.name.startswith("model_"): self.write(self.doc.header) self.newline(node) self.write(self.doc.desc) self.newline(node) self.write(self.doc.inputs_doc) self.newline(node) self.write(self.doc.outputs_doc) self.newline(node) self.body(node.block) self.newline(node) self.write("END FUNCTION %s"%node.name) if node.recursive==True else self.write("END SUBROUTINE %s"%node.name) self.newline(node)
[docs] def visit_program(self, node): self.write("PROGRAM MAIN") self.newline(node) self.write("IMPLICIT NONE") self.newline(node) self.indentation +=1 self.initialValue=[] newNode = self.add_features(node) self.visit_declaration(newNode) #self.visit_decl(node) if self.initialValue: for n in self.initialValue: if len(n.value)>=1 and (isinstance(n.pseudo_type, list) and n.pseudo_type[0] in ("list", "array")): self.write("%s = " %n.name) self.write(u'(/') self.comma_separated_list(n.value) self.write(u'/)') self.newline(node) elif isinstance(n.pseudo_type, str): if n.value==b'': self.write('%s = ""' %(n.name)) else: self.write("%s = %s" %(n.name, n.value)) self.newline(node) self.newline(node) self.body(node.block) self.newline(node) self.indentation -=1 self.write("END PROGRAM MAIN")
[docs] def subOrFun(self, node): res = False # if subroutine return res
[docs] def transform_return(self, node): if len(self.z.returns)==1: returnvalues=self.z.returns[0].value if returnvalues.type=="tuple": output = [elt.name for elt in returnvalues.elements] node_output = [elt for elt in returnvalues.elements] else: if "name" in dir(returnvalues): output = [returnvalues.name] node_output = [returnvalues] else: output = [] node_output = [] else: output = [] node_output = [] return output, node_output
[docs] def retrieve_params(self, node): parameters=[] node_params=[] for pa in node.params: parameters.append(pa.name) node_params.append(pa) return node.params
[docs] def internal_declaration(self, node): statements = node.block if isinstance(statements, list): intern_decl = statements[0].decl if statements[0].type == "declaration" else None for stmt in statements[1:]: if stmt.type == "declaration": intern_decl = (intern_decl if intern_decl else []) + stmt.decl if self.z.ForSequence: for i in range(self.z.nbForSeq): intern_decl = intern_decl + [Node(type="int", name="i_cyml%s" % i, pseudo_type="int")] else: intern_decl = statements.decl if statements.type == "declaration" else None return intern_decl
[docs] def add_features(self, node): self.internal = self.internal_declaration(node) internal_name=[] if self.internal is not None: self.internal = self.internal if isinstance(self.internal,list) else [self.internal] for inter in self.internal: if 'elements' in dir(inter):# and not isinstance(inter.pseudo_type, list) self.initialValue.append(Node(type="initial",name = inter.name, pseudo_type=inter.pseudo_type, value = inter.elements)) elif 'value' in dir(inter): self.initialValue.append(Node(type="initial",name = inter.name, pseudo_type=inter.pseudo_type, value = inter.value)) elif 'elts' in dir(inter) and inter.elts and inter.elts[0].type!="int": self.initialValue.append(Node(type="initial",name = inter.name, pseudo_type=inter.pseudo_type, elts = inter.elts)) internal_name= [e.name for e in self.internal] self.params = self.retrieve_params(node) params_name = [e.name for e in self.params] outputs = self.transform_return(node)[1] if not isinstance(outputs, list): outputs=[outputs] outputs_name = [e.name for e in outputs] variables = self.params+self.internal if self.internal else self.params newNode=[] for var in variables: if var not in newNode: if var.name in params_name and var.name not in outputs_name: var.feat = "IN" newNode.append(var) if var.name in params_name and var.name in outputs_name: var.feat = "INOUT" newNode.append(var) if var.name in internal_name and var.name in outputs_name: var.feat = "OUT" newNode.append(var) if var.name in internal_name and var.name not in outputs_name: newNode.append(var) return newNode
[docs] def part_declaration(self, node): self.visit_decl(node) if node.name in self.mod_parameters: self.write(", PARAMETER :: %s = %s"%(transf_var_name(node.name), valParam(self.model,node.name))) elif 'feat' in dir(node): self.write(", INTENT(%s) "%(node.feat))
[docs] def visit_declaration(self, node): self.newline(node) node = node if isinstance(node, list) else node.decl for n in node: if n.name not in self.mod_parameters: self.newline(node) self.part_declaration(n) self.write(':: %s'%(transf_var_name(n.name))) else: self.newline(node) self.part_declaration(n) self.newline(node)
[docs] def visit_implicit_return(self, node): if (not self.funcname.startswith("model_") and not self.funcname.startswith("init_")) : self.newline(node) if len(self.z.returns)==1 and "name" in dir(self.z.returns[0].value) and self.z.returns[0].value.name in self.parameters: newNode = Node(type="assignment",target=Node(type="local", name="res_cyml"),\ value=node.value) self.visit(newNode) self.newline(node) self.write("RETURN") self.newline(node) elif len(self.z.returns)==1 and "name" in dir(self.z.returns[0].value): pass elif len(self.z.returns)>1 or self.z.returns[0].value.type!="tuple" : newNode = Node(type="assignment",target=Node(type="local", name="res_cyml"),\ value=node.value) self.visit(newNode) self.newline(node) self.write("RETURN") self.newline(node) else: pass
[docs] def visit_list_decl(self, node): if not isinstance(node[1], list): self.write(self.types[node[1]]) self.write(', ALLOCATABLE ') self.write(", DIMENSION(:)") else: node = node[1] self.write(self.types[node[1]]) self.write(', ALLOCATABLE') self.write(", DIMENSION(:) ")
[docs] def visit_datetime_decl(self, node): return self.visit_str_decl(node)
[docs] def visit_datetime(self, node): return self.visit_str(node)
[docs] def visit_array_decl(self, node): self.write(self.types[node.pseudo_type[1]]) self.write(" , DIMENSION(") if node.name in self.z.allocated_var: self.write(":") elif "elts" not in dir(node) or not node.elts or len(node.elts)==0: self.write(":") else: self.comma_separated_list(node.elts) if isinstance(node.elts, list) else self.visit(node.elts) self.write(" )") if node.name in self.z.allocated_var or (node.name=="res_cyml" and ("elts" not in dir(node) or not node.elts or len(node.elts)==0)): self.write(", ALLOCATABLE ") elif node.name in self.z.allocated_var_s and node.name in self.parameters: self.write(", ALLOCATABLE ") elif self.funcname.startswith("model_") or self.funcname.startswith("init_") : if node.name in self.privates or node.name in self.states_arr: self.write(", ALLOCATABLE ") self.allocatable[self.funcname].append(node.name) '''else: if ("feat" not in dir(node)) and (("elts" not in dir(node) or not node.elts or len(node.elts)==0)): # and node.name not in self.parameters : self.write(", ALLOCATABLE ") if("feat" in dir(node) and node.feat in ("OUT", "INOUT")) and ("elts" in dir(node) and (not node.elts or len(node.elts)==0)): self.write(", ALLOCATABLE ") if("feat" in dir(node) and node.feat == "INOUT" and node.type in ("floatarray", "intarray", "strarray", "boolarray")): self.write(", ALLOCATABLE ")'''
[docs] def visit_float_decl(self, node): self.write(self.types[node])
[docs] def visit_int_decl(self, node): self.write(self.types[node])
[docs] def visit_str_decl(self, node): self.write(self.types[node])
[docs] def visit_bool_decl(self, node): self.write(self.types[node])
[docs] def visit_decl(self, nodeT): node = nodeT.pseudo_type if isinstance(node, list) or node[0]=="array" : if node[0]=="list": self.visit_list_decl(node) if node[0]=="array": self.visit_array_decl(nodeT) else: if node=="float": self.visit_float_decl(node) if node=="int": self.visit_int_decl(node) if node=="str": self.visit_str_decl(node) if node=="bool": self.visit_str_decl(node) if node=="datetime": self.visit_str_decl(node)
[docs] def visit_call(self, node): want_comma = [] def write_comma(): if want_comma: self.write(', ') else: want_comma.append(True) if "attrib" in dir(node): self.write(u"%s.%s"%(node.namespace,self.visit(node.function))) else: if callable(node.function): self.visit(node.function(node)) else: self.write(node.function) self.write('(') if isinstance(node.args, list): for arg in node.args: write_comma() self.visit(arg) else:self.visit(node.args) self.write(')')
[docs] def visit_standard_call(self, node): node.function = self.functions[node.namespace][node.function] self.visit_call(node)
[docs] def visit_combine(self, node): self.newline(node) for n in node.args: if not isinstance(n, list): self.visit(n) else: for ni in n: self.visit(ni) if ni!=n[len(n)-1]: self.write(", ")
[docs] def visit_subroutine(self,node): self.write(node.function) self.write('(') self.comma_separated_list(node.args) if "elements" in dir(node.receiver): elts = node.receiver.elements else: elts = [node.receiver] argname=[] for n in node.args: if "name" in dir(n): argname.append(n.name) for n in elts: if "name" in dir(n) and n.name not in argname: self.write(',') self.write(n.name) elif "sequence" in dir(n): self.write(',') self.visit(n) self.write(')')
[docs] def visit_constant(self, node): self.write(self.constant[node.library][node.name])
[docs] def visit_importfrom(self, node): pass
[docs] def visit_custom_call(self, node): self.visit_call(node)
[docs] def visit_for_statement(self, node): self.newline(node) self.write("DO i_cyml%s = 1, SIZE("%self.nb) if "sequences" in dir(node): self.visit(node.sequences) self.write(")") self.newline(node) self.indentation +=1 if "iterators" in dir(node): self.visit(node.iterators) self.write(" = ") self.visit(node.sequences) self.write("(i_cyml%s)"%self.nb) self.nb = self.nb+1 self.newline(node) self.indentation -=1 self.body(node.block) self.newline(node) self.write("END DO")
[docs] def visit_for_iterator_with_index(self, node): self.visit(node.index) self.write(' , ') self.visit(node.iterator)
[docs] def visit_for_iterator(self, node): self.visit(node.iterator)
[docs] def visit_for_sequence(self, node): self.visit(node.sequence)
[docs] def visit_for_range_statement(self, node): self.newline(node) self.write("DO ") self.index.append(node.index.name) self.visit(node.index) self.write(" = ") self.visit(node.start) self.write(' , ') self.visit(node.end) if node.step.type=='unary_op' and node.step.operator=="-": self.write("+1") else: self.write("-1") self.write(', ') self.visit(node.step) self.body(node.block) self.newline(node) self.write("END DO")
[docs] def visit_while_statement(self, node): self.newline(node) self.write('DO WHILE ( ') self.visit(node.test) self.write(' ) ') self.body_or_else(node) self.newline(node) self.write("END DO")
[docs] def checkIndex(self, node): indexNames=[] if node.type=="index": if node.index.type=="binary_op": z1=node.index while z1.type=="binary_op": if "name" in dir(z1.left): indexNames.append(z1.left.name) if "name" in dir(z1.right): indexNames.append(z1.right.name) z1=z1.left return indexNames
[docs] def valParam(model,name): for mod in model.inputs: if mod.name==name: val = mod.default return val
[docs] def checkList(list1, list2): test=False for i in list1: for j in list2: if i==j: test=True break return test
[docs] class FortranCompo(FortranGenerator): """ his class used to generates states, rates and auxiliary classes for Fortran90 language. Args: FortranGenerator (FortranGenertor): Generation of fortran source code """ def __init__(self, tree=None, model=None, name = None): self.tree = tree self.model=model self.name = name FortranGenerator.__init__(self,tree, model, self.name)
[docs] def visit_importfrom(self, node): pass