def add_plugin(self, plugin): self.plugins.append(plugin) # TODO: hack? if isinstance(plugin, templFileGenPlug.TemplateFileGeneratorPlugin): plugin.model_globals["toStream"] = templFileGenPlug.LambdaValue( lambda args: vals.StringValue( self.array_stream((args[0]).value))) plugin.model_globals["isArray"] = templFileGenPlug.LambdaValue( lambda args: vals.BooleanValue(self.is_array((args[0]).value))) plugin.model_globals["toArray"] = templFileGenPlug.LambdaValue( lambda args: vals.StringValue(self.to_array((args[0]).type))) plugin.model_globals["escape"] = templFileGenPlug.LambdaValue( lambda args: vals.StringValue(self.escape(args[0]))) plugin.model_globals["escapeRepl"] = templFileGenPlug.LambdaValue( lambda args: vals.StringValue(self.escape_repl(args[0])))
def expr(self, expr): is_call_expr = isinstance(expr, exprs.StaticMethodCallExpression) or isinstance(expr, exprs.InstanceMethodCallExpression) or isinstance(expr, exprs.GlobalFunctionCallExpression) or isinstance(expr, exprs.NewExpression) is_field_ref = isinstance(expr, refs.StaticFieldReference) or isinstance(expr, refs.StaticPropertyReference) or isinstance(expr, refs.InstanceFieldReference) or isinstance(expr, refs.InstancePropertyReference) if not is_call_expr and not is_field_ref: return None # quick return code_tmpl = None model = vals.ObjectValue({}) context = exprVM.VMContext(model, self) model.props["type"] = TypeValue(expr.get_type()) for name in self.model_globals.keys(): model.props[name] = self.model_globals.get(name) if is_call_expr: call = expr parent_intf = call.get_parent_interface() method_name = f'''{("" if parent_intf == None else f'{parent_intf.name}.')}{call.get_method_name()}@{len(call.args)}''' call_tmpls = self.methods.get(method_name) if call_tmpls == None: return None for call_tmpl in call_tmpls: if isinstance(expr, exprs.InstanceMethodCallExpression): model.props["this"] = ExpressionValue(expr.object) i = 0 while i < len(call_tmpl.args): model.props[call_tmpl.args[i]] = ExpressionValue(call.args[i]) i = i + 1 if call_tmpl.template.if_expr == None or (exprVM.ExprVM(context).evaluate(call_tmpl.template.if_expr)).value: code_tmpl = call_tmpl.template break elif is_field_ref: cm = (expr).get_variable() field = self.fields.get(f'''{cm.get_parent_interface().name}.{cm.name}''') if field == None: return None if isinstance(expr, refs.InstanceFieldReference) or isinstance(expr, refs.InstancePropertyReference): model.props["this"] = ExpressionValue((expr).object) code_tmpl = field.template else: return None if code_tmpl == None: return None for inc in code_tmpl.includes or []: self.generator.add_include(inc) tmpl = templPars.TemplateParser(code_tmpl.template).parse() result = tmpl.format(context) return result
def evaluate(self, expr): if isinstance(expr, exprs.Identifier): return self.prop_access(self.context.model, expr.text) elif isinstance(expr, exprs.PropertyAccessExpression): obj_value = self.evaluate(expr.object) return self.prop_access(obj_value, expr.property_name) elif isinstance(expr, exprs.UnresolvedCallExpression): func = self.evaluate(expr.func) args = list(map(lambda x: self.evaluate(x), expr.args)) result = func.call(args) return result elif isinstance(expr, exprs.StringLiteral): return vals.StringValue(expr.string_value) elif isinstance(expr, exprs.NumericLiteral): return vals.NumericValue(int(expr.value_as_text)) elif isinstance(expr, exprs.ConditionalExpression): cond_result = self.evaluate(expr.condition) result = self.evaluate(expr.when_true if ( cond_result).value else expr.when_false) return result elif isinstance(expr, exprs.TemplateString): result = "" for part in expr.parts: if part.is_literal: result += part.literal_text else: value = self.evaluate(part.expression) result += value.value if isinstance( value, vals.StringValue ) else self.context.hooks.stringify_value(value) return vals.StringValue(result) elif isinstance(expr, exprs.BinaryExpression): left = self.evaluate(expr.left) right = self.evaluate(expr.right) if expr.operator == "==" or expr.operator == "===": return vals.BooleanValue(left.equals(right)) elif expr.operator == "!=" or expr.operator == "!==": return vals.BooleanValue(not left.equals(right)) else: raise Error( f'''Unsupported binary operator: {expr.operator}''') else: raise Error("Unsupported expression!")
def prop_access(self, obj, prop_name): if isinstance(obj, ExpressionValue) and prop_name == "type": return TypeValue(obj.value.get_type()) if isinstance(obj, TypeValue) and prop_name == "name" and isinstance(obj.type, astTypes.ClassType): return vals.StringValue(obj.type.decl.name) return None
def add_plugin(self, plugin): self.plugins.append(plugin) if isinstance(plugin, templFileGenPlug.TemplateFileGeneratorPlugin): plugin.model_globals["escape"] = templFileGenPlug.LambdaValue(lambda args: vals.StringValue(self.escape(args[0]))) plugin.model_globals["escapeBackslash"] = templFileGenPlug.LambdaValue(lambda args: vals.StringValue(self.escape_backslash(args[0])))
def generate(self): # copy native source codes from one project native_src_dir = f'''{self.proj_dir}/{self.project_file.native_source_dir}''' for fn in OneFile.list_files(native_src_dir, True): OneFile.copy(f'''{native_src_dir}/{fn}''', f'''{self.out_dir}/{fn}''') generators = [ javaGen.JavaGenerator(), cshGen.CsharpGenerator(), pythGen.PythonGenerator(), phpGen.PhpGenerator() ] for tmpl_name in self.project_file.project_templates: compiler = compHelp.CompilerHelper.init_project( self.project_file.name, self.src_dir, self.project_file.source_lang, None) compiler.process_workspace() proj_template = ProjectTemplate( f'''{self.base_dir}/project-templates/{tmpl_name}''') lang_id = proj_template.meta.language generator = next( filter(lambda x: x.get_lang_name().lower() == lang_id, generators), None) lang_name = generator.get_lang_name() out_dir = f'''{self.out_dir}/{lang_name}''' for trans in generator.get_transforms(): trans.visit_files(compiler.project_pkg.files.values()) # copy implementation native sources one_deps = [] native_deps = {} for dep in self.project_file.dependencies: impl = next( filter(lambda x: x.content.id.name == dep.name, compiler.pac_man.implementation_pkgs), None) one_deps.append(impl) lang_data = impl.implementation_yaml.languages.get(lang_id) if lang_data == None: continue for nat_dep in lang_data.native_dependencies or []: native_deps[nat_dep.name] = nat_dep.version if lang_data.native_src_dir != None: if proj_template.meta.package_dir == None: raise Error( "Package directory is empty in project template!") src_dir = lang_data.native_src_dir + ( "" if lang_data.native_src_dir.endswith("/") else "/") dst_dir = f'''{out_dir}/{proj_template.meta.package_dir}/{lang_data.package_dir or impl.content.id.name}''' dep_files = list( map( lambda x: x[len(src_dir):], list( filter(lambda x: x.startswith(src_dir), impl.content.files.keys())))) for fn in dep_files: OneFile.write_text( f'''{dst_dir}/{fn}''', impl.content.files.get(f'''{src_dir}{fn}''')) if lang_data.generator_plugins != None: for gen_plug_fn in lang_data.generator_plugins: generator.add_plugin( templFileGenPlug.TemplateFileGeneratorPlugin( generator, impl.content.files.get(gen_plug_fn))) # generate cross compiled source code console.log(f'''Generating {lang_name} code...''') files = generator.generate(compiler.project_pkg) for file in files: OneFile.write_text( f'''{out_dir}/{proj_template.meta.destination_dir or ""}/{file.path}''', file.content) # generate files from project template model = vals.ObjectValue({ "dependencies": vals.ArrayValue( list( map( lambda name: vals.ObjectValue({ "name": vals.StringValue(name), "version": vals.StringValue(native_deps.get(name)) }), native_deps.keys()))), "onepackages": vals.ArrayValue( list( map( lambda dep: vals.ObjectValue({ "vendor": vals.StringValue(dep.implementation_yaml.vendor ), "id": vals.StringValue(dep.implementation_yaml.name) }), one_deps))) }) proj_template.generate(f'''{out_dir}''', model)