While thinking about the remaining task of #466 (simple parsing), I though that there useful functions where missing in order to have a sane `Reader::read_word` method
Pull-Request: #1179
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
return id
end
- fun collections_list: Array[String] is cached do return ["List", "ArrayList", "LinkedList", "Vector", "Set", "SortedSet", "HashSet", "TreeSet", "LinkedHashSet", "Map", "SortedMap", "HashMap", "TreeMap", "Hashtable", "LinkedHashMap"]
- fun iterable: Array[String] is cached do return ["ArrayList", "Set", "HashSet", "LinkedHashSet", "LinkedList", "Stack", "TreeSet", "Vector"]
- fun maps: Array[String] is cached do return ["Map", "SortedMap", "HashMap", "TreeMap", "Hashtable", "LinkedHashMap"]
+ var collections_list: Array[String] is lazy do return ["List", "ArrayList", "LinkedList", "Vector", "Set", "SortedSet", "HashSet", "TreeSet", "LinkedHashSet", "Map", "SortedMap", "HashMap", "TreeMap", "Hashtable", "LinkedHashMap"]
+ var iterable: Array[String] is lazy do return ["ArrayList", "Set", "HashSet", "LinkedHashSet", "LinkedList", "Stack", "TreeSet", "Vector"]
+ var maps: Array[String] is lazy do return ["Map", "SortedMap", "HashMap", "TreeMap", "Hashtable", "LinkedHashMap"]
end
class NitType
# Result is returned as an array containg ordered entries:
# `breadcrumbs.first` is the root entry and
# `breadcrumbs.last == self`
- fun breadcrumbs: Array[WikiEntry] is cached do
+ var breadcrumbs: Array[WikiEntry] is lazy do
var path = new Array[WikiEntry]
var entry: nullable WikiEntry = self
while entry != null and not entry.is_root do
# Extract the markdown text from `source_file`.
#
# REQUIRE: `has_source`.
- fun md: String is cached do
+ var md: String is lazy do
assert has_source
var file = new FileReader.open(src_full_path.to_s)
var md = file.read_all
#
# * key: `wiki.name`
# * default: `MyWiki`
- fun wiki_name: String is cached do return value_or_default("wiki.name", "MyWiki")
+ var wiki_name: String is lazy do return value_or_default("wiki.name", "MyWiki")
# Site description.
#
#
# * key: `wiki.desc`
# * default: ``
- fun wiki_desc: String is cached do return value_or_default("wiki.desc", "")
+ var wiki_desc: String is lazy do return value_or_default("wiki.desc", "")
# Site logo url.
#
#
# * key: `wiki.logo`
# * default: ``
- fun wiki_logo: String is cached do return value_or_default("wiki.logo", "")
+ var wiki_logo: String is lazy do return value_or_default("wiki.logo", "")
# Root url of the wiki.
#
# * key: `wiki.root_url`
# * default: `http://localhost/`
- fun root_url: String is cached do return value_or_default("wiki.root_url", "http://localhost/")
+ var root_url: String is lazy do return value_or_default("wiki.root_url", "http://localhost/")
# Root directory of the wiki.
#
# * key: `wiki.root_dir`
# * default: `./`
- fun root_dir: String is cached do return value_or_default("wiki.root_dir", "./").simplify_path
+ var root_dir: String is lazy do return value_or_default("wiki.root_dir", "./").simplify_path
# Pages directory.
#
#
# * key: `wiki.source_dir
# * default: `pages/`
- fun source_dir: String is cached do
+ var source_dir: String is lazy do
return value_or_default("wiki.source_dir", "pages/").simplify_path
end
#
# * key: `wiki.out_dir`
# * default: `out/`
- fun out_dir: String is cached do return value_or_default("wiki.out_dir", "out/").simplify_path
+ var out_dir: String is lazy do return value_or_default("wiki.out_dir", "out/").simplify_path
# Asset files directory.
#
#
# * key: `wiki.assets_dir`
# * default: `assets/`
- fun assets_dir: String is cached do
+ var assets_dir: String is lazy do
return value_or_default("wiki.assets_dir", "assets/").simplify_path
end
#
# * key: `wiki.templates_dir`
# * default: `templates/`
- fun templates_dir: String is cached do
+ var templates_dir: String is lazy do
return value_or_default("wiki.templates_dir", "templates/").simplify_path
end
#
# * key: `wiki.template`
# * default: `template.html`
- fun template_file: String is cached do
+ var template_file: String is lazy do
return value_or_default("wiki.template", "template.html")
end
#
# * key: `wiki.header`
# * default: `header.html`
- fun header_file: String is cached do
+ var header_file: String is lazy do
return value_or_default("wiki.header", "header.html")
end
#
# * key: `wiki.menu`
# * default: `menu.html`
- fun menu_file: String is cached do
+ var menu_file: String is lazy do
return value_or_default("wiki.menu", "menu.html")
end
#
# * key: `wiki.footer`
# * default: `footer.html`
- fun footer_file: String is cached do
+ var footer_file: String is lazy do
return value_or_default("wiki.footer", "footer.html")
end
#
# * key: `wiki.rsync_dir`
# * default: ``
- fun rsync_dir: String is cached do return value_or_default("wiki.rsync_dir", "")
+ var rsync_dir: String is lazy do return value_or_default("wiki.rsync_dir", "")
# Remote repository used to pull modifications on sources.
#
# * key: `wiki.git_origin`
# * default: `origin`
- fun git_origin: String is cached do return value_or_default("wiki.git_origin", "origin")
+ var git_origin: String is lazy do return value_or_default("wiki.git_origin", "origin")
# Remote branch used to pull modifications on sources.
#
# * key: `wiki.git_branch`
# * default: `master`
- fun git_branch: String is cached do return value_or_default("wiki.git_branch", "master")
+ var git_branch: String is lazy do return value_or_default("wiki.git_branch", "master")
end
# WikiSection custom configuration.
#
# If no file `index.md` exists for this section,
# a summary is generated using contained articles.
- fun index: WikiArticle is cached do
+ var index: WikiArticle is lazy do
for child in children.values do
if child isa WikiArticle and child.is_index then return child
end
redef class User
# The player linked to `self`.
- fun player(game: Game): Player is lazy do
- var player = game.load_player(login)
+ fun player(game: Game): Player do
+ var player = player_cache.get_or_null(game)
+ if player != null then return player
+ player = game.load_player(login)
if player == null then player = game.add_player(self)
+ player_cache[game] = player
return player
end
+
+ private var player_cache = new HashMap[Game, Player]
end
# A GameReactor reacts to event sent by a `Github::HookListener`.
redef class App
# Resource Manager used to manage resources placed in the `res` folder of the app
- fun resource_manager: ResourcesManager is cached do return new ResourcesManager(self.resources, self.package_name.to_s)
+ var resource_manager: ResourcesManager is lazy do return new ResourcesManager(self.resources, self.package_name.to_s)
# Assets Manager used to manage resources placed in the `assets` folder of the app
- fun asset_manager: AssetManager is cached do return new AssetManager(self)
+ var asset_manager: AssetManager is lazy do return new AssetManager(self)
# Get the native AssetsManager of the application, used to initialize the nit's AssetManager
private fun assets: NativeAssetManager import native_activity in "Java" `{ return App_native_activity(recv).getAssets(); `}
# Returns the default MediaPlayer of the application.
# When you load a music, it goes in this MediaPlayer.
# Use it for advanced sound management
- fun default_mediaplayer: MediaPlayer is cached do return new MediaPlayer
+ var default_mediaplayer: MediaPlayer is lazy do return new MediaPlayer
# Returns the default MediaPlayer of the application.
# When you load a short sound (not a music), it's added to this soundpool.
# Use it for advanced sound management.
- fun default_soundpool: SoundPool is cached do return new SoundPool
+ var default_soundpool: SoundPool is lazy do return new SoundPool
# Get the native audio manager
fun audio_manager: NativeAudioManager import native_activity in "Java" `{
end
redef class App
- fun shared_preferences: SharedPreferences is cached do
+ var shared_preferences: SharedPreferences is lazy do
return new SharedPreferences.privately(self, "")
end
end
redef class App
# Get the handle to this device vibrator as a global ref
- fun vibrator: Vibrator is cached do
+ var vibrator: Vibrator is lazy do
var v = vibrator_native(native_activity)
return v.new_global_ref
end
# GL capability: blend the computed fragment color values
#
# Foreign: GL_BLEND
- fun blend: GLCap is lazy do return new GLCap(0x0BE2)
+ var blend: GLCap is lazy do return new GLCap(0x0BE2)
# GL capability: cull polygons based of their winding in window coordinates
#
# Foreign: GL_CULL_FACE
- fun cull_face: GLCap is lazy do return new GLCap(0x0B44)
+ var cull_face: GLCap is lazy do return new GLCap(0x0B44)
# GL capability: do depth comparisons and update the depth buffer
#
# Foreign: GL_DEPTH_TEST
- fun depth_test: GLCap is lazy do return new GLCap(0x0B71)
+ var depth_test: GLCap is lazy do return new GLCap(0x0B71)
# GL capability: dither color components or indices before they are written to the color buffer
#
# Foreign: GL_DITHER
- fun dither: GLCap is lazy do return new GLCap(0x0BE2)
+ var dither: GLCap is lazy do return new GLCap(0x0BE2)
# GL capability: add an offset to depth values of a polygon fragment before depth test
#
# Foreign: GL_POLYGON_OFFSET_FILL
- fun polygon_offset_fill: GLCap is lazy do return new GLCap(0x8037)
+ var polygon_offset_fill: GLCap is lazy do return new GLCap(0x8037)
# GL capability: compute a temporary coverage value where each bit is determined by the alpha value at the corresponding location
#
# Foreign: GL_SAMPLE_ALPHA_TO_COVERAGE
- fun sample_alpha_to_coverage: GLCap is lazy do return new GLCap(0x809E)
+ var sample_alpha_to_coverage: GLCap is lazy do return new GLCap(0x809E)
# GL capability: AND the fragment coverage with the temporary coverage value
#
# Foreign: GL_SAMPLE_COVERAGE
- fun sample_coverage: GLCap is lazy do return new GLCap(0x80A0)
+ var sample_coverage: GLCap is lazy do return new GLCap(0x80A0)
# GL capability: discard fragments that are outside the scissor rectangle
#
# Foreign: GL_SCISSOR_TEST
- fun scissor_test: GLCap is lazy do return new GLCap(0x0C11)
+ var scissor_test: GLCap is lazy do return new GLCap(0x0C11)
# GL capability: do stencil testing and update the stencil buffer
#
# Foreign: GL_STENCIL_TEST
- fun stencil_test: GLCap is lazy do return new GLCap(0x0B90)
+ var stencil_test: GLCap is lazy do return new GLCap(0x0B90)
end
# Float related data types of OpenGL ES 2.0 shaders
# Name of the column
#
# require: `self.statement.is_open`
- fun name: String is cached do
+ var name: String is lazy do
assert statement_closed: statement.is_open
return statement.native_statement.column_name(index)
# Note: the value is returned *as is*, implementations may want to store the value in the map before returning it
# @toimplement
protected fun provide_default_value(key: K): V do abort
+
+ # Does `self` and `other` have the same keys associated with the same values?
+ #
+ # ~~~
+ # var a = new HashMap[String, Int]
+ # var b = new ArrayMap[Object, Numeric]
+ # assert a == b
+ # a["one"] = 1
+ # assert a != b
+ # b["one"] = 1
+ # assert a == b
+ # b["one"] = 2
+ # assert a != b
+ # ~~~
+ redef fun ==(other)
+ do
+ if not other isa MapRead[nullable Object, nullable Object] then return false
+ if other.length != self.length then return false
+ for k, v in self do
+ if not other.has_key(k) then return false
+ if other[k] != v then return false
+ end
+ return true
+ end
end
# Maps are associative collections: `key` -> `item`.
# assert a == b
class Array[E]
super AbstractArray[E]
+ super Cloneable
redef fun [](index)
do
return true
end
+ # Shallow clone of `self`
+ #
+ # ~~~
+ # var a = [1,2,3]
+ # var b = a.clone
+ # assert a == b
+ # a.add 4
+ # assert a != b
+ # b.add 4
+ # assert a == b
+ # ~~~
+ #
+ # Note that the clone is shallow and elements are shared between `self` and the result.
+ #
+ # ~~~
+ # var aa = [a]
+ # var bb = aa.clone
+ # assert aa == bb
+ # aa.first.add 5
+ # assert aa == bb
+ # ~~~
+ redef fun clone do return to_a
+
# Concatenation of arrays.
#
# Returns a new array built by concatenating `self` and `other` together.
# A set implemented with an Array.
class ArraySet[E]
super Set[E]
+ super Cloneable
# The stored elements.
private var array: Array[E] is noinit
init with_capacity(i: Int) do _array = new Array[E].with_capacity(i)
redef fun new_set do return new ArraySet[E]
+
+ # Shallow clone of `self`
+ #
+ # ~~~
+ # var a = new ArraySet[Int]
+ # a.add 1
+ # a.add 2
+ # var b = a.clone
+ # assert a == b
+ # a.add 3
+ # assert a != b
+ # b.add 3
+ # assert a == b
+ # ~~~
+ #
+ # Note that the clone is shallow and keys and values are shared between `self` and the result.
+ #
+ # ~~~
+ # var aa = new ArraySet[Array[Int]]
+ # aa.add([1,2])
+ # var bb = aa.clone
+ # assert aa == bb
+ # aa.first.add 5
+ # assert aa == bb
+ # ~~~
+ redef fun clone
+ do
+ var res = new ArraySet[E]
+ res.add_all self
+ return res
+ end
end
# Iterators on sets implemented with arrays.
# Associative arrays implemented with an array of (key, value) pairs.
class ArrayMap[K, E]
super CoupleMap[K, E]
+ super Cloneable
# O(n)
redef fun [](key)
end
return -1
end
+
+ # Shallow clone of `self`
+ #
+ # ~~~
+ # var a = new ArrayMap[String,Int]
+ # a["one"] = 1
+ # a["two"] = 2
+ # var b = a.clone
+ # assert a == b
+ # a["zero"] = 0
+ # assert a != b
+ # ~~~
+ #
+ # Note that the clone is shallow and keys and values are shared between `self` and the result.
+ #
+ # ~~~
+ # var aa = new ArrayMap[String, Array[Int]]
+ # aa["two"] = [1,2]
+ # var bb = aa.clone
+ # assert aa == bb
+ # aa["two"].add 5
+ # assert aa == bb
+ # ~~~
+ redef fun clone
+ do
+ var res = new ArrayMap[K,E]
+ res.recover_with self
+ return res
+ end
end
private class ArrayMapKeys[K, E]
end
end
+# Something that can be cloned
+#
+# This interface introduces the `clone` method used to duplicate an instance
+# Its specific semantic is let to the subclasses.
+interface Cloneable
+ # Duplicate `self`
+ #
+ # The specific semantic of this method is let to the subclasses;
+ # Especially, if (and how) attributes are cloned (depth vs. shallow).
+ #
+ # As a rule of thumb, the principle of least astonishment should
+ # be used to guide the semantic.
+ #
+ # Note that as the returned clone depends on the semantic,
+ # the `==` method, if redefined, should ensure the equality
+ # between an object and its clone.
+ fun clone: SELF is abstract
+end
+
# A numeric value supporting mathematical operations
interface Numeric
super Comparable
super Rope
super String
- redef fun chars is cached do return new RopeChars(self)
+ redef var chars is lazy do return new RopeChars(self)
end
# Node that represents a concatenation between two `String`
redef fun empty do return ""
- redef fun to_cstring is cached do
+ redef var to_cstring is lazy do
var len = length
var ns = new NativeString(len + 1)
ns[len] = '\0'
super Rope
super Buffer
- redef fun chars: Sequence[Char] is cached do return new RopeBufferChars(self)
+ redef var chars: Sequence[Char] is lazy do return new RopeBufferChars(self)
# The final string being built on the fly
private var str: String is noinit
`--log`
: Generate various log files.
- Currently unused.
+
+ The tool will generate some files in the logging directory (see `--log-dir`).
+ These files are intended to the advanced user and the developers of the tools.
`--log-dir`
: Directory where to generate log files.
- Currently unused.
+
+ By default the directory is called `logs` in the working directory.
`-h`, `-?`, `--help`
var name = self.get_name("varonce")
self.add_decl("static {mtype.ctype} {name};")
var res = self.new_var(mtype)
- self.add("if ({name}) \{")
+ self.add("if (likely({name}!=NULL)) \{")
self.add("{res} = {name};")
self.add("\} else \{")
var native_mtype = self.get_class("NativeString").mclass_type
v.add_decl("static {mtype.ctype} {name};")
v.add_decl("static int {guard};")
var res = v.new_var(mtype)
- v.add("if ({guard}) \{")
+ v.add("if (likely({guard})) \{")
v.add("{res} = {name};")
v.add("\} else \{")
var i = v.expr(self.n_expr, mtype)
redef fun compile_callsite(callsite, args)
do
var rta = compiler.runtime_type_analysis
- var mmethod = callsite.mproperty
# TODO: Inlining of new-style constructors with initializers
if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null and callsite.mpropdef.initializers.is_empty then
var tgs = rta.live_targets(callsite)
if tgs.length == 1 then
- # DIRECT CALL
- var res0 = before_send(mmethod, args)
- var res = call(tgs.first, tgs.first.mclassdef.bound_mtype, args)
- if res0 != null then
- assert res != null
- self.assign(res0, res)
- res = res0
- end
- add("\}") # close the before_send
- return res
+ return direct_call(tgs.first, args)
end
end
+ # Shortcut intern methods as they are not usually redefinable
+ if callsite.mpropdef.is_intern and callsite.mproperty.name != "object_id" then
+ # `object_id` is the only redefined intern method, so it can not be directly called.
+ # TODO find a less ugly approach?
+ return direct_call(callsite.mpropdef, args)
+ end
return super
end
+
+ # Fully and directly call a mpropdef
+ #
+ # This method is used by `compile_callsite`
+ private fun direct_call(mpropdef: MMethodDef, args: Array[RuntimeVariable]): nullable RuntimeVariable
+ do
+ var res0 = before_send(mpropdef.mproperty, args)
+ var res = call(mpropdef, mpropdef.mclassdef.bound_mtype, args)
+ if res0 != null then
+ assert res != null
+ self.assign(res0, res)
+ res = res0
+ end
+ add("\}") # close the before_send
+ return res
+ end
redef fun send(mmethod, arguments)
do
if arguments.first.mcasttype.ctype != "val*" then
var nclass = self.get_class("NativeArray")
var recv = "((struct instance_{nclass.c_name}*){arguments[0]})->values"
if pname == "[]" then
- self.ret(self.new_expr("{recv}[{arguments[1]}]", ret_type.as(not null)))
+ # Because the objects are boxed, return the box to avoid unnecessary (or broken) unboxing/reboxing
+ var res = self.new_expr("{recv}[{arguments[1]}]", compiler.mainmodule.object_type)
+ res.mcasttype = ret_type.as(not null)
+ self.ret(res)
return
else if pname == "[]=" then
self.add("{recv}[{arguments[1]}]={arguments[2]};")
+++ /dev/null
-# 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}<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
- 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 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}<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(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
writable
autoinit
noautoinit
-cached
nosuper
old_style_init
abstract
import modelize
import semantize
import div_by_zero
-import cached
import serialization_phase
import check_annotation
import glsl_validation
end
redef class MProject
- redef fun concern_rank is cached do
+ redef var concern_rank is lazy do
var max = 0
for mgroup in mgroups do
var mmax = mgroup.concern_rank
return res
end
- redef fun concern_rank is cached do
+ redef var concern_rank is lazy do
var max = 0
for mmodule in collect_mmodules do
var mmax = mmodule.concern_rank
return mclasses
end
- redef fun concern_rank is cached do
+ redef var concern_rank is lazy do
var max = 0
for p in in_importation.direct_greaters do
var pmax = p.concern_rank
mpropdef.is_abstract = self.get_single_annotation("abstract", modelbuilder) != null
mpropdef.is_intern = self.get_single_annotation("intern", modelbuilder) != null
mpropdef.is_extern = self.n_extern_code_block != null or self.get_single_annotation("extern", modelbuilder) != null
+
+ # Check annotations
+ var at = self.get_single_annotation("lazy", modelbuilder)
+ if at != null then modelbuilder.error(at, "Syntax error: `lazy` must be used on attributes.")
end
redef fun check_signature(modelbuilder)
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
redef class MModule
# Get the type of the class `Serializable`
- fun serializable_type: MClassType is cached do
+ var serializable_type: MClassType is lazy do
return self.get_primitive_class("Serializable").mclass_type
end
end
do
var analysis = new RapidTypeAnalysis(self, mainmodule)
analysis.run_analysis
+
+ if toolcontext.opt_log.value then
+ var basename = toolcontext.log_directory / mainmodule.name
+ analysis.live_methods_to_tree.write_to_file(basename + ".rta_methods.txt")
+ analysis.live_types_to_csv.write_to_file(basename + ".rta_types.csv")
+ end
+
return analysis
end
end
# Directory where to generate log files
var log_directory: String = "logs"
+ # Stream in `log_directory` where all info messages are written
+ var log_info: nullable Writer = null
+
# Messages
private var messages = new Array[Message]
private var message_sorter: Comparator = default_comparator
if level <= verbose_level then
print "{s}"
end
+ if log_info != null then
+ log_info.write s
+ log_info.write "\n"
+ end
end
# Executes a program while checking if it's available and if the execution ended correctly
if opt_log.value then
# Make sure the output directory exists
log_directory.mkdir
- end
+ # Redirect the verbose messages
+ log_info = (log_directory/"info.txt").to_path.open_wo
+ end
end
# Get the current `nit_version` or "DUMMY_VERSION" if `--set-dummy-tool` is set.
+++ /dev/null
-# 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.
-
-import kernel
-
-class Base
- var foo: Int = 10
- fun -: Int do return foo + 20
- fun bar: Int do return -self + 40
- #alt1#fun fail is cached do end
- #alt2#fun fail(i: Int): Int is cached do return i
-end
-
-class CMinus
- super Base
-
- redef fun - is cached do return foo + 1
-end
-
-class CBar
- super Base
-
- redef fun bar is cached do return -self + 2
-end
-
-#alt3#fun fail: Int is cached do return 0
-
-fun test(b: Base)
-do
- b.foo.output
- (-b).output
- b.bar.output
- b.foo = 110
- b.foo.output
- (-b).output
- b.bar.output
- '\n'.output
-end
-
-test(new Base)
-test(new CMinus)
-test(new CBar)
return 20
end
#alt1#var a3: Object is lazy
+ #alt2#fun a4: Object is lazy
end
var f = new Foo
--separate ../examples/hello_world.nit -m test_mixin.nit -o out/nitgs-hello_world_mixed ; out/nitgs-hello_world_mixed
base_simple_import.nit base_simple.nit --dir out/ ; out/base_simple ; out/base_simple_import
test_define.nit -D text=hello -D num=42 -D flag --dir out/ ; out/test_define
+--log --log-dir $WRITE test_prog -o out/test_prog.bin
+++ /dev/null
-10
-30
-70
-110
-130
-170
-
-10
-11
-51
-110
-11
-51
-
-10
-30
-32
-110
-130
-32
-
+++ /dev/null
-alt/base_at_cached_alt1.nit:21,6--9: Syntax error: only a function can be cached.
+++ /dev/null
-alt/base_at_cached_alt2.nit:22,6--9: Syntax error: only a function without arguments can be cached.
+++ /dev/null
-alt/base_at_cached_alt3.nit:37,5--8: Error: only abstract and concrete classes can have cached functions.
--- /dev/null
+alt/base_attr_lazy_alt2.nit:29,20--23: Syntax error: `lazy` must be used on attributes.
--- /dev/null
+info.txt
+test_prog.rta_methods.txt
+test_prog.rta_types.csv
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:413)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:432)
11
21
31
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:413)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:432)
11
21
31
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:413)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:432)
11
21
31
]
Comparable -> Discrete [dir=back arrowtail=open style=dashed];
+Cloneable [
+ label = "{interface\nCloneable||+ clone(): SELF\l}"
+]
+Object -> Cloneable [dir=back arrowtail=open style=dashed];
+
Numeric [
label = "{interface\nNumeric||+ +(i: OTHER): OTHER\l+ -(i: OTHER): OTHER\l+ unary -(): OTHER\l+ *(i: OTHER): OTHER\l+ /(i: OTHER): OTHER\l+ to_i(): Int\l+ to_f(): Float\l+ is_zero(): Bool\l+ zero(): OTHER\l+ value_of(val: Numeric): OTHER\l}"
]
]
Comparable -> Discrete [dir=back arrowtail=open style=dashed];
+Cloneable [
+ label = "{interface\nCloneable||+ clone(): SELF\l}"
+]
+Object -> Cloneable [dir=back arrowtail=open style=dashed];
+
Numeric [
label = "{interface\nNumeric||+ +(i: OTHER): OTHER\l+ -(i: OTHER): OTHER\l+ unary -(): OTHER\l+ *(i: OTHER): OTHER\l+ /(i: OTHER): OTHER\l+ to_i(): Int\l+ to_f(): Float\l+ is_zero(): Bool\l+ zero(): OTHER\l+ value_of(val: Numeric): OTHER\l}"
]
-Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:808)
+Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:894)
NativeString
N
Nit