X-Git-Url: http://nitlanguage.org diff --git a/src/phase.nit b/src/phase.nit index 667ba43..ace2cb9 100644 --- a/src/phase.nit +++ b/src/phase.nit @@ -27,23 +27,68 @@ redef class ToolContext # it is often simpler to use the constructor in `Phase` var phases = new POSet[Phase] + # --disable-phase + var opt_disable_phase = new OptionArray("DEBUG: Disable a specific phase; use `list` to get the list.", "--disable-phase") + + redef init + do + super + + option_context.add_option(opt_disable_phase) + end + + redef fun process_options(args) + do + super + + for v in opt_disable_phase.value do + if v == "list" then + for p in phases_list do + var deps = p.in_hierarchy.direct_greaters + if deps.is_empty then + print p + else + print "{p} (dep: {deps.join(", ")})" + end + end + exit 0 + end + + var found = false + for p in phases do + if v != p.to_s then continue + found = true + p.disabled = true + end + if not found then fatal_error(null, "Error: no phase named `{v}`. Use `list` to list all phases.") + end + end + + fun phases_list: Sequence[Phase] + do + var phases = self.phases.to_a + self.phases.sort(phases) + return phases + end + # Run all registered phases on a set of modules fun run_phases(nmodules: Collection[AModule]) do var time0 = get_time self.info("*** SEMANTIC ANALYSIS ***", 1) #phases.show_dot - var phases = self.phases.to_a - self.phases.sort(phases) + + var phases = phases_list for phase in phases do - self.info(" registered phases: {phase.class_name}", 2) + self.info(" registered phases: {phase}", 2) end for nmodule in nmodules do self.info("Semantic analysis module {nmodule.location.file.filename}", 2) for phase in phases do - self.info(" phase: {phase.class_name}", 3) + if phase.disabled then continue + self.info(" phase: {phase}", 3) assert phase.toolcontext == self var errcount = self.error_count phase.process_nmodule(nmodule) @@ -53,8 +98,10 @@ redef class ToolContext end errcount = self.error_count for nclassdef in nmodule.n_classdefs do + self.info(" phase: {phase} for {nclassdef.location}", 3) + assert phase.toolcontext == self + phase.process_nclassdef(nclassdef) for npropdef in nclassdef.n_propdefs do - self.info(" phase: {phase.class_name} for {npropdef.location}", 4) assert phase.toolcontext == self phase.process_npropdef(npropdef) end @@ -63,6 +110,12 @@ redef class ToolContext self.check_errors break end + var v = new AnnotationPhaseVisitor(phase) + v.enter_visit(nmodule) + if errcount != self.error_count then + self.check_errors + break + end end self.check_errors end @@ -72,9 +125,22 @@ redef class ToolContext end end +private class AnnotationPhaseVisitor + super Visitor + + var phase: Phase + + init(phase: Phase) do self.phase = phase + + redef fun visit(n) + do + n.visit_all(self) + if n isa AAnnotation then phase.process_annotated_node(n.parent.parent.as(not null), n) + end +end + # Abstraction of steps in the analysis/processing of Nit programs -# Specific phases should implements either `process_nmodule` or -# `process_npropdef`. +# Specific phases should implements one of the `process_*` method abstract class Phase # The toolcontext instance attached to the phase var toolcontext: ToolContext @@ -94,12 +160,29 @@ abstract class Phase end end + # By default, the name is the lowercased prefix of the classname + redef fun to_s do return class_name.strip_extension("Phase").to_lower + + # Is the phase globally disabled? + # A disabled phase is not called automatically called by `ToolContext::run_phases` and cie. + var disabled = false + # Specific actions to execute on the whole tree of a module # @toimplement fun process_nmodule(nmodule: AModule) do end + # Specific actions to execute on the tree of a class definition + # Note that the order of the visit is the one of the file + # @toimplement + fun process_nclassdef(nclassdef: AClassdef) do end + # Specific actions to execute on the tree of a property # Note that the order of the visit is the one of the file # @toimplement fun process_npropdef(npropdef: APropdef) do end + + # Specific actions to execute on annotated nodes + # Note that the order of the visit is the one of the file + # @toimplement + fun process_annotated_node(node: ANode, nat: AAnnotation) do end end