예제 #1
0
    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])))
예제 #2
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
예제 #3
0
 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!")
예제 #4
0
 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])))
예제 #6
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)