From d1f59b0b06b9b6f34e01daa3df627a135639f641 Mon Sep 17 00:00:00 2001 From: Jean Privat Date: Thu, 26 Feb 2015 11:50:42 +0700 Subject: [PATCH] frontend: remove deprecated cached annotation and phase Signed-off-by: Jean Privat --- src/frontend/cached.nit | 154 ------------------------------------- src/frontend/check_annotation.nit | 1 - src/frontend/frontend.nit | 1 - src/nitlight.nit | 3 - 4 files changed, 159 deletions(-) delete mode 100644 src/frontend/cached.nit diff --git a/src/frontend/cached.nit b/src/frontend/cached.nit deleted file mode 100644 index f331b1d..0000000 --- a/src/frontend/cached.nit +++ /dev/null @@ -1,154 +0,0 @@ -# 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. - -# Implementation of the method-related annotation `cached` -# -# The cached annotation is deprecated, use the `lazy` annotation instead. -module cached - -import modelize -private import parser_util -import simple_misc_analysis -private import annotation -intrude import modelize::modelize_property - -redef class ToolContext - # Process the `cached` annotation on methods - var cached_phase: Phase = new CachedPhase(self, [modelize_property_phase]) -end - -private class CachedPhase - super Phase - - init - do - # FIXME The phase has to be executed just after `modelize_property_phase` - # But there is no simple way to express this - # So, for the moment, I just looked at the linearization and see what phase is after `modelize_property_phase` - # And inserted before it - toolcontext.phases.add_edge(toolcontext.simple_misc_analysis_phase, self) - end - - redef fun process_annotated_node(npropdef, nat) - do - # Skip if we are not interested - if nat.name != "cached" then return - - # Do some validity checks and print errors if the annotation is used incorrectly - var modelbuilder = toolcontext.modelbuilder - - if not npropdef isa AMethPropdef then - modelbuilder.error(npropdef, "Syntax error: only a function can be cached.") - return - end - - var mpropdef = npropdef.mpropdef.as(not null) - - var mtype = mpropdef.msignature.return_mtype - if mtype == null then - modelbuilder.error(npropdef, "Syntax error: only a function can be cached.") - return - end - - if not npropdef.n_signature.n_params.is_empty then - modelbuilder.error(npropdef, "Syntax error: only a function without arguments can be cached.") - return - end - - # OK, let we do some meta-programming... - - var location = npropdef.location - var name = mpropdef.mproperty.name - var nclassdef = npropdef.parent.as(AClassdef) - var mclassdef = nclassdef.mclassdef.as(not null) - - if not mclassdef.mclass.kind.need_init then - modelbuilder.error(npropdef, "Error: only abstract and concrete classes can have cached functions.") - return - end - - # Create a new private attribute to store the cache - var cache_mpropdef = new MAttributeDef(mclassdef, new MAttribute(mclassdef, "@{name}", private_visibility), location) - cache_mpropdef.static_mtype = mtype.as_nullable - - # Create another new private attribute to store the boolean «is the function cached?» - # The point is to manage the case where `null` is a genuine return value of the method - var is_cached_mpropdef = new MAttributeDef(mclassdef, new MAttribute(mclassdef, "@{name}", private_visibility), location) - is_cached_mpropdef.static_mtype = mclassdef.mmodule.get_primitive_class("Bool").mclass_type - # FIXME? Because there is a default value ("false") a real propdef is required - var is_cached_npropdef = toolcontext.parse_propdef("var is_cached = false").as(AAttrPropdef) - associate_propdef(is_cached_mpropdef, is_cached_npropdef) - - # Create a new private method to do the real work - var real_mpropdef = new MMethodDef(mclassdef, new MMethod(mclassdef, "{name}", private_visibility), location) - real_mpropdef.msignature = mpropdef.msignature - # FIXME: Again, if the engine require a real propdef even if it is empty - var real_npropdef = toolcontext.parse_propdef("fun real do end").as(AMethPropdef) - associate_propdef(real_mpropdef, real_npropdef) - # Note: the body is set at the last line of this function - - # Save the original body - var real_body = npropdef.n_block.as(not null) - - # Replace the original body with a new body that do the proxy'n'cache work - var proxy_body = toolcontext.parse_stmts("if self._is_cached then return self._cache.as(not null)\nvar res = call_real\nself._cache_write = res\nself._is_cached_write = true\nreturn res") - real_body.replace_with(proxy_body) - - # Do some transformation on the identifiers used on the proxy body so that correct entities are designated - # FIXME: we just trick the following phases into associating by name some tokens with some model-entities - # But this is bad at at least two levels - # - we already know the real model-entities, so why doing latter the association and not now? - # - associating by names may cause a useless fragility (name-conflicts, etc.) - proxy_body.collect_tokens_by_text("_is_cached").first.text = is_cached_mpropdef.mproperty.name - proxy_body.collect_tokens_by_text("_is_cached_write").first.text = is_cached_mpropdef.mproperty.name - proxy_body.collect_tokens_by_text("_cache").first.text = cache_mpropdef.mproperty.name - proxy_body.collect_tokens_by_text("_cache_write").first.text = cache_mpropdef.mproperty.name - proxy_body.collect_tokens_by_text("call_real").first.text = real_mpropdef.mproperty.name - - # FIXME a last transformation cannot be done yet. So, the call to `super` (`ASuperExpr`) is broken in cached methods. - - # Give the original body to the private real methoddef - real_npropdef.n_block.replace_with(real_body) - end - - # Detach `n` from its original AST and attach it to `m` (and its related AST) - # `n` must not be already attached to an existing model entity - # `m` must not be already attached to an existing AST node - fun associate_propdef(m: MPropDef, n: APropdef) - do - # FIXME: the model-AST relations **must** be rationalized: - # * 1- fragility: the risk of inconsistencies is too hight - # * 2- complexity: there is too much paths to access the same things - - # Easy attach - assert n.mpropdef == null - n.mpropdef = m - - # Required to so that look-for implementation works - assert not toolcontext.modelbuilder.mpropdef2npropdef.has_key(m) - toolcontext.modelbuilder.mpropdef2npropdef[m] = n - - var mclassdef = m.mclassdef - var nclassdef = toolcontext.modelbuilder.mclassdef2nclassdef[mclassdef] - # Sanity checks - assert nclassdef.mclassdef == mclassdef - - if n isa AAttrPropdef then - n.has_value = n.n_expr != null or n.n_block != null - end - - # Required so that propdef are visited in visitors - if not nclassdef.n_propdefs.has(n) then nclassdef.n_propdefs.add(n) - end -end diff --git a/src/frontend/check_annotation.nit b/src/frontend/check_annotation.nit index 9408e95..419c5ae 100644 --- a/src/frontend/check_annotation.nit +++ b/src/frontend/check_annotation.nit @@ -84,7 +84,6 @@ readonly writable autoinit noautoinit -cached nosuper old_style_init abstract diff --git a/src/frontend/frontend.nit b/src/frontend/frontend.nit index 5b04e01..8c5079f 100644 --- a/src/frontend/frontend.nit +++ b/src/frontend/frontend.nit @@ -21,7 +21,6 @@ import literal import modelize import semantize import div_by_zero -import cached import serialization_phase import check_annotation import glsl_validation diff --git a/src/nitlight.nit b/src/nitlight.nit index 5b64e3d..9a7b050 100644 --- a/src/nitlight.nit +++ b/src/nitlight.nit @@ -19,9 +19,6 @@ import highlight var toolcontext = new ToolContext -# Disable `cached` because it causes issues when printing transformed AST. FIXME -toolcontext.cached_phase.disabled = true - # Try to colorize, even if programs are non valid toolcontext.keep_going = true -- 1.7.9.5