class RCodeGenerator(CLikeCodeGenerator): tpl_return_statement = CodeTemplate("return({value})") tpl_var_assignment = CodeTemplate("{var_name} <- {value}") def __init__(self, *args, **kwargs): super(RCodeGenerator, self).__init__(*args, **kwargs) def add_var_declaration(self, size): return self.get_var_name() def add_function_def(self, name, args): function_def = name + " <- function(" function_def += ",".join([arg for _, arg in args]) function_def += ") {" self.add_code_line(function_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args, is_vector_output): self.add_function_def(name, args) yield self.add_block_termination() def array_index_access(self, array_name, index): return super().array_index_access(array_name, index + 1) def vector_init(self, values): return "c(" + ", ".join(values) + ")"
class RustCodeGenerator(CLikeCodeGenerator): tpl_var_declaration = CodeTemplate("let {var_name}: {var_type};") tpl_num_value = CodeTemplate("{value}_f64") tpl_if_statement = CodeTemplate("if {if_def} {{") tpl_return_statement = CodeTemplate("{value}") scalar_type = "f64" vector_type = "Vec<f64>" def add_function_def(self, name, args, is_scalar_output): func_args = ", ".join([ f"{n}: {self._get_var_declare_type(is_vector)}" for is_vector, n in args]) return_type = self._get_var_declare_type(not is_scalar_output) function_def = f"fn {name}({func_args}) -> {return_type} {{" self.add_code_line(function_def) self.increase_indent() @contextmanager def function_definition(self, name, args, is_scalar_output): self.add_function_def(name, args, is_scalar_output) yield self.add_block_termination() def vector_init(self, values): return (f"vec![{', '.join(values)}]") def _get_var_declare_type(self, is_vector): return self.vector_type if is_vector else self.scalar_type
class RCodeGenerator(CLikeCodeGenerator): tpl_return_statement = CodeTemplate("return({value})") tpl_var_assignment = CodeTemplate("{var_name} <- {value}") def add_var_declaration(self, size): return self.get_var_name() def add_function_def(self, name, args): func_args = ', '.join([arg for _, arg in args]) function_def = f"{name} <- function({func_args}) {{" self.add_code_line(function_def) self.increase_indent() @contextmanager def function_definition(self, name, args, is_vector_output): self.add_function_def(name, args) yield self.add_block_termination() def array_index_access(self, array_name, index): return super().array_index_access(array_name, index + 1) def vector_init(self, values): return f"c({', '.join(values)})"
class PowershellCodeGenerator(CLikeCodeGenerator): tpl_var_declare = CodeTemplate("{var_type}{var_name} = {init_val}") tpl_var_assignment = CodeTemplate("{var_name} = {value}") tpl_array_index_access = CodeTemplate("${array_name}[{index}]") tpl_return_statement = CodeTemplate("return {value}") scalar_type = "[double]" vector_type = "[double[]]" operator_map = { CompOpType.EQ: "-eq", CompOpType.NOT_EQ: "-ne", CompOpType.GTE: "-ge", CompOpType.LTE: "-le", CompOpType.GT: "-gt", CompOpType.LT: "-lt" } def add_function_def(self, name, args, is_scalar_output): func_args = ", ".join( [f"{self._get_var_type(is_vector)} ${n}" for is_vector, n in args]) function_def = f"function {name}({func_args}) {{" self.add_code_line(function_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args, is_scalar_output): self.add_function_def(name, args, is_scalar_output) yield self.add_block_termination() def function_invocation(self, function_name, *args): functions_args = " ".join(map(lambda x: f"$({x})", args)) return f"{function_name} {functions_args}" def math_function_invocation(self, function_name, *args): return f"{function_name}({', '.join(map(str, args))})" def get_var_name(self): return f"${super().get_var_name()}" def add_var_declaration(self, size): var_name = self.get_var_name() self.add_code_line( self.tpl_var_declare(var_type=self._get_var_type(size > 1), var_name=var_name, init_val="@(0.0)" if size > 1 else "0.0")) return var_name def vector_init(self, values): vals = ", ".join(map(lambda x: f"$({x})", values)) return f"@({vals})" def _get_var_type(self, is_vector): return self.vector_type if is_vector else self.scalar_type def _comp_op_overwrite(self, op): return self.operator_map[op]
class CCodeGenerator(CLikeCodeGenerator): tpl_scalar_var_declare = CodeTemplate("double {var_name};") tpl_vector_var_declare = CodeTemplate("double {var_name}[{size}];") scalar_type = "double" vector_type = "double *" def add_function_def(self, name, args, is_scalar_output): return_type = self.scalar_type if is_scalar_output else "void" func_args = ", ".join([ f"{self._get_var_declare_type(is_vector)} {n}" for is_vector, n in args]) function_def = f"{return_type} {name}({func_args}) {{" self.add_code_line(function_def) self.increase_indent() @contextmanager def function_definition(self, name, args, is_scalar_output): self.add_function_def(name, args, is_scalar_output) yield self.add_block_termination() def add_var_declaration(self, size): var_name = self.get_var_name() if size > 1: tpl = self.tpl_vector_var_declare else: tpl = self.tpl_scalar_var_declare self.add_code_line(tpl(var_name=var_name, size=size)) return var_name def add_var_assignment(self, var_name, value, value_size): if value_size == 1: return super().add_var_assignment(var_name, value, value_size) # vectors require special handling since we can't just assign # vectors in C. self.add_assign_array_statement(value, var_name, value_size) def add_assign_array_statement(self, source_var, target_var, size): self.add_code_line(f"memcpy({target_var}, {source_var}, " f"{size} * sizeof(double));") def add_dependency(self, dep): self.prepend_code_line(f"#include {dep}") def vector_init(self, values): return f"(double[]){{{', '.join(values)}}}" def _get_var_declare_type(self, is_vector): return self.vector_type if is_vector else self.scalar_type
class PythonCodeGenerator(ImperativeCodeGenerator): tpl_num_value = CodeTemplate("{value}") tpl_infix_expression = CodeTemplate("({left}) {op} ({right})") tpl_return_statement = CodeTemplate("return {value}") tpl_array_index_access = CodeTemplate("{array_name}[{index}]") tpl_if_statement = CodeTemplate("if {if_def}:") tpl_else_statement = CodeTemplate("else:") tpl_var_assignment = CodeTemplate("{var_name} = {value}") tpl_var_declaration = CodeTemplate("") tpl_block_termination = CodeTemplate("") def add_function_def(self, name, args): function_def = f"def {name}({', '.join(args)}):" self.add_code_line(function_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args): self.add_function_def(name, args) yield def vector_init(self, values): return f"[{', '.join(values)}]" def add_dependency(self, dep, alias=None): dep_str = f"import {dep}" if alias: dep_str += f" as {alias}" self.prepend_code_line(dep_str)
class RubyCodeGenerator(ImperativeCodeGenerator): tpl_var_declaration = CodeTemplate("") tpl_num_value = CodeTemplate("{value}") tpl_infix_expression = CodeTemplate("({left}) {op} ({right})") tpl_return_statement = tpl_num_value tpl_array_index_access = CodeTemplate("{array_name}[{index}]") tpl_if_statement = CodeTemplate("if {if_def}") tpl_else_statement = CodeTemplate("else") tpl_block_termination = CodeTemplate("end") tpl_var_assignment = CodeTemplate("{var_name} = {value}") def add_function_def(self, name, args): func_def = f"def {name}({', '.join(args)})" self.add_code_line(func_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args): self.add_function_def(name, args) yield self.add_block_termination() def method_invocation(self, method_name, obj, args): return f"({obj}).{method_name}({', '.join(map(str, args))})" def vector_init(self, values): return f"[{', '.join(values)}]"
class GoCodeGenerator(ImperativeCodeGenerator): tpl_num_value = CodeTemplate("{value}") tpl_infix_expression = CodeTemplate("({left}) {op} ({right})") tpl_array_index_access = CodeTemplate("{array_name}[{index}]") tpl_else_statement = CodeTemplate("}} else {{") tpl_block_termination = CodeTemplate("}}") tpl_var_declaration = CodeTemplate("var {var_name} {var_type}") tpl_return_statement = CodeTemplate("return {value}") tpl_if_statement = CodeTemplate("if {if_def} {{") tpl_var_assignment = CodeTemplate("{var_name} = {value}") scalar_type = "float64" vector_type = "[]float64" def __init__(self, *args, **kwargs): super(GoCodeGenerator, self).__init__(*args, **kwargs) def add_function_def(self, name, args, is_scalar_output): return_type = self._get_var_declare_type(not is_scalar_output) function_def = "func " + name + "(" function_def += ", ".join([ n + " " + self._get_var_declare_type(is_vector) for is_vector, n in args ]) function_def += ") " + return_type + " {" self.add_code_line(function_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args, is_scalar_output): self.add_function_def(name, args, is_scalar_output) yield self.add_block_termination() def _get_var_declare_type(self, is_vector): return self.vector_type if is_vector else self.scalar_type def add_dependency(self, dep): dep_str = 'import "' + dep + '"' super().prepend_code_line(dep_str) @staticmethod def vector_init(values): return "[]float64{" + ", ".join(values) + "}"
class GoCodeGenerator(ImperativeCodeGenerator): tpl_num_value = CodeTemplate("{value}") tpl_infix_expression = CodeTemplate("({left}) {op} ({right})") tpl_array_index_access = CodeTemplate("{array_name}[{index}]") tpl_else_statement = CodeTemplate("}} else {{") tpl_block_termination = CodeTemplate("}}") tpl_var_declaration = CodeTemplate("var {var_name} {var_type}") tpl_return_statement = CodeTemplate("return {value}") tpl_if_statement = CodeTemplate("if {if_def} {{") tpl_var_assignment = CodeTemplate("{var_name} = {value}") scalar_type = "float64" vector_type = "[]float64" def add_function_def(self, name, args, is_scalar_output): return_type = self._get_var_declare_type(not is_scalar_output) func_args = ", ".join([ f"{n} {self._get_var_declare_type(is_vector)}" for is_vector, n in args ]) function_def = f"func {name}({func_args}) {return_type} {{" self.add_code_line(function_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args, is_scalar_output): self.add_function_def(name, args, is_scalar_output) yield self.add_block_termination() def _get_var_declare_type(self, is_vector): return self.vector_type if is_vector else self.scalar_type def add_dependency(self, dep): super().prepend_code_line(f'import "{dep}"') def vector_init(self, values): return f"[]float64{{{', '.join(values)}}}"
class PhpCodeGenerator(CLikeCodeGenerator): tpl_array_index_access = CodeTemplate("$$${array_name}[${index}]") def __init__(self, *args, **kwargs): super(PhpCodeGenerator, self).__init__(*args, **kwargs) def add_function_def(self, name, args): function_def = "function " + name + "(" function_def += ", ".join([("array " if is_vector else "") + "$" + n for is_vector, n in args]) function_def += ") {" self.add_code_line(function_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args): self.add_function_def(name, args) yield self.add_block_termination() def get_var_name(self): return "$" + super().get_var_name() def add_var_declaration(self, size): var_name = self.get_var_name() self.add_var_assignment(var_name=var_name, value="array()" if size > 1 else "null", value_size=size) return var_name def vector_init(self, values): return "array(" + ", ".join(values) + ")" def _comp_op_overwrite(self, op): if op == CompOpType.EQ: return "===" elif op == CompOpType.NOT_EQ: return "!==" else: return op.value
class PhpCodeGenerator(CLikeCodeGenerator): tpl_array_index_access = CodeTemplate("${array_name}[{index}]") def add_function_def(self, name, args): func_args = ", ".join([ f"{'array ' if is_vector else ''}${n}" for is_vector, n in args]) function_def = f"function {name}({func_args}) {{" self.add_code_line(function_def) self.increase_indent() @contextmanager def function_definition(self, name, args): self.add_function_def(name, args) yield self.add_block_termination() def get_var_name(self): return f"${super().get_var_name()}" def add_var_declaration(self, size): var_name = self.get_var_name() self.add_var_assignment( var_name=var_name, value="array()" if size > 1 else "null", value_size=size) return var_name def vector_init(self, values): return f"array({', '.join(values)})" def _comp_op_overwrite(self, op): if op == CompOpType.EQ: return "===" elif op == CompOpType.NOT_EQ: return "!==" else: return op.value
class HaskellCodeGenerator(FunctionalCodeGenerator): tpl_function_signature = CodeTemplate("{function_name} =") tpl_if_statement = CodeTemplate("if ({if_def}) then") tpl_else_statement = CodeTemplate("else") tpl_num_value = CodeTemplate("{value}") tpl_infix_expression = CodeTemplate("({left}) {op} ({right})") tpl_module_definition = CodeTemplate("module {module_name} where") def array_index_access(self, array_name, index): return self.tpl_infix_expression(left=array_name, op="!!", right=index) def add_if_termination(self): self.decrease_indent() def add_function_def(self, name, args, is_scalar_output): types = " -> ".join([ "[Double]" if is_vector else "Double" for is_vector, _ in [*args, (not is_scalar_output, None)] ]) signature = f"{name} :: {types}" self.add_code_line(signature) func_args = " ".join([n for _, n in args]) function_def = f"{name} {func_args} =" self.add_code_line(function_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args, is_scalar_output): self.add_function_def(name, args, is_scalar_output) yield self.decrease_indent() def vector_init(self, values): return f"[{', '.join(values)}]" def _comp_op_overwrite(self, op): if op == CompOpType.NOT_EQ: return "/=" else: return op.value
class FSharpCodeGenerator(FunctionalCodeGenerator): tpl_function_signature = CodeTemplate("let {function_name} =") tpl_if_statement = CodeTemplate("if ({if_def}) then") tpl_else_statement = CodeTemplate("else") tpl_num_value = CodeTemplate("{value}") tpl_infix_expression = CodeTemplate("({left}) {op} ({right})") tpl_array_index_access = CodeTemplate("{array_name}.[{index}]") def add_if_termination(self): self.decrease_indent() def add_function_def(self, name, args): func_args = " ".join([ f"({n} : double{' list' if is_vector else ''})" for is_vector, n in args ]) function_def = f"let {name} {func_args} =" self.add_code_line(function_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args): self.add_function_def(name, args) yield self.decrease_indent() def vector_init(self, values): return f"[{'; '.join(values)}]" def _comp_op_overwrite(self, op): if op == CompOpType.EQ: return "=" elif op == CompOpType.NOT_EQ: return "<>" else: return op.value
class VisualBasicCodeGenerator(BaseCodeGenerator): tpl_num_value = CodeTemplate("${value}") tpl_infix_expression = CodeTemplate("(${left}) ${op} (${right})") tpl_var_declaration = \ CodeTemplate("Dim ${var_name}${type_modifier} As ${var_type}") tpl_return_statement = CodeTemplate("${func_name} = ${value}") tpl_if_statement = CodeTemplate("If ${if_def} Then") tpl_else_statement = CodeTemplate("Else") tpl_block_termination = CodeTemplate("End ${block_name}") tpl_array_index_access = CodeTemplate("${array_name}(${index})") tpl_array_set_by_index = CodeTemplate("${array_name}(${index}) = ${value}") tpl_var_assignment = CodeTemplate("${var_name} = ${value}") tpl_module_definition = CodeTemplate("Module ${module_name}") scalar_type = "Double" def __init__(self, *args, **kwargs): super(VisualBasicCodeGenerator, self).__init__(*args, **kwargs) def add_return_statement(self, value, func_name): self.add_code_line( self.tpl_return_statement(func_name=func_name, value=value)) def add_var_declaration(self, size, exac_size=False): var_name = self.get_var_name() type_modifier = ("({})".format((size - 1) if exac_size else "") if size > 1 else "") self.add_code_line( self.tpl_var_declaration(var_name=var_name, type_modifier=type_modifier, var_type=self.scalar_type)) return var_name def add_block_termination(self, block_name="If"): self.decrease_indent() self.add_code_line(self.tpl_block_termination(block_name=block_name)) def add_function_def(self, name, args, is_scalar_output): return_type = self.scalar_type return_type += "" if is_scalar_output else "()" function_def = "Function " + name + "(" function_def += ", ".join([ ("ByRef " if is_vector else "ByVal ") + n + ("()" if is_vector else "") + " As " + self.scalar_type for is_vector, n in args ]) function_def += ") As " + return_type self.add_code_line(function_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args, is_scalar_output): self.add_function_def(name, args, is_scalar_output) yield self.decrease_indent() self.add_code_line(self.tpl_block_termination(block_name="Function")) def vector_init(self, values): var_name = self.add_var_declaration(len(values), exac_size=True) for i, val in enumerate(values): self.add_code_line( self.tpl_array_set_by_index(array_name=var_name, index=i, value=val)) return var_name
class VisualBasicCodeGenerator(ImperativeCodeGenerator): tpl_num_value = CodeTemplate("{value}") tpl_infix_expression = CodeTemplate("({left}) {op} ({right})") tpl_var_declaration = CodeTemplate("Dim {var_name}{type_modifier} As {var_type}") tpl_return_statement = CodeTemplate("{func_name} = {value}") tpl_if_statement = CodeTemplate("If {if_def} Then") tpl_else_statement = CodeTemplate("Else") tpl_block_termination = CodeTemplate("End {block_name}") tpl_array_index_access = CodeTemplate("{array_name}({index})") tpl_array_set_by_index = CodeTemplate("{array_name}({index}) = {value}") tpl_var_assignment = CodeTemplate("{var_name} = {value}") tpl_module_definition = CodeTemplate("Module {module_name}") scalar_type = "Double" def add_return_statement(self, value, func_name): self.add_code_line(self.tpl_return_statement( func_name=func_name, value=value)) def add_var_declaration(self, size, exac_size=False): var_name = self.get_var_name() type_modifier = (f"({(size - 1) if exac_size else ''})" if size > 1 else "") self.add_code_line( self.tpl_var_declaration( var_name=var_name, type_modifier=type_modifier, var_type=self.scalar_type)) return var_name def add_block_termination(self, block_name="If"): self.decrease_indent() self.add_code_line(self.tpl_block_termination(block_name=block_name)) def add_function_def(self, name, args, is_scalar_output): return_type = f"{self.scalar_type}{'' if is_scalar_output else '()'}" func_args = ", ".join([ f"{'ByRef' if is_vector else 'ByVal'} {n}" f"{'()' if is_vector else ''} As {self.scalar_type}" for is_vector, n in args]) function_def = f"Function {name}({func_args}) As {return_type}" self.add_code_line(function_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args, is_scalar_output): self.add_function_def(name, args, is_scalar_output) yield self.decrease_indent() self.add_code_line(self.tpl_block_termination(block_name="Function")) def vector_init(self, values): var_name = self.add_var_declaration(len(values), exac_size=True) for i, val in enumerate(values): self.add_code_line(self.tpl_array_set_by_index( array_name=var_name, index=i, value=val)) return var_name def _comp_op_overwrite(self, op): if op == CompOpType.EQ: return "=" elif op == CompOpType.NOT_EQ: return "<>" else: return op.value
class FastlyVCLCodeGenerator(CLikeCodeGenerator): tpl_var_declaration = CodeTemplate("declare local {var_name} FLOAT;") tpl_var_assignment = CodeTemplate("set {var_name} = {value};") tpl_array_index_access = CodeTemplate("{array_name}_{index}") tpl_infix_expression = CodeTemplate("{left} {op} {right}") def __init__(self, indent=4, id_prefix="score"): self.id_prefix = self.header_var(id_prefix) super().__init__(indent) def header_var(self, name): return f"req.http.{name}" def reset_state(self): super().reset_state() self._sub_prefix = self.id_prefix self._sub_start_pos = 0 self._output_size = 1 self._input_idxs = {} self._var_sizes = {} def get_var_name(self): var_name = f"var.var{self._var_idx}" self._var_idx += 1 return var_name def add_var_declaration(self, size): var_name = self.get_var_name() self._var_sizes[var_name] = size for i in range(size): self.add_code_line( self.tpl_var_declaration(var_name=f"{var_name}_{i}")) if size == 1: return var_name + "_0" return var_name def add_return_statement(self, value): if value in self._var_sizes: # this wont work if an array is passed directly to value # todo: check if that is a possibility self._output_size = self._var_sizes[value] if self._output_size > 1: for i in range(self._output_size): self.add_code_line( self.tpl_var_assignment( var_name=f"{self._sub_prefix}_output_{i}", value=f"{value}_{i}")) else: self.add_code_line( self.tpl_var_assignment( var_name=f"{self._sub_prefix}_output_0", value=f"{value}")) self.add_code_line("return;") def add_var_assignment(self, var_name, value, value_size): for i in range(value_size): if var_name in self._var_sizes: var = f"{var_name}_{i}" else: var = var_name self.add_code_line( self.tpl_var_assignment( var_name=var, value=(value[i] if value_size > 1 else value))) def add_function_def(self, name, args, is_vector_output): if args != [(True, "input")]: print(args) raise "Unexpected args given from FastlyVCLInterpreter" self.add_code_line(f"sub {name} {{") self._sub_start_pos = self._code_buf.tell() self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args, is_vector_output): if self._sub_prefix != self.header_var(name): self._sub_prefix = f"{self._sub_prefix}_{name}" self.add_function_def(name, args, is_vector_output) yield self.add_block_termination() self._code_buf.seek(0) content = self._code_buf.read(self._sub_start_pos) for index, var_name in self._input_idxs.items(): content += str(self._indent * " ") + \ self.tpl_var_declaration(var_name=var_name) + "\n" content += str(self._indent * " ") content += self.tpl_var_assignment( var_name=f"{var_name}", value=f"std.atof({self.id_prefix}_input_{index})") content += "\n\n" content += self._code_buf.read() self._code_buf.seek(0) self._code_buf.write(content) def infix_expression(self, left, right, op): if op == "=": raise "Assignment should be done with add_var_assignment" elif op in ["+", "-", "*", "/", "%", "|", "&", "^", "<<", ">>", "rol"]: # this could be optimized var_name = self.add_var_declaration(1) self.add_var_assignment(var_name, left, 1) self.add_code_line(f"set {var_name} {op}= {right};") return var_name return self.tpl_infix_expression(left=left, right=right, op=op) def sub_invocation(self, sub_name): self.add_code_line(f"call {sub_name};") var_name = self.add_var_declaration(1) self.add_var_assignment( var_name, f"std.atof({self.id_prefix}_{sub_name}_output_0)", 1) return var_name def array_index_access(self, array_name, index): if array_name == "input": var_name = f"var.input_{index}" self._input_idxs[index] = var_name return var_name return super().array_index_access(array_name, index) def vector_init(self, values): # vectors must be assigned value by value # this is done in add_var_assignment return values
class HaskellCodeGenerator(BaseCodeGenerator): tpl_num_value = CodeTemplate("{value}") tpl_infix_expression = CodeTemplate("({left}) {op} ({right})") tpl_module_definition = CodeTemplate("module {module_name} where") def __init__(self, *args, **kwargs): self._func_idx = 0 super().__init__(*args, **kwargs) def reset_state(self): super().reset_state() self._func_idx = 0 def array_index_access(self, array_name, index): return self.tpl_infix_expression(left=array_name, op="!!", right=index) def add_if_statement(self, if_def): self.add_code_line("if ({})".format(if_def)) self.increase_indent() self.add_code_line("then") self.increase_indent() def add_else_statement(self): self.decrease_indent() self.add_code_line("else") self.increase_indent() def add_if_termination(self): self.decrease_indent() self.decrease_indent() def get_func_name(self): func_name = "func" + str(self._func_idx) self._func_idx += 1 return func_name def add_function(self, function_name, function_body): self.add_code_line("{} =".format(function_name)) self.increase_indent() self.add_code_lines(function_body) self.decrease_indent() def function_invocation(self, function_name, *args): return (function_name + " " + " ".join(map(lambda x: "({})".format(x), args))) def add_function_def(self, name, args, is_scalar_output): signature = name + " :: " signature += " -> ".join([ "[Double]" if is_vector else "Double" for is_vector, _ in [*args, (not is_scalar_output, None)] ]) self.add_code_line(signature) function_def = name + " " function_def += " ".join([n for _, n in args]) function_def += " =" self.add_code_line(function_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args, is_scalar_output): self.add_function_def(name, args, is_scalar_output) yield self.decrease_indent() def vector_init(self, values): return "[" + ", ".join(values) + "]" def _comp_op_overwrite(self, op): if op == CompOpType.NOT_EQ: return "/=" else: return op.value
class FSharpCodeGenerator(BaseCodeGenerator): tpl_num_value = CodeTemplate("{value}") tpl_infix_expression = CodeTemplate("({left}) {op} ({right})") tpl_array_index_access = CodeTemplate("{array_name}.[{index}]") def reset_state(self): super().reset_state() self._func_idx = 0 def add_if_statement(self, if_def): self.add_code_line(f"if ({if_def}) then") self.increase_indent() def add_else_statement(self): self.decrease_indent() self.add_code_line("else") self.increase_indent() def add_if_termination(self): self.decrease_indent() def get_func_name(self): func_name = f"func{self._func_idx}" self._func_idx += 1 return func_name def add_function(self, function_name, function_body): self.add_code_line(f"let {function_name} =") self.increase_indent() self.add_code_lines(function_body) self.decrease_indent() def function_invocation(self, function_name, *args): function_args = " ".join(map(lambda x: f"({x})", args)) return f"{function_name} {function_args}" def add_function_def(self, name, args): func_args = " ".join([ f"({n} : double{' list' if is_vector else ''})" for is_vector, n in args ]) function_def = f"let {name} {func_args} =" self.add_code_line(function_def) self.increase_indent() @contextlib.contextmanager def function_definition(self, name, args): self.add_function_def(name, args) yield self.decrease_indent() def vector_init(self, values): return f"[{'; '.join(values)}]" def _comp_op_overwrite(self, op): if op == CompOpType.EQ: return "=" elif op == CompOpType.NOT_EQ: return "<>" else: return op.value