X-Git-Url: http://nitlanguage.org diff --git a/src/phase.nit b/src/phase.nit index df72660..502d817 100644 --- a/src/phase.nit +++ b/src/phase.nit @@ -21,7 +21,7 @@ import poset redef class ToolContext # The various registered phases to performs - # The order in the poset is the dependance of phases + # The order in the poset is the dependence of phases # # While you can directly modify the poset (nodes and edges), # it is often simpler to use the constructor in `Phase` @@ -30,11 +30,14 @@ redef class ToolContext # --disable-phase var opt_disable_phase = new OptionArray("DEBUG: Disable a specific phase; use `list` to get the list.", "--disable-phase") + # --disable-phase + var opt_sloppy = new OptionBool("DEBUG: force lazy semantic analysis of the source-code", "--sloppy") + redef init do super - option_context.add_option(opt_disable_phase) + option_context.add_option(opt_disable_phase, opt_sloppy) end redef fun process_options(args) @@ -62,15 +65,24 @@ redef class ToolContext end if not found then fatal_error(null, "Error: no phase named `{v}`. Use `list` to list all phases.") end + + if opt_sloppy.value then semantize_is_lazy = true end - fun phases_list: Sequence[Phase] - do + # The list of registered phases in the application order. + var phases_list: Sequence[Phase] is lazy do var phases = self.phases.to_a self.phases.sort(phases) return phases end + # Is `phase_process_npropdef` not called automatically by `run_phases`? + # + # When set to true, it is the responsibility of the tools + # + # Is false by default. + var semantize_is_lazy = false is writable + # Set of already analyzed modules. private var phased_modules = new HashSet[AModule] @@ -98,7 +110,6 @@ redef class ToolContext for phase in phases do if phase.disabled then continue - self.info(" phase: {phase}", 3) assert phase.toolcontext == self var errcount = self.error_count phase.process_nmodule(nmodule) @@ -110,9 +121,9 @@ redef class ToolContext for nclassdef in nmodule.n_classdefs do assert phase.toolcontext == self phase.process_nclassdef(nclassdef) - for npropdef in nclassdef.n_propdefs do + if not semantize_is_lazy then for npropdef in nclassdef.n_propdefs do assert phase.toolcontext == self - phase.process_npropdef(npropdef) + phase_process_npropdef(phase, npropdef) end end if errcount != self.error_count then @@ -120,7 +131,10 @@ redef class ToolContext break end for na in vannot.annotations do - phase.process_annotated_node(na.parent.parent.as(not null), na) + var p = na.parent + if p isa AAnnotations then p = p.parent + assert p != null + phase.process_annotated_node(p, na) end if errcount != self.error_count then self.check_errors @@ -132,9 +146,43 @@ redef class ToolContext var time1 = get_time self.info("*** END SEMANTIC ANALYSIS: {time1-time0} ***", 2) + + self.check_errors + end + + # Process the given `phase` on the `npropdef` + # Called by `run_phases` + protected fun phase_process_npropdef(phase: Phase, npropdef: APropdef) + do + phase.process_npropdef(npropdef) + end + + # Run the phase on the given npropdef. + # Does nothing if `semantize_is_lazy` is false. + fun run_phases_on_npropdef(npropdef: APropdef) + do + if not semantize_is_lazy then return + if npropdef.is_phased then return + npropdef.is_phased = true + + #self.info("Semantic analysis of property {npropdef.location.file.filename}", 0) + + var phases = phases_list + for phase in phases do + if phase.disabled then continue + assert phase.toolcontext == self + phase_process_npropdef(phase, npropdef) + self.check_errors + end end end +redef class APropdef + # Is the propdef already analyzed by `run_phases_on_npropdef`. + # Unused unless `semantize_is_lazy` is true. + private var is_phased = false +end + # Collect all annotation private class AnnotationPhaseVisitor super Visitor @@ -156,13 +204,16 @@ abstract class Phase var toolcontext: ToolContext # The dependence relation of the phase with the other phases - var in_hierarchy: POSetElement[Phase] + var in_hierarchy: POSetElement[Phase] is noinit + + # The explicit dependences, used to initialize `in_importation` + var depends: nullable Collection[Phase] # Initialize and register a phase to the toolcontext - init(toolcontext: ToolContext, depends: nullable Collection[Phase]) + init do - self.toolcontext = toolcontext in_hierarchy = toolcontext.phases.add_node(self) + var depends = self.depends if depends != null then for d in depends do toolcontext.phases.add_edge(self, d) @@ -175,7 +226,9 @@ abstract class Phase # Is the phase globally disabled? # A disabled phase is not called automatically called by `ToolContext::run_phases` and cie. - var disabled = false + # + # Warning: disabling a phase may cause subsequent phases to work in a degraded way or to fail. + var disabled = false is writable # Specific actions to execute on the whole tree of a module # @toimplement