Beispiel #1
0
    def _compile(self):
        """
        Compile the language specification: perform legality checks and type
        inference.
        """
        # Compile the first time, do nothing next times
        if self.compiled:
            return
        self.compiled = True

        assert self.grammar, "Set grammar before compiling"

        if not self.grammar.rules.get(self.main_rule_name, None):
            close_matches = difflib.get_close_matches(
                self.main_rule_name, self.grammar.rules.keys()
            )

            with self.grammar.context():
                check_source_language(
                    False,
                    'Invalid rule name specified for main rule: "{}". '
                    '{}'.format(
                        self.main_rule_name,
                        'Did you mean "{}"?'.format(close_matches[0])
                        if close_matches else ""
                    )
                )

        unreferenced_rules = self.grammar.get_unreferenced_rules()

        check_source_language(
            not unreferenced_rules, "The following parsing rules are not "
            "used: {}".format(", ".join(sorted(unreferenced_rules))),
            severity=Severity.warning
        )

        # Compute type information, so that it is available for further
        # compilation stages.
        self.compute_types()
        errors_checkpoint()

        if self.verbosity.info:
            printcol("Compiling the grammar...", Colors.OKBLUE)

        with names.camel_with_underscores:
            # Compute the type of fields for types used in the grammar
            for r_name, r in self.grammar.rules.items():
                r.compute_fields_types()

            # Compute properties information, so that it is available for
            # further compilation stages.
            self.compute_properties()
            errors_checkpoint()

            for r_name, r in self.grammar.rules.items():
                r.compile()
                self.rules_to_fn_names[r_name] = r

        unresolved_types = set([t for t in self.astnode_types
                                if not t.is_type_resolved])
        check_source_language(
            not unresolved_types,
            "The following ASTNode subclasses are not type resolved. They are"
            " not used by the grammar, and their types not annotated:"
            " {}".format(", ".join(t.name().camel for t in unresolved_types))
        )

        astnodes_files = {
            path.abspath(inspect.getsourcefile(n)) for n in self.astnode_types
        }

        if self.annotate_fields_types:
            # Only import lib2to3 if the users needs it
            import lib2to3.main

            lib2to3.main.main(
                "langkit",
                ["-f", "annotate_fields_types",
                 "--no-diff", "-w"] + list(astnodes_files)
            )

        for i, astnode in enumerate(
            (astnode
             for astnode in self.astnode_types
             if not astnode.abstract),
            # Compute kind constants for all ASTNode concrete subclasses.
            # Start with 2: the constant 0 is reserved as an
            # error/uninitialized code and the constant 1 is reserved for all
            # ASTList nodes.
            start=2
        ):
            self.node_kind_constants[astnode] = i

        # Now that all Struct subclasses referenced by the grammar have been
        # typed, iterate over all declared subclasses to register the ones that
        # are unreachable from the grammar.  TODO: this kludge will eventually
        # disappear as part of OC22-016.
        for t in self.struct_types + self.astnode_types:
            t.add_to_context()

        errors_checkpoint()
Beispiel #2
0
        :param pass_fn: Function to be run when executing the pass. Called once
            per PropertyDef instance. This function must take the PropertyDef
            instance and the context.
        :type (langkit.expressions.base.PropertyDef,
               langkit.compile_context.CompileCtx) -> None

        :param bool disabled: See AbstractPass.
        """
        super(PropertyPass, self).__init__(name, disabled)
        self.pass_fn = pass_fn

    def run(self, context):
        for prop in context.all_properties(include_inherited=False):
            with prop.diagnostic_context:
                self.pass_fn(prop, context)


class StopPipeline(AbstractPass):
    """
    Dummy concrete pass to abort the execution of a pipeline.

    Used with the "disabled" attribute, this is useful to conditionnaly limit
    the set of passes to be executed.
    """
    pass


errors_checkpoint_pass = GlobalPass('errors checkpoint',
                                    lambda _: errors_checkpoint())
Beispiel #3
0
    def _compile(self, compile_only=False):
        """
        Compile the language specification: perform legality checks and type
        inference.
        """
        # Compile the first time, do nothing next times
        if self.compiled:
            return
        self.compiled = True

        assert self.grammar, "Set grammar before compiling"

        if not self.grammar.rules.get(self.main_rule_name, None):
            close_matches = difflib.get_close_matches(
                self.main_rule_name, self.grammar.rules.keys())

            with self.grammar.context():
                check_source_language(
                    False, 'Invalid rule name specified for main rule: "{}". '
                    '{}'.format(
                        self.main_rule_name, 'Did you mean "{}"?'.format(
                            close_matches[0]) if close_matches else ""))

        unreferenced_rules = self.grammar.get_unreferenced_rules()

        check_source_language(not unreferenced_rules,
                              "The following parsing rules are not "
                              "used: {}".format(", ".join(
                                  sorted(unreferenced_rules))),
                              severity=Severity.warning)

        if self.verbosity.info:
            printcol("Compiling the grammar...", Colors.OKBLUE)

        with names.camel_with_underscores:
            # Compute the type of fields for types used in the grammar. Also
            # register its symbol literals.
            for r_name, r in self.grammar.rules.items():
                with r.error_context():
                    r.compute_fields_types()
                for sym in r.symbol_literals:
                    self.add_symbol_literal(sym)

        # Compute type information, so that it is available for further
        # compilation stages.
        self.compute_types()
        errors_checkpoint()

        with names.camel_with_underscores:
            # Compute properties information, so that it is available for
            # further compilation stages.
            self.compute_properties(compile_only=compile_only)
            errors_checkpoint()

            # Past this point, the set of symbol literals is frozen
            self.finalize_symbol_literals()

        unresolved_types = set(
            [t for t in self.astnode_types if not t.is_type_resolved])
        check_source_language(
            not unresolved_types,
            "The following ASTNode subclasses are not type resolved. They are"
            " not used by the grammar, and their types not annotated:"
            " {}".format(", ".join(t.name().camel for t in unresolved_types)))

        astnodes_files = {
            path.abspath(inspect.getsourcefile(n))
            for n in self.astnode_types
        }

        if compile_only:
            return

        with names.camel_with_underscores:
            for r_name, r in self.grammar.rules.items():
                with r.error_context():
                    r.compile()

        if self.annotate_fields_types:
            # Only import lib2to3 if the users needs it
            import lib2to3.main

            lib2to3.main.main(
                "langkit", ["-f", "annotate_fields_types", "--no-diff", "-w"] +
                list(astnodes_files))

        for i, astnode in enumerate(
            (astnode
             for astnode in self.astnode_types if not astnode.abstract),
                # Compute kind constants for all ASTNode concrete subclasses.
                # Start with 1: the constant 0 is reserved as an
                # error/uninitialized code.
                start=1):
            self.node_kind_constants[astnode] = i

        # Now that all Struct subclasses referenced by the grammar have been
        # typed, iterate over all declared subclasses to register the ones that
        # are unreachable from the grammar.  TODO: this kludge will eventually
        # disappear as part of OC22-016.
        for t in self.struct_types + self.astnode_types:
            t.add_to_context()

        errors_checkpoint()