import modelize_property
import parser_util
import simple_misc_analysis
+private import annotation
redef class ToolContext
var cached_phase: Phase = new CachedPhase(self, [modelize_property_phase])
redef fun process_annotated_node(npropdef, nat)
do
# Skip if we are not interested
- if nat.n_atid.n_id.text != "cached" then return
+ 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 AConcreteMethPropdef then
+ if not npropdef isa AMethPropdef then
modelbuilder.error(npropdef, "Syntax error: only a function can be cached.")
return
end
var location = npropdef.location
var name = mpropdef.mproperty.name
- var nclassdef = npropdef.parent.as(AStdClassdef)
+ 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}<cache>", 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
+ # 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}<is_cached>", 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 real_mpropdef = new MMethodDef(mclassdef, new MMethod(mclassdef, "{name}<real>", 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(AConcreteMethPropdef)
+ 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
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.
+ # 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
+ # `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: