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>
tables_nit.c -diff
c_src/**/*.[ch] -diff
c_src/Makefile -diff
+
+tests/sav/**/*.res -whitespace
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()
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()
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
}
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
}
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
}
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
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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)
--- /dev/null
+# 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)
--- /dev/null
+# 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
--- /dev/null
+# 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)
# 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
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}"
--- /dev/null
+# 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
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")
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
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")
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
# 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
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
# 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.
#
# 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.
#
# 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]
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
# ~~~
class MinHeapCmp[E: Comparable]
super MinHeap[E]
- init do super(new DefaultComparator[E])
+ init is old_style_init do super(new DefaultComparator[E])
end
* 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
`}
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
# 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)
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
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
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
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
v.send(su, args_of_super)
end
end
+
var recv = arguments.first
var i = 1
# Collect undefined attributes
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)
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
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)
writable
cached
nosuper
+old_style_init
pkgconfig
c_compiler_option
# 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
# 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
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)
# 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)
# 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
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
# 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
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
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
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
# 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
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)
# 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
# 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
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
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
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
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
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)
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
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
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
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)
a2.output
end
- init
+ init is
+ old_style_init
do
a1 = 1
a2 = 2
a3.output
end
- init
+ init is
+ old_style_init
do
a1 = 10
a2 = 20
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class 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
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
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
class D1
super A
- init(j) do
+ init(j: Int) do
super
j.output
end
class D2
super A
- init(j) do
+ init(j: Int) do
super(j)
j.output
end
class D3
super A
- init(j) do
+ init(j: Int) do
j.output
end
end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class 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)
---no-colors --all --csv base_simple3.nit base_empty_module.nit -d $WRITE
+--no-colors --all --csv base_simple3.nit -d $WRITE
--- /dev/null
+*** No Array stats ***
--- /dev/null
+a
+ab
+ac
+1
+abcd
+2
+abce
+3
+30
+abcdef
+4
+40
+abcdeg
+5
+50
+500
+abcdefgh
+6
+60
+600
--- /dev/null
+
+
+c
+1
+cd
+2
+c
+3
+30
+cd
+4
+40
+cdg
+5
+50
+500
+cdg
+6
+60
+600
--- /dev/null
+
+
+
+1
+
+2
+
+3
+30
+
+4
+40
+
+5
+50
+500
+
+6
+60
+600
--- /dev/null
+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=)
--- /dev/null
+a
+ab
+ac
+1
+abcd
+2
+abce
+3
+30
+abcdef
+4
+40
+abcdeg
+5
+50
+500
+abcdefgh
+6
+60
+600
1
2
-1
2
3
-1
2
-1
2
5
-1
2
6
-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)
-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
--- /dev/null
+10
+20
+21
+31
+30
+41
+50
+51
+60
+61
+71
+70
+81
+90
+91
-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)
-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
-Fatal Error: no primitive class Object
+base_no_object.nit:11,9--13: Error: Method 'init' doesn't exists in A.
+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'.
-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`?
-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
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
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:
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
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
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
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
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
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
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
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)
\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
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 -
-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
すで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です
'\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