Merge: lib/standard: optimize Array.to_s
authorJean Privat <jean@pryen.org>
Tue, 26 Aug 2014 22:56:25 +0000 (18:56 -0400)
committerJean Privat <jean@pryen.org>
Tue, 26 Aug 2014 22:56:25 +0000 (18:56 -0400)
Micro-optimized version of Array::to_s based on the results of benchmarks available in PR #685.

`./bin/nitg ./src/nitg.nit`
Before : `15.080 s`
After : `13.928 s`

Pull-Request: #686
Reviewed-by: Jean Privat <jean@pryen.org>

64 files changed:
.gitattributes
benchmarks/bench_strings.sh
benchmarks/strings/array_to_s_vars/array_to_s_buffer.nit [new file with mode: 0644]
benchmarks/strings/array_to_s_vars/array_to_s_flatstr.nit [new file with mode: 0644]
benchmarks/strings/array_to_s_vars/array_to_s_man_buf.nit [new file with mode: 0644]
benchmarks/strings/array_to_s_vars/array_to_s_manual.nit [new file with mode: 0644]
benchmarks/strings/array_to_s_vars/array_to_s_rope.nit [new file with mode: 0644]
benchmarks/strings/array_tos.nit [new file with mode: 0644]
benchmarks/strings/utf_chain_concat.nit [new file with mode: 0644]
benchmarks/strings/utf_iteration_bench.nit [new file with mode: 0644]
benchmarks/strings/utf_substr_bench.nit [new file with mode: 0644]
contrib/pep8analysis/src/parser/parser_nodes.nit
examples/curl_mail.nit
lib/array_debug.nit [new file with mode: 0644]
lib/curl/curl.nit
lib/privileges.nit
lib/sendmail.nit
lib/standard/collection/abstract_collection.nit
lib/standard/collection/array.nit
lib/standard/queue.nit
lib/string_experimentations/README
lib/string_experimentations/utf8_noindex.nit
src/abstract_compiler.nit
src/auto_super_init.nit
src/check_annotation.nit
src/model/model.nit
src/modelize_property.nit
src/naive_interpreter.nit
src/parser/parser_nodes.nit
src/rapid_type_analysis.nit
src/separate_compiler.nit
src/typing.nit
tests/base_attr_def.nit
tests/base_init_basic.nit [new file with mode: 0644]
tests/base_init_super_call.nit
tests/base_init_super_call2.nit
tests/base_init_super_call3.nit [new file with mode: 0644]
tests/nitmetrics.args
tests/sav/array_debug.res [new file with mode: 0644]
tests/sav/base_init_basic.res [new file with mode: 0644]
tests/sav/base_init_basic_alt1.res [new file with mode: 0644]
tests/sav/base_init_basic_alt2.res [new file with mode: 0644]
tests/sav/base_init_basic_alt3.res [new file with mode: 0644]
tests/sav/base_init_basic_alt4.res [new file with mode: 0644]
tests/sav/base_init_combine.res
tests/sav/base_init_simple.res
tests/sav/base_init_super_call2_alt1.res
tests/sav/base_init_super_call2_alt2.res
tests/sav/base_init_super_call3.res [new file with mode: 0644]
tests/sav/base_init_super_call_alt1.res
tests/sav/base_init_super_call_alt2.res
tests/sav/base_no_object.res
tests/sav/base_no_object_alt1.res
tests/sav/error_class_glob.res
tests/sav/error_init_auto_alt4.res
tests/sav/nitdoc_args1.res
tests/sav/nitg-g/base_no_object.res [deleted file]
tests/sav/niti/base_no_object.res [deleted file]
tests/sav/nitmetrics_args1.res
tests/sav/nitx_args1.res
tests/sav/test_neo_args1.res
tests/sav/test_new_native_alt1.res
tests/sav/utf_noindex_test.res
tests/utf_noindex_test.nit

index e41014a..c373f7c 100644 (file)
@@ -5,3 +5,5 @@ lexer.nit               -diff
 tables_nit.c           -diff
 c_src/**/*.[ch]                -diff
 c_src/Makefile         -diff
+
+tests/sav/**/*.res     -whitespace
index 811eddd..c327d58 100755 (executable)
@@ -36,6 +36,8 @@ function usage()
        echo "    - usage : cct max_nb_cct loops strlen"
        echo "  substr: substring benching"
        echo "    - usage : substr max_nb_cct loops strlen"
+       echo "  array: Benchmark for the to_s in array"
+       echo "    - usage : array nb_cct loops max_arrlen"
 }
 
 function benches()
@@ -43,6 +45,81 @@ function benches()
        bench_concat $@;
        bench_iteration $@;
        bench_substr $@;
+       bench_array $@;
+}
+
+function bench_array()
+{
+       if $verbose; then
+               echo "*** Benching Array.to_s performance ***"
+       fi
+
+       ../bin/nitg --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_rope.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
+       prepare_res arr_tos_ropes.out arr_tos_ropes ropes
+       if $verbose; then
+               echo "Ropes :"
+       fi
+       for i in `seq 1 "$3"`; do
+               if $verbose; then
+                       echo "String length = $i, Concats/loop = $1, Loops = $2"
+               fi
+               bench_command $i ropes$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
+       done
+
+       ../bin/nitg --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_flatstr.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
+       prepare_res arr_tos_flat.out arr_tos_flat flatstring
+       if $verbose; then
+               echo "FlatStrings :"
+       fi
+       for i in `seq 1 "$3"`; do
+               if $verbose; then
+                       echo "String length = $i, Concats/loop = $1, Loops = $2"
+               fi
+               bench_command $i flatstring$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
+       done
+
+       ../bin/nitg --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_buffer.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
+       prepare_res arr_tos_buf.out arr_tos_buf flatbuffer
+       if $verbose; then
+               echo "FlatBuffers :"
+       fi
+       for i in `seq 1 "$3"`; do
+               if $verbose; then
+                       echo "String length = $i, Concats/loop = $1, Loops = $2"
+               fi
+               bench_command $i flatbuffer$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
+       done
+
+       ../bin/nitg --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_manual.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
+       prepare_res arr_tos_man.out arr_tos_man memmove
+       if $verbose; then
+               echo "Memmove :"
+       fi
+       for i in `seq 1 "$3"`; do
+               if $verbose; then
+                       echo "String length = $i, Concats/loop = $1, Loops = $2"
+               fi
+               bench_command $i memmove$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
+       done
+
+       ../bin/nitg --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_man_buf.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
+       prepare_res arr_tos_man_buf.out arr_tos_man_buf flatbuf_with_capacity
+       if $verbose; then
+               echo "Memmove :"
+       fi
+       for i in `seq 1 "$3"`; do
+               if $verbose; then
+                       echo "String length = $i, Concats/loop = $1, Loops = $2"
+               fi
+               bench_command $i flatbuf_with_capacity$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
+       done
+
+       plot array_tos.gnu
 }
 
 function bench_concat()
@@ -84,6 +161,17 @@ function bench_concat()
                bench_command $i flatbuffer$i ./chain_concat -m flatbuf --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
        done
 
+       prepare_res concat_flatstr_utf8_noindex.out concat_flatstr_utf8_noindex flatstring_utf8_noindex
+       if $verbose; then
+               echo "FlatString UTF-8 (without index) :"
+       fi
+       for i in `seq 1 "$1"`; do
+               if $verbose; then
+                       echo "String length = $i, Concats/loop = $2, Loops = $3"
+               fi
+               bench_command $i flatstr_utf8_noindex$i ./utf_chain_concat -m flatstr_utf8_noindex --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+       done
+
        plot concat.gnu
 }
 
@@ -159,6 +247,28 @@ function bench_iteration()
                bench_command $i flatbuf_index$i ./iteration_bench -m flatbuf --iter-mode index --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
        done
 
+       prepare_res iter_flat_utf8_noindex_iter.out iter_flat_iter_utf8_noindex flatstring_utf8_noindex_iter
+       if $verbose; then
+               echo "FlatStrings by iterator :"
+       fi
+       for i in `seq 1 "$1"`; do
+               if $verbose; then
+                       echo "String base length = $1, Concats = $i, Loops = $3"
+               fi
+               bench_command $i flatstr_iter_utf8_noindex$i ./utf_iteration_bench -m flatstr_utf8_noindex --iter-mode iterator --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+       done
+
+       prepare_res iter_flat_utf8_noindex_index.out iter_flat_index_utf8_noindex flatstring_utf8_noindex_index
+       if $verbose; then
+               echo "FlatStrings by index :"
+       fi
+       for i in `seq 1 "$1"`; do
+               if $verbose; then
+                       echo "String base length = $1, Concats = $i, Loops = $3"
+               fi
+               bench_command $i flatstr_index_utf8_noindex$i ./utf_iteration_bench -m flatstr_utf8_noindex --iter-mode index --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+       done
+
        plot iter.gnu
 }
 
@@ -201,6 +311,17 @@ function bench_substr()
                bench_command $i flatbuffer$i ./substr_bench -m flatbuf --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
        done
 
+       prepare_res substr_flat_utf8_noindex.out substr_flat_utf8_noindex flatstring_utf8_noindex
+       if $verbose; then
+               echo "FlatStrings UTF-8 (without index) :"
+       fi
+       for i in `seq 1 "$1"`; do
+               if $verbose; then
+                       echo "String length = $i, loops = $2, Loops = $3"
+               fi
+               bench_command $i flatstring_utf8_noindex$i ./utf_substr_bench -m flatstr_utf8_noindex --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+       done
+
        plot substr.gnu
 }
 
@@ -224,13 +345,17 @@ if $verbose; then
 fi
 
 ../bin/nitg --global ./strings/chain_concat.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+../bin/nitg --global ./strings/utf_chain_concat.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
 ../bin/nitg --global ./strings/iteration_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+../bin/nitg --global ./strings/utf_iteration_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
 ../bin/nitg --global ./strings/substr_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+../bin/nitg --global ./strings/utf_substr_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
 
 case "$1" in
        iter) shift; bench_iteration $@ ;;
        cct) shift; bench_concat $@ ;;
        substr) shift; bench_substr $@ ;;
+       array) shift; bench_array $@ ;;
        all) shift; benches $@ ;;
        *) usage; exit;;
 esac
diff --git a/benchmarks/strings/array_to_s_vars/array_to_s_buffer.nit b/benchmarks/strings/array_to_s_vars/array_to_s_buffer.nit
new file mode 100644 (file)
index 0000000..d61b742
--- /dev/null
@@ -0,0 +1,29 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Implementation of Array::to_s with FlatBuffer exclusively
+#
+# To be used as a Mixin at compile-time for benchmarking purposes.
+module array_to_s_buffer
+
+redef class Array[E]
+       redef fun to_s: String do
+               var s = new FlatBuffer
+               var i = 0
+               var l = length
+               var its = _items
+               while i < l do
+                       var e = its[i]
+                       if e != null then s.append(e.to_s)
+                       i += 1
+               end
+               return s.to_s
+       end
+end
diff --git a/benchmarks/strings/array_to_s_vars/array_to_s_flatstr.nit b/benchmarks/strings/array_to_s_vars/array_to_s_flatstr.nit
new file mode 100644 (file)
index 0000000..0240d5b
--- /dev/null
@@ -0,0 +1,31 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Implementation of Array::to_s with FlatStrings exclusively
+#
+# To be used as a Mixin at compile-time for benchmarking purposes.
+module array_to_s_flatstr
+
+redef class Array[E]
+
+       redef fun to_s do
+               var i = 1
+               var l = length
+               if l == 0 then return ""
+               var its = _items
+               var s = its[0].to_s
+               while i < l do
+                       var e = its[i]
+                       if e != null then s += e.to_s
+                       i += 1
+               end
+               return s
+       end
+end
diff --git a/benchmarks/strings/array_to_s_vars/array_to_s_man_buf.nit b/benchmarks/strings/array_to_s_vars/array_to_s_man_buf.nit
new file mode 100644 (file)
index 0000000..ec81322
--- /dev/null
@@ -0,0 +1,41 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Implementation of Array::to_s with manual FlatBuffer (precalc its capacity)
+#
+# To be used as a Mixin at compile-time for benchmarking purposes.
+module array_to_s_man_buf
+
+redef class NativeArray[E]
+       new(length: Int) is intern
+end
+
+redef class Array[E]
+       redef fun to_s: String do
+               var l = length
+               var its = _items
+               var na = new NativeArray[String](l)
+               var i = 0
+               var sl = 0
+               while i < l do
+                       var tmp = its[i].to_s
+                       sl += tmp.length
+                       na[i] = tmp
+                       i += 1
+               end
+               var ns = new FlatBuffer.with_capacity(sl)
+               i = 0
+               while i < l do
+                       ns.append na[i]
+                       i += 1
+               end
+               return ns.to_s
+       end
+end
diff --git a/benchmarks/strings/array_to_s_vars/array_to_s_manual.nit b/benchmarks/strings/array_to_s_vars/array_to_s_manual.nit
new file mode 100644 (file)
index 0000000..843eb93
--- /dev/null
@@ -0,0 +1,59 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Implementation of Array::to_s with manual management of the String
+#
+# To be used as a Mixin at compile-time for benchmarking purposes.
+module array_to_s_manual
+
+intrude import standard::string
+intrude import standard::collection::array
+
+redef class NativeArray[E]
+       new(length: Int) is intern
+end
+
+redef class Array[E]
+       super StringCapable
+
+       redef fun to_s: String do
+               var l = length
+               var its = _items
+               var na = new NativeArray[String](l)
+               var i = 0
+               var sl = 0
+               while i < l do
+                       var tmp = its[i].to_s
+                       sl += tmp.length
+                       na[i] = tmp
+                       i += 1
+               end
+               var ns = calloc_string(sl + 1)
+               ns[sl] = '\0'
+               i = 0
+               var off = 0
+               while i < l do
+                       var tmp = na[i]
+                       var tpl = tmp.length
+                       if tmp isa FlatString then
+                               tmp.items.copy_to(ns, tpl, tmp.index_from, off)
+                               off += tpl
+                       else
+                               for j in tmp.substrings do
+                                       var s = j.as(FlatString)
+                                       s.items.copy_to(ns, tpl, s.index_from, off)
+                                       off += tpl
+                               end
+                       end
+                       i += 1
+               end
+               return ns.to_s_with_length(sl)
+       end
+end
diff --git a/benchmarks/strings/array_to_s_vars/array_to_s_rope.nit b/benchmarks/strings/array_to_s_vars/array_to_s_rope.nit
new file mode 100644 (file)
index 0000000..c162dff
--- /dev/null
@@ -0,0 +1,31 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Implementation of Array::to_s with a Rope exclusively
+#
+# To be used as a Mixin at compile-time for benchmarking purposes.
+module array_to_s_rope
+
+redef class Array[E]
+
+       redef fun to_s do
+               var i = 1
+               var l = length
+               if l == 0 then return ""
+               var s: String = new RopeString.from(self[0].to_s)
+               var its = _items
+               while i < l do
+                       var e = its[i]
+                       if e != null then s += e.to_s
+                       i += 1
+               end
+               return s
+       end
+end
diff --git a/benchmarks/strings/array_tos.nit b/benchmarks/strings/array_tos.nit
new file mode 100644 (file)
index 0000000..8dff9e4
--- /dev/null
@@ -0,0 +1,41 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Benchmark on the Array.to_s function using several methods.
+module array_tos
+
+import opts
+
+fun bench_array(arr_size, item_size, loops: Int)
+do
+       var arr = new Array[String].with_capacity(arr_size)
+       var s = "a" * item_size
+
+       for i in [0 .. arr_size[ do arr.push s
+
+       for i in [0..loops[ do
+               s = arr.to_s
+       end
+end
+
+var opts = new OptionContext
+var nb_ccts = new OptionInt("Size of an element", -1, "--ccts")
+var loops = new OptionInt("Number of loops to be done", -1, "--loops")
+var strlen = new OptionInt("Length of the Array", -1, "--strlen")
+opts.add_option(nb_ccts, loops, strlen)
+
+opts.parse(args)
+
+if nb_ccts.value == -1 or loops.value == -1 or strlen.value == -1 then
+       opts.usage
+       exit(-1)
+end
+
+bench_array(strlen.value, nb_ccts.value, loops.value)
diff --git a/benchmarks/strings/utf_chain_concat.nit b/benchmarks/strings/utf_chain_concat.nit
new file mode 100644 (file)
index 0000000..d720403
--- /dev/null
@@ -0,0 +1,42 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Benches measuring the performance of several concatenations on Text variants
+module utf_chain_concat
+
+import opts
+import string_experimentations::utf8_noindex
+
+fun bench_flatstr(str_size: Int, nb_ccts: Int, loops: Int)
+do
+       var lft = "a" * str_size
+
+       for i in [0..loops] do
+               var str: String = lft
+               for j in [0..nb_ccts] do
+                       str += lft
+               end
+       end
+end
+
+var opts = new OptionContext
+var nb_ccts = new OptionInt("Number of concatenations per loop", -1, "--ccts")
+var loops = new OptionInt("Number of loops to be done", -1, "--loops")
+var strlen = new OptionInt("Length of the base string", -1, "--strlen")
+opts.add_option(nb_ccts, loops, strlen)
+
+opts.parse(args)
+
+if nb_ccts.value == -1 or loops.value == -1 or strlen.value == -1 then
+       opts.usage
+       exit -1
+end
+
+bench_flatstr(strlen.value, nb_ccts.value, loops.value)
diff --git a/benchmarks/strings/utf_iteration_bench.nit b/benchmarks/strings/utf_iteration_bench.nit
new file mode 100644 (file)
index 0000000..80277c0
--- /dev/null
@@ -0,0 +1,74 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Benches for iteration on variants of Text
+module utf_iteration_bench
+
+import opts
+import string_experimentations::utf8_noindex
+
+fun bench_flatstr_iter(nb_cct: Int, loops: Int, strlen: Int)
+do
+       var a = "a" * strlen
+       var x = a.as(FlatString)
+       for i in [0 .. nb_cct] do x = (x + a).as(FlatString)
+       var cnt = 0
+       var c: UnicodeChar
+       while cnt != loops do
+               var it = new FlatStringIter(x)
+               for i in it do
+                       c = i
+               end
+               cnt += 1
+       end
+end
+
+fun bench_flatstr_index(nb_cct: Int, loops: Int, strlen: Int)
+do
+       var a = "a" * strlen
+       var x = a.as(FlatString)
+       for i in [0 .. nb_cct] do x = (x + a).as(FlatString)
+       var cnt = 0
+       var c: UnicodeChar
+       var pos = 0
+       while cnt != loops do
+               pos = 0
+               while pos < x.length do
+                       c = x.char_at(pos)
+                       pos += 1
+               end
+               cnt += 1
+       end
+end
+
+var opts = new OptionContext
+var access_mode = new OptionEnum(["iterator", "index"], "Iteration mode", -1, "--iter-mode")
+var nb_ccts = new OptionInt("Number of concatenations done to the string (in the case of the rope, this will increase its depth)", -1, "--ccts")
+var loops = new OptionInt("Number of loops to be done", -1, "--loops")
+var strlen = new OptionInt("Length of the base string", -1, "--strlen")
+opts.add_option(nb_ccts, loops, strlen, access_mode)
+
+opts.parse(args)
+
+if nb_ccts.value == -1 or loops.value == -1 or strlen.value == -1 then
+       opts.usage
+       exit(-1)
+end
+
+var iterval = access_mode.value
+
+if iterval == 0 then
+       bench_flatstr_iter(nb_ccts.value, loops.value, strlen.value)
+else if iterval == 1 then
+       bench_flatstr_index(nb_ccts.value, loops.value, strlen.value)
+else
+       opts.usage
+       exit(-1)
+end
diff --git a/benchmarks/strings/utf_substr_bench.nit b/benchmarks/strings/utf_substr_bench.nit
new file mode 100644 (file)
index 0000000..7d71a8b
--- /dev/null
@@ -0,0 +1,42 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Benches on the substring operation on variants of Text
+module utf_substr_bench
+
+import opts
+import string_experimentations::utf8_noindex
+
+fun bench_flatstr(nb_cct: Int, loops: Int, strlen: Int)
+do
+       var a = "a" * strlen
+       var x = a
+       for i in [0 .. nb_cct] do x += a
+       var cnt = 0
+       while cnt != loops do
+               x.substring(0,5)
+               cnt += 1
+       end
+end
+
+var opts = new OptionContext
+var nb_ccts = new OptionInt("Number of concatenations done to the string (in the case of the rope, this will increase its depth)", -1, "--ccts")
+var loops = new OptionInt("Number of loops to be done", -1, "--loops")
+var strlen = new OptionInt("Length of the base string", -1, "--strlen")
+opts.add_option(nb_ccts, loops, strlen)
+
+opts.parse(args)
+
+if nb_ccts.value == -1 or loops.value == -1 or strlen.value == -1 then
+       opts.usage
+       exit(-1)
+end
+
+bench_flatstr(nb_ccts.value, loops.value, strlen.value)
index f84afe5..e1fb641 100644 (file)
@@ -1,6 +1,6 @@
 # Raw AST node hierarchy.
 # This file was generated by SableCC (http://www.sablecc.org/).
-module parser_nodes
+module parser_nodes is old_style_init
 
 import location
 
index b28f5a4..d791611 100644 (file)
@@ -23,7 +23,7 @@ var curl = new Curl
 var mail_request = new CurlMailRequest(curl)
 
 # Networks
-var response = mail_request.set_outgoing_server("smtps://smtp.example.org:465", "user@example.org", "mypassword")
+var response: nullable CurlResponse = mail_request.set_outgoing_server("smtps://smtp.example.org:465", "user@example.org", "mypassword")
 if response isa CurlResponseFailed then
        print "Error code : {response.error_code}"
        print "Error msg : {response.error_msg}"
diff --git a/lib/array_debug.nit b/lib/array_debug.nit
new file mode 100644 (file)
index 0000000..f112d7a
--- /dev/null
@@ -0,0 +1,78 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Exposes functions to help profile or debug Arrays.
+module array_debug
+
+import counter
+
+redef class Sys
+
+       # Tracks the average length of the Strings of an array when calling to_s
+       var arr_s_len = new Counter[Int]
+
+       # Keeps the average length of an Array when calling to_s
+       var arr_len = new Counter[Int]
+
+       fun avg_arr_len: Float do
+               var total = 0
+               var sum = 0
+               for i in arr_len.keys do
+                       total += arr_len[i]
+                       sum += arr_len[i] * i
+               end
+               return sum.to_f / total.to_f
+       end
+
+       fun avg_s_len: Float do
+               var total = 0
+               var sum = 0
+               for i in arr_s_len.keys do
+                       total += arr_s_len[i]
+                       sum += arr_s_len[i] * i
+               end
+               return sum.to_f / total.to_f
+       end
+
+       fun print_stats do
+               if arr_len.sum == 0 then
+                       print "*** No Array stats ***"
+                       return
+               end
+               print "*** Array Stats ***"
+               print "Number of calls to Array::to_s : {sys.arr_len.sum}"
+               print "Average number of elements in an Array (when calling to_s) : {sys.avg_arr_len}"
+               print "Average string size in Array : {sys.avg_s_len}"
+               print "*** End of Stats ***"
+       end
+
+       redef fun run do
+               super
+               print_stats
+       end
+end
+
+redef fun exit(i)
+do
+       sys.print_stats
+       super
+end
+
+redef class Array[E]
+
+       redef fun to_s do
+               sys.arr_len.inc length
+               for i in self do
+                       sys.arr_s_len.inc i.to_s.length
+               end
+               return super
+       end
+
+end
index fd6e359..d0c445d 100644 (file)
@@ -47,7 +47,7 @@ class CurlRequest
        fun execute: CurlResponse is abstract
 
        # Intern perform method, lowest level of request launching
-       private fun perform: nullable CurlResponse
+       private fun perform: nullable CurlResponseFailed
        do
                if not self.curl.is_ok then return answer_failure(0, "Curl instance is not correctly initialized")
 
@@ -63,7 +63,7 @@ class CurlRequest
        end
 
        # Intern method with return a failed answer with given code and message
-       private fun answer_failure(error_code: Int, error_msg: String): CurlResponse
+       private fun answer_failure(error_code: Int, error_msg: String): CurlResponseFailed
        do
                return new CurlResponseFailed(error_code, error_msg)
        end
@@ -242,7 +242,7 @@ class CurlMailRequest
        end
 
        # Configure server host and user credentials if needed.
-       fun set_outgoing_server(host: String, user: nullable String, pwd: nullable String):nullable CurlResponse
+       fun set_outgoing_server(host: String, user: nullable String, pwd: nullable String): nullable CurlResponseFailed
        do
                # Check Curl initialisation
                if not self.curl.is_ok then return answer_failure(0, "Curl instance is not correctly initialized")
index e3e1220..7a5503f 100644 (file)
@@ -22,6 +22,22 @@ module privileges
 
 import opts
 
+redef class Text
+       # Does the operating system know the user named `self`?
+       fun user_exists: Bool
+       do
+               var passwd = new Passwd.from_name(to_s)
+               return not passwd.address_is_null
+       end
+
+       # Does the operating system know the group named `self`?
+       fun group_exists: Bool
+       do
+               var passwd = new Group.from_name(to_s)
+               return not passwd.address_is_null
+       end
+end
+
 # Class to manage user groups
 class UserGroup
 
@@ -31,16 +47,20 @@ class UserGroup
        # Group name
        var group: nullable String
 
-       # Drop privileges of a user and set his privileges back to default (program privileges)
+       # Drop privileges of the running program to those of `self`
+       #
+       # require: `user.user_exists and (group == null or group.group_exists)`
        fun drop_privileges
        do
                var passwd = new Passwd.from_name(user)
+               assert not passwd.address_is_null
                var uid = passwd.uid
 
                var group = group
                var gid
                if group != null then
                        var gpasswd = new Group.from_name(group)
+                       assert not gpasswd.address_is_null
                        gid = gpasswd.gid
                else gid = passwd.gid
 
index c8be5f8..0040c71 100644 (file)
@@ -102,7 +102,7 @@ To: {{{to.join(",")}}}\r
 CC: {{{cc.join(",")}}}\r
 BCC: {{{bcc.join(",")}}}\r
 Subject: {{{subject}}}\r
-{{{header.join("\r\n", ": ")}}}\r
+{{{header.join("\r\n", ": ")}}}\r\n\r
 {{{content}}}"""
        end
 end
index 5501290..a806c57 100644 (file)
@@ -781,7 +781,9 @@ interface Sequence[E]
        #     var a = [1,2,3]
        #     a.append([7..9])
        #     assert a  == [1,2,3,7,8,9]
-       fun append(coll: Collection[E]) do for i in coll do push(i)
+       #
+       # Alias of `add_all`
+       fun append(coll: Collection[E]) do add_all(coll)
 
        # Remove the last item.
        #
@@ -801,6 +803,15 @@ interface Sequence[E]
        #     assert a  == [20,10,1,2,3]
        fun unshift(e: E) is abstract
 
+       # Add all items of `coll` before the first one.
+       #
+       #     var a = [1,2,3]
+       #     a.prepend([7..9])
+       #     assert a  == [7,8,9,1,2,3]
+       #
+       # Alias of `insert_at(coll, 0)`
+       fun prepend(coll: Collection[E]) do insert_all(coll, 0)
+
        # Remove the first item.
        # The second item thus become the first.
        #
@@ -833,10 +844,30 @@ interface Sequence[E]
        #     a.insert(100, 2)
        #     assert a      ==  [10, 20, 100, 30, 40]
        #
-       # REQUIRE `index >= 0 and index < length`
+       # REQUIRE `index >= 0 and index <= length`
        # ENSURE `self[index] == item`
        fun insert(item: E, index: Int) is abstract
 
+       # Insert all elements at a given position, following elements are shifted.
+       #
+       #     var a = [10, 20, 30, 40]
+       #     a.insert_all([100..102], 2)
+       #     assert a      ==  [10, 20, 100, 101, 102, 30, 40]
+       #
+       # REQUIRE `index >= 0 and index <= length`
+       # ENSURE `self[index] == coll.first`
+       fun insert_all(coll: Collection[E], index: Int)
+       do
+               assert index >= 0 and index < length
+               if index == length then
+                       add_all(coll)
+               end
+               for c in coll do
+                       insert(c, index)
+                       index += 1
+               end
+       end
+
        # Remove the item at `index` and shift all following elements
        #
        #     var a = [10,20,30]
index a819d54..b23f533 100644 (file)
@@ -186,6 +186,19 @@ abstract class AbstractArray[E]
                self[pos] = item
        end
 
+       redef fun insert_all(coll, pos)
+       do
+               var l = coll.length
+               if l == 0 then return
+               enlarge(length + l)
+               _length += l
+               copy_to(pos, length-pos-l, self, pos + l)
+               for c in coll do
+                       self[pos] = c
+                       pos += 1
+               end
+       end
+
        redef fun add(item) do self[length] = item
 
        redef fun clear do _length = 0
index bd4dcf1..c4cce96 100644 (file)
@@ -320,5 +320,5 @@ end
 # ~~~
 class MinHeapCmp[E: Comparable]
        super MinHeap[E]
-       init do super(new DefaultComparator[E])
+       init is old_style_init do super(new DefaultComparator[E])
 end
index aec087f..7cbce13 100644 (file)
@@ -17,6 +17,8 @@ TODO :
   * to_upper/lower fully-compatible with Unicode
 
  * utf8_no_index:
-  * Add cache for the last indexed character
-  * Two-way iteration
-  * Intelligent indexed access (calculating the nearest point of insertion, i.e. begin, end, or cache)
+  * Add cache for the last indexed character - DONE
+  * Two-way iteration - DONE
+  * Intelligent indexed access (calculating the nearest point of insertion, i.e. begin, end, or cache) - DONE
+  * UnicodeChar as universal type
+  * UnicodeChar => Char and Char => Byte
index c63e93a..323f0ab 100644 (file)
@@ -171,6 +171,99 @@ extern class UnicodeChar `{ uint32_t* `}
        `}
 end
 
+# Used to keep track of the last accessed char in a String
+class CharCache
+       # The position (as in char) of a String
+       var position: Int
+       # The position in the NativeString underlying the String
+       var bytepos: Int
+end
+
+class FlatStringReviter
+       super IndexedIterator[UnicodeChar]
+
+       # The NativeString to iterate upon
+       private var ns: NativeString
+
+       # The position in the string
+       private var pos: Int
+
+       # The position in the native string
+       private var bytepos: Int
+
+       init(s: FlatString) do from(s, s.length - 1)
+
+       init from(s: FlatString, position: Int)
+       do
+               ns = s.items
+               pos = position
+               bytepos = s.byte_index(position)
+       end
+
+       redef fun next
+       do
+               bytepos -= 1
+               while ns[bytepos].ascii.bin_and(0xC0) == 0x80 do
+                       bytepos -= 1
+               end
+               pos -= 1
+       end
+
+       redef fun index do return pos
+
+       redef fun item do return new UnicodeChar.from_ns(ns, bytepos)
+
+       redef fun is_ok do return pos >= 0
+end
+
+class FlatStringIter
+       super IndexedIterator[UnicodeChar]
+
+       private var ns: NativeString
+
+       private var pos: Int
+
+       private var bytepos: Int
+
+       private var slen: Int
+
+       private var it: UnicodeChar
+
+       private var is_created: Bool
+
+       init(s: FlatString) do from(s, 0)
+
+       init from(s: FlatString, position: Int) do
+               ns = s.items
+               pos = position
+               bytepos = s.byte_index(position)
+               slen = s.length
+       end
+
+       redef fun index do return pos
+
+       redef fun is_ok do return pos < slen
+
+       redef fun item do
+               if not is_created then
+                       it = new UnicodeChar.from_ns(ns, bytepos)
+                       is_created = true
+               end
+               return it
+       end
+
+       redef fun next
+       do
+               if not is_created then
+                       it = new UnicodeChar.from_ns(ns, bytepos)
+               end
+               is_created = false
+               var pace = it.len
+               pos += 1
+               bytepos += pace
+       end
+end
+
 redef class FlatString
 
        redef type OTHER: FlatString
@@ -178,6 +271,9 @@ redef class FlatString
        # Length in bytes of the string (e.g. the length of the C string)
        redef var bytelen: Int
 
+       # Cache for the last accessed character in the char
+       var cache = new CharCache(-1,-1)
+
        redef var length = length_l is lazy
 
        private init full(items: NativeString, from, to, bytelen, len: Int)
@@ -239,22 +335,57 @@ redef class FlatString
        private fun byte_index(index: Int): Int do
                assert index >= 0
                assert index < length
-               var ns_i = index_from
-               var my_i = 0
-               while my_i != index do
-                       if items[ns_i].ascii.bin_and(0x80) == 0 then
+
+               # Find best insertion point
+               var delta_begin = index
+               var delta_end = (length - 1) - index
+               var delta_cache = (cache.position - index).abs
+               var min = delta_begin
+
+               if delta_cache < min then min = delta_cache
+               if delta_end < min then min = delta_end
+
+               var ns_i: Int
+               var my_i: Int
+               var myits = items
+
+               if min == delta_begin then
+                       ns_i = index_from
+                       my_i = 0
+               else if min == delta_cache then
+                       ns_i = cache.bytepos
+                       my_i = cache.position
+               else
+                       ns_i = index_to
+                       my_i = length
+               end
+
+               while my_i < index do
+                       if myits[ns_i].ascii.bin_and(0x80) == 0 then
                                ns_i += 1
-                       else if items[ns_i].ascii.bin_and(0xE0) == 0xC0 then
+                       else if myits[ns_i].ascii.bin_and(0xE0) == 0xC0 then
                                ns_i += 2
-                       else if items[ns_i].ascii.bin_and(0xF0) == 0xE0 then
+                       else if myits[ns_i].ascii.bin_and(0xF0) == 0xE0 then
                                ns_i += 3
-                       else if items[ns_i].ascii.bin_and(0xF7) == 0xF0 then
+                       else if myits[ns_i].ascii.bin_and(0xF7) == 0xF0 then
                                ns_i += 4
                        else
                                ns_i += 1
                        end
                        my_i += 1
                end
+
+               while my_i > index do
+                       if myits[ns_i].ascii.bin_and(0xC0) != 0x80 then
+                               my_i -= 1
+                               if my_i == index then break
+                       end
+                       ns_i -= 1
+               end
+
+               cache.position = index
+               cache.bytepos = ns_i
+
                return ns_i
        end
 
index 6656d5b..9d441cc 100644 (file)
@@ -1044,9 +1044,27 @@ abstract class AbstractCompilerVisitor
                return self.compiler.modelbuilder.force_get_primitive_method(self.current_node.as(not null), name, recv.mclass, self.compiler.mainmodule)
        end
 
-       fun compile_callsite(callsite: CallSite, args: Array[RuntimeVariable]): nullable RuntimeVariable
+       fun compile_callsite(callsite: CallSite, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
        do
-               return self.send(callsite.mproperty, args)
+               var initializers = callsite.mpropdef.initializers
+               if not initializers.is_empty then
+                       var recv = arguments.first
+
+                       assert initializers.length == arguments.length - 1 else debug("expected {initializers.length}, got {arguments.length - 1}")
+                       var i = 1
+                       for p in initializers do
+                               if p isa MMethod then
+                                       self.send(p, [recv, arguments[i]])
+                               else if p isa MAttribute then
+                                       self.write_attribute(p, recv, arguments[i])
+                               else abort
+                               i += 1
+                       end
+
+                       return self.send(callsite.mproperty, [recv])
+               end
+
+               return self.send(callsite.mproperty, arguments)
        end
 
        fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable is abstract
@@ -1834,9 +1852,13 @@ redef class AMethPropdef
                                for i in [0..auto_super_init.msignature.arity+1[ do
                                        args.add(arguments[i])
                                end
+                               assert auto_super_init.mproperty != mpropdef.mproperty
                                v.compile_callsite(auto_super_init, args)
                        end
                end
+               if auto_super_call then
+                       v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
+               end
 
                var n_block = n_block
                if n_block != null then
@@ -2247,6 +2269,15 @@ redef class AClassdef
        private fun compile_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable])
        do
                if mpropdef == self.mfree_init then
+                       if mpropdef.mproperty.is_root_init then
+                               assert self.super_inits == null
+                               assert arguments.length == 1
+                               if not mpropdef.is_intro then
+                                       v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
+                               end
+                               return
+                       end
+
                        var super_inits = self.super_inits
                        if super_inits != null then
                                var args_of_super = arguments
@@ -2255,6 +2286,7 @@ redef class AClassdef
                                        v.send(su, args_of_super)
                                end
                        end
+
                        var recv = arguments.first
                        var i = 1
                        # Collect undefined attributes
index 92ee003..8891df3 100644 (file)
@@ -48,9 +48,12 @@ end
 
 
 redef class AMethPropdef
-       # In case of constructor, the list of implicit auto super init constructors invoked (if needed)
+       # In case of introduced constructor, the list of implicit auto super init constructors invoked (if needed)
        var auto_super_inits: nullable Array[CallSite] = null
 
+       # In case of redefined constructors, is an implicit call-to-super required?
+       var auto_super_call = false
+
        fun do_auto_super_init(modelbuilder: ModelBuilder)
        do
                var mclassdef = self.parent.as(AClassdef).mclassdef.as(not null)
@@ -94,8 +97,17 @@ redef class AMethPropdef
 
                if nosuper != null then return
 
+               # Still here? So it means that we must add an implicit super-call on redefinitions.
+               if not mpropdef.is_intro then
+                       auto_super_call = true
+                       mpropdef.has_supercall = true
+                       return
+               end
+
                # Still here? So it means that we must determine what super inits need to be automatically invoked
+               # The code that follow is required to deal with complex cases with old-style and new-style inits
 
+               # Look for old-style super constructors
                var auto_super_inits = new Array[CallSite]
                for msupertype in mclassdef.supertypes do
                        # FIXME: the order is quite arbitrary
@@ -111,20 +123,59 @@ redef class AMethPropdef
                        end
                        assert candidate isa MMethod
 
+                       # Skip new-style init
+                       if candidate.is_root_init then continue
+
                        var candidatedefs = candidate.lookup_definitions(mmodule, anchor)
                        var candidatedef = candidatedefs.first
                        # TODO, we drop the others propdefs in the callsite, that is not great :(
 
-                       var msignature = candidatedef.msignature
+                       var msignature = candidatedef.new_msignature or else candidatedef.msignature
                        msignature = msignature.resolve_for(recvtype, anchor, mmodule, true)
 
                        var callsite = new CallSite(self, recvtype, mmodule, anchor, true, candidate, candidatedef, msignature, false)
                        auto_super_inits.add(callsite)
                end
+
+               # No old style? The look for new-style super constructors (called from a old style constructor)
+               var the_root_init_mmethod = modelbuilder.the_root_init_mmethod
+               if the_root_init_mmethod != null and auto_super_inits.is_empty then
+                       var candidatedefs = the_root_init_mmethod.lookup_definitions(mmodule, anchor)
+
+                       # Search the longest-one and checks for conflict
+                       var candidatedef = candidatedefs.first
+                       if candidatedefs.length > 1 then
+                               # Check for conflict in the order of initializers
+                               # Each initializer list must me a prefix of the longest list
+                               # part 1. find the longest list
+                               for spd in candidatedefs do
+                                       if spd.initializers.length > candidatedef.initializers.length then candidatedef = spd
+                               end
+                               # compare
+                               for spd in candidatedefs do
+                                       var i = 0
+                                       for p in spd.initializers do
+                                               if p != candidatedef.initializers[i] then
+                                                       modelbuilder.error(self, "Error: Cannot do an implicit constructor call to comflicting for inherited inits {spd}({spd.initializers.join(", ")}) and {candidatedef}({candidatedef.initializers.join(", ")}). NOTE: Do not mix old-style and new-style init!")
+                                                       return
+                                               end
+                                               i += 1
+                                       end
+                               end
+                       end
+
+                       var msignature = candidatedef.new_msignature or else candidatedef.msignature
+                       msignature = msignature.resolve_for(recvtype, anchor, mmodule, true)
+
+                       var callsite = new CallSite(self, recvtype, mmodule, anchor, true, the_root_init_mmethod, candidatedef, msignature, false)
+                       auto_super_inits.add(callsite)
+               end
                if auto_super_inits.is_empty then
                        modelbuilder.error(self, "Error: No constructors to call implicitely in {mpropdef}. Call one explicitely.")
                        return
                end
+
+               # Can the super-constructors be called?
                for auto_super_init in auto_super_inits do
                        var auto_super_init_def = auto_super_init.mpropdef
                        var msig = mpropdef.msignature.as(not null)
index e374876..f91dc55 100644 (file)
@@ -82,6 +82,7 @@ readonly
 writable
 cached
 nosuper
+old_style_init
 
 pkgconfig
 c_compiler_option
index cc6ca95..f3c3164 100644 (file)
@@ -1827,6 +1827,9 @@ class MMethod
        # therefore, you should use `is_init_for` the verify if the property is a legal constructor for a given class
        var is_init: Bool writable = false
 
+       # The constructor is a (the) root init with empty signature but a set of initializers
+       var is_root_init: Bool writable = false
+
        # The the property a 'new' contructor?
        var is_new: Bool writable = false
 
@@ -1945,6 +1948,19 @@ class MMethodDef
        # The signature attached to the property definition
        var msignature: nullable MSignature writable = null
 
+       # The signature attached to the `new` call on a root-init
+       # This is a concatenation of the signatures of the initializers
+       #
+       # REQUIRE `mproperty.is_root_init == (new_msignature != null)`
+       var new_msignature: nullable MSignature writable = null
+
+       # List of initialisers to call in root-inits
+       #
+       # They could be setters or attributes
+       #
+       # REQUIRE `mproperty.is_root_init == (new_msignature != null)`
+       var initializers = new Array[MProperty]
+
        # Is the method definition abstract?
        var is_abstract: Bool writable = false
 
index 8273fb8..146125b 100644 (file)
@@ -68,6 +68,11 @@ redef class ModelBuilder
                process_default_constructors(nclassdef)
        end
 
+       # the root init of the Object class
+       # Is usually implicitly defined
+       # Then explicit or implicit definitions of root-init are attached to it
+       var the_root_init_mmethod: nullable MMethod
+
        # Introduce or inherit default constructor
        # This is the last part of `build_properties`.
        private fun process_default_constructors(nclassdef: AClassdef)
@@ -77,27 +82,54 @@ redef class ModelBuilder
                # Are we a refinement
                if not mclassdef.is_intro then return
 
+               var mmodule = nclassdef.mclassdef.mmodule
+
+               # Look for the init in Object, or create it
+               if mclassdef.mclass.name == "Object" and the_root_init_mmethod == null then
+                       # Create the implicit root-init method
+                       var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
+                       mprop.is_root_init = true
+                       var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
+                       var mparameters = new Array[MParameter]
+                       var msignature = new MSignature(mparameters, null)
+                       mpropdef.msignature = msignature
+                       mpropdef.new_msignature = msignature
+                       mprop.is_init = true
+                       nclassdef.mfree_init = mpropdef
+                       self.toolcontext.info("{mclassdef} gets a free empty constructor {mpropdef}{msignature}", 3)
+                       the_root_init_mmethod = mprop
+                       return
+               end
+
                # Is the class forbid constructors?
                if not mclassdef.mclass.kind.need_init then return
 
                # Is there already a constructor defined?
+               var defined_init: nullable MMethodDef = null
                for mpropdef in mclassdef.mpropdefs do
                        if not mpropdef isa MMethodDef then continue
-                       if mpropdef.mproperty.is_init then return
+                       if not mpropdef.mproperty.is_init then continue
+                       if mpropdef.mproperty.is_root_init then
+                               assert defined_init == null
+                               defined_init = mpropdef
+                       else
+                               # An explicit old-style init, so return
+                               return
+                       end
                end
 
                if not nclassdef isa AStdClassdef then return
 
-               var mmodule = mclassdef.mmodule
-               # Do we inherit for a constructor?
-               var combine = new Array[MMethod]
-               var inhc: nullable MClass = null
-               for st in mclassdef.supertypes do
+               # Do we inherit a old-style constructor?
+               var combine = new Array[MMethod] # old-style constructors without arguments
+               var inhc: nullable MClass = null # single super-class with a constructor with arguments
+               if defined_init == null then for st in mclassdef.supertypes do
                        var c = st.mclass
                        if not c.kind.need_init then continue
                        st = st.anchor_to(mmodule, mclassdef.bound_mtype)
                        var candidate = self.try_get_mproperty_by_name2(nclassdef, mmodule, st, "init").as(nullable MMethod)
                        if candidate != null then
+                               if candidate.is_root_init then continue
                                if candidate.intro.msignature != null then
                                        if candidate.intro.msignature.arity == 0 then
                                                combine.add(candidate)
@@ -117,6 +149,7 @@ redef class ModelBuilder
 
                # Collect undefined attributes
                var mparameters = new Array[MParameter]
+               var initializers = new Array[MProperty]
                var anode: nullable ANode = null
                for npropdef in nclassdef.n_propdefs do
                        if npropdef isa AAttrPropdef then
@@ -135,6 +168,14 @@ redef class ModelBuilder
                                if ret_type == null then return
                                var mparameter = new MParameter(paramname, ret_type, false)
                                mparameters.add(mparameter)
+                               var msetter = npropdef.mwritepropdef
+                               if msetter == null then
+                                       # No setter, it is a old-style attribute, so just add it
+                                       initializers.add(npropdef.mpropdef.mproperty)
+                               else
+                                       # Add the setter to the list
+                                       initializers.add(msetter.mproperty)
+                               end
                                if anode == null then anode = npropdef
                        end
                end
@@ -148,15 +189,14 @@ redef class ModelBuilder
 
                        # TODO: actively inherit the consturctor
                        self.toolcontext.info("{mclassdef} inherits all constructors from {inhc}", 3)
-                       mclassdef.mclass.inherit_init_from = inhc
-                       return
+                       #mclassdef.mclass.inherit_init_from = inhc
+                       #return
                end
 
                if not combine.is_empty and inhc != null then
                        self.error(nclassdef, "Error: Cannot provide a defaut constructor: conflict for {combine.join(", ")} and {inhc}")
                        return
                end
-
                if not combine.is_empty then
                        if mparameters.is_empty and combine.length == 1 then
                                # No need to create a local init, the inherited one is enough
@@ -166,13 +206,75 @@ redef class ModelBuilder
                                return
                        end
                        nclassdef.super_inits = combine
+                       var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
+                       var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
+                       var msignature = new MSignature(mparameters, null)
+                       mpropdef.msignature = msignature
+                       mprop.is_init = true
+                       nclassdef.mfree_init = mpropdef
+                       self.toolcontext.info("{mclassdef} gets a free empty constructor {mpropdef}{msignature}", 3)
+                       return
+               end
+
+               if the_root_init_mmethod == null then return
+
+               # Look for nost-specific new-stype init definitions
+               var spropdefs = the_root_init_mmethod.lookup_super_definitions(mclassdef.mmodule, mclassdef.bound_mtype)
+               if spropdefs.is_empty then
+                       toolcontext.fatal_error(nclassdef.location, "Fatal error: {mclassdef} does not specialize {the_root_init_mmethod.intro_mclassdef}. Possible duplication of the root class `Object`?")
+               end
+
+               # Search the longest-one and checks for conflict
+               var longest = spropdefs.first
+               if spropdefs.length > 1 then
+                       # Check for conflict in the order of initializers
+                       # Each initializer list must me a prefix of the longest list
+                       # part 1. find the longest list
+                       for spd in spropdefs do
+                               if spd.initializers.length > longest.initializers.length then longest = spd
+                       end
+                       # part 2. compare
+                       for spd in spropdefs do
+                               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(", ")})")
+                                               return
+                                       end
+                                       i += 1
+                               end
+                       end
+               end
+
+               # Can we just inherit?
+               if spropdefs.length == 1 and mparameters.is_empty and defined_init == null then
+                       self.toolcontext.info("{mclassdef} inherits the basic constructor {longest}", 3)
+                       return
+               end
+
+               # Combine the inherited list to what is collected
+               if longest.initializers.length > 0 then
+                       mparameters.prepend longest.new_msignature.mparameters
+                       initializers.prepend longest.initializers
+               end
+
+               # If we already have a basic init definition, then setup its initializers
+               if defined_init != null then
+                       defined_init.initializers.add_all(initializers)
+                       var msignature = new MSignature(mparameters, null)
+                       defined_init.new_msignature = msignature
+                       self.toolcontext.info("{mclassdef} extends its basic constructor signature to {defined_init}{msignature}", 3)
+                       return
                end
 
-               var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
+               # Else create the local implicit basic init definition
+               var mprop = the_root_init_mmethod.as(not null)
                var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
+               mpropdef.has_supercall = true
+               mpropdef.initializers.add_all(initializers)
                var msignature = new MSignature(mparameters, null)
-               mpropdef.msignature = msignature
-               mprop.is_init = true
+               mpropdef.new_msignature = msignature
+               mpropdef.msignature = new MSignature(new Array[MParameter], null) # always an empty real signature
                nclassdef.mfree_init = mpropdef
                self.toolcontext.info("{mclassdef} gets a free constructor for attributes {mpropdef}{msignature}", 3)
        end
@@ -439,6 +541,31 @@ end
 redef class AMethPropdef
        redef type MPROPDEF: MMethodDef
 
+
+       # Can self be used as a root init?
+       private fun look_like_a_root_init(modelbuilder: ModelBuilder): Bool
+       do
+               # Need the `init` keyword
+               if n_kwinit == null then return false
+               # Need to by anonymous
+               if self.n_methid != null then return false
+               # No parameters
+               if self.n_signature.n_params.length > 0 then return false
+               # Cannot be private or something
+               if not self.n_visibility isa APublicVisibility then return false
+               # No annotation on itself
+               if get_single_annotation("old_style_init", modelbuilder) != null then return false
+               # Nor on its module
+               var amod = self.parent.parent.as(AModule)
+               var amoddecl = amod.n_moduledecl
+               if amoddecl != null then
+                       var old = amoddecl.get_single_annotation("old_style_init", modelbuilder)
+                       if old != null then return false
+               end
+
+               return true
+       end
+
        redef fun build_property(modelbuilder, mclassdef)
        do
                var n_kwinit = n_kwinit
@@ -475,15 +602,22 @@ redef class AMethPropdef
 
                var mprop: nullable MMethod = null
                if not is_init or n_kwredef != null then mprop = modelbuilder.try_get_mproperty_by_name(name_node, mclassdef, name).as(nullable MMethod)
+               if mprop == null and look_like_a_root_init(modelbuilder) then
+                       mprop = modelbuilder.the_root_init_mmethod
+               end
                if mprop == null then
                        var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility)
                        mprop = new MMethod(mclassdef, name, mvisibility)
+                       if look_like_a_root_init(modelbuilder) and modelbuilder.the_root_init_mmethod == null then
+                               modelbuilder.the_root_init_mmethod = mprop
+                               mprop.is_root_init = true
+                       end
                        mprop.is_init = is_init
                        mprop.is_new = n_kwnew != null
                        if parent isa ATopClassdef then mprop.is_toplevel = true
                        if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mprop) then return
                else
-                       if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, not self isa AMainMethPropdef, mprop) then return
+                       if not mprop.is_root_init and not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, not self isa AMainMethPropdef, mprop) then return
                        check_redef_property_visibility(modelbuilder, self.n_visibility, mprop)
                end
                mclassdef.mprop2npropdef[mprop] = self
index 7525a00..c741f04 100644 (file)
@@ -408,6 +408,22 @@ private class NaiveInterpreter
        # Use this method, instead of `send` to execute and control the aditionnal behavior of the call-sites
        fun callsite(callsite: nullable CallSite, arguments: Array[Instance]): nullable Instance
        do
+               var initializers = callsite.mpropdef.initializers
+               if not initializers.is_empty then
+                       assert initializers.length == arguments.length - 1 else debug("expected {initializers.length} got {arguments.length - 1}")
+                       var recv = arguments.first
+                       var i = 1
+                       for p in initializers do
+                               if p isa MMethod then
+                                       self.send(p, [recv, arguments[i]])
+                               else if p isa MAttribute then
+                                       assert recv isa MutableInstance
+                                       recv.attributes[p] = arguments[i]
+                               else abort
+                               i += 1
+                       end
+                       return send(callsite.mproperty, [recv])
+               end
                return send(callsite.mproperty, arguments)
        end
 
@@ -648,9 +664,15 @@ redef class AMethPropdef
                                for i in [0..auto_super_init.msignature.arity+1[ do
                                        args.add(arguments[i])
                                end
+                               assert auto_super_init.mproperty != mpropdef.mproperty
                                v.callsite(auto_super_init, args)
                        end
                end
+               if auto_super_call then
+                       # standard call-next-method
+                       var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
+                       v.call_without_varargs(superpd, arguments)
+               end
 
                if n_block != null then
                        v.stmt(self.n_block)
@@ -1040,6 +1062,17 @@ redef class AClassdef
        # Execute an implicit `mpropdef` associated with the current node.
        private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
        do
+               if mpropdef.mproperty.is_root_init then
+                       assert self.super_inits == null
+                       assert args.length == 1
+                       if not mpropdef.is_intro then
+                               # standard call-next-method
+                               var superpd = mpropdef.lookup_next_definition(v.mainmodule, args.first.mtype)
+                               v.call_without_varargs(superpd, args)
+                       end
+                       return null
+               end
+
                var super_inits = self.super_inits
                if super_inits != null then
                        var args_of_super = args
index 8a6bf20..5190abd 100644 (file)
@@ -14,7 +14,7 @@
 
 # AST nodes of the Nit language
 # Was previously based on parser_abs.nit.
-module parser_nodes
+module parser_nodes is old_style_init
 
 import location
 
index ceca71d..6518860 100644 (file)
@@ -226,6 +226,7 @@ class RapidTypeAnalysis
                                v.add_monomorphic_send(vararg, self.modelbuilder.force_get_primitive_method(node, "with_native", vararg.mclass, self.mainmodule))
                        end
 
+                       # TODO? new_msignature
                        var sig = mmethoddef.msignature.as(not null)
                        var osig = mmeth.intro.msignature.as(not null)
                        for i in [0..sig.arity[ do
@@ -248,6 +249,9 @@ class RapidTypeAnalysis
                                                end
                                        end
 
+                                       if mmethoddef.mproperty.is_root_init and not mmethoddef.is_intro then
+                                               self.add_super_send(v.receiver, mmethoddef)
+                                       end
                                else
                                        abort
                                end
@@ -263,6 +267,9 @@ class RapidTypeAnalysis
                                                v.add_callsite(auto_super_init)
                                        end
                                end
+                               if npropdef.auto_super_call then
+                                       self.add_super_send(v.receiver, mmethoddef)
+                               end
                        end
 
                        if mmeth.is_new then
@@ -497,6 +504,11 @@ class RapidTypeVisitor
        fun add_cast_type(mtype: MType) do analysis.add_cast(mtype)
 
        fun add_callsite(callsite: nullable CallSite) do if callsite != null then
+               for m in callsite.mpropdef.initializers do
+                       if m isa MMethod then
+                               analysis.add_send(callsite.recv, m)
+                       end
+               end
                analysis.add_send(callsite.recv, callsite.mproperty)
                analysis.live_callsites.add(callsite)
        end
index 1e05f7e..4dfbeb0 100644 (file)
@@ -958,11 +958,12 @@ class SeparateCompilerVisitor
        do
                var rta = compiler.runtime_type_analysis
                var recv = args.first.mtype
-               if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null then
+               var mmethod = callsite.mproperty
+               # TODO: Inlining of new-style constructors
+               if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null and not mmethod.is_root_init then
                        var tgs = rta.live_targets(callsite)
                        if tgs.length == 1 then
                                # DIRECT CALL
-                               var mmethod = callsite.mproperty
                                self.varargize(mmethod.intro, mmethod.intro.msignature.as(not null), args)
                                var res0 = before_send(mmethod, args)
                                var res = call(tgs.first, tgs.first.mclassdef.bound_mtype, args)
index d4e33eb..a415667 100644 (file)
@@ -277,7 +277,7 @@ private class TypeVisitor
                end
 
 
-               var msignature = mpropdef.msignature.as(not null)
+               var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null)
                msignature = resolve_for(msignature, recvtype, recv_is_self).as(MSignature)
 
                var erasure_cast = false
@@ -1267,6 +1267,9 @@ redef class ASendExpr
                        if not (vmpropdef isa MMethodDef and vmpropdef.mproperty.is_init) then
                                v.error(self, "Can call a init only in another init")
                        end
+                       if vmpropdef isa MMethodDef and vmpropdef.mproperty.is_root_init and not callsite.mproperty.is_root_init then
+                               v.error(self, "Error: {vmpropdef} cannot call a factory {callsite.mproperty}")
+                       end
                end
 
                var ret = msignature.return_mtype
@@ -1522,12 +1525,15 @@ redef class ASuperExpr
                                if v.modelbuilder.toolcontext.error_count > errcount then return # Forard error
                                continue # Try next super-class
                        end
-                       if superprop != null and superprop.mproperty != candidate then
+                       if superprop != null and candidate.is_root_init then
+                               continue
+                       end
+                       if superprop != null and superprop.mproperty != candidate and not superprop.mproperty.is_root_init then
                                v.error(self, "Error: conflicting super constructor to call for {mproperty}: {candidate.full_name}, {superprop.mproperty.full_name}")
                                return
                        end
                        var candidatedefs = candidate.lookup_definitions(v.mmodule, recvtype)
-                       if superprop != null then
+                       if superprop != null and superprop.mproperty == candidate then
                                if superprop == candidatedefs.first then continue
                                candidatedefs.add(superprop)
                        end
@@ -1542,7 +1548,7 @@ redef class ASuperExpr
                        return
                end
 
-               var msignature = superprop.msignature.as(not null)
+               var msignature = superprop.new_msignature or else superprop.msignature.as(not null)
                msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
 
                var callsite = new CallSite(self, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)
index 17da0d3..4b1d21e 100644 (file)
@@ -32,7 +32,8 @@ class Foo
                a2.output
        end
 
-       init
+       init is
+               old_style_init
        do
                a1 = 1
                a2 = 2
@@ -49,7 +50,8 @@ class Bar
                a3.output
        end
 
-       init 
+       init is
+               old_style_init
        do 
                a1 = 10
                a2 = 20
diff --git a/tests/base_init_basic.nit b/tests/base_init_basic.nit
new file mode 100644 (file)
index 0000000..6842aa3
--- /dev/null
@@ -0,0 +1,101 @@
+# 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 A
+       init do 'a'.output #alt1,2#
+end
+
+class B
+       super A
+       init do 'b'.output #alt1,2#
+end
+
+class C
+       super A
+       var c: Int
+       init do 'c'.output #alt2#
+end
+
+class D
+       super B
+       super C
+       #alt3#var b: Int
+       #alt4#var b = 11
+       init do 'd'.output #alt2#
+end
+
+class E
+       super B
+       super C
+       var e: Int
+       init do 'e'.output #alt1,2#
+end
+
+class F
+       super D
+       super E
+       init do 'f'.output #alt1,2#
+end
+
+class G
+       super D
+       super E
+       var g: Int
+       init do 'g'.output #alt2#
+end
+
+class H
+       super F
+       super G
+       init do 'h'.output #alt1,2#
+end
+
+
+var a = new A
+'\n'.output
+
+var b = new B
+'\n'.output
+
+var c = new C(1)
+'\n'.output
+c.c.output
+
+var d = new D(2)
+'\n'.output
+d.c.output
+
+var e = new E(3, 30)
+'\n'.output
+e.c.output
+e.e.output
+
+var f = new F(4, 40)
+'\n'.output
+f.c.output
+f.e.output
+
+var g = new G(5, 50, 500)
+'\n'.output
+g.c.output
+g.e.output
+g.g.output
+
+var h = new H(6, 60, 600)
+'\n'.output
+h.c.output
+h.e.output
+h.g.output
index 5d863ab..34cebdd 100644 (file)
@@ -20,22 +20,22 @@ end
 
 class B1
        super A
-       #alt1#init do super
+       #alt1#init is old_style_init do super
 end
 
 class B2
        super A
-       init do super(3)
+       init is old_style_init do super(3)
 end
 
 class B3
        super A
-       #alt2#init do super(true)
+       #alt2#init is old_style_init do super(true)
 end
 
 class B4
        super A
-       #alt3#init do end
+       #alt3#init is old_style_init do end
 end
 
 class C1
index f229ddb..1211acf 100644 (file)
@@ -20,22 +20,22 @@ end
 
 class B1
        super A
-       #alt1#init do super
+       #alt1#init is old_style_init do super
 end
 
 class B2
        super A
-       init do super(3)
+       init is old_style_init do super(3)
 end
 
 class B3
        super A
-       #alt2#init do super(true)
+       #alt2#init is old_style_init do super(true)
 end
 
 class B4
        super A
-       #alt3#init do end
+       #alt3#init is old_style_init do end
 end
 
 class C1
@@ -48,7 +48,7 @@ end
 
 class D1
        super A
-       init(j) do
+       init(j: Int) do
                super
                j.output
        end
@@ -72,7 +72,7 @@ end
 
 class D2
        super A
-       init(j) do
+       init(j: Int) do
                super(j)
                j.output
        end
@@ -95,7 +95,7 @@ end
 
 class D3
        super A
-       init(j) do
+       init(j: Int) do
                j.output
        end
 end
diff --git a/tests/base_init_super_call3.nit b/tests/base_init_super_call3.nit
new file mode 100644 (file)
index 0000000..430026d
--- /dev/null
@@ -0,0 +1,101 @@
+# 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 A
+       init(i: Int) do i.output
+end
+
+class B
+       super A
+       init(i)
+       do
+               super
+               (i+1).output
+       end
+end
+
+class C
+       super A
+       init(i)
+       do
+               (i+1).output
+               super
+       end
+end
+
+class D
+       super A
+       init(i)
+       is
+               nosuper
+       do
+               (i+1).output
+       end
+end
+
+class E
+       super A
+       init(i)
+       do
+               (i+1).output
+       end
+end
+
+class F
+       super A
+       redef init(i)
+       do
+               super
+               (i+1).output
+       end
+end
+
+class G
+       super A
+       redef init(i)
+       do
+               (i+1).output
+               super
+       end
+end
+
+class H
+       super A
+       redef init(i)
+       is
+               nosuper
+       do
+               (i+1).output
+       end
+end
+
+class I
+       super A
+       redef init(i)
+       do
+               (i+1).output
+       end
+end
+
+var a = new A(10)
+var b = new B(20)
+var c = new C(30)
+var d = new D(40)
+var e = new E(50)
+var f = new F(60)
+var g = new G(70)
+var h = new H(80)
+var i = new I(90)
index 7cf3e1e..c6b8e98 100644 (file)
@@ -1 +1 @@
---no-colors --all --csv base_simple3.nit base_empty_module.nit -d $WRITE
+--no-colors --all --csv base_simple3.nit -d $WRITE
diff --git a/tests/sav/array_debug.res b/tests/sav/array_debug.res
new file mode 100644 (file)
index 0000000..c4b2490
--- /dev/null
@@ -0,0 +1 @@
+*** No Array stats ***
diff --git a/tests/sav/base_init_basic.res b/tests/sav/base_init_basic.res
new file mode 100644 (file)
index 0000000..024fc50
--- /dev/null
@@ -0,0 +1,20 @@
+a
+ab
+ac
+1
+abcd
+2
+abce
+3
+30
+abcdef
+4
+40
+abcdeg
+5
+50
+500
+abcdefgh
+6
+60
+600
diff --git a/tests/sav/base_init_basic_alt1.res b/tests/sav/base_init_basic_alt1.res
new file mode 100644 (file)
index 0000000..debd61b
--- /dev/null
@@ -0,0 +1,20 @@
+
+
+c
+1
+cd
+2
+c
+3
+30
+cd
+4
+40
+cdg
+5
+50
+500
+cdg
+6
+60
+600
diff --git a/tests/sav/base_init_basic_alt2.res b/tests/sav/base_init_basic_alt2.res
new file mode 100644 (file)
index 0000000..a08a7a2
--- /dev/null
@@ -0,0 +1,20 @@
+
+
+
+1
+
+2
+
+3
+30
+
+4
+40
+
+5
+50
+500
+
+6
+60
+600
diff --git a/tests/sav/base_init_basic_alt3.res b/tests/sav/base_init_basic_alt3.res
new file mode 100644 (file)
index 0000000..a7be1ec
--- /dev/null
@@ -0,0 +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=)
diff --git a/tests/sav/base_init_basic_alt4.res b/tests/sav/base_init_basic_alt4.res
new file mode 100644 (file)
index 0000000..024fc50
--- /dev/null
@@ -0,0 +1,20 @@
+a
+ab
+ac
+1
+abcd
+2
+abce
+3
+30
+abcdef
+4
+40
+abcdeg
+5
+50
+500
+abcdefgh
+6
+60
+600
index d210e23..510c2f5 100644 (file)
@@ -1,13 +1,9 @@
 1
 2
-1
 2
 3
-1
 2
-1
 2
 5
-1
 2
 6
index b4d9a32..38219a0 100644 (file)
@@ -1 +1 @@
-alt/base_init_super_call2_alt1.nit:23,10--14: Error: Not enough implicit arguments to pass. Got 0, expected at least 1. Signature is (i: Int)
+alt/base_init_super_call2_alt1.nit:23,28--32: Error: Not enough implicit arguments to pass. Got 0, expected at least 1. Signature is (i: Int)
index 4cc34a8..9a5cbe0 100644 (file)
@@ -1 +1 @@
-alt/base_init_super_call2_alt2.nit:33,16--19: Type error: expected Int, got Bool
+alt/base_init_super_call2_alt2.nit:33,34--37: Type error: expected Int, got Bool
diff --git a/tests/sav/base_init_super_call3.res b/tests/sav/base_init_super_call3.res
new file mode 100644 (file)
index 0000000..aa7d0fd
--- /dev/null
@@ -0,0 +1,15 @@
+10
+20
+21
+31
+30
+41
+50
+51
+60
+61
+71
+70
+81
+90
+91
index 73082d3..3231e7e 100644 (file)
@@ -1 +1 @@
-alt/base_init_super_call_alt1.nit:23,10--14: Error: Not enough implicit arguments to pass. Got 0, expected at least 1. Signature is (i: Int)
+alt/base_init_super_call_alt1.nit:23,28--32: Error: Not enough implicit arguments to pass. Got 0, expected at least 1. Signature is (i: Int)
index ca41f99..64f3f2f 100644 (file)
@@ -1 +1 @@
-alt/base_init_super_call_alt2.nit:33,16--19: Type error: expected Int, got Bool
+alt/base_init_super_call_alt2.nit:33,34--37: Type error: expected Int, got Bool
index a799a1d..508b97a 100644 (file)
@@ -1 +1 @@
-Fatal Error: no primitive class Object
+base_no_object.nit:11,9--13: Error: Method 'init' doesn't exists in A.
index 4965b26..e262c78 100644 (file)
@@ -1,2 +1,3 @@
+alt/base_no_object_alt1.nit:11,9--13: Error: Method 'init' doesn't exists in A.
 alt/base_no_object_alt1.nit:13,4--12: Type Error: missing primitive class `Bool'.
 alt/base_no_object_alt1.nit:13,4--12: Type Error: missing primitive class `Bool'.
index 7cc24f3..30a32a5 100644 (file)
@@ -1 +1 @@
-Fatal Error: more than one primitive class Object: module_0::Object standard::kernel::Object
+../lib/standard/kernel.nit:79,1--95,3: Fatal error: kernel#Sys does not specialize module_0#Object. Possible duplication of the root class `Object`?
index 3fbb2e0..0bb1a5e 100644 (file)
@@ -1,4 +1,3 @@
-alt/error_init_auto_alt4.nit:34,5--9: Error: Method 'init' doesn't exists in A.
-alt/error_init_auto_alt4.nit:35,5--12: Error: Method 'init' doesn't exists in A.
-alt/error_init_auto_alt4.nit:36,5--15: Error: Method 'init' doesn't exists in A.
-alt/error_init_auto_alt4.nit:37,5--18: Error: Method 'init' doesn't exists in A.
+alt/error_init_auto_alt4.nit:35,5--12: Error: Incorrect number of parameters. Got 1, expected 0. Signature is 
+alt/error_init_auto_alt4.nit:36,5--15: Error: Incorrect number of parameters. Got 2, expected 0. Signature is 
+alt/error_init_auto_alt4.nit:37,5--18: Error: Incorrect number of parameters. Got 3, expected 0. Signature is 
index 76554ac..b9a9402 100644 (file)
@@ -39,16 +39,14 @@ js/
 less/
 module_module_0.html
 module_module_1.html
-proprety_module_0__Int__init.html
+proprety_module_0__Object__init.html
 proprety_module_0__Object__output.html
 proprety_module_0__Object__print.html
-proprety_module_0__Sys__init.html
 proprety_module_0__Sys__main.html
 proprety_module_1__A__a1.html
 proprety_module_1__A__a12.html
 proprety_module_1__A__a123.html
 proprety_module_1__A__a13.html
-proprety_module_1__A__init.html
 proprety_module_1__B__all2.html
 proprety_module_1__B__all25.html
 quicksearch-list.js
diff --git a/tests/sav/nitg-g/base_no_object.res b/tests/sav/nitg-g/base_no_object.res
deleted file mode 100644 (file)
index d00491f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/sav/niti/base_no_object.res b/tests/sav/niti/base_no_object.res
deleted file mode 100644 (file)
index d00491f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-1
index 9dc118b..ab778d5 100644 (file)
          std: 0.0
          sum: 0
        mnoc: number of child modules
-         avg: 1.0
-         max: base_simple3 (1)
-         min: base_simple3 (1)
+         avg: 0.0
+         max: base_simple3 (0)
+         min: base_simple3 (0)
          std: 0.0
-         sum: 1
+         sum: 0
        mnod: number of descendant modules
-         avg: 1.0
-         max: base_simple3 (1)
-         min: base_simple3 (1)
+         avg: 0.0
+         max: base_simple3 (0)
+         min: base_simple3 (0)
          std: 0.0
-         sum: 1
+         sum: 0
        mdit: depth in module tree
          avg: 0.0
          max: base_simple3 (0)
          std: 0.0
          sum: 1
 
- ## project base_empty_module
-  `- group base_empty_module
+ ## global metrics
        mnoa: number of ancestor modules
          avg: 0.0
-         max: base_empty_module (0)
-         min: base_empty_module (0)
+         max: base_simple3 (0)
+         min: base_simple3 (0)
          std: 0.0
          sum: 0
        mnop: number of parent modules
          avg: 0.0
-         max: base_empty_module (0)
-         min: base_empty_module (0)
+         max: base_simple3 (0)
+         min: base_simple3 (0)
          std: 0.0
          sum: 0
        mnoc: number of child modules
-         avg: 1.0
-         max: base_empty_module (1)
-         min: base_empty_module (1)
-         std: 0.0
-         sum: 1
-       mnod: number of descendant modules
-         avg: 1.0
-         max: base_empty_module (1)
-         min: base_empty_module (1)
-         std: 0.0
-         sum: 1
-       mdit: depth in module tree
-         avg: 0.0
-         max: base_empty_module (0)
-         min: base_empty_module (0)
-         std: 0.0
-         sum: 0
-       mnbi: number of introduction in module
-         avg: 1.0
-         max: base_empty_module (1)
-         min: base_empty_module (1)
-         std: 0.0
-         sum: 1
-       mnbr: number of refinement in module
-         avg: 0.0
-         max: base_empty_module (0)
-         min: base_empty_module (0)
-         std: 0.0
-         sum: 0
-       mnbcc: number of concrete class in module (intro + redef)
-         avg: 1.0
-         max: base_empty_module (1)
-         min: base_empty_module (1)
-         std: 0.0
-         sum: 1
-       mnbac: number of abstract class in module (intro + redef)
-         avg: 0.0
-         max: base_empty_module (0)
-         min: base_empty_module (0)
-         std: 0.0
-         sum: 0
-       mnbic: number of interface in module (intro + redef)
-         avg: 0.0
-         max: base_empty_module (0)
-         min: base_empty_module (0)
-         std: 0.0
-         sum: 0
-
- ## global metrics
-       mnoa: number of ancestor modules
          avg: 0.0
          max: base_simple3 (0)
          min: base_simple3 (0)
          std: 0.0
          sum: 0
-       mnop: number of parent modules
+       mnod: number of descendant modules
          avg: 0.0
          max: base_simple3 (0)
          min: base_simple3 (0)
          std: 0.0
          sum: 0
-       mnoc: number of child modules
-         avg: 1.0
-         max: base_simple3 (1)
-         min: base_simple3 (1)
-         std: 0.0
-         sum: 2
-       mnod: number of descendant modules
-         avg: 1.0
-         max: base_simple3 (1)
-         min: base_simple3 (1)
-         std: 0.0
-         sum: 2
        mdit: depth in module tree
          avg: 0.0
          max: base_simple3 (0)
          std: 0.0
          sum: 0
        mnbi: number of introduction in module
-         avg: 4.0
+         avg: 7.0
          max: base_simple3 (7)
-         min: base_empty_module (1)
-         std: 3.0
-         sum: 8
+         min: base_simple3 (7)
+         std: 0.0
+         sum: 7
        mnbr: number of refinement in module
          avg: 0.0
          max: base_simple3 (0)
          std: 0.0
          sum: 0
        mnbcc: number of concrete class in module (intro + redef)
-         avg: 2.0
+         avg: 4.0
          max: base_simple3 (4)
-         min: base_empty_module (1)
-         std: 1.581
-         sum: 5
+         min: base_simple3 (4)
+         std: 0.0
+         sum: 4
        mnbac: number of abstract class in module (intro + redef)
          avg: 0.0
          max: base_simple3 (0)
          std: 0.0
          sum: 0
        mnbic: number of interface in module (intro + redef)
-         avg: 0.0
+         avg: 1.0
          max: base_simple3 (1)
-         min: base_empty_module (0)
-         std: 0.707
+         min: base_simple3 (1)
+         std: 0.0
          sum: 1
 
 # MClasses metrics
          std: 0.926
          sum: 6
        cnbp: number of accessible properties (inherited + local)
-         avg: 5.0
+         avg: 6.0
          max: C (10)
-         min: Object (3)
-         std: 2.507
-         sum: 37
+         min: Object (4)
+         std: 2.268
+         sum: 42
        cnba: number of accessible attributes (inherited + local)
          avg: 0.0
          max: C (2)
          sum: 3
        cnbip: number of introduced properties
          avg: 2.0
-         max: C (7)
+         max: C (6)
          min: Bool (0)
-         std: 2.42
-         sum: 19
-       cnbrp: number of redefined properties
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnbhp: number of inherited properties
-         avg: 2.0
-         max: Bool (3)
-         min: Object (0)
-         std: 1.195
+         std: 2.268
          sum: 18
-
- ## project base_empty_module
-  `- group base_empty_module
-       cnoa: number of ancestor classes
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnop: number of parent classes
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnoc: number of child classes
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnod: number of descendant classes
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cdit: depth in class tree
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnbp: number of accessible properties (inherited + local)
-         avg: 1.0
-         max: Object (1)
-         min: Object (1)
-         std: 0.0
-         sum: 1
-       cnba: number of accessible attributes (inherited + local)
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnbip: number of introduced properties
-         avg: 1.0
-         max: Object (1)
-         min: Object (1)
-         std: 0.0
-         sum: 1
        cnbrp: number of redefined properties
          avg: 0.0
-         max: Object (0)
+         max: A (1)
          min: Object (0)
-         std: 0.0
-         sum: 0
+         std: 0.535
+         sum: 2
        cnbhp: number of inherited properties
-         avg: 0.0
-         max: Object (0)
+         avg: 3.0
+         max: Bool (4)
          min: Object (0)
-         std: 0.0
-         sum: 0
+         std: 1.464
+         sum: 24
 
  ## global metrics
        cnoa: number of ancestor classes
          avg: 0.0
          max: Bool (1)
          min: Object (0)
-         std: 0.866
+         std: 0.926
          sum: 6
        cnop: number of parent classes
          avg: 0.0
          max: Bool (1)
          min: Object (0)
-         std: 0.866
+         std: 0.926
          sum: 6
        cnoc: number of child classes
          avg: 0.0
          max: Object (6)
          min: Bool (0)
-         std: 2.121
+         std: 2.268
          sum: 6
        cnod: number of descendant classes
          avg: 0.0
          max: Object (6)
          min: Bool (0)
-         std: 2.121
+         std: 2.268
          sum: 6
        cdit: depth in class tree
          avg: 0.0
          max: Bool (1)
          min: Object (0)
-         std: 0.866
+         std: 0.926
          sum: 6
        cnbp: number of accessible properties (inherited + local)
-         avg: 4.0
+         avg: 6.0
          max: C (10)
-         min: Object (1)
-         std: 2.828
-         sum: 38
+         min: Object (4)
+         std: 2.268
+         sum: 42
        cnba: number of accessible attributes (inherited + local)
          avg: 0.0
          max: C (2)
          min: Object (0)
-         std: 0.791
+         std: 0.845
          sum: 3
        cnbip: number of introduced properties
          avg: 2.0
-         max: C (7)
+         max: C (6)
          min: Bool (0)
-         std: 2.291
-         sum: 20
+         std: 2.268
+         sum: 18
        cnbrp: number of redefined properties
          avg: 0.0
-         max: Object (0)
+         max: A (1)
          min: Object (0)
-         std: 0.0
-         sum: 0
+         std: 0.535
+         sum: 2
        cnbhp: number of inherited properties
-         avg: 2.0
-         max: Bool (3)
+         avg: 3.0
+         max: Bool (4)
          min: Object (0)
-         std: 1.323
-         sum: 18
+         std: 1.464
+         sum: 24
 --- Poset metrics ---
 ## Module importation hierarchy
-Number of nodes: 3
-Number of edges: 5 (1.66 per node)
-Number of direct edges: 2 (0.66 per node)
+Number of nodes: 1
+Number of edges: 1 (1.00 per node)
+Number of direct edges: 0 (0.0 per node)
 Distribution of greaters
- population: 3
+ population: 1
  minimum value: 1
- maximum value: 3
- total value: 5
- average value: 1.66
+ maximum value: 1
+ total value: 1
+ average value: 1.00
  distribution:
-  <=1: sub-population=2 (66.66%); cumulated value=2 (40.00%)
-  <=4: sub-population=1 (33.33%); cumulated value=3 (60.00%)
+  <=1: sub-population=1 (100.00%); cumulated value=1 (100.00%)
 Distribution of direct greaters
- population: 3
+ population: 1
  minimum value: 0
- maximum value: 2
- total value: 2
- average value: 0.66
+ maximum value: 0
+ total value: 0
+ average value: 0.0
  distribution:
-  <=0: sub-population=2 (66.66%); cumulated value=0 (0.0%)
-  <=2: sub-population=1 (33.33%); cumulated value=2 (100.00%)
+  <=0: sub-population=1 (100.00%); cumulated value=0 (na%)
 Distribution of smallers
- population: 3
+ population: 1
  minimum value: 1
- maximum value: 2
- total value: 5
- average value: 1.66
+ maximum value: 1
+ total value: 1
+ average value: 1.00
  distribution:
-  <=1: sub-population=1 (33.33%); cumulated value=1 (20.00%)
-  <=2: sub-population=2 (66.66%); cumulated value=4 (80.00%)
+  <=1: sub-population=1 (100.00%); cumulated value=1 (100.00%)
 Distribution of direct smallers
- population: 3
+ population: 1
  minimum value: 0
- maximum value: 1
- total value: 2
- average value: 0.66
+ maximum value: 0
+ total value: 0
+ average value: 0.0
  distribution:
-  <=0: sub-population=1 (33.33%); cumulated value=0 (0.0%)
-  <=1: sub-population=2 (66.66%); cumulated value=2 (100.00%)
+  <=0: sub-population=1 (100.00%); cumulated value=0 (na%)
 ## Classdef hierarchy
-Number of nodes: 8
-Number of edges: 14 (1.75 per node)
-Number of direct edges: 6 (0.75 per node)
+Number of nodes: 7
+Number of edges: 13 (1.85 per node)
+Number of direct edges: 6 (0.85 per node)
 Distribution of greaters
- population: 8
+ population: 7
  minimum value: 1
  maximum value: 2
- total value: 14
- average value: 1.75
+ total value: 13
+ average value: 1.85
  distribution:
-  <=1: sub-population=2 (25.00%); cumulated value=2 (14.28%)
-  <=2: sub-population=6 (75.00%); cumulated value=12 (85.71%)
+  <=1: sub-population=1 (14.28%); cumulated value=1 (7.69%)
+  <=2: sub-population=6 (85.71%); cumulated value=12 (92.30%)
 Distribution of direct greaters
- population: 8
+ population: 7
  minimum value: 0
  maximum value: 1
  total value: 6
- average value: 0.75
+ average value: 0.85
  distribution:
-  <=0: sub-population=2 (25.00%); cumulated value=0 (0.0%)
-  <=1: sub-population=6 (75.00%); cumulated value=6 (100.00%)
+  <=0: sub-population=1 (14.28%); cumulated value=0 (0.0%)
+  <=1: sub-population=6 (85.71%); cumulated value=6 (100.00%)
 Distribution of smallers
- population: 8
+ population: 7
  minimum value: 1
  maximum value: 7
- total value: 14
- average value: 1.75
+ total value: 13
+ average value: 1.85
  distribution:
-  <=1: sub-population=7 (87.50%); cumulated value=7 (50.00%)
-  <=8: sub-population=1 (12.50%); cumulated value=7 (50.00%)
+  <=1: sub-population=6 (85.71%); cumulated value=6 (46.15%)
+  <=8: sub-population=1 (14.28%); cumulated value=7 (53.84%)
 Distribution of direct smallers
- population: 8
+ population: 7
  minimum value: 0
  maximum value: 6
  total value: 6
- average value: 0.75
+ average value: 0.85
  distribution:
-  <=0: sub-population=7 (87.50%); cumulated value=0 (0.0%)
-  <=8: sub-population=1 (12.50%); cumulated value=6 (100.00%)
+  <=0: sub-population=6 (85.71%); cumulated value=0 (0.0%)
+  <=8: sub-population=1 (14.28%); cumulated value=6 (100.00%)
 ## Class hierarchy
-Number of nodes: 8
-Number of edges: 14 (1.75 per node)
-Number of direct edges: 6 (0.75 per node)
+Number of nodes: 7
+Number of edges: 13 (1.85 per node)
+Number of direct edges: 6 (0.85 per node)
 Distribution of greaters
- population: 8
+ population: 7
  minimum value: 1
  maximum value: 2
- total value: 14
- average value: 1.75
+ total value: 13
+ average value: 1.85
  distribution:
-  <=1: sub-population=2 (25.00%); cumulated value=2 (14.28%)
-  <=2: sub-population=6 (75.00%); cumulated value=12 (85.71%)
+  <=1: sub-population=1 (14.28%); cumulated value=1 (7.69%)
+  <=2: sub-population=6 (85.71%); cumulated value=12 (92.30%)
 Distribution of direct greaters
- population: 8
+ population: 7
  minimum value: 0
  maximum value: 1
  total value: 6
- average value: 0.75
+ average value: 0.85
  distribution:
-  <=0: sub-population=2 (25.00%); cumulated value=0 (0.0%)
-  <=1: sub-population=6 (75.00%); cumulated value=6 (100.00%)
+  <=0: sub-population=1 (14.28%); cumulated value=0 (0.0%)
+  <=1: sub-population=6 (85.71%); cumulated value=6 (100.00%)
 Distribution of smallers
- population: 8
+ population: 7
  minimum value: 1
  maximum value: 7
- total value: 14
- average value: 1.75
+ total value: 13
+ average value: 1.85
  distribution:
-  <=1: sub-population=7 (87.50%); cumulated value=7 (50.00%)
-  <=8: sub-population=1 (12.50%); cumulated value=7 (50.00%)
+  <=1: sub-population=6 (85.71%); cumulated value=6 (46.15%)
+  <=8: sub-population=1 (14.28%); cumulated value=7 (53.84%)
 Distribution of direct smallers
- population: 8
+ population: 7
  minimum value: 0
  maximum value: 6
  total value: 6
- average value: 0.75
+ average value: 0.85
  distribution:
-  <=0: sub-population=7 (87.50%); cumulated value=0 (0.0%)
-  <=8: sub-population=1 (12.50%); cumulated value=6 (100.00%)
+  <=0: sub-population=6 (85.71%); cumulated value=0 (0.0%)
+  <=8: sub-population=1 (14.28%); cumulated value=6 (100.00%)
 --- AST Metrics ---
 ## All nodes of the AST
  population: 47
  minimum value: 1
  maximum value: 39
- total value: 267
- average value: 5.68
+ total value: 256
+ average value: 5.44
  distribution:
-  <=1: sub-population=10 (21.27%); cumulated value=10 (3.74%)
-  <=2: sub-population=9 (19.14%); cumulated value=18 (6.74%)
-  <=4: sub-population=10 (21.27%); cumulated value=34 (12.73%)
-  <=8: sub-population=9 (19.14%); cumulated value=54 (20.22%)
-  <=16: sub-population=5 (10.63%); cumulated value=55 (20.59%)
-  <=32: sub-population=3 (6.38%); cumulated value=57 (21.34%)
-  <=64: sub-population=1 (2.12%); cumulated value=39 (14.60%)
+  <=1: sub-population=13 (27.65%); cumulated value=13 (5.07%)
+  <=2: sub-population=6 (12.76%); cumulated value=12 (4.68%)
+  <=4: sub-population=10 (21.27%); cumulated value=32 (12.50%)
+  <=8: sub-population=10 (21.27%); cumulated value=61 (23.82%)
+  <=16: sub-population=4 (8.51%); cumulated value=44 (17.18%)
+  <=32: sub-population=3 (6.38%); cumulated value=55 (21.48%)
+  <=64: sub-population=1 (2.12%); cumulated value=39 (15.23%)
  list:
-  TId: 39 (14.60%)
-  APublicVisibility: 20 (7.49%)
-  AListExprs: 19 (7.11%)
-  ACallExpr: 18 (6.74%)
-  TClassid: 16 (5.99%)
-  TKwend: 10 (3.74%)
-  TNumber: 10 (3.74%)
-  ADecIntExpr: 10 (3.74%)
-  AType: 9 (3.37%)
-  ASignature: 8 (2.99%)
+  TId: 39 (15.23%)
+  AListExprs: 19 (7.42%)
+  APublicVisibility: 18 (7.03%)
+  ACallExpr: 18 (7.03%)
+  TClassid: 15 (5.85%)
+  TNumber: 10 (3.90%)
+  ADecIntExpr: 10 (3.90%)
+  AType: 9 (3.51%)
+  TKwend: 8 (3.12%)
+  ASignature: 8 (3.12%)
   ...
-  ASelfExpr: 1 (0.37%)
-  ACallAssignExpr: 1 (0.37%)
-  TKwself: 1 (0.37%)
-  AReturnExpr: 1 (0.37%)
-  AInterfaceClasskind: 1 (0.37%)
-  TKwinterface: 1 (0.37%)
-  TKwreturn: 1 (0.37%)
-  AInternMethPropdef: 1 (0.37%)
-  AMainMethPropdef: 1 (0.37%)
-  AMainClassdef: 1 (0.37%)
+  AModule: 1 (0.39%)
+  ACallAssignExpr: 1 (0.39%)
+  AMainClassdef: 1 (0.39%)
+  AReturnExpr: 1 (0.39%)
+  TKwreturn: 1 (0.39%)
+  TKwinterface: 1 (0.39%)
+  ANoImport: 1 (0.39%)
+  AInterfaceClasskind: 1 (0.39%)
+  AMainMethPropdef: 1 (0.39%)
+  TKwimport: 1 (0.39%)
 ## All identifiers of the AST
  population: 19
  minimum value: 1
  maximum value: 11
- total value: 55
- average value: 2.89
+ total value: 54
+ average value: 2.84
  distribution:
-  <=1: sub-population=1 (5.26%); cumulated value=1 (1.81%)
-  <=2: sub-population=13 (68.42%); cumulated value=26 (47.27%)
-  <=4: sub-population=3 (15.78%); cumulated value=10 (18.18%)
-  <=8: sub-population=1 (5.26%); cumulated value=7 (12.72%)
-  <=16: sub-population=1 (5.26%); cumulated value=11 (20.00%)
+  <=1: sub-population=2 (10.52%); cumulated value=2 (3.70%)
+  <=2: sub-population=12 (63.15%); cumulated value=24 (44.44%)
+  <=4: sub-population=3 (15.78%); cumulated value=10 (18.51%)
+  <=8: sub-population=1 (5.26%); cumulated value=7 (12.96%)
+  <=16: sub-population=1 (5.26%); cumulated value=11 (20.37%)
  list:
-  output: 11 (20.00%)
-  Int: 7 (12.72%)
-  run: 4 (7.27%)
-  c: 3 (5.45%)
-  val: 3 (5.45%)
-  i: 2 (3.63%)
-  bar: 2 (3.63%)
-  foo: 2 (3.63%)
-  val2: 2 (3.63%)
-  val1: 2 (3.63%)
-  C: 2 (3.63%)
-  v: 2 (3.63%)
-  baz: 2 (3.63%)
-  a: 2 (3.63%)
-  A: 2 (3.63%)
-  B: 2 (3.63%)
-  b: 2 (3.63%)
-  Object: 2 (3.63%)
-  Bool: 1 (1.81%)
+  output: 11 (20.37%)
+  Int: 7 (12.96%)
+  run: 4 (7.40%)
+  c: 3 (5.55%)
+  val: 3 (5.55%)
+  i: 2 (3.70%)
+  bar: 2 (3.70%)
+  foo: 2 (3.70%)
+  val2: 2 (3.70%)
+  val1: 2 (3.70%)
+  C: 2 (3.70%)
+  v: 2 (3.70%)
+  baz: 2 (3.70%)
+  a: 2 (3.70%)
+  A: 2 (3.70%)
+  B: 2 (3.70%)
+  b: 2 (3.70%)
+  Object: 1 (1.85%)
+  Bool: 1 (1.85%)
 --- Metrics of refinement usage ---
-Number of modules: 3
+Number of modules: 1
 
-Number of classes: 8
-  Number of interface kind: 1 (12.50%)
-  Number of enum kind: 2 (25.00%)
-  Number of class kind: 5 (62.50%)
+Number of classes: 7
+  Number of interface kind: 1 (14.28%)
+  Number of enum kind: 2 (28.57%)
+  Number of class kind: 4 (57.14%)
 
-Number of class definitions: 8
+Number of class definitions: 7
 Number of refined classes: 0 (0.0%)
 Average number of class refinments by classes: 0.0
 Average number of class refinments by refined classes: na
 
-Number of properties: 20
-  Number of MAttribute: 3 (15.00%)
-  Number of MMethod: 17 (85.00%)
+Number of properties: 18
+  Number of MAttribute: 3 (16.66%)
+  Number of MMethod: 15 (83.33%)
 
 Number of property definitions: 20
-Number of redefined properties: 0 (0.0%)
-Average number of property redefinitions by property: 0.0
-Average number of property redefinitions by redefined property: na
+Number of redefined properties: 1 (5.55%)
+Average number of property redefinitions by property: 0.11
+Average number of property redefinitions by redefined property: 2.00
 --- Metrics of the explitic static types ---
 Total number of explicit static types: 9
 Statistics of type usage:
@@ -610,25 +480,25 @@ Statistics of type usage:
 Total number of self: 5
 Total number of implicit self: 4 (80.00%)
 --- Construction of tables ---
-Number of runtime classes: 7 (excluding interfaces and abstract classes)
-Average number of composing class definition by runtime class: 1.85
-Total size of tables (classes and instances): 35 (not including stuff like info for subtyping or call-next-method)
-Average size of table by runtime class: 5.00
-Values never redefined: 35 (100.00%)
+Number of runtime classes: 6 (excluding interfaces and abstract classes)
+Average number of composing class definition by runtime class: 2.00
+Total size of tables (classes and instances): 38 (not including stuff like info for subtyping or call-next-method)
+Average size of table by runtime class: 6.33
+Values never redefined: 32 (84.21%)
 
 # Mendel metrics
-       large mclasses (threshold: 2.195)
+       large mclasses (threshold: 2.291)
           B: 3
           C: 3
-       budding mclasses (threshold: 0.869)
-          B: 1.0
-          C: 1.0
-       blooming mclasses (threshold: 2.388)
-          B: 3.0
-          C: 3.0
-       blooming mclasses (threshold: 2.388)
-          B: 3.0
-          C: 3.0
+       budding mclasses (threshold: 0.693)
+          B: 0.75
+          C: 0.75
+       blooming mclasses (threshold: 1.935)
+          B: 2.25
+          C: 2.25
+       blooming mclasses (threshold: 1.935)
+          B: 2.25
+          C: 2.25
 generating out/nitmetrics_args1.write/project_hierarchy.dot
 generating out/nitmetrics_args1.write/module_hierarchy.dot
 
@@ -645,23 +515,12 @@ generating out/nitmetrics_args1.write/module_hierarchy.dot
        cnbna: number of accessible nullable attributes (inherited + local) -- nothing
          sum: 0
 
- ## project base_empty_module
-  `- group base_empty_module
-       cnba: number of accessible attributes (inherited + local)
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnbna: number of accessible nullable attributes (inherited + local) -- nothing
-         sum: 0
-
  ## global metrics
        cnba: number of accessible attributes (inherited + local)
          avg: 0.0
          max: C (2)
          min: Object (0)
-         std: 0.791
+         std: 0.845
          sum: 3
        cnbna: number of accessible nullable attributes (inherited + local) -- nothing
          sum: 0
@@ -765,99 +624,6 @@ Number of buggy sends (cannot determine the type of the receiver): 0 (0.0%)
          std: 0.0
          sum: 0.143
 
- ## project base_empty_module
-  `- group base_empty_module
-       cnoac: number of class_kind ancestor
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnopc: number of class_kind parent
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnocc: number of class_kind children
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnodc: number of class_kind descendants
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnopi: number of interface_kind parent
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnoci: number of interface_kind children
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cnodi: number of interface_kind descendants
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cditc: depth in class tree following only class, abstract, extern kind
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       cditi: depth in class tree following only interface_kind
-         avg: 0.0
-         max: Object (0)
-         min: Object (0)
-         std: 0.0
-         sum: 0
-       mdui: proportion of mclass defined using inheritance (has other parent than Object)
-         avg: 0.0
-         max: base_empty_module (0.0)
-         min: base_empty_module (0.0)
-         std: 0.0
-         sum: 0.0
-       mduic: proportion of class_kind defined using inheritance
-         avg: 0.0
-         max: base_empty_module (0.0)
-         min: base_empty_module (0.0)
-         std: 0.0
-         sum: 0.0
-       mduii: proportion of interface_kind defined using inheritance
-         avg: 0.0
-         max: base_empty_module (0.0)
-         min: base_empty_module (0.0)
-         std: 0.0
-         sum: 0.0
-       mif: proportion of mclass inherited from
-         avg: 0.0
-         max: base_empty_module (0.0)
-         min: base_empty_module (0.0)
-         std: 0.0
-         sum: 0.0
-       mifc: proportion of class_kind inherited from
-         avg: 0.0
-         max: base_empty_module (0.0)
-         min: base_empty_module (0.0)
-         std: 0.0
-         sum: 0.0
-       mifi: proportion of interface_kind inherited from
-         avg: 0.0
-         max: base_empty_module (0.0)
-         min: base_empty_module (0.0)
-         std: 0.0
-         sum: 0.0
-
  ## global metrics
        cnoac: number of class_kind ancestor
          avg: 0.0
@@ -875,19 +641,19 @@ Number of buggy sends (cannot determine the type of the receiver): 0 (0.0%)
          avg: 0.0
          max: Object (4)
          min: Bool (0)
-         std: 1.414
+         std: 1.512
          sum: 4
        cnodc: number of class_kind descendants
          avg: 0.0
          max: Object (4)
          min: Bool (0)
-         std: 1.414
+         std: 1.512
          sum: 4
        cnopi: number of interface_kind parent
          avg: 0.0
          max: Bool (1)
          min: Object (0)
-         std: 0.866
+         std: 0.926
          sum: 6
        cnoci: number of interface_kind children
          avg: 0.0
@@ -911,7 +677,7 @@ Number of buggy sends (cannot determine the type of the receiver): 0 (0.0%)
          avg: 0.0
          max: Bool (1)
          min: Object (0)
-         std: 0.866
+         std: 0.926
          sum: 6
        mdui: proportion of mclass defined using inheritance (has other parent than Object)
          avg: 0.0
@@ -932,10 +698,10 @@ Number of buggy sends (cannot determine the type of the receiver): 0 (0.0%)
          std: 0.0
          sum: 0.0
        mif: proportion of mclass inherited from
-         avg: 0.071
+         avg: 0.143
          max: base_simple3 (0.143)
-         min: base_empty_module (0.0)
-         std: 0.071
+         min: base_simple3 (0.143)
+         std: 0.0
          sum: 0.143
        mifc: proportion of class_kind inherited from
          avg: 0.0
@@ -944,10 +710,10 @@ Number of buggy sends (cannot determine the type of the receiver): 0 (0.0%)
          std: 0.0
          sum: 0.0
        mifi: proportion of interface_kind inherited from
-         avg: 0.071
+         avg: 0.143
          max: base_simple3 (0.143)
-         min: base_empty_module (0.0)
-         std: 0.071
+         min: base_simple3 (0.143)
+         std: 0.0
          sum: 0.143
 
 # RTA metrics
@@ -984,11 +750,11 @@ Number of buggy sends (cannot determine the type of the receiver): 0 (0.0%)
          std: 0.0
          sum: 14
        mnlmd: number of live method definitions in a mmodule
-         avg: 14.0
-         max: base_simple3 (14)
-         min: base_simple3 (14)
+         avg: 16.0
+         max: base_simple3 (16)
+         min: base_simple3 (16)
          std: 0.0
-         sum: 14
+         sum: 16
        mnldd: number of dead method definitions in a mmodule
          avg: 0.0
          max: base_simple3 (0)
index 9e982c2..bf43dd3 100644 (file)
@@ -10,7 +10,7 @@
     
     \e[1m== constructors\e[0m
       
-      \e[1m\e[32minit\e[0m\e[0m
+      redef \e[1m\e[32minit\e[0m\e[0m
       \e[30m\e[1mbase_simple3::A::init\e[0m\e[0m\e[30m (lines 30-30)\e[0m
     
     \e[1m== methods\e[0m
index 8b3a417..5291a1e 100644 (file)
@@ -8,5 +8,5 @@ mclasses:
 Alcoholic Bool Career Character Combatable Dwarf Elf Float Game Human Int List Magician Object Race Starter String Sys Warrior Weapon
 Alcoholic Bool Career Character Combatable Dwarf Elf Float Game Human Int List Magician Object Race Starter String Sys Warrior Weapon
 mproperties:
-!= * * + + - - / / == > > OTHER _age _base_endurance _base_intelligence _base_strength _career _endurance_bonus _health _intelligence_bonus _name _race _sex _strength_bonus age age= attack base_endurance base_endurance= base_intelligence base_intelligence= base_strength base_strength= career career= computer_characters defend direct_attack dps endurance_bonus endurance_bonus= health health= hit_points init init init init init init init init init init intelligence_bonus intelligence_bonus= is_dead main max_health name name= pause_game player_characters quit race race= sex sex= start start_game stop_game strength_bonus strength_bonus= to_f total_endurance total_intelligence total_strengh unary -
-!= * * + + - - / / == > > OTHER _age _base_endurance _base_intelligence _base_strength _career _endurance_bonus _health _intelligence_bonus _name _race _sex _strength_bonus age age= attack base_endurance base_endurance= base_intelligence base_intelligence= base_strength base_strength= career career= computer_characters defend direct_attack dps endurance_bonus endurance_bonus= health health= hit_points init init init init init init init init init init intelligence_bonus intelligence_bonus= is_dead main max_health name name= pause_game player_characters quit race race= sex sex= start start_game stop_game strength_bonus strength_bonus= to_f total_endurance total_intelligence total_strengh unary -
+!= * * + + - - / / == > > OTHER _age _base_endurance _base_intelligence _base_strength _career _endurance_bonus _health _intelligence_bonus _name _race _sex _strength_bonus age age= attack base_endurance base_endurance= base_intelligence base_intelligence= base_strength base_strength= career career= computer_characters defend direct_attack dps endurance_bonus endurance_bonus= health health= hit_points init intelligence_bonus intelligence_bonus= is_dead main max_health name name= pause_game player_characters quit race race= sex sex= start start_game stop_game strength_bonus strength_bonus= to_f total_endurance total_intelligence total_strengh unary -
+!= * * + + - - / / == > > OTHER _age _base_endurance _base_intelligence _base_strength _career _endurance_bonus _health _intelligence_bonus _name _race _sex _strength_bonus age age= attack base_endurance base_endurance= base_intelligence base_intelligence= base_strength base_strength= career career= computer_characters defend direct_attack dps endurance_bonus endurance_bonus= health health= hit_points init intelligence_bonus intelligence_bonus= is_dead main max_health name name= pause_game player_characters quit race race= sex sex= start start_game stop_game strength_bonus strength_bonus= to_f total_endurance total_intelligence total_strengh unary -
index 7b6ea2d..83c6493 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Cast failed. Expected `NativeArray#0`, got `Bool` (../lib/standard/collection/array.nit:742)
+Runtime error: Cast failed. Expected `NativeArray#0`, got `Bool` (../lib/standard/collection/array.nit:755)
 NativeString
 N
 Nit
index 5877a29..b5e3e16 100644 (file)
@@ -4,6 +4,10 @@
 すでa語A本日a 𐍆,A ᓂ . ᓀ 界世a𐍃ーЖロaハ
 ー𐍃a世
 世a𐍃ー
+世a𐍃ー
+ー𐍃a世
+すでa語A本日a 𐍆,A ᓂ . ᓀ 界世a𐍃ーЖロaハ
+ハaロЖー𐍃a世界 ᓀ . ᓂ A,𐍆 a日本A語aです
 ハAロЖー𐍃A世界 ᓀ . ᓂ A,𐍆 A日本A語Aです
 ハaロЖー𐍃a世界 ᓀ . ᓂ a,𐍆 a日本a語aです
 aハロЖー𐍃a世界 ᓀ . ᓂ A,𐍆 a日本A語aです
index a731499..5353bdb 100644 (file)
@@ -46,6 +46,34 @@ for i in [0 .. xx.length[ do xx.char_at(i).output
 
 '\n'.output
 
+var it = new FlatStringReviter(x)
+for i in it do
+       i.output
+end
+
+'\n'.output
+
+var it2 = new FlatStringIter(x)
+for i in it2 do
+       i.output
+end
+
+'\n'.output
+
+it = new FlatStringReviter(str)
+for i in it do
+       i.output
+end
+
+'\n'.output
+
+it2 = new FlatStringIter(str)
+for i in it2 do
+       i.output
+end
+
+'\n'.output
+
 assert str * 2 == str + str
 
 assert x * 2 == x + x