Merge: Protected setters
authorJean Privat <jean@pryen.org>
Sat, 18 Jul 2015 01:42:35 +0000 (21:42 -0400)
committerJean Privat <jean@pryen.org>
Sat, 18 Jul 2015 01:42:35 +0000 (21:42 -0400)
Setters of attributes are private by default. This cause some issue as they are exposed as initializers but still invisible in client modules.
The proposed solution to resolve this inconsistency is to make setters protected by default so they are visible in client modules but only usable in subclasses.

This is a change is the spec, to RFC label is set is people have comments on the sanity/usability/kiss/pola/etc.

Close #1552

Pull-Request: #1567
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>

58 files changed:
contrib/nitcc/src/autom.nit
contrib/nitrpg/src/achievements.nit
contrib/nitrpg/src/events.nit
contrib/nitrpg/src/game.nit
contrib/refund/src/refund_base.nit
examples/mnit_dino/src/dino.nit
examples/mnit_dino/src/game_logic.nit
examples/mnit_moles/src/moles_android.nit
examples/rosettacode/entropy.nit [new file with mode: 0644]
examples/rosettacode/entropy_narcissist.nit [new file with mode: 0644]
examples/rosettacode/fibonacci_word.nit [new file with mode: 0644]
lib/counter.nit
lib/curl/native_curl.nit
lib/date.nit
lib/geometry/boxes.nit
lib/geometry/polygon.nit
lib/neo4j/neo4j.nit
lib/noise.nit
lib/pthreads/concurrent_collections.nit
lib/pthreads/redef_collections.nit
lib/serialization/serialization.nit
lib/sqlite3/sqlite3.nit
lib/standard/bytes.nit
lib/standard/collection/abstract_collection.nit
lib/standard/collection/array.nit
lib/standard/collection/list.nit
lib/standard/text/flat.nit
src/compiler/separate_compiler.nit
src/interpreter/primitive_types.nit
src/location.nit
src/modelize/modelize_property.nit
src/semantize/auto_super_init.nit
tests/base_init_basic.nit
tests/base_label_for.nit
tests/example_hanoi.nit
tests/niti.skip
tests/nitvm.skip
tests/sav/base_init_basic_alt3.res
tests/sav/base_init_basic_alt5.res [new file with mode: 0644]
tests/sav/base_init_combine.res
tests/sav/base_init_combine_alt1.res
tests/sav/base_init_inherit6.res
tests/sav/base_init_inherit6_alt1.res
tests/sav/base_init_inherit6_alt2.res
tests/sav/base_init_linext2.res
tests/sav/base_init_linext2_alt2.res
tests/sav/base_init_linext2_alt3.res
tests/sav/base_init_linext2_alt4.res
tests/sav/base_init_linext2_alt5.res
tests/sav/base_init_simple.res
tests/sav/entropy.res [new file with mode: 0644]
tests/sav/entropy_narcissist.res [new file with mode: 0644]
tests/sav/fibonacci_word.res [new file with mode: 0644]
tests/sav/nitce/test_binary_deserialization_alt1.res
tests/sav/nitce/test_json_deserialization_alt1.res
tests/sav/nitmetrics_args1.res
tests/sav/nitpick_args1.res
tests/sav/test_new_native_alt1.res

index f286894..d143684 100644 (file)
@@ -21,7 +21,7 @@ import grammar
 # A finite automaton
 class Automaton
        # The start state
-       var start: State
+       var start: State is noinit
 
        # State that are accept states
        var accept = new Array[State]
index c799b86..9b18a6b 100644 (file)
@@ -97,11 +97,7 @@ class Achievement
        #
        # Used to load achievements from storage.
        init from_json(game: Game, json: JsonObject) do
-               self.game = game
-               id = json["id"].to_s
-               name = json["name"].to_s
-               desc = json["desc"].to_s
-               reward = json["reward"].as(Int)
+               init(game, json["id"].to_s, json["name"].to_s, json["desc"].to_s, json["reward"].as(Int))
        end
 
        redef fun to_json do
index dde2c55..d1ba25a 100644 (file)
@@ -89,11 +89,9 @@ class GameEvent
        #
        # Used to load events from json storage.
        init from_json(game: Game, json: JsonObject) do
-               self.game = game
+               init(game, json["kind"].to_s, json["data"].as(JsonObject))
                internal_id = json["internal_id"].to_s
-               kind = json["kind"].to_s
                time = new ISODate.from_string(json["time"].to_s)
-               data = json["data"].as(JsonObject)
        end
 
        redef fun to_json do
index 1ab143e..a8175a8 100644 (file)
@@ -212,8 +212,7 @@ class Player
        #
        # Used to load players from saved data.
        init from_json(game: Game, json: JsonObject) do
-               self.game = game
-               name = json["name"].to_s
+               init(game, json["name"].to_s)
                nitcoins = json["nitcoins"].as(Int)
        end
 
index fbd5fee..ec1de5a 100644 (file)
@@ -402,7 +402,7 @@ class Dollar
 
        # Inits `self` from a float `value`.
        init from_float(value: Float) do
-               self.value = (value * 100.0).to_i
+               init((value * 100.0).to_i)
        end
 
        redef fun to_s do return "{value / 100}.{value % 100}$"
index d92c468..df97ad5 100644 (file)
@@ -31,7 +31,7 @@ redef class App
        var cavemen_incr = 4
 
        var game : nullable Game = null
-       var score = new Container[Int](0)
+       var score = new Ref[Int](0)
        var imgs : nullable ImageSet = null
        var splash : nullable SplashScreen = null
 
@@ -81,7 +81,7 @@ redef class App
                                if game.won then
                                        next_nbr_caveman += cavemen_incr
                                else
-                                       score = new Container[Int](0)
+                                       score = new Ref[Int](0)
                                        next_nbr_caveman = cavemen_at_first_level
                                end
                                game = new Game( next_nbr_caveman, score )
index 8d1a849..29712de 100644 (file)
@@ -34,7 +34,7 @@ class Game
 
        var over_since = 0
 
-       var score: Container[Int]
+       var score: Ref[Int]
 
        var random_radius_min = 200
        var random_radius_max = 400
@@ -43,7 +43,7 @@ class Game
 
        var entities_sorter = new EntitiesSorter
 
-       init( cavemen_nbr : Int, score: Container[Int] )
+       init( cavemen_nbr : Int, score: Ref[Int] )
        do
                srand_from(cavemen_nbr)
 
index ad2b1f1..677cb5b 100644 (file)
@@ -47,7 +47,7 @@ redef class App
        end
 end
 
-fun display_scale_container: Container[Float] do return once new Container[Float](0.1)
+fun display_scale_container: Ref[Float] do return once new Ref[Float](0.1)
 redef fun display_scale do return display_scale_container.item
 redef fun display_offset_x: Int do return (300.0*display_scale).to_i
 redef fun display_offset_y: Int do return (800.0*display_scale).to_i
diff --git a/examples/rosettacode/entropy.nit b/examples/rosettacode/entropy.nit
new file mode 100644 (file)
index 0000000..f47910c
--- /dev/null
@@ -0,0 +1,32 @@
+#!/usr/bin/env nit
+#
+# This file is part of NIT ( http://www.nitlanguage.org ).
+# This program is public domain
+
+# Task: Entropy
+# SEE: <http://rosettacode.org/wiki/Entropy>
+module entropy
+
+import counter
+
+# Basic implementation with a hashmap of chars to count them
+fun entropy(string: String): Float
+do
+       var cpt = new HashMap[Char, Int]
+       for char in string.chars do
+               var occ = cpt.get_or_default(char, 0)
+               cpt[char] = occ + 1
+       end
+
+       var len = string.length.to_f
+       var e = 0.0
+       for char, occ in cpt do
+               var freq = occ.to_f / len
+               e = e - freq * freq.log_base(2.0)
+       end
+       return e
+end
+print entropy("1223334444")
+
+# Alternative one-liner implementation using the `Counter::entropy` method of the library `counter`
+print "1223334444".chars.to_counter.entropy
diff --git a/examples/rosettacode/entropy_narcissist.nit b/examples/rosettacode/entropy_narcissist.nit
new file mode 100644 (file)
index 0000000..28b6212
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/env nit
+#
+# This file is part of NIT ( http://www.nitlanguage.org ).
+# This program is public domain
+
+# Task: Entropy/Narcissist
+# SEE: <http://rosettacode.org/wiki/Entropy/Narcissist>
+module entropy_narcissist
+
+import counter
+
+# Should be run in the right directory
+print "entropy_narcissist.nit".to_path.read_all.chars.to_counter.entropy
diff --git a/examples/rosettacode/fibonacci_word.nit b/examples/rosettacode/fibonacci_word.nit
new file mode 100644 (file)
index 0000000..fec4929
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/env nit
+#
+# This file is part of NIT ( http://www.nitlanguage.org ).
+# This program is public domain
+
+# Task: Fibonacci_word
+# SEE: <http://rosettacode.org/wiki/Fibonacci_word>
+module fibonacci_word
+
+import counter
+
+var words = new Array[String]
+words[0] = ""
+words[1] = "1"
+words[2] = "0"
+
+for i in [1..37] do
+       var w
+       if i >= words.length then
+               w = words[i-1] + words[i-2]
+               words[i] = w
+       else
+               w = words[i]
+       end
+       var out = w
+       if w.length > 40 then out = "..."
+       print "{i}\t{w.length}\t{w.chars.to_counter.entropy.to_precision(16)}\t{out}"
+end
index befce9c..644c115 100644 (file)
@@ -254,6 +254,36 @@ class Counter[E]
                end
                return (sum / map.length.to_f).sqrt
        end
+
+       # The information entropy (Shannon entropy) of the elements in the counter (in bits).
+       fun entropy: Float
+       do
+               var res = 0.0
+               var sum = self.sum.to_f
+               for k, v in self do
+                       var f = v.to_f / sum
+                       res = res - f * f.log_base(2.0)
+               end
+               return res
+       end
+end
+
+redef class Collection[E]
+       # Create and fill up a counter with the elements of `self.
+       #
+       # ~~~
+       # var cpt = "abaa".chars.to_counter
+       # assert cpt['a'] == 3
+       # assert cpt['b'] == 1
+       # assert cpt.length == 2
+       # assert cpt.sum == 4
+       # ~~~
+       fun to_counter: Counter[E]
+       do
+               var res = new Counter[E]
+               res.inc_all(self)
+               return res
+       end
 end
 
 private class CounterComparator[E]
index 29ab34d..cc6f298 100644 (file)
@@ -115,59 +115,59 @@ extern class NativeCurl `{ CURL * `}
        # Request Chars internal information from the CURL session
        fun easy_getinfo_chars(opt: CURLInfoChars): nullable String
        do
-                var answ = new Container[NativeString]("".to_cstring)
+                var answ = new Ref[NativeString]("".to_cstring)
                 if not native_getinfo_chars(opt, answ).is_ok then return null
                 if answ.item.address_is_null then return null
                 return answ.item.to_s
        end
 
        # Internal method used to get String object information initially knowns as C Chars type
-       private fun native_getinfo_chars(opt: CURLInfoChars, res: Container[NativeString]): CURLCode
-       import Container[NativeString].item= `{
+       private fun native_getinfo_chars(opt: CURLInfoChars, res: Ref[NativeString]): CURLCode
+       import Ref[NativeString].item= `{
                char *r;
                CURLcode c = curl_easy_getinfo( self, opt, &r);
-               if (c == CURLE_OK) Container_of_NativeString_item__assign(res, r);
+               if (c == CURLE_OK) Ref_of_NativeString_item__assign(res, r);
                return c;
        `}
 
        # Request Long internal information from the CURL session
        fun easy_getinfo_long(opt: CURLInfoLong): nullable Int
        do
-                var answ = new Container[Int](0)
+                var answ = new Ref[Int](0)
                 if not native_getinfo_long(opt, answ).is_ok then return null
                 return answ.item
        end
 
        # Internal method used to get Int object information initially knowns as C Long type
-       private fun native_getinfo_long(opt: CURLInfoLong, res: Container[Int]): CURLCode
-       import Container[Int].item= `{
+       private fun native_getinfo_long(opt: CURLInfoLong, res: Ref[Int]): CURLCode
+       import Ref[Int].item= `{
                long r;
                CURLcode c = curl_easy_getinfo( self, opt, &r);
-               if (c == CURLE_OK) Container_of_Int_item__assign(res, r);
+               if (c == CURLE_OK) Ref_of_Int_item__assign(res, r);
                return c;
        `}
 
        # Request Double internal information from the CURL session
        fun easy_getinfo_double(opt: CURLInfoDouble): nullable Float
        do
-                var answ = new Container[Float](0.0)
+                var answ = new Ref[Float](0.0)
                 if not native_getinfo_double(opt, answ).is_ok then return null
                 return answ.item
        end
 
        # Internal method used to get Int object information initially knowns as C Double type
-       private fun native_getinfo_double(opt: CURLInfoDouble, res: Container[Float]): CURLCode
-       import Container[Float].item= `{
+       private fun native_getinfo_double(opt: CURLInfoDouble, res: Ref[Float]): CURLCode
+       import Ref[Float].item= `{
                double r;
                CURLcode c = curl_easy_getinfo(self, opt, &r);
-               if (c == CURLE_OK) Container_of_Float_item__assign(res, r);
+               if (c == CURLE_OK) Ref_of_Float_item__assign(res, r);
                return c;
        `}
 
        # Request SList internal information from the CURL session
        fun easy_getinfo_slist(opt: CURLInfoSList): nullable Array[String]
        do
-               var answ = new Container[CURLSList](new CURLSList)
+               var answ = new Ref[CURLSList](new CURLSList)
                if not native_getinfo_slist(opt, answ).is_ok then return null
 
                var native = answ.item
@@ -177,11 +177,11 @@ extern class NativeCurl `{ CURL * `}
        end
 
        # Internal method used to get Array[String] object information initially knowns as C SList type
-       private fun native_getinfo_slist(opt: CURLInfoSList, res: Container[CURLSList]): CURLCode
-       import Container[CURLSList].item= `{
+       private fun native_getinfo_slist(opt: CURLInfoSList, res: Ref[CURLSList]): CURLCode
+       import Ref[CURLSList].item= `{
                struct curl_slist* csl;
                CURLcode c = curl_easy_getinfo(self, opt, &csl);
-               if (c == CURLE_OK) Container_of_CURLSList_item__assign(res, csl);
+               if (c == CURLE_OK) Ref_of_CURLSList_item__assign(res, csl);
                return c;
        `}
 
index 19e8ceb..d47b33f 100755 (executable)
@@ -58,9 +58,7 @@ class Time
        # Get the current time of the day
        init now do
                var tm = new Tm.localtime
-               hour = tm.hour
-               minute = tm.min
-               second = tm.sec
+               init(tm.hour, tm.min, tm.sec)
        end
 
        # Get the difference between two times in second
@@ -104,9 +102,7 @@ class Date
        # The date of this day
        init today do
                var tm = new Tm.localtime
-               year = 1900 + tm.year
-               month = tm.mon + 1
-               day = tm.mday
+               init(1900 + tm.year, tm.mon + 1, tm.mday)
        end
 
        # `self` formatted according to ISO 8601
index fc35c20..0e2d4b5 100644 (file)
@@ -120,48 +120,31 @@ class Box[N: Numeric]
 
                assert left != null and right != null and top != null and bottom != null
 
-               self.left = left
-               self.right = right
-               self.top = top
-               self.bottom = bottom
+               init(left, right, top, bottom)
        end
 
        # Create a `Box` using left, right, bottom and top
        init lrbt(left, right, bottom, top: N)
        do
-               self.left = left
-               self.right = right
-               self.top = top
-               self.bottom = bottom
+               init(left, right, top, bottom)
        end
 
        # Create a `Box` using left, right, top and bottom
        init lrtb(left, right, top, bottom: N)
        do
-               self.left = left
-               self.right = right
-               self.top = top
-               self.bottom = bottom
+               init(left, right, top, bottom)
        end
 
        # Create a `Box` using left, bottom, width and height
        init lbwh(left, bottom, width, height: N)
        do
-               self.left = left
-               self.bottom = bottom
-
-               self.right = left + width
-               self.top = bottom + height
+               init(left, left + width, bottom + height, bottom)
        end
 
        # Create a `Box` using left, top, width and height
        init ltwh(left, top, width, height: N)
        do
-               self.left = left
-               self.top = top
-
-               self.right = left + width
-               self.bottom = top - height
+               init(left, left+width, top, top - height)
        end
 
        redef fun to_s do return "<left: {left}, right: {right}, top: {top}, bottom: {bottom}>"
index 8fc1969..7d274a5 100644 (file)
@@ -302,7 +302,7 @@ private abstract class PolygonSorter
 
        # init calculating the center
        init with_center(pts : Array[Array[Float]]) do
-               center = calc_center(pts)
+               init(calc_center(pts))
        end
 
        # Calculate the center
index a45a116..9f96118 100644 (file)
@@ -509,13 +509,13 @@ abstract class NeoEntity
        private var batch_id: nullable Int = null
 
        # Load the entity from base
-       private init from_neo(neo: Neo4jClient, url: String) do
+       private init from_neo(neo: Neo4jClient, url: String) is nosuper do
                self.neo = neo
                self.url = url
        end
 
        # Init entity from JSON representation
-       private init from_json(neo: Neo4jClient, obj: JsonObject) do
+       private init from_json(neo: Neo4jClient, obj: JsonObject) is nosuper do
                self.neo = neo
                self.url = obj["self"].to_s
                self.internal_properties = obj["data"].as(JsonObject)
index 0754d4b..1a0d7ce 100644 (file)
@@ -13,7 +13,9 @@
 # limitations under the License.
 
 # Provides the noise generators `PerlinNoise` and `InterpolatedNoise`
-module noise
+module noise is serialize
+
+import serialization
 
 # 2D noise generator
 abstract class Noise
@@ -64,7 +66,7 @@ abstract class Noise
        # Seed to the random number generator `gradient_vector`
        #
        # By default, `seed` has a random value created with `Int::rand`.
-       var seed: Int = 19559.rand is lazy, writable
+       var seed: Int = 19511359.rand is lazy, writable
 end
 
 # 2D Perlin noise generator using layered `InterpolatedNoise`
@@ -195,7 +197,7 @@ class PerlinNoise
        # Used to get seeds for layers from the previous layers or `seed`.
        protected fun pseudo_random(value: Int): Int
        do
-               return value + 2935391 % 954847
+               return (value * 3537391).mask % 1291377
        end
 end
 
@@ -299,7 +301,8 @@ class InterpolatedNoise
                var ix1 = sx.lerp(n0, n1)
                var val = sy.lerp(ix0, ix1)
 
-               # Return value in [min...max] from val in [-0.5...0.5]
+               # Return value in [min...max] from val in [-1.0...1.0]
+               val /= 2.0
                val += 0.5
                return val.lerp(min, max)
        end
@@ -319,10 +322,20 @@ class InterpolatedNoise
                #
                # These magic prime numbers were determined good enough by
                # non-emperical experimentation. They may need to be changed/improved.
-               var i = 17957*seed + 45127*x + 22613*y
-               var mod = 19031
+               var seed = 817721 + self.seed
+               var i = seed * (x+seed) * 25111217 * (y+seed) * 72233613
+               var mod = 137121
+               var angle = (i.mask.abs%mod).to_f*2.0*pi/mod.to_f
+
+               # Debug code to evaluate the efficiency of the random angle generator
+               # The average of the produced angles should be at pi
+               #
+               #var sum = once new Container[Float](0.0)
+               #var count = once new Container[Float](0.0)
+               #sum.item += angle
+               #count.item += 1.0
+               #if count.item.to_i % 1000 == 0 then print "avg:{sum.item/count.item}/{count.item} i:{i} a:{angle} ({x}, {y}: {seed})"
 
-               var angle = (i%mod).to_f*2.0*pi/mod.to_f
                if w == 0 then return angle.cos
                return angle.sin
        end
@@ -335,3 +348,14 @@ class InterpolatedNoise
                return dx*gradient_vector(ix, iy, 0) + dy*gradient_vector(ix, iy, 1)
        end
 end
+
+redef universal Int
+       # The value of the least-significant 30 bits of `self`
+       #
+       # This mask is used as compatibility with 32 bits architecture.
+       # The missing 2 bits are used to tag integers by the Nit system.
+       private fun mask: Int
+       do
+               return bin_and(0x3FFF_FFFF)
+       end
+end
index 00201a9..6df0ea5 100644 (file)
@@ -26,7 +26,7 @@
 # - [x] `ConcurrentList`
 # - [ ] `ConcurrentHashMap`
 # - [ ] `ConcurrentHashSet`
-# - [ ] `ConcurrentContainer`
+# - [ ] `ConcurrentRef`
 # - [ ] `ConcurrentQueue`
 #
 # Introduced collections specialize their critical methods according to the
index 5e0a18c..4893cb2 100644 (file)
@@ -27,7 +27,7 @@
 # - [ ] `List`
 # - [ ] `HashMap`
 # - [ ] `HashSet`
-# - [ ] `Container`
+# - [ ] `Ref`
 # - [ ] `Queue`
 module redef_collections
 
index 9408af0..1fec7e9 100644 (file)
@@ -242,7 +242,7 @@ redef class Couple[F, S]
        end
 end
 
-redef class Container[E]
+redef class Ref[E]
        super Serializable
 
        redef init from_deserializer(v)
index 5f90801..023c6c1 100644 (file)
@@ -35,7 +35,7 @@ class Sqlite3DB
        # Open a connection to the database file at `path`
        init open(path: Text)
        do
-               native_connection = new NativeSqlite3.open(path.to_s)
+               init(new NativeSqlite3.open(path.to_s))
                if native_connection.is_valid then is_open = true
        end
 
index 2a3526f..9843ddc 100644 (file)
@@ -46,6 +46,7 @@ class Bytes
                init(ns, 0, 0)
        end
 
+       # Init a `Bytes` with capacity `cap`
        init with_capacity(cap: Int) do
                var ns = new NativeString(cap)
                init(ns, 0, cap)
@@ -96,6 +97,16 @@ class Bytes
                end
        end
 
+       #     var b = new Bytes.empty
+       #     b.append([0x41u8, 0x41u8, 0x18u8])
+       #     b.pop
+       #     assert b.to_s == "AA"
+       redef fun pop do
+               assert length >= 1
+               length -= 1
+               return items[length]
+       end
+
        redef fun clear do length = 0
 
        # Regenerates the buffer, necessary when it was persisted
@@ -159,6 +170,7 @@ private class BytesIterator
 end
 
 redef class NativeString
+       # Creates a new `Bytes` object from `self` with `strlen` as length
        fun to_bytes: Bytes do
                var len = cstring_length
                return new Bytes(self, len, len)
index 16e4b1e..39938bd 100644 (file)
@@ -282,7 +282,7 @@ end
 #
 # Also used when one want to give a single element when a full
 # collection is expected
-class Container[E]
+class Ref[E]
        super Collection[E]
 
        redef fun first do return item
@@ -304,14 +304,14 @@ class Container[E]
                end
        end
 
-       redef fun iterator do return new ContainerIterator[E](self)
+       redef fun iterator do return new RefIterator[E](self)
 
        # The stored item
        var item: E is writable
 end
 
 # This iterator is quite stupid since it is used for only one item.
-private class ContainerIterator[E]
+private class RefIterator[E]
        super Iterator[E]
        redef fun item do return _container.item
 
@@ -319,7 +319,7 @@ private class ContainerIterator[E]
 
        redef var is_ok = true
 
-       var container: Container[E]
+       var container: Ref[E]
 end
 
 # Items can be removed from this collection
index b6721df..ce89435 100644 (file)
@@ -553,6 +553,9 @@ private class ArrayReverseIterator[E]
        do
                _index = _array.length - 1
        end
+
+       # Do not cache `self`
+       redef fun finish do end
 end
 
 # Others collections ##########################################################
index 2cdc431..021a80c 100644 (file)
@@ -327,7 +327,7 @@ end
 
 # Linked nodes that constitute a linked list.
 private class ListNode[E]
-       super Container[E]
+       super Ref[E]
 
        # The next node.
        var next: nullable ListNode[E] = null
index 15ea14f..4064b57 100644 (file)
@@ -317,8 +317,7 @@ private class FlatStringCharReverseIterator
 
        init with_pos(tgt: FlatString, pos: Int)
        do
-               target = tgt
-               curr_pos = pos
+               init(tgt, pos)
        end
 
        redef fun is_ok do return curr_pos >= 0
@@ -342,9 +341,7 @@ private class FlatStringCharIterator
 
        init with_pos(tgt: FlatString, pos: Int)
        do
-               target = tgt
-               curr_pos = pos
-               max = tgt.length - 1
+               init(tgt, tgt.length - 1, pos)
        end
 
        redef fun is_ok do return curr_pos <= max
@@ -381,9 +378,7 @@ private class FlatStringByteReverseIterator
 
        init with_pos(tgt: FlatString, pos: Int)
        do
-               target = tgt
-               target_items = tgt.items
-               curr_pos = pos + tgt.index_from
+               init(tgt, tgt.items, pos + tgt.index_from)
        end
 
        redef fun is_ok do return curr_pos >= target.index_from
@@ -407,9 +402,7 @@ private class FlatStringByteIterator
 
        init with_pos(tgt: FlatString, pos: Int)
        do
-               target = tgt
-               target_items = tgt.items
-               curr_pos = pos + target.index_from
+               init(tgt, tgt.items, pos + tgt.index_from)
        end
 
        redef fun is_ok do return curr_pos <= target.index_to
@@ -697,9 +690,7 @@ private class FlatBufferByteReverseIterator
 
        init with_pos(tgt: FlatBuffer, pos: Int)
        do
-               target = tgt
-               if tgt.length > 0 then target_items = tgt.items
-               curr_pos = pos
+               init(tgt, tgt.items, pos)
        end
 
        redef fun index do return curr_pos
@@ -769,9 +760,7 @@ private class FlatBufferByteIterator
 
        init with_pos(tgt: FlatBuffer, pos: Int)
        do
-               target = tgt
-               if tgt.length > 0 then target_items = tgt.items
-               curr_pos = pos
+               init(tgt, tgt.items, pos)
        end
 
        redef fun index do return curr_pos
@@ -793,8 +782,7 @@ private class FlatBufferCharReverseIterator
 
        init with_pos(tgt: FlatBuffer, pos: Int)
        do
-               target = tgt
-               curr_pos = pos
+               init(tgt, pos)
        end
 
        redef fun index do return curr_pos
@@ -863,9 +851,7 @@ private class FlatBufferCharIterator
 
        init with_pos(tgt: FlatBuffer, pos: Int)
        do
-               target = tgt
-               max = tgt.length - 1
-               curr_pos = pos
+               init(tgt, tgt.length - 1, pos)
        end
 
        redef fun index do return curr_pos
index b1e08c8..c73bf58 100644 (file)
@@ -819,12 +819,15 @@ class SeparateCompiler
                var v = new_visitor
 
                var rta = runtime_type_analysis
-               var is_dead = rta != null and not rta.live_classes.has(mclass) and not mtype.is_c_primitive and mclass.name != "NativeArray" and mclass.name != "Pointer"
+               var is_dead = rta != null and not rta.live_classes.has(mclass)
+               # While the class may be dead, some part of separately compiled code may use symbols associated to the class, so
+               # in order to compile and link correctly the C code, these symbols should be declared and defined.
+               var need_corpse = is_dead and mtype.is_c_primitive or mclass.kind == extern_kind or mclass.kind == enum_kind
 
-               v.add_decl("/* runtime class {c_name} */")
+               v.add_decl("/* runtime class {c_name}: {mclass.full_name} (dead={is_dead}; need_corpse={need_corpse})*/")
 
                # Build class vft
-               if not is_dead then
+               if not is_dead or need_corpse then
                        self.provide_declaration("class_{c_name}", "extern const struct class class_{c_name};")
                        v.add_decl("const struct class class_{c_name} = \{")
                        v.add_decl("{self.box_kind_of(mclass)}, /* box_kind */")
@@ -861,7 +864,8 @@ class SeparateCompiler
                        self.header.add_decl("{mtype.ctype_extern} value;")
                        self.header.add_decl("\};")
 
-                       if not rta.live_types.has(mtype) and mtype.mclass.name != "Pointer" then return
+                       # Pointer is needed by extern types, live or not
+                       if is_dead and mtype.mclass.name != "Pointer" then return
 
                        #Build BOX
                        self.provide_declaration("BOX_{c_name}", "val* BOX_{c_name}({mtype.ctype_extern});")
@@ -877,6 +881,7 @@ class SeparateCompiler
                        v.add("return (val*)res;")
                        v.add("\}")
 
+                       # A Pointer class also need its constructor
                        if mtype.mclass.name != "Pointer" then return
 
                        v = new_visitor
@@ -931,7 +936,7 @@ class SeparateCompiler
                        var pointer_type = mainmodule.pointer_type
 
                        self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(const struct type* type);")
-                       v.add_decl("/* allocate {mtype} */")
+                       v.add_decl("/* allocate extern {mtype} */")
                        v.add_decl("{mtype.ctype} NEW_{c_name}(const struct type* type) \{")
                        if is_dead then
                                v.add_abort("{mclass} is DEAD")
@@ -1203,27 +1208,29 @@ class SeparateCompilerVisitor
                        end
                        return self.new_expr("((struct instance_{mtype.c_name}*){value})->value; /* autounbox from {value.mtype} to {mtype} */", mtype)
                else if not mtype.is_c_primitive then
+                       assert value.mtype == value.mcasttype
                        if value.mtype.is_tagged then
+                               var res
                                if value.mtype.name == "Int" then
-                                       return self.new_expr("(val*)({value}<<2|1)", mtype)
+                                       res = self.new_expr("(val*)({value}<<2|1)", mtype)
                                else if value.mtype.name == "Char" then
-                                       return self.new_expr("(val*)((long)({value})<<2|2)", mtype)
+                                       res = self.new_expr("(val*)((long)({value})<<2|2)", mtype)
                                else if value.mtype.name == "Bool" then
-                                       return self.new_expr("(val*)((long)({value})<<2|3)", mtype)
+                                       res = self.new_expr("(val*)((long)({value})<<2|3)", mtype)
                                else
                                        abort
                                end
+                               # Do not loose type info
+                               res.mcasttype = value.mcasttype
+                               return res
                        end
                        var valtype = value.mtype.as(MClassType)
                        if mtype isa MClassType and mtype.mclass.kind == extern_kind and mtype.mclass.name != "NativeString" then
                                valtype = compiler.mainmodule.pointer_type
                        end
                        var res = self.new_var(mtype)
-                       if compiler.runtime_type_analysis != null and not compiler.runtime_type_analysis.live_types.has(valtype) then
-                               self.add("/*no autobox from {value.mtype} to {mtype}: {value.mtype} is not live! */")
-                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); fatal_exit(1);")
-                               return res
-                       end
+                       # Do not loose type info
+                       res.mcasttype = value.mcasttype
                        self.require_declaration("BOX_{valtype.c_name}")
                        self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
                        return res
@@ -1259,11 +1266,7 @@ class SeparateCompilerVisitor
                   mtype.mclass.name != "NativeString" then
                        var valtype = compiler.mainmodule.pointer_type
                        var res = self.new_var(mtype)
-                       if compiler.runtime_type_analysis != null and not compiler.runtime_type_analysis.live_types.has(value.mtype.as(MClassType)) then
-                               self.add("/*no boxing of {value.mtype}: {value.mtype} is not live! */")
-                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); fatal_exit(1);")
-                               return res
-                       end
+                       compiler.undead_types.add(mtype)
                        self.require_declaration("BOX_{valtype.c_name}")
                        self.add("{res} = BOX_{valtype.c_name}({value}); /* boxing {value.mtype} */")
                        self.require_declaration("type_{mtype.c_name}")
index 8f12c78..496840d 100644 (file)
@@ -23,23 +23,23 @@ class PrimitiveNativeFile
        var file: Stream
 
        init native_stdin do
-               file = sys.stdin
+               init(sys.stdin)
        end
 
        init native_stdout do
-               file = sys.stdout
+               init(sys.stdout)
        end
 
        init native_stderr do
-               file = sys.stderr
+               init(sys.stderr)
        end
 
        init io_open_read(path: String) do
-               file = new FileReader.open(path.to_s)
+               init(new FileReader.open(path.to_s))
        end
 
        init io_open_write(path: String) do
-               file = new FileWriter.open(path.to_s)
+               init(new FileWriter.open(path.to_s))
        end
 
        fun address_is_null: Bool do
index 108cf28..786ffc2 100644 (file)
@@ -35,7 +35,8 @@ class SourceFile
        end
 
        # Create a new sourcefile using a dummy filename and a given content
-       init from_string(filename: String, string: String)
+       init from_string(filename: String, string: String) is
+               nosuper
        do
                self.filename = filename
                self.string = string
@@ -99,7 +100,9 @@ class Location
        # loc = new Location.from_string("location.nit:82--105,8")
        # assert loc.to_s == "location.nit:82,0--105,8"
        # ~~~
-       init from_string(string: String) do
+       init from_string(string: String) is
+               nosuper
+       do
                self.line_start = 0
                self.line_end = 0
                self.column_start = 0
index 64ef46c..467fccd 100644 (file)
@@ -305,7 +305,12 @@ redef class ModelBuilder
                                        var i = 0
                                        for p in spd.initializers do
                                                if p != longest.initializers[i] then
-                                                       self.error(nclassdef, "Error: conflict for inherited inits {spd}({spd.initializers.join(", ")}) and {longest}({longest.initializers.join(", ")})")
+                                                       var proposal = new ArraySet[MProperty]
+                                                       for spd2 in spropdefs do
+                                                               proposal.add_all spd2.initializers
+                                                       end
+                                                       proposal.add_all initializers
+                                                       self.error(nclassdef, "Error: cannot generate automatic init for class {mclassdef.mclass}. Conflict in the order in inherited initializers {spd}({spd.initializers.join(", ")}) and {longest}({longest.initializers.join(", ")}). Use `autoinit` to order initializers. eg `autoinit {proposal.join(", ")}`")
                                                        # TODO: invalidate the initializer to avoid more errors
                                                        return
                                                end
index cb4b70a..4a432c7 100644 (file)
@@ -73,13 +73,6 @@ redef class AMethPropdef
                        return
                end
 
-               # Do we inherit for a constructor?
-               var skip = true
-               for cd in mclassdef.in_hierarchy.direct_greaters do
-                       if cd.mclass.kind.need_init then skip = false
-               end
-               if skip then return
-
                # Now we search for the absence of any explicit super-init invocation
                #  * via a "super"
                #  * via a call of an other init
index 6842aa3..36a1be1 100644 (file)
@@ -32,7 +32,7 @@ end
 class D
        super B
        super C
-       #alt3#var b: Int
+       #alt3,5#var b: Int
        #alt4#var b = 11
        init do 'd'.output #alt2#
 end
@@ -48,6 +48,7 @@ class F
        super D
        super E
        init do 'f'.output #alt1,2#
+       #alt5#autoinit c=, e=
 end
 
 class G
@@ -55,6 +56,7 @@ class G
        super E
        var g: Int
        init do 'g'.output #alt2#
+       #alt5#autoinit c=, e=, g=
 end
 
 class H
index 0f81381..7e89814 100644 (file)
@@ -18,7 +18,7 @@ import abstract_collection
 
 fun maybe: Bool do return true
 
-var a = new Container[Int](1)
+var a = new Ref[Int](1)
 1.output
 for i in a do
        2.output
index da0cf31..3bb4205 100644 (file)
@@ -53,13 +53,13 @@ class Tower
                end
        end
 
-       var t: Array[Int] # The stack of discus (only the diameter is stored).
+       var t = new Array[Int] # The stack of discus (only the diameter is stored).
 
        init full(n: Int)
        # Build a new tower with `n' discus.
        do
                assert positive: n >= 0
-               _t = new Array[Int].with_capacity(n)
+               t.enlarge(n)
                for i in [0..n[ do
                        push(n-i)
                end
@@ -68,7 +68,6 @@ class Tower
        init empty
        # Build a empty tower.
        do
-               _t = new Array[Int]
        end
 end
 
index 0da465e..5c4ff8a 100644 (file)
@@ -27,3 +27,4 @@ mpi_simple
 blink
 input
 first_letter_last_letter
+fibonacci_word
index 0da465e..5c4ff8a 100644 (file)
@@ -27,3 +27,4 @@ mpi_simple
 blink
 input
 first_letter_last_letter
+fibonacci_word
index a7be1ec..90f67d3 100644 (file)
@@ -1,2 +1,2 @@
-alt/base_init_basic_alt3.nit:47,7: Error: conflict for inherited inits base_init_basic_alt3#E#init(c=, e=) and base_init_basic_alt3#D#init(c=, b=)
-alt/base_init_basic_alt3.nit:53,7: Error: conflict for inherited inits base_init_basic_alt3#E#init(c=, e=) and base_init_basic_alt3#D#init(c=, b=)
+alt/base_init_basic_alt3.nit:47,7: Error: cannot generate automatic init for class F. Conflict in the order in inherited initializers base_init_basic_alt3#E#init(c=, e=) and base_init_basic_alt3#D#init(c=, b=). Use `autoinit` to order initializers. eg `autoinit c=, b=, e=`
+alt/base_init_basic_alt3.nit:54,7: Error: cannot generate automatic init for class G. Conflict in the order in inherited initializers base_init_basic_alt3#E#init(c=, e=) and base_init_basic_alt3#D#init(c=, b=). Use `autoinit` to order initializers. eg `autoinit c=, b=, e=, g=`
diff --git a/tests/sav/base_init_basic_alt5.res b/tests/sav/base_init_basic_alt5.res
new file mode 100644 (file)
index 0000000..ae87071
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_basic_alt5.nit:79,9--11: Error: expected 2 argument(s) for `init(c: Int, b: Int)`; got 1. See introduction at `standard::Object::init`.
index 510c2f5..d210e23 100644 (file)
@@ -1,9 +1,13 @@
 1
 2
+1
 2
 3
+1
 2
+1
 2
 5
+1
 2
 6
index daa73b2..f25a887 100644 (file)
@@ -4,5 +4,5 @@ B1 A B2
 A B3 
 A B4y 
 C1 C2 
-A2z C3z 
-D1 B1 A B2 D2 D3 
+C1 C2 A2z C3z 
+D1 B1 C1 C2 A B2 D2 D3 
index fe7551d..ad0b634 100644 (file)
@@ -4,5 +4,5 @@ B1 A B2
 A B3 
 A B4y 
 C1 C2 
-A2z C3z 
+C1 C2 A2z C3z 
 C1 C2 D1 D2 D3 
index 7eadb94..7777753 100644 (file)
@@ -4,5 +4,5 @@ B1 A B2
 A B3 
 A B4y 
 C1 C2 
-A2z C3z 
-D1 B1 A B2 D2 C1 C2 D3 
+C1 C2 A2z C3z 
+D1 B1 C1 C2 A B2 D2 C1 C2 D3 
index 9bc59e1..4320fe1 100644 (file)
@@ -4,5 +4,5 @@ B1 A B2
 A B3 
 A B4y 
 C1 C2 
-A2z C3z 
-D1 C1 C2 B1 A B2 D2 D3 
+C1 C2 A2z C3z 
+D1 C1 C2 B1 C1 C2 A B2 D2 D3 
index bc59762..2f2b274 100644 (file)
@@ -4,5 +4,5 @@ B1 A B2
 A B3 
 A B4y 
 C1 C2 
-A2z C3z 
-D1 B1 A B2 D2 B1 A B2 D3 
+C1 C2 A2z C3z 
+D1 B1 C1 C2 A B2 D2 B1 C1 C2 A B2 D3 
diff --git a/tests/sav/entropy.res b/tests/sav/entropy.res
new file mode 100644 (file)
index 0000000..29f9066
--- /dev/null
@@ -0,0 +1,2 @@
+1.846
+1.846
diff --git a/tests/sav/entropy_narcissist.res b/tests/sav/entropy_narcissist.res
new file mode 100644 (file)
index 0000000..ba66466
--- /dev/null
@@ -0,0 +1 @@
+0.0
diff --git a/tests/sav/fibonacci_word.res b/tests/sav/fibonacci_word.res
new file mode 100644 (file)
index 0000000..38a9498
--- /dev/null
@@ -0,0 +1,37 @@
+1      1       0.0000000000000000      1
+2      1       0.0000000000000000      0
+3      2       1.0000000000000000      01
+4      3       0.9182958340544894      010
+5      5       0.9709505944546686      01001
+6      8       0.9544340029249650      01001010
+7      13      0.9612366047228760      0100101001001
+8      21      0.9587118829771316      010010100100101001010
+9      34      0.9596868937742170      0100101001001010010100100101001001
+10     55      0.9593160320543778      ...
+11     89      0.9594579158386696      ...
+12     144     0.9594037542210228      ...
+13     233     0.9594244469559864      ...
+14     377     0.9594165437404406      ...
+15     610     0.9594195626031440      ...
+16     987     0.9594184095152248      ...
+17     1597    0.9594188499578102      ...
+18     2584    0.9594186817240320      ...
+19     4181    0.9594187459836638      ...
+20     6765    0.9594187214386752      ...
+21     10946   0.9594187308140276      ...
+22     17711   0.9594187272329618      ...
+23     28657   0.9594187286008076      ...
+24     46368   0.9594187280783368      ...
+25     75025   0.9594187282779028      ...
+26     121393  0.9594187282016752      ...
+27     196418  0.9594187282307916      ...
+28     317811  0.9594187282196702      ...
+29     514229  0.9594187282239182      ...
+30     832040  0.9594187282222962      ...
+31     1346269 0.9594187282229156      ...
+32     2178309 0.9594187282226794      ...
+33     3524578 0.9594187282227690      ...
+34     5702887 0.9594187282227344      ...
+35     9227465 0.9594187282227478      ...
+36     14930352        0.9594187282227430      ...
+37     24157817        0.9594187282227448      ...
index 4d4a3a0..2c6e10c 100644 (file)
@@ -32,5 +32,5 @@ Deserialization Error: Doesn't know how to deserialize class "HashSet", Deserial
 # Src:
 <G: hs: -1, 0; s: one, two; hm: one. 1, two. 2; am: three. 3, four. 4>
 # Dst:
-<G: hs: ; s: ; hm: ; am: >
+<G: hs: -1, 0; s: one, two; hm: one. 1, two. 2; am: three. 3, four. 4>
 
index 7681dab..d3738c4 100644 (file)
@@ -70,5 +70,5 @@ null
 {"__kind": "obj", "__id": 0, "__class": "G", "hs": {"__kind": "obj", "__id": 1, "__class": "HashSet", "__items": [-1, 0]}, "s": {"__kind": "obj", "__id": 2, "__class": "ArraySet", "__items": ["one", "two"]}, "hm": {"__kind": "obj", "__id": 3, "__class": "HashMap", "__length": 2, "__keys": ["one", "two"], "__values": [1, 2]}, "am": {"__kind": "obj", "__id": 4, "__class": "ArrayMap", "__length": 2, "__keys": ["three", "four"], "__values": ["3", "4"]}}
 
 # Back in Nit:
-<G: hs: ; s: ; hm: ; am: >
+<G: hs: -1, 0; s: one, two; hm: one. 1, two. 2; am: three. 3, four. 4>
 
index a6d703a..63f0d62 100644 (file)
@@ -858,49 +858,49 @@ Number of buggy sends (cannot determine the type of the receiver): 0 (0.00%)
          sum: 0
 
  ## Callsites
-* 22 live callsites
+* 23 live callsites
 MMethodDef locally designated (by number of CallSites)
- population: 13
+ population: 14
  minimum value: 1
  maximum value: 10
- total value: 22
- average value: 1.69
+ total value: 23
+ average value: 1.64
  distribution:
-  <=1: sub-population=12 (92.30%); cumulated value=12 (54.54%)
-  <=16: sub-population=1 (7.69%); cumulated value=10 (45.45%)
+  <=1: sub-population=13 (92.85%); cumulated value=13 (56.52%)
+  <=16: sub-population=1 (7.14%); cumulated value=10 (43.47%)
  list:
-  base_simple3#Int#output: 10 (45.45%)
-  base_simple3#B#val: 1 (4.54%)
-  base_simple3#B#val=: 1 (4.54%)
-  base_simple3#C#val2: 1 (4.54%)
-  base_simple3#C#val1: 1 (4.54%)
+  base_simple3#Int#output: 10 (43.47%)
+  base_simple3#B#val: 1 (4.34%)
+  base_simple3#B#val=: 1 (4.34%)
+  base_simple3#Object#init: 1 (4.34%)
+  base_simple3#C#val2: 1 (4.34%)
   ...
-  base_simple3#A#init: 1 (4.54%)
-  base_simple3#Sys#baz: 1 (4.54%)
-  base_simple3#Sys#bar: 1 (4.54%)
-  base_simple3#Sys#foo: 1 (4.54%)
-  base_simple3#C#init: 1 (4.54%)
+  base_simple3#A#init: 1 (4.34%)
+  base_simple3#Sys#baz: 1 (4.34%)
+  base_simple3#Sys#bar: 1 (4.34%)
+  base_simple3#Sys#foo: 1 (4.34%)
+  base_simple3#C#init: 1 (4.34%)
 MMethodDef possibly invoked at runtime (by number of CallSites)
- population: 13
+ population: 14
  minimum value: 1
  maximum value: 10
- total value: 22
- average value: 1.69
+ total value: 23
+ average value: 1.64
  distribution:
-  <=1: sub-population=12 (92.30%); cumulated value=12 (54.54%)
-  <=16: sub-population=1 (7.69%); cumulated value=10 (45.45%)
+  <=1: sub-population=13 (92.85%); cumulated value=13 (56.52%)
+  <=16: sub-population=1 (7.14%); cumulated value=10 (43.47%)
  list:
-  base_simple3#Int#output: 10 (45.45%)
-  base_simple3#B#val: 1 (4.54%)
-  base_simple3#B#val=: 1 (4.54%)
-  base_simple3#C#val2: 1 (4.54%)
-  base_simple3#C#val1: 1 (4.54%)
+  base_simple3#Int#output: 10 (43.47%)
+  base_simple3#B#val: 1 (4.34%)
+  base_simple3#B#val=: 1 (4.34%)
+  base_simple3#Object#init: 1 (4.34%)
+  base_simple3#C#val2: 1 (4.34%)
   ...
-  base_simple3#A#init: 1 (4.54%)
-  base_simple3#Sys#baz: 1 (4.54%)
-  base_simple3#Sys#bar: 1 (4.54%)
-  base_simple3#Sys#foo: 1 (4.54%)
-  base_simple3#C#init: 1 (4.54%)
+  base_simple3#A#init: 1 (4.34%)
+  base_simple3#Sys#baz: 1 (4.34%)
+  base_simple3#Sys#bar: 1 (4.34%)
+  base_simple3#Sys#foo: 1 (4.34%)
+  base_simple3#C#init: 1 (4.34%)
 class_hierarchy.dot
 classdef_hierarchy.dot
 inheritance/
index 6e97e37..ba7c7ea 100644 (file)
@@ -1,5 +1,3 @@
-../lib/standard/bytes.nit:49,7--19: Documentation warning: Undocumented property `with_capacity`
-../lib/standard/bytes.nit:162,6--13: Documentation warning: Undocumented property `to_bytes`
 ../lib/standard/stream.nit:426,6--17: Documentation warning: Undocumented property `buffer_reset`
 ../lib/standard/file.nit:455,6--19: Documentation warning: Undocumented property `read_all_bytes`
 test_advice_repeated_types.nit:36,15--20: Warning: useless type repetition on redefined attribute `_a`
index 7d3c3bb..fcde192 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:957)
+Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:960)
 NativeString
 0x4e
 Nit