From: Jean Privat Date: Thu, 31 Jul 2014 05:36:47 +0000 (-0400) Subject: src: new phase check_annotation X-Git-Tag: v0.6.8~44^2~4 X-Git-Url: http://nitlanguage.org src: new phase check_annotation Signed-off-by: Jean Privat --- diff --git a/src/check_annotation.nit b/src/check_annotation.nit new file mode 100644 index 0000000..38b179f --- /dev/null +++ b/src/check_annotation.nit @@ -0,0 +1,112 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Check that annotation present in the AST are either primitive or user-declared +# There is no verification on the syntax or the semantic of the annotation: just the name is checked +# +# Specific phases or tools have to process their annotation and check them correclty. +module check_annotation + +import phase +import annotation + +redef class ToolContext + var check_annotation_phase: Phase = new CheckAnnotationPhase(self, null) +end + +private class CheckAnnotationPhase + super Phase + + # The map of all declared user annotation + # note: lazy because toolcontex is set in the init + var declared_annotations = new MModuleMultiData[String](toolcontext.modelbuilder.model) is lazy + + # The current module. + var mmodule: nullable MModule = null + + redef fun process_nmodule(nmodule) + do + # Get the mmodule + var mmodule = nmodule.mmodule + assert mmodule != null + self.mmodule = mmodule + + # If no decl block then quit + var nmoduledecl = nmodule.n_moduledecl + if nmoduledecl == null then return + + var modelbuilder = toolcontext.modelbuilder + + # Get all the new annotations + var annots = nmoduledecl.get_annotations("new_annotation") + + # Add each new annotations in the map + for annot in annots do + var name = annot.arg_as_id(modelbuilder) + if name == null then continue + + declared_annotations[mmodule].add(name) + #annot.debug "add {mmodule}: {name}" + end + end + + # Raw new-line separated list of primitive annotation + # Note: empty-lines will be ignored since there is no annotation named by the empty string. + var primtives_annotations_list = """ +new_annotation + +fixed +lazy +noinit +readonly +writable +cached + +pkgconfig +c_compiler_option +c_linker_option + +platform +""" + + # Efficient set build from `primtives_annotations_list` + var primtives_annotations = new HashSet[String].from(primtives_annotations_list.split("\n")) + + # All user-declared annotations for each mmodule + var user_annotations = new HashMap[MModule, HashSet[String]] + + redef fun process_annotated_node(node, nat) + do + var name = nat.name + if primtives_annotations.has(name) then return + + var mmodule = self.mmodule + assert mmodule != null + + # Lazily build the full user-list + var annots = user_annotations.get_or_null(mmodule) + if annots == null then + annots = new HashSet[String] + annots.add_all(declared_annotations.lookup_joined_values(mmodule, private_visibility)) + user_annotations[mmodule] = annots + end + #nat.debug "for {mmodule}: {annots.join(" ")}" + + if annots.has(name) then return + + toolcontext.modelbuilder.warning(nat, "Warning: unknown annotation `{name}`") + + annots.add(name) # to avoid multiple errors on the same name + end +end diff --git a/src/frontend.nit b/src/frontend.nit index 3d635a3..9b6e84b 100644 --- a/src/frontend.nit +++ b/src/frontend.nit @@ -26,6 +26,7 @@ import auto_super_init import div_by_zero import cached import serialization_phase +import check_annotation redef class ToolContext # FIXME: there is conflict in linex in nitc, so use this trick to force invocation