# coding: utf8
from pycropml.transpiler.codeGenerator import CodeGenerator
from pycropml.transpiler.rules.rRules import RRules, changetyp
from pycropml.transpiler.generators.docGenerator import DocGenerator
import os
from pycropml.render_cyml import signature
from path import Path
from pycropml.transpiler.Parser import parser
from pycropml.transpiler.ast_transform import AstTransformer, transform_to_syntax_tree
from pycropml.nameconvention import signature2, signature2_from_name
[docs]
class RGenerator(CodeGenerator, RRules):
"""This class contains the specific properties of
R language and use the NodeVisitor to generate a R
code source from a well formed syntax tree.
"""
def __init__(self, tree, model=None, name = None):
CodeGenerator.__init__(self)
RRules.__init__(self)
self.tree=tree
self.model=model
self.name = name
self.indent_with=' '*4
self.imp=True
self.index=[]
self.funcname=None
self.write("library(gsubfn)")
self.newline(1)
if self.model:
self.doc= DocGenerator(model, "#'")
[docs]
def visit_import(self, node):
pass
[docs]
def visit_notAnumber(self, node):
self.write("NaN")
[docs]
def visit_assignment(self, node):
self.newline(node)
if node.target.type=="tuple" and node.value.type=="custom_call":
self.write("result <- ")
self.visit(node.value)
self.newline(node)
for i, n in enumerate(node.target.elements):
self.visit(n)
self.write(f" <- result[[{i+1}]]")
self.newline(node)
elif node.target.type=="tuple" and node.value.type=="tuple":
self.write("result <- list(")
self.comma_separated_list(node.value.elements)
self.write(")")
self.newline(node)
for i, n in enumerate(node.target.elements):
self.visit(n)
self.write(f" <- result[[{i+1}]]")
self.newline(node)
else:
self.newline(node)
self.visit(node.target)
self.write(' <- ')
self.visit(node.value)
[docs]
def visit_constant(self, node):
self.write(self.constant[node.library][node.name])
[docs]
def visit_cond_expr_node(self, node):
self.write(u" if (")
self.visit(node.test)
self.write(")")
self.visit(node.true_val)
self.write(u" else ")
self.visit(node.false_val)
[docs]
def visit_if_statement(self, node):
self.newline(node)
self.write('if (')
self.visit(node.test)
self.write(')')
self.newline(node)
self.write('{')
self.body(node.block)
self.newline(node)
self.write('}')
while True:
else_ = node.otherwise
if len(else_) == 0:
break
elif len(else_) == 1 and else_[0].type=='elseif_statement':
self.visit(else_[0])
else:
self.visit(else_)
break
break
[docs]
def visit_elseif_statement(self, node):
self.newline()
self.write('else if ( ')
self.visit(node.test)
self.write(')')
self.newline(node)
self.write('{')
self.body(node.block)
self.newline(node)
self.write('}')
[docs]
def visit_else_statement(self, node):
self.newline()
self.write('else')
self.newline(node)
self.write('{')
self.body(node.block)
self.newline(node)
self.write('}')
[docs]
def visit_float(self, node):
self.write(node.value)
[docs]
def visit_bool(self, node):
print(node.y)
self.write(node.value.upper())
[docs]
def visit_str(self, node):
self.emit_string(node)
#self.write("%s"%str(node.value))
[docs]
def visit_tuple(self, node):
self.write("list")
self.emit_sequence(node.elements, u"[]")
[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):
if len(node.elements)==0: return self.write("vector()")
self.write("c")
self.emit_sequence(node.elements, u"()")
[docs]
def visit_datetime(self, node):
self.write("'%s/%s/%s'"%(node.value[0].value,node.value[1].value,node.value[2].value))
[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_standard_call(self, node):
node.function = self.functions[node.namespace][node.function]
self.visit_call(node)
[docs]
def visit_index(self, node):
self.visit(node.sequence)
self.write(u"[")
if isinstance(node.index.type, tuple):
self.emit_sequence(node.index)
self.write(u"]")
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]")
[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_module(self, node):
self.newline(extra=1)
self.newline(node)
self.visit(node.body)
[docs]
def visit_comparison(self, node):
#self.write('(')
self.visit_binary_op(node)
#self.write(')')
[docs]
def visit_method_call(self, node):
"%s.%s"%(self.visit(node.receiver),self.write(node.message))
[docs]
def visit_binary_op(self, node):
op = node.op
prec = self.binop_precedence.get(op, 0)
self.operator_enter(prec)
if op in ("is_not", "is"):
self.visit(self.binary_op[op](node))
else:
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)
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 visit_function_definition(self, node):
self.newline(extra=1)
self.newline(node)
self.funcname = node.name
if node.name.startswith("init_"):
self.write(f"#' Initialization of the {self.model.description.Title}\n")
self.write(f"#' \n")
self.write(f"#' This function initialize the {self.model.description.Title}")
self.newline(1)
for arg in node.params:
for inp in self.model.inputs:
if arg.name == inp.name:
self.write(f"#' @param {inp.name} ({inp.unit}) {inp.description} {inp.parametercategory if 'parametercategory' in dir(inp) else inp.variablecategory} ({inp.default}, {inp.min}-{inp.max}) ")
self.newline(1)
self.write(f"#'")
self.newline(1)
self.write(f"#' @return")
self.newline(1)
self.write(f"#' \\describe{{")
self.newline(1)
for out in self.model.outputs:
if out.variablecategory=="state":
self.write(f"#' \\item{{{out.name} ({out.unit})}}{{{out.description} {out.variablecategory} ({out.min}-{inp.max})}}")
self.newline(1)
self.newline(1)
self.write(f"#' }}")
self.newline(1)
self.write(f"#' @export")
self.newline(1)
if self.model and node.name.startswith("model_") and node.name.split("model_")[1]==signature(self.model):
"""self.write(f"#' @Title {self.model.description.Title}")
self.newline(1)
self.write(f"#' @Description {self.model.description.ExtendedDescription}")
self.newline(1)
self.write(f"#' @Authors {self.model.description.Authors} ")
self.newline(1)
self.write(f"#' @Institutions {self.model.description.Institution}")
self.newline(1)
self.write(f"#' @Reference {self.model.description.Reference}")
self.newline(1)
self.write(f"#' @Version {self.model.version}")"""
self.write(f"#' {self.model.description.Title}")
self.newline(1)
self.write(f"#'")
self.newline(1)
self.write(f"#' This function compute the {self.model.description.Title}")
self.newline(1)
for inp in self.model.inputs:
self.write(f"#' @param {inp.name} ({inp.unit}) {inp.description} {inp.parametercategory if 'parametercategory' in dir(inp) else inp.variablecategory} ({inp.default}, {inp.min}-{inp.max}) ")
self.newline(1)
self.write(f"#'")
self.newline(1)
self.write(f"#' @return")
self.newline(1)
self.write(f"#' \\describe{{")
self.newline(1)
for out in self.model.outputs:
self.write(f"#' \\item{{{out.name} ({out.unit})}}{{{out.description} {out.variablecategory} ({out.min}-{inp.max})}} ")
self.newline(1)
self.newline(1)
self.write(f"#' }}")
self.newline(1)
self.write(f"#' @export")
self.newline(1)
"""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.model = None"""
self.write('%s <- function (' % node.name)
for i, pa in enumerate(node.params):
self.write(pa.name)
if "value" in dir(pa) or "elements" in dir(pa) or "pairs" in dir(pa) :
self.write(" = ")
self.visit(pa)
if i!= (len(node.params)-1):
self.write(',\n ')
self.write('){')
self.newline(node)
self.body(node.block)
self.newline(node)
self.write("}")
[docs]
def visit_implicit_return(self, node):
self.newline(node)
if node.value is None:
pass
elif node.value.type=="tuple":
self.write("return (list (")
self.multValreturn(node.value.elements)
self.write("))")
else:
if self.funcname.startswith("model"):
self.write("return (list('%s' = %s))"%(node.value.name, node.value.name))
else:
self.write('return( ')
self.visit(node.value)
self.write(')')
[docs]
def multValreturn(self, node):
for n in node:
self.write('"%s" = %s'%(n. name, n.name))
if n!=node[len(node)-1]:
self.write(",")
[docs]
def visit_declaration(self, node):
self.newline(node)
for n in node.decl :
if 'value' in dir(n) and n.type in ("int", "float"):
self.newline(node)
self.write(n.name)
self.write(" <- ")
if isinstance(n.value, str):
self.write(n.value)
else:
# n.value is a Node (e.g., unary_op for -999), so visit it
self.visit(n.value)
elif "value" not in dir(n) and n.type =="int":
self.newline(node)
self.write(n.name)
self.write(" <- ")
self.write("0")
elif "value" not in dir(n) and n.type =="float":
self.newline(node)
self.write(n.name)
self.write(" <- ")
self.write("0.0")
elif 'value' in dir(n) and n.type=="bool":
self.newline(node)
self.write(n.name)
self.write(" <- ")
self.write(str(n.value).upper())
elif "value" not in dir(n) and n.type =="bool":
self.newline(node)
self.write(n.name)
self.write(" <- ")
self.write("FALSE")
elif 'value' in dir(n) and n.type=="str":
self.newline(node)
self.write(n.name)
self.write(" <- ")
self.emit_string(n)
elif "value" not in dir(n) and n.type =="str":
self.newline(node)
self.write(n.name)
self.write(" <- ")
self.write("''")
elif 'elements' in dir(n) and n.type in ("list", "tuple"):
self.newline(node)
self.write(n.name)
self.write(" <- ")
if n.type=="list":
self.visit_list(n)
else: self.visit_tuple(n)
elif "elts" in dir(n) and n.type=='datetime':
self.newline(node)
self.write(n.name)
self.write(" <- ")
self.visit(n.elts)
elif n.type=="array" and 'elements' in dir(n):
self.visit_array(n)
elif n.type in ("list", "array"):
self.newline(node)
self.write(n.name)
if n.type=="list": self.write(" <- vector()")
if n.type=="array":
typ = n.pseudo_type[-1]
newtyp = changetyp(typ)
if "elts" in dir(n) and n.elts:
self.write(" <- vector(,")
self.visit(n.elts[0])
self.write(")")
else:
self.write("<- vector()")
[docs]
def visit_empty(self, node):
pass
[docs]
def visit_array(self,node):
if node.elements.type != "list":
self.write(" rep(")
self.visit(node.elements.left.elements[0])
self.write(",")
self.visit(node.elements.right)
self.write(")")
else:
self.write("c(")
self.comma_separated_list(node.elements)
self.write(")")
[docs]
def visit_none(self, node):
self.write("NULL")
[docs]
def visit_continuestatnode(self, node):
self.newline(node)
self.write('next')
[docs]
def visit_breakstatnode(self, node):
self.newline(node)
self.write('break')
[docs]
def visit_importfrom(self, node):
pass
[docs]
def visit_for_statement(self, node):
self.newline(node)
self.write("for( ")
if "iterators" in dir(node):
self.visit(node.iterators)
if "sequences" in dir(node):
self.visit(node.sequences)
self.write(')')
self.newline(node)
self.newline(node)
self.write('{')
self.body(node.block)
self.write('}')
[docs]
def visit_for_iterator_with_index(self, node):
self.visit(node.index)
self.write(' , ')
self.visit(node.iterator)
[docs]
def visit_for_sequence_with_index(self, node):
self.write(" in enumerate(")
self.visit(node.sequence)
self.write('){')
[docs]
def visit_for_iterator(self, node):
self.visit(node.iterator)
self.write(" in ")
[docs]
def visit_for_sequence(self, node):
self.visit(node.sequence)
#self.write(":")
[docs]
def visit_for_range_statement(self, node):
self.newline(node)
self.index.append(node.index.name)
self.write("for( ")
self.visit(node.index)
self.write(" in seq(")
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.write(')){')
self.body(node.block)
self.newline(node )
self.write('}')
[docs]
def visit_while_statement(self, node):
self.newline(node)
self.write('while( ')
self.visit(node.test)
self.write('){')
self.body_or_else(node)
self.write('}')
[docs]
class RCompo(RGenerator):
""" This class used to generates states, rates and auxiliary classes
for C# languages.
"""
def __init__(self, tree, model=None, name=None):
RGenerator.__init__(self,tree, model, name)
self.tree = tree
self.model = model
self.name = name
[docs]
def visit_module(self, node):
self.newline(extra=1)
self.newline(node)
self.visit(node.body)