Merge: Refactor FFI, the framework is now based on MModules
authorJean Privat <jean@pryen.org>
Tue, 13 May 2014 19:22:37 +0000 (15:22 -0400)
committerJean Privat <jean@pryen.org>
Tue, 13 May 2014 19:22:37 +0000 (15:22 -0400)
* Should fix #437 by supporting the use of the Java FFI across many modules in global compilation.
* Should also work (but we need an example for it): `nitg cross_platform_prog.nit -m android`

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

75 files changed:
benchmarks/bench_engines.sh
benchmarks/bench_languages.sh
contrib/pep8analysis/src/ast/rich_instructions.nit
contrib/pep8analysis/src/parser/parser_nodes.nit
examples/shoot/src/shoot_logic.nit
lib/github_api.nit
lib/java.nit
lib/json/.gitattributes [moved from lib/simple_json_reader/.gitattributes with 100% similarity]
lib/json/.gitignore [moved from lib/simple_json_reader/.gitignore with 100% similarity]
lib/json/Makefile [moved from lib/simple_json_reader/Makefile with 100% similarity]
lib/json/dynamic.nit [new file with mode: 0644]
lib/json/json.nit
lib/json/json_lexer.nit [moved from lib/simple_json_reader/json_lexer.nit with 100% similarity]
lib/json/json_parser.nit [moved from lib/simple_json_reader/json_parser.nit with 100% similarity]
lib/json/json_reader.nit [deleted file]
lib/json/json_writer.nit [deleted file]
lib/json/jsonable.nit [deleted file]
lib/json/static.nit [moved from lib/simple_json_reader/simple_json_reader.nit with 86% similarity]
lib/json_serialization.nit
lib/jvm.nit
lib/nitcc_runtime.nit
lib/poset.nit
lib/standard/collection/abstract_collection.nit
lib/standard/collection/sorter.nit
lib/standard/ropes.nit
lib/template.nit
lib/trees/abstract_tree.nit [new file with mode: 0644]
lib/trees/bintree.nit [new file with mode: 0644]
lib/trees/rbtree.nit [new file with mode: 0644]
lib/trees/trees.nit [new file with mode: 0644]
lib/union_find.nit [new file with mode: 0644]
misc/vim/indent/nit.vim
misc/vim/syntax/nit.vim
share/nitdoc/css/main.css
src/abstract_compiler.nit
src/android_platform.nit
src/auto_super_init.nit
src/cached.nit
src/coloring.nit [new file with mode: 0644]
src/common_ffi/c.nit
src/common_ffi/common_ffi.nit
src/common_ffi/ffi_base.nit
src/common_ffi/java.nit
src/compiler_ffi.nit
src/debugger.nit
src/doc_template.nit
src/layout_builders.nit [deleted file]
src/model/model.nit
src/modelize_property.nit
src/naive_interpreter.nit
src/nitdoc.nit
src/nitlight.nit
src/nitni/nitni_callbacks.nit
src/nitx.nit
src/parser/parser_nodes.nit
src/parser_util.nit
src/rapid_type_analysis.nit
src/separate_compiler.nit
src/separate_erasure_compiler.nit
src/typing.nit
tests/base_init_combine.nit [new file with mode: 0644]
tests/bench_netsim.nit
tests/error_spe_attr.nit
tests/nitg-e.skip
tests/nitg-g.skip
tests/nitg-s.skip
tests/sav/base_init_combine.res [new file with mode: 0644]
tests/sav/base_init_combine_alt1.res [new file with mode: 0644]
tests/sav/base_init_simple_alt1.res
tests/sav/test_json.res [deleted file]
tests/sav/test_json_static.res [moved from tests/sav/test_simple_json_reader.res with 100% similarity]
tests/sav/test_markdown_args1.res
tests/sav/test_parser_args7.res
tests/test_json.nit [deleted file]
tests/test_json_static.nit [moved from tests/test_simple_json_reader.nit with 56% similarity]

index 4168579..55db63e 100755 (executable)
@@ -262,7 +262,6 @@ function bench_nitg-s_options()
 bench_nitg-s_options "slower" --hardening --no-inline-intern --no-union-attribute --no-shortcut-equal --no-shortcut-range "--no-gcc-directive likely" "--no-gcc-directive noreturn"
 bench_nitg-s_options "nocheck" --no-check-covariance --no-check-attr-isset --no-check-assert --no-check-autocast --no-check-other
 bench_nitg-s_options "faster" --inline-coloring-numbers --inline-some-methods --direct-call-monomorph "--inline-some-methods --direct-call-monomorph"
-bench_nitg-s_options "typing" NOALL --bm-typing --phand-typing
 
 function bench_nitg-e_options()
 {
@@ -291,7 +290,6 @@ function bench_nitg-e_options()
 bench_nitg-e_options "slower" --hardening --no-inline-intern --no-union-attribute --no-shortcut-equal --no-shortcut-range
 bench_nitg-e_options "nocheck" --no-check-covariance --no-check-attr-isset --no-check-assert --no-check-autocast --no-check-other --no-check-erasure-cast
 bench_nitg-e_options "faster" --inline-coloring-numbers
-bench_nitg-e_options "typing" NOALL --bm-typing # --phand-typing
 
 function bench_engines()
 {
index 5348c8d..d9db525 100755 (executable)
@@ -232,27 +232,6 @@ function bench_language()
        done
 
 <<XXX
-       tg="nitg-s-bm"
-       prepare_res $nitdir/$name-$tg.dat "$tg" "$tg"
-       for b in $seq; do
-               run_command ./nitg $nitdir/${t}_$b.nit --separate --bm-typing -o "$nitdir/${t}_$b.$tg.bin" --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-               bench_command "$b" "" "$nitdir/${t}_$b.$tg.bin" $s
-       done
-
-       tg="nitg-s-pha"
-       prepare_res $nitdir/$name-$tg.dat "$tg" "$tg"
-       for b in $seq; do
-               run_command ./nitg $nitdir/${t}_$b.nit --separate --phand-typing -o "$nitdir/${t}_$b.$tg.bin" --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-               bench_command "$b" "" "$nitdir/${t}_$b.$tg.bin" $s
-       done
-
-       tg="nitg-s-phm"
-       prepare_res $nitdir/$name-$tg.dat "$tg" "$tg"
-       for b in $seq; do
-               run_command ./nitg $nitdir/${t}_$b.nit --separate --phmod-typing -o "$nitdir/${t}_$b.$tg.bin" --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-               bench_command "$b" "" "$nitdir/${t}_$b.$tg.bin" $s
-       done
-
        prepare_res $nitdir/$name-nitg-su.dat "nitg-su" "nitg-su"
        for b in $seq; do
                run_command ./nitg $nitdir/${t}_$b.nit --separate --no-check-covariance -o "$nitdir/${t}_$b.nitg-su.bin" --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
index 6989980..8049e34 100644 (file)
@@ -145,7 +145,8 @@ abstract class ARichBinaryInstruction
                _n_id = src.n_id
                parent = src.parent
 
-               init(src.location)
+               init
+               _location = src.location
        end
 end
 
@@ -156,7 +157,8 @@ abstract class ARichUnaryInstruction
                _n_id = src.n_id
                parent = src.parent
 
-               init(src.location)
+               init
+               _location = src.location
        end
 end
 
index 62efb2a..3399de0 100644 (file)
@@ -6,7 +6,7 @@ import location
 
 # Root of the AST hierarchy
 abstract class ANode
-       var _location: nullable Location
+       var _location: nullable Location = null
 
        # Location is set during AST building. Once built, location cannon be null
        # However, manual instanciated nodes may need mode care
@@ -96,10 +96,12 @@ end
 class AInstruction
        super Prod
     readable writable var _n_id: TId
+       init do end
 end
 class AOperand
        super Prod
     readable var _n_value: AValue
+       init do end
 end
 class AValue super Prod end
 class ADirective super Prod end
@@ -109,10 +111,12 @@ class AListing
     readable var _n_lines: List[ALine] = new List[ALine]
     readable var _n_label_decl: nullable ALabelDecl = null
     readable var _n_end_block: TEndBlock
+       init do end
 end
 class AEmptyLine
        super ALine
     readable var _n_eol: TEol
+       init do end
 end
 abstract class ANonEmptyLine
        super ALine
@@ -121,16 +125,19 @@ class AInstructionLine
        super ANonEmptyLine
     readable var _n_instruction: AInstruction
     readable var _n_eol: TEol
+       init do end
 end
 class ADirectiveLine
        super ANonEmptyLine
     readable var _n_directive: ADirective
     readable var _n_eol: TEol
+       init do end
 end
 class ALabelDecl
        super Prod
     readable var _n_id: TId
     readable var _n_colon: TColon
+       init do end
 end
 class AUnaryInstruction
        super AInstruction
@@ -138,6 +145,7 @@ end
 class ABinaryInstruction
        super AInstruction
     readable var _n_operand: AOperand
+       init do end
 end
 class AImmediateOperand
        super AOperand
@@ -146,61 +154,74 @@ class AAnyOperand
        super AOperand
     readable var _n_comma: TComma
     readable var _n_id: TId
+       init do end
 end
 class ALabelValue
        super AValue
     readable var _n_id: TId
+       init do end
 end
 class ANumberValue
        super AValue
     readable var _n_number: TNumber
+       init do end
 end
 class ACharValue
        super AValue
     readable var _n_char: TChar
+       init do end
 end
 class AStringValue
        super AValue
     readable var _n_string: TString
+       init do end
 end
 class AHexValue
        super AValue
     readable var _n_hex: THex
+       init do end
 end
 class AByteDirective
        super ADirective
     readable var _n_tk_byte: TTkByte
     readable var _n_value: AValue
+       init do end
 end
 class AWordDirective
        super ADirective
     readable var _n_tk_word: TTkWord
     readable var _n_value: AValue
+       init do end
 end
 class ABlockDirective
        super ADirective
     readable var _n_tk_block: TTkBlock
     readable var _n_value: AValue
+       init do end
 end
 class AAsciiDirective
        super ADirective
     readable var _n_tk_ascii: TTkAscii
     readable var _n_value: AValue
+       init do end
 end
 class AAddrssDirective
        super ADirective
     readable var _n_tk_addrss: TTkAddrss
     readable var _n_value: AValue
+       init do end
 end
 class AEquateDirective
        super ADirective
     readable var _n_tk_equate: TTkEquate
     readable var _n_value: AValue
+       init do end
 end
 class ABurnDirective
        super ADirective
     readable var _n_tk_burn: TTkBurn
     readable var _n_value: AValue
+       init do end
 end
 
 class Start
@@ -209,7 +230,7 @@ class Start
     readable var _n_eof: EOF
        init(n_base: nullable AListing, n_eof: EOF)
        do
-               super(null)
+               super
                _n_base = n_base
                _n_eof = n_eof
        end
index 907b8b1..3443a47 100644 (file)
@@ -209,7 +209,7 @@ class Missile
        super Shoot
 
        # The target aquired by the missile
-       var target: nullable Sprite
+       var target: nullable Sprite = null
 
        # When ttl is 0 then the angle stay fixed
        # The angle is updated toward the target if ttl>0
index b0240ca..d1a66e6 100644 (file)
@@ -17,7 +17,7 @@
 module github_api
 
 import curl
-import simple_json_reader
+import json::static
 
 # Specific Curl that know hot to talk to the github API
 class GithubCurl
index b27f627..de82015 100644 (file)
@@ -156,4 +156,11 @@ redef extern class JavaObject
                JNIEnv *env = Sys_jni_env(sys);
                (*env)->DeleteGlobalRef(env, recv);
        `}
+
+       # Delete this local reference
+       fun delete_local_ref import sys, Sys.jni_env `{
+               Sys sys = JavaObject_sys(recv);
+               JNIEnv *env = Sys_jni_env(sys);
+               (*env)->DeleteLocalRef(env, recv);
+       `}
 end
diff --git a/lib/json/dynamic.nit b/lib/json/dynamic.nit
new file mode 100644 (file)
index 0000000..ec3ba25
--- /dev/null
@@ -0,0 +1,226 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# Dynamic interface to read Json strings.
+#
+# `String::to_json_value` returns a `JsonValue` which can be queried
+# to get the underlying Json data. It can also be used as any Json types.
+module dynamic
+
+private import static
+import standard
+
+class JsonValue
+       var value: nullable Object
+
+       # Is this value null?
+       #
+       #     assert "null".to_json_value.is_null
+       #     assert not "123".to_json_value.is_null
+       fun is_null: Bool do return value == null
+
+       # Is this value an integer?
+       #
+       #     assert "123".to_json_value.is_int
+       #     assert not "1.23".to_json_value.is_int
+       #     assert not "\"str\"".to_json_value.is_int
+       fun is_int: Bool do return value isa Int
+
+       # Get this value as a `Int`
+       #
+       # require: `self.is_int`
+       #
+       #     assert "-10".to_json_value.to_i == -10
+       #     assert "123".to_json_value.to_i == 123
+       fun to_i: Int do return value.as(Int)
+
+       # Is this value a float?
+       #
+       #     assert "0.0".to_json_value.is_float
+       #     assert "123.456".to_json_value.is_float
+       #     assert not "123".to_json_value.is_float
+       fun is_float: Bool do return value isa Float
+
+       # Get this value as a `Float`
+       #
+       # require: `self.is_float`
+       #
+       #     assert "0.0".to_json_value.to_f == 0.0
+       #     assert "123.456".to_json_value.to_f == 123.456
+       fun to_f: Float do return value.as(Float)
+
+       # Is the value numeric?
+       #
+       #     assert "1.234".to_json_value.is_numeric
+       #     assert "1234".to_json_value.is_numeric
+       #     assert not "\"str\"".to_json_value.is_numeric
+       #     assert not "1.2.3.4".to_json_value.is_numeric
+       fun is_numeric: Bool do return is_int or is_float
+
+       # Get this value as a `Numeric`
+       #
+       # require: `self.is_numeric`
+       #
+       #     assert "1.234".to_json_value.to_numeric = 1.234
+       #     assert "1234".to_json_value.to_numeric = 1234
+       fun to_numeric: Numeric
+       do
+               if is_int then return to_i
+               return to_f
+       end
+
+       # Is this value a boolean?
+       #
+       #     assert "true".to_json_value.is_bool
+       #     assert "false".to_json_value.is_bool
+       fun is_bool: Bool do return value isa Bool
+
+       # Get this value as a `Bool`
+       #
+       # require: `self.is_bool`
+       #
+       #     assert "true".to_json_value.to_bool
+       #     assert not "false".to_json_value.to_bool
+       fun to_bool: Bool do return value.as(Bool)
+
+       # Is this value a string?
+       #
+       #     assert "\"str\"".to_json_value.is_string
+       #     assert not "123".to_json_value.is_string
+       fun is_string: Bool do return value isa String
+
+       # Get this value as a `String`
+       #
+       # If value is null, return "null", otherwise returns `value.to_s`. It is practical
+       # on most types, except maps which does not have a custom `to_s`.
+       #
+       #     assert "\"str\"".to_json_value.to_s == "str"
+       #     assert "123".to_json_value.to_s == "123"
+       #     assert "true".to_json_value.to_s == "true"
+       #     assert "[1, 2, 3]".to_json_value.to_s == "123"
+       redef fun to_s: String
+       do
+               if value == null then return "null"
+               return value.to_s
+       end
+
+       ### Objects
+
+       # Is this value a Json object (a map)?
+       #
+       #     assert """{"a": 123}""".to_json_value.is_map
+       #     assert not "123".to_json_value.is_map
+       fun is_map: Bool do return value isa HashMap[String, nullable Object]
+
+       # Get this value as a `Map[String, JsonValue]`
+       #
+       # require: `self.is_map`
+       fun to_map: Map[String, JsonValue] do
+               var value = value
+               assert value isa HashMap[String, nullable Object]
+
+               var map = new HashMap[String, JsonValue]
+               for k, v in value do map[k] = new JsonValue(v)
+               return map
+       end
+
+       ### Arrays
+
+       # Is this value an array?
+       #
+       #     assert "[]".to_json_value.is_array
+       #     assert "[1, 2, 3, 4, 5]".to_json_value.is_array
+       #     assert "[null, true, false, 0.0, 1, \"str\"]".to_json_value.is_array
+       #     assert """["a", "b", "c"]""".to_json_value.is_array
+       fun is_array: Bool do return value isa Array[nullable Object]
+
+       # Get this value as an `Array[JsonValue]`
+       #
+       # require: `self.is_array`
+       #
+       #     assert """["a", "b", "c"]""".to_json_value.to_a.join(", ") == "a, b, c"
+       fun to_a: Array[JsonValue]
+       do
+               var value = value
+               assert value isa Array[nullable Object]
+
+               var a = new Array[JsonValue]
+               for e in value do a.add(new JsonValue(e))
+               return a
+       end
+
+       # Iterator over the values of the array `self`
+       #
+       # require: `self.is_array`
+       #
+       #     var a = new Array[String]
+       #     for e in """["a", "b", "c"]""".to_json_value do a.add(e.to_s)
+       #     assert a[0] == "a"
+       #     assert a[1] == "b"
+       #     assert a[2] == "c"
+       fun iterator: Iterator[JsonValue] do return to_a.iterator
+
+       # Get value at index `key` on the array or map `self`
+       #
+       # require: `self.is_array or self.is_map`
+       # require: `self.is_array implies key isa Int`
+       #
+       #     assert """{"a": 123}""".to_json_value["a"].to_i == 123
+       #     assert """{"123": "a"}""".to_json_value[123].to_s == "a"
+       #     assert """{"John Smith": 1980}""".to_json_value[["John ", "Smith"]].to_i == 1980
+       #
+       #     assert """["a", "b", "c"]""".to_json_value[0].to_s == "a"
+       fun [](key: Object): JsonValue
+       do
+               var value = value
+               if value isa HashMap[String, nullable Object] then
+                       return new JsonValue(value[key.to_s])
+               else if value isa Array[nullable Object] then
+                       assert key isa Int
+                       return new JsonValue(value[key])
+               else abort
+       end
+
+       # Advanced query to get a value within the map `self` or it's children.
+       #
+       # A query is composed of the keys to each map seperated by '.'.
+       #
+       # require: `self.is_map`
+       #
+       #     assert """{"a": {"t": true, "f": false}}""".to_json_value.get("a").is_map
+       #     assert """{"a": {"t": true, "f": false}}""".to_json_value.get("a.t").to_bool
+       #     assert not """{"a": {"t": true, "f": false}}""".to_json_value.get("a.f").to_bool
+       #     assert """{"a": {"b": {"c": {"d": 123}}}}""".to_json_value.get("a.b.c.d").to_i == 123
+       fun get(query: String): JsonValue
+       do
+               var keys = query.split(".")
+               var value = value
+               for key in keys do
+                       assert value isa HashMap[String, nullable Object]
+                       value = value[key]
+               end
+               return new JsonValue(value)
+       end
+end
+
+redef class String
+       # Parse `self` to obtain a `JsonValue`
+       fun to_json_value: JsonValue
+       do
+               var value = json_to_nit_object
+               return new JsonValue(value)
+       end
+end
index 1e9522f..9353350 100644 (file)
@@ -1,6 +1,6 @@
 # This file is part of NIT ( http://www.nitlanguage.org ).
 #
-# Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Writing to and reading from the Json format.
-# Based on the json0 C library
+# Offers two APIs to manipulate read Json strings.
+#
+# The `dynamic` module provides a simple interface to get information
+# from a Json document. You must be careful as all services are provided on
+# each nodes and a wrongful use can `abort`.
+#
+# The `static` module converts a Json string to a nullable Nit object. The object
+# must then be type checked before it can be used.
 module json
 
-import jsonable
-import json_reader
-import json_writer
-
-redef class String
-       fun json_load_from_file : nullable Map[ String, nullable Jsonable ]
-       do
-               var f = new IFStream.open( self )
-               var data = f.read_all.json_to_object
-               f.close
-
-               return data.as(not null) # ( Map[ String, nullable Jsonable ] )
-       end
-end
+import static
+import dynamic
diff --git a/lib/json/json_reader.nit b/lib/json/json_reader.nit
deleted file mode 100644 (file)
index 6af4fb8..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
-#
-# 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.
-
-# Deserialisation from the Json format to Nit objects
-module json_reader
-
-intrude import jsonable
-
-in "C Header" `{
-       #define __STRICT_ANSI__
-       #include <json/json.h>
-`}
-
-redef class String
-       # Deserializes this String and return its value as a Map[String, nullable Jsonable]
-       # On error, null is returned.
-       fun json_to_object : nullable Map[String, nullable Jsonable] import NativeString.to_s, JsonObject.json_to_map `{
-               char *native_recv;
-               json_object *jobj;
-               nullable_Map_of_String_nullable_Jsonable map;
-
-               native_recv = String_to_cstring( recv );
-               jobj = json_tokener_parse( native_recv );
-               map = JsonObject_json_to_map( jobj );
-
-               /*json_object_put( jobj );*/
-               return map;
-       `}
-end
-
-redef extern class JsonObject
-       # Get this json object as a Map
-       private fun json_to_map : nullable Map[String, nullable Jsonable] import NativeString.to_s, String.to_cstring, HashMap[String,nullable Jsonable], HashMap[String,nullable Jsonable].[]=, json_cross, HashMap[String, nullable Jsonable].as(nullable Map[String, nullable Jsonable]) `{
-               HashMap_of_String_nullable_Jsonable map;
-               String nit_key;
-               nullable_Jsonable nit_val;
-               enum json_type type;
-
-               map = new_HashMap_of_String_nullable_Jsonable();
-
-               { /* prevents "mixed declaration and code" warning for C90 */
-               json_object_object_foreach( recv, key, val ) {
-                       nit_key = NativeString_to_s( key );
-
-                       if ( val == NULL ) type = json_type_null;
-                       else type = json_object_get_type( val );
-
-                       nit_val = JsonObject_json_cross( val, type );
-
-                       HashMap_of_String_nullable_Jsonable__index_assign( map, nit_key, nit_val );
-               }
-               }
-
-               return HashMap_of_String_nullable_Jsonable_as_nullable_Map_of_String_nullable_Jsonable( map );
-       `}
-
-       # Get this json object as a Bool
-       private fun json_to_bool : Bool `{
-               return json_object_get_boolean( recv );
-       `}
-
-       # Get this json object as a Float
-       private fun json_to_float : Float `{
-               return json_object_get_double( recv );
-       `}
-
-       # Get this json object as an Int
-       private fun json_to_int : Int `{
-               return json_object_get_int( recv );
-       `}
-
-       # Get this json object as a Sequence
-       private fun json_to_sequence : Sequence[nullable Jsonable] import Array[nullable Jsonable], Array[nullable Jsonable].push, json_cross, Array[nullable Jsonable].as(Sequence[nullable Jsonable]) `{
-               array_list* jlist;
-               json_object* jobj;
-               nullable_Jsonable obj;
-               Array_of_nullable_Jsonable dest;
-               int i;
-               int len;
-               enum json_type type;
-
-               jlist = json_object_get_array( recv );
-               len = json_object_array_length( recv );
-               dest = new_Array_of_nullable_Jsonable();
-               for ( i = 0; i < len; i ++ ) {
-                       jobj = json_object_array_get_idx( recv, i );
-                       if ( jobj == NULL ) type = json_type_null;
-                       else type = json_object_get_type( jobj );
-                       obj = JsonObject_json_cross( jobj, type );
-                       Array_of_nullable_Jsonable_push( dest, obj );
-               }
-
-               return Array_of_nullable_Jsonable_as_Sequence_of_nullable_Jsonable( dest );
-       `}
-
-       # Get this json object as a String
-       private fun json_to_string : String import NativeString.to_s `{
-               const char *cstring;
-               cstring = json_object_get_string( recv );
-               return NativeString_to_s( (char*)cstring );
-       `}
-
-       # Intermediate function to convert to gt this Json object as a given type.
-       # Imlemented in Nit because Nit should manage all possible typing-related work.
-       private fun json_cross( json_type : Int ) : nullable Jsonable
-       do
-               if json_type == 0 then # null
-                       return null
-               else if json_type == 1 then # Bool
-                       return json_to_bool
-               else if json_type == 2 then # Float
-                       return json_to_float
-               else if json_type == 3 then # Int
-                       return json_to_int
-               else if json_type == 4 then # Map
-                       return json_to_map
-               else if json_type == 5 then # Sequence
-                       return json_to_sequence
-               else if json_type == 6 then # String
-                       return json_to_string
-               else
-                       print "WARNING: Unrecongnized json object type id: {json_type}"
-                       return null
-               end
-       end
-end
diff --git a/lib/json/json_writer.nit b/lib/json/json_writer.nit
deleted file mode 100644 (file)
index fcbe7ea..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
-#
-# 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.
-
-# Serialisation from Nit objects to the Json format
-module json_writer
-
-intrude import jsonable
-
-in "C Header" `{
-       #define __STRICT_ANSI__
-       #include <json/json.h>
-`}
-
-redef interface Jsonable
-       # Get a JsonObject representing this instance, specific to the C library
-       private fun to_json_object : JsonObject is abstract
-end
-
-# Will ignore non-jsonable
-redef class Map[ K, V ]
-       # Get a json-formatted string of this map
-       fun to_pretty_json: String do return native_to_json(true)
-       fun to_json: String do return native_to_json(false)
-
-       fun native_to_json( pretty: Bool ): String import to_json_object, NativeString.to_s `{
-               json_object *jobj;
-               const char *json_native_string;
-               String json_string;
-
-               jobj = Map_of_Object_nullable_Object_to_json_object( recv );
-#ifdef JSON_C_TO_STRING_PRETTY
-               if ( pretty )
-                       json_native_string = json_object_to_json_string_ext( jobj, JSON_C_TO_STRING_PRETTY );
-               else
-                       json_native_string = json_object_to_json_string_ext( jobj, JSON_C_TO_STRING_PLAIN );
-#else
-               json_native_string = json_object_to_json_string( jobj );
-#endif
-               json_string = NativeString_to_s( (char*)json_native_string );
-               return json_string;
-       `}
-
-       redef fun to_json_object
-       do
-               var jobj = new JsonObject
-
-               var iter = iterator
-               while iter.is_ok do
-                       var key = iter.key
-                       if key isa String then
-                               var val = iter.item
-                               if val isa Jsonable then
-                                       var jsubobj = val.to_json_object
-                                       jobj.add( key, jsubobj )
-                               else if val == null then
-                                       jobj.add( key, null )
-                               else
-                                       print "WARNING: value \"{val}\" not jsonable, cannot be converted to json."
-                               end
-                       else
-                               print "WARNING: key \"{key}\" not a string, cannot be converted to json."
-                       end
-
-                       iter.next
-               end
-               return jobj
-       end
-end
-
-redef class SequenceRead[ E ]
-       redef fun to_json_object
-       do
-               var jarray = new JsonArray
-               for e in self do
-                       if e isa nullable Jsonable then
-                               if e == null then
-                                       jarray.push( null )
-                               else
-                                       var obj = e.to_json_object
-                                       jarray.push( obj )
-                               end
-                       else
-                               print "WARNING: element \"{e}\" not a Jsonable, cannot be converted to json."
-                       end
-               end
-
-               return jarray
-       end
-end
-
-redef class String
-       redef fun to_json_object import NativeString.to_s, String.to_cstring `{
-               char *native_recv = String_to_cstring( recv );
-               return json_object_new_string( native_recv );
-       `}
-end
-
-redef class Int
-       redef fun to_json_object `{
-               return json_object_new_int( recv );
-       `}
-end
-
-redef class Bool
-       redef fun to_json_object `{
-               return json_object_new_boolean( recv );
-       `}
-end
-
-redef class Float
-       redef fun to_json_object `{
-               return json_object_new_double( recv );
-       `}
-end
-
-redef class JsonObject
-       new `{ return json_object_new_object(); `}
-
-       # Add a key and value to the object
-       fun add( key : String, val : nullable JsonObject ) import String.to_cstring, JsonObject.as not nullable `{
-               char* native_key;
-
-               native_key = String_to_cstring( key );
-
-               if ( nullable_JsonObject_is_null(val) ) {
-                       json_object_object_add( recv, native_key, NULL );
-               } else {
-                       json_object *jobj;
-                       jobj = nullable_JsonObject_as_JsonObject( val );
-                       json_object_object_add( recv, native_key, jobj );
-               }
-       `}
-end
-
-private extern class JsonArray
-       super JsonObject
-
-       new `{ return json_object_new_array(); `}
-
-       fun push( val : nullable JsonObject ) `{
-               if ( nullable_JsonObject_is_null(val) )
-                       json_object_array_add( recv, NULL );
-               else
-                       json_object_array_add( recv, nullable_JsonObject_as_JsonObject(val) );
-       `}
-end
diff --git a/lib/json/jsonable.nit b/lib/json/jsonable.nit
deleted file mode 100644 (file)
index 6eb95ac..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
-#
-# 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.
-
-# Basic json related functionalities
-module jsonable is pkgconfig("json")
-
-in "C Header" `{
-       #define __STRICT_ANSI__
-       #include <json/json.h>
-`}
-
-# Type supported by the Json format
-interface Jsonable
-end
-
-# Main object type used by C library
-private extern class JsonObject `{ struct json_object* `}
-       # Give up ownership of this object and decrease the reference count.
-       fun put `{ json_object_put( recv ); `}
-
-       # Aquire ownership of this object and increase the reference count.
-       fun get `{ json_object_get( recv ); `}
-end
-
-redef class SequenceRead[ V ]
-       super Jsonable
-end
-
-redef class String
-       super Jsonable
-end
-
-# Can b converted to a Json object
-redef class Map[ K, V ]
-       super Jsonable
-end
-
-redef class Int
-       super Jsonable
-end
-
-redef class Bool
-       super Jsonable
-end
-
-redef class Float
-       super Jsonable
-end
similarity index 86%
rename from lib/simple_json_reader/simple_json_reader.nit
rename to lib/json/static.nit
index 3ebc5eb..3d3f0f0 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-module simple_json_reader
+# Static interface to get Nit objects from a Json string.
+#
+# `String::json_to_nit_object` returns an equivalent Nit object from
+# the Json source. This object can then be type checked by the usual
+# languages features (`isa` and `as`).
+module static
 
 import standard
 private import json_parser
@@ -132,11 +137,14 @@ redef class String
                var root_node = parser.parse
                if root_node isa NStart then
                        return root_node.n_0.to_nit_object
-               else
-                       assert root_node isa NLexerError
+               else if root_node isa NLexerError then
+                       var pos = root_node.position
+                       print "Json lexer error: {root_node.message} at {pos or else "<unknown>"} for {root_node}"
+                       return null
+               else if root_node isa NParserError then
                        var pos = root_node.position
                        print "Json parsing error: {root_node.message} at {pos or else "<unknown>"} for {root_node}"
                        return null
-               end
+               else abort
        end
 end
index b361f88..c06c3f4 100644 (file)
@@ -17,7 +17,7 @@
 module json_serialization
 
 import serialization
-import simple_json_reader
+import json::static
 
 class JsonSerializer
        super Serializer
index 8a07b2a..e4c52a2 100644 (file)
@@ -374,6 +374,16 @@ extern class JniEnv `{JNIEnv *`}
        fun string_to_jobject(string: String): JavaObject `{
                return (*recv)->NewStringUTF(recv, String_to_cstring(string));
        `}
+
+       # Pushes a local reference frame on the JNI stack
+       fun push_local_frame(capacity: Int): Bool `{
+               return (*recv)->PushLocalFrame(recv, capacity);
+       `}
+
+       # Pops the current local reference frame on the JNI stack
+       fun pop_local_frame `{
+               (*recv)->PopLocalFrame(recv, NULL);
+       `}
 end
 
 # used to initialize a JavaVM 
index 3e77c20..51ee0c8 100644 (file)
@@ -473,8 +473,9 @@ end
 # A parser error linked to a unexpected token
 class NParserError
        super NError
+
        # The unexpected token
-       var token: nullable NToken
+       var token: nullable NToken = null
 
        redef fun unexpected
        do
index 65695da..ac0765e 100644 (file)
@@ -163,6 +163,13 @@ class POSet[E: Object]
                if res != 0 then return res
                return elements[a].count <=> elements[b].count
        end
+
+       # Sort a sorted array of poset elements using linearization order
+       fun linearize(elements: Collection[E]): Array[E] do
+               var lin = elements.to_a
+               sort(lin)
+               return lin
+       end
 end
 
 # View of an objet in a poset
index a08f7d4..d67d80e 100644 (file)
@@ -624,7 +624,7 @@ interface SequenceRead[E]
                var p = 0
                var i = iterator
                while i.is_ok do
-                       if p>pos and i.item == item then return i.index
+                       if p>=pos and i.item == item then return i.index
                        i.next
                        p += 1
                end
index beca2ca..b6319e1 100644 (file)
@@ -4,7 +4,7 @@
 #
 # 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 
+# 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
 # a custom `Comparator::compare` function.
 module sorter
 
+import range
 import array
 
 # This abstract class generalizes ways to sort an array
 interface Comparator[E]
        # Compare `a` and `b`.
        # Returns:
-       #       -1 if a < b
+       #       -1 if a < b
        #       0  if a = b
        #       1  if a > b
        fun compare(a: E, b: E): Int is abstract
 
        # Sort `array` using the `compare` function.
+       #
+       #     var s = new DefaultComparator[Int]
+       #     var a = [5, 2, 3, 1, 4]
+       #     s.sort(a)
+       #     assert a == [1, 2, 3, 4, 5]
        fun sort(array: Array[E]) do sub_sort(array, 0, array.length-1)
 
        # Sort `array` between `from` and `to` indices
@@ -42,8 +48,13 @@ interface Comparator[E]
        end
 
        # Quick-sort `array` between `from` and `to` indices
-       private fun quick_sort(array: Array[E], from: Int, to: Int)
-       do
+       # Worst case: O(n^2), Average case: O(n lg n)
+       #
+       #     var s = new DefaultComparator[Int]
+       #     var a = [5, 2, 3, 1, 4]
+       #     s.quick_sort(a, 0, a.length - 1)
+       #     assert a == [1, 2, 3, 4, 5]
+       fun quick_sort(array: Array[E], from: Int, to: Int) do
                var pivot = array[from]
                var i = from
                var j = to
@@ -61,9 +72,15 @@ interface Comparator[E]
                sub_sort(array, from, i-2)
                sub_sort(array, i, to)
        end
-       
+
        # Bubble-sort `array` between `from` and `to` indices
-       private fun bubble_sort(array: Array[E], from: Int, to: Int)
+       # Worst case: O(n^2), average case: O(n^2)
+       #
+       #     var s = new DefaultComparator[Int]
+       #     var a = [5, 2, 3, 1, 4]
+       #     s.bubble_sort(a, 0, a.length - 1)
+       #     assert a == [1, 2, 3, 4, 5]
+       fun bubble_sort(array: Array[E], from: Int, to: Int)
        do
                var i = from
                while i < to do
@@ -84,6 +101,108 @@ interface Comparator[E]
                        i += 1
                end
        end
+
+       # Insertion-sort `array` between `from` and `to` indices
+       # Worst case: O(n^2), average case: O(n^2)
+       #
+       #     var s = new DefaultComparator[Int]
+       #     var a = [5, 2, 3, 1, 4]
+       #     s.insertion_sort(a, 0, a.length - 1)
+       #     assert a == [1, 2, 3, 4, 5]
+       fun insertion_sort(array: Array[E], from: Int, to: Int) do
+               var last = array.length
+               for i in [from..to] do
+                       var j = i
+                       while j > 0 and compare(array[j], array[j - 1]) < 0 do
+                               array.swap_at(j, j - 1)
+                               j -= 1
+                       end
+               end
+       end
+
+       # Merge-sort `array` between `from` and `to` indices
+       # Worst case: O(n lg n), average: O(n lg n)
+       #
+       #     var s = new DefaultComparator[Int]
+       #     var a = [5, 2, 3, 1, 4]
+       #     s.merge_sort(a, 0, a.length - 1)
+       #     assert a == [1, 2, 3, 4, 5]
+       fun merge_sort(array: Array[E], from, to: Int) do
+               if from >= to then return
+               var mid = (to + from) / 2
+               merge_sort(array, from, mid)
+               merge_sort(array, mid + 1, to)
+               merge(array, from, mid, to)
+       end
+
+       private fun merge(array: Array[E], from, mid, to: Int) do
+               var l = new Array[E]
+               for i in [from..mid] do l.add array[i]
+               var r = new Array[E]
+               for i in [mid + 1..to] do r.add array[i]
+               var i = 0
+               var j = 0
+               for k in [from..to] do
+                       if i >= l.length then
+                               array[k] = r[j]
+                               j += 1
+                       else if j >= r.length then
+                               array[k] = l[i]
+                               i += 1
+                       else if compare(l[i], r[j]) <= 0 then
+                               array[k] = l[i]
+                               i += 1
+                       else
+                               array[k] = r[j]
+                               j += 1
+                       end
+               end
+       end
+
+       # Heap-sort `array` between `from` and `to` indices
+       # Worst case: O(n lg n), average: O(n lg n)
+       #
+       #     var s = new DefaultComparator[Int]
+       #     var a = [5, 2, 3, 1, 4]
+       #     s.heap_sort(a, 0, a.length - 1)
+       #     assert a == [1, 2, 3, 4, 5]
+       fun heap_sort(array: Array[E], from, to: Int) do
+               var size = build_heap(array)
+               for j in [from..to[ do
+                       array.swap_at(0, size)
+                       size -= 1
+                       heapify(array, 0, size)
+               end
+       end
+
+       private fun build_heap(array: Array[E]): Int do
+               var size = array.length - 1
+               var i = size / 2
+               while i >= 0 do
+                       heapify(array, i, size)
+                       i -= 1
+               end
+               return size
+       end
+
+       private fun heapify(array: Array[E], from, to: Int) do
+               var l = from * 2
+               var r = l + 1
+               var largest: Int
+               if l < to and compare(array[l], array[from]) > 0 then
+                       largest = l
+               else
+                       largest = from
+               end
+               if r < to and compare(array[r], array[largest]) > 0 then
+                       largest = r
+               end
+               if largest != from then
+                       array.swap_at(from, largest)
+                       heapify(array, largest, to)
+               end
+       end
+
 end
 
 # Deprecated class, use `Comparator` instead
index ad093ae..8d507a1 100644 (file)
@@ -967,8 +967,8 @@ end
 private class ConcatNode
        super RopeNode
 
-       private var _left_child: nullable RopeNode
-       private var _right_child: nullable RopeNode
+       private var _left_child: nullable RopeNode = null
+       private var _right_child: nullable RopeNode = null
 
        private fun left_child: nullable RopeNode
        do
index d254c24..f8916b3 100644 (file)
@@ -79,9 +79,7 @@ module template
 #         end
 #         # ...
 #     end
-#     var l = new LnkTmpl
-#     l.text = "hello world"
-#     l.href = "hello.png"
+#     var l = new LnkTmpl("hello world", null, "hello.png")
 #     assert l.write_to_string == """<a href="hello.png">hello world</a>"""
 #
 class Template
diff --git a/lib/trees/abstract_tree.nit b/lib/trees/abstract_tree.nit
new file mode 100644 (file)
index 0000000..63ac67a
--- /dev/null
@@ -0,0 +1,67 @@
+# 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.
+
+# Introduce tree structures abstraction
+# Trees are a widely used abstract data type (ADT) or data structure
+# implementing this ADT that simulates a hierarchical tree structure,
+# with a root value and subtrees of children, represented as a set of linked nodes.
+module abstract_tree
+
+# Abstract tree map structure
+# * `K`: tree node key
+# * `E`: tree node value
+abstract class TreeMap[K: Comparable, E]
+       super Map[K, E]
+
+       # Type of nodes used in this tree implementation
+       protected type N: TreeNode[K, E]
+
+       # The `root` node of the tree (null if tree is empty)
+       protected var root: nullable N protected writable = null
+
+       # Display the tree in a gaphical windows
+       # Graphviz with a working -Txlib is expected
+       # Used for debugging
+       fun show_dot is abstract
+end
+
+# Node used in Tree implementation
+# nodes are used to store values
+# * `E`: type of value
+class TreeNode[K: Comparable, E]
+
+       # TreeNode type
+       type SELF: TreeNode[K, E]
+
+       # `key` for this node
+       var key: K
+
+       # `value` stored in the node
+       var value: E
+
+       # Direct parent of this node (null if the node is root)
+       var parent: nullable SELF writable = null
+
+       redef fun to_s do return "\{{value}\}"
+
+       # Return dot representation of this node
+       # Used for debugging by `AbstractTree::show_dot`
+       fun to_dot: String do
+               var res = new FlatBuffer
+               res.append "\"{self}\";\n"
+               if parent != null then res.append "\"{parent.as(not null)}\" -> \"{self}\"[dir=back];\n"
+               return res.to_s
+       end
+end
+
diff --git a/lib/trees/bintree.nit b/lib/trees/bintree.nit
new file mode 100644 (file)
index 0000000..235b298
--- /dev/null
@@ -0,0 +1,364 @@
+# 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.
+
+# Binary Tree data-structure
+# A binary tree is a tree data structure in which each node has at most two children
+# (referred to as the left child and the right child).
+# In a binary tree, the degree of each node can be at most two.
+# Binary trees are used to implement binary search trees and binary heaps,
+# and are used for efficient searching and sorting.
+module bintree
+
+import abstract_tree
+
+# Binary Tree Map
+#
+# Properties:
+#  * unique root
+#  * node.left.key < node.key
+#  * node.right.key > node.key
+#  * no duplicates allowed
+#
+# Operations:
+#  * search average O(lg n) worst O(n)
+#  * insert average O(lg n) worst O(n)
+#  * delete average O(lg n) worst O(n)
+#
+# Usage:
+#     var tree = new BinTreeMap[Int, String]
+#     tree[1] = "n1"
+#     assert tree.min == "n1"
+class BinTreeMap[K: Comparable, E]
+       super TreeMap[K, E]
+
+       redef type N: BinTreeNode[K, E]
+
+       # Get the node value associated to `key`
+       # O(n) in worst case, average is O(h) with h: tree height
+       #
+       #     var tree = new BinTreeMap[Int, String]
+       #     for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
+       #     assert tree[1] == "n1"
+       redef fun [](key: K): E do
+               assert not_empty: root != null
+               var res = search_down(root.as(not null), key)
+               assert has_key: res != null
+               return res.value
+       end
+
+       protected fun search_down(from: N, key: K): nullable N do
+               if key == from.key then return from
+               if from.left != null and key < from.key then
+                       return search_down(from.left.as(not null), key)
+               else if from.right != null then
+                       return search_down(from.right.as(not null), key)
+               end
+               return null
+       end
+
+       # Get the node with the minimum key
+       # O(n) in worst case, average is O(h) with h: tree height
+       #
+       #     var tree = new BinTreeMap[Int, String]
+       #     for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
+       #     assert tree.min == "n1"
+       fun min: E do
+               assert not_empty: root != null
+               return min_from(root.as(not null)).value
+       end
+
+       protected fun min_from(node: N): N do
+               if node.left == null then return node
+               return min_from(node.left.as(not null))
+       end
+
+       # Get the node with the maximum key
+       # O(n) in worst case, average is O(h) with h: tree height
+       #
+       #     var tree = new BinTreeMap[Int, String]
+       #     for i in [4, 2, 1, 5, 3, 6, 7, 8] do tree[i] = "n{i}"
+       #     assert tree.max == "n8"
+       fun max: E do
+               assert not_empty: root != null
+               return max_from(root.as(not null)).value
+       end
+
+       protected fun max_from(node: N): N do
+               if node.right == null then return node
+               return max_from(node.right.as(not null))
+       end
+
+       # Insert a new node in tree using `key` and `item`
+       # O(n) in worst case, average is O(h) with h: tree height
+       #
+       #     var tree = new BinTreeMap[Int, String]
+       #     tree[1] = "n1"
+       #     assert tree.max == "n1"
+       #     tree[3] = "n3"
+       #     assert tree.max == "n3"
+       redef fun []=(key, item) do
+               insert_node(new BinTreeNode[K, E](key, item))
+       end
+
+       protected fun insert_node(node: N) do
+               if root == null then
+                       root = node
+               else
+                       shift_down(root.as(not null), node)
+               end
+       end
+
+       # Push down the `node` in tree from a specified `from` index
+       protected fun shift_down(from, node: N) do
+               if node.key < from.key then
+                       if from.left == null then
+                               from.left = node
+                               node.parent = from
+                       else
+                               shift_down(from.left.as(not null), node)
+                       end
+               else if node.key > from.key then
+                       if from.right == null then
+                               from.right = node
+                               node.parent = from
+                       else
+                               shift_down(from.right.as(not null), node)
+                       end
+               end
+       end
+
+       # Delete node at `key` (also return the deleted node value)
+       # O(n) in worst case, average is O(h) with h: tree height
+       #
+       #     var tree = new BinTreeMap[Int, String]
+       #     tree[1] = "n1"
+       #     assert tree.max == "n1"
+       #     tree[3] = "n3"
+       #     assert tree.max == "n3"
+       #     tree.delete(3)
+       #     assert tree.max == "n1"
+       fun delete(key: K): nullable E do
+               assert is_empty: root != null
+               var node = search_down(root.as(not null), key)
+               if node == null then return null
+               if node.left == null then
+                       transplant(node, node.right)
+               else if node.right == null then
+                       transplant(node, node.left)
+               else
+                       var min = min_from(node.right.as(not null))
+                       if min.parent != node then
+                               transplant(min, min.right)
+                               min.right = node.right
+                               min.right.parent = min
+                       end
+                       transplant(node, min)
+                       min.left = node.left
+                       min.left.parent = min
+               end
+               return node.value
+       end
+
+       # Swap a `node` with the `other` in this Tree
+       # note: Nodes parents are updated, children still untouched
+       protected fun transplant(node, other: nullable N) do
+               if node == null then return
+               if node.parent == null then
+                       root = other
+               else if node == node.parent.left then
+                       node.parent.left = other
+               else
+                       node.parent.right = other
+               end
+               if other != null then other.parent = node.parent
+       end
+
+       # Perform left rotation on `node`
+       #
+       #     N             Y
+       #    / \     >     / \
+       #   a   Y         N   c
+       #      / \   <   / \
+       #     b   c     a   b
+       #
+       protected fun rotate_left(node: N) do
+               var y = node.right
+               node.right = y.left
+               if y.left != null then
+                       y.left.parent = node
+               end
+               y.parent = node.parent
+               if node.parent == null then
+                       root = y
+               else if node == node.parent.left then
+                       node.parent.left = y
+               else
+                       node.parent.right = y
+               end
+               y.left = node
+               node.parent = y
+       end
+
+       # Perform right rotation on `node`
+       #
+       #     N             Y
+       #    / \     >     / \
+       #   a   Y         N   c
+       #      / \   <   / \
+       #     b   c     a   b
+       #
+       protected fun rotate_right(node: N) do
+               var y = node.left
+               node.left = y.right
+               if y.right != null then
+                       y.right.parent = node
+               end
+               y.parent = node.parent
+               if node.parent == null then
+                       root = y
+               else if node == node.parent.right then
+                       node.parent.right = y
+               else
+                       node.parent.left = y
+               end
+               y.right = node
+               node.parent = y
+       end
+
+       # Sort the tree into an array
+       # O(n)
+       #
+       #     var tree = new BinTreeMap[Int, String]
+       #     for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
+       #     assert tree.sort == ["n1", "n2", "n3", "n4", "n5"]
+       fun sort: Array[E] do
+               var sorted = new Array[E]
+               if root == null then return sorted
+               sort_down(root.as(not null), sorted)
+               return sorted
+       end
+
+       protected fun sort_down(node: N, sorted: Array[E]) do
+               if node.left != null then sort_down(node.left.as(not null), sorted)
+               sorted.add(node.value)
+               if node.right != null then sort_down(node.right.as(not null), sorted)
+       end
+
+       redef fun to_s do
+               var root = self.root
+               if root == null then return "[]"
+               return "[{print_tree(root)}]"
+       end
+
+       protected fun print_tree(node: N): String do
+               var s = new FlatBuffer
+               s.append(node.to_s)
+               if node.left != null then s.append(print_tree(node.left.as(not null)))
+               if node.right != null then s.append(print_tree(node.right.as(not null)))
+               return s.to_s
+       end
+
+       redef fun show_dot do
+               assert not_empty: root != null
+               var f = new OProcess("dot", "-Txlib")
+               f.write "digraph \{\n"
+               dot_down(root.as(not null), f)
+               f.write "\}\n"
+               f.close
+       end
+
+       protected fun dot_down(node: N, f: OProcess) do
+               if node.left != null then dot_down(node.left.as(not null), f)
+               f.write node.to_dot
+               if node.right != null then dot_down(node.right.as(not null), f)
+       end
+end
+
+# TreeNode used by BinTree
+class BinTreeNode[K: Comparable, E]
+       super TreeNode[K, E]
+
+       redef type SELF: BinTreeNode[K, E]
+
+       init(key: K, item: E) do
+               super(key, item)
+       end
+
+       private var left_node: nullable SELF = null
+
+       # `left` tree node child (null if node has no left child)
+       fun left: nullable SELF do return left_node
+
+       # set `left` child for this node (or null if left no child)
+       # ENSURE: node.key < key (only if node != null)
+       fun left=(node: nullable SELF) do
+               assert node != null implies node.key < key
+               left_node = node
+       end
+
+       private var right_node: nullable SELF = null
+
+       # `right` tree node child (null if node has no right child)
+       fun right: nullable SELF do return right_node
+
+       # set `right` child for this node (or null if right no child)
+       # ENSURE: node.key < key (only if node != null)
+       fun right=(node: nullable SELF) do
+               if node != null then
+                       assert node.key > key
+               end
+               right_node = node
+       end
+
+       # `parent` of the `parent` of this node (null if root)
+       fun grandparent: nullable SELF do
+               if parent == null then
+                       return null
+               else
+                       return parent.parent
+               end
+       end
+
+       # Other child of the `grandparent`
+       # `left` or `right` depends on the position of the current node against its parent
+       fun uncle: nullable SELF do
+               var g = grandparent
+               if g == null then
+                       return null
+               else
+                       if parent == g.left then
+                               return g.right
+                       else
+                               return g.left
+                       end
+               end
+       end
+
+       # Other child of the parent
+       # `left` or `right` depends on the position of the current node against its parent
+       fun sibling: nullable SELF do
+               if parent == null then
+                       return null
+               else if self == parent.left then
+                       return parent.right
+               else if self == parent.right then
+                       return parent.left
+               else
+                       return null
+               end
+       end
+
+       redef fun to_s do return "\{{key}: {value}\}"
+end
+
diff --git a/lib/trees/rbtree.nit b/lib/trees/rbtree.nit
new file mode 100644 (file)
index 0000000..ce17feb
--- /dev/null
@@ -0,0 +1,147 @@
+# 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.
+
+# A red–black tree is a data structure which is a type of self-balancing binary search tree.
+#
+# Balance is preserved by painting each node of the tree with one of two colors
+# (typically called 'red' and 'black') in a way that satisfies certain properties,
+# which collectively constrain how unbalanced the tree can become in the worst case.
+# When the tree is modified, the new tree is subsequently rearranged and repainted
+# to restore the coloring properties.
+# The properties are designed in such a way that this rearranging and recoloring
+# can be performed efficiently.
+#
+# The balancing of the tree is not perfect but it is good enough to allow it
+# to guarantee searching in O(log n) time, where n is the total number of elements in the tree.
+# The insertion and deletion operations, along with the tree rearrangement and recoloring,
+# are also performed in O(log n) time.
+module rbtree
+
+import bintree
+
+# Red-Black Tree Map
+# Properties of a Red-Black tree map:
+#  * every node is either red or black
+#  * root is black
+#  * every leaf (null) is black
+#  * if a node is red, then both its children are black
+#  * for each node, all simple path from the node to descendant
+#    leaves contain the same number of black nodes
+#
+# Operations:
+#  * search average O(lg n) worst O(lg n)
+#  * insert average O(lg n) worst O(lg n)
+#  * delete average O(lg n) worst O(lg n)
+class RBTreeMap[K: Comparable, E]
+       super BinTreeMap[K, E]
+
+       redef type N: RBTreeNode[K, E]
+
+       redef fun []=(key, item) do
+               insert_node(new RBTreeNode[K, E](key, item))
+       end
+
+       redef fun insert_node(node) do
+               super
+               insert_fixup_case1(node)
+       end
+
+       # Case 1: node is root
+       # color node as black
+       # it adds a black node on every path so we do nothing else
+       private fun insert_fixup_case1(node: N) do
+               if node.parent == null then
+                       node.is_red = false
+               else
+                       insert_fixup_case2(node)
+               end
+       end
+
+       # Case 2: parent is black
+       # it do not add black node so we do nothing else
+       private fun insert_fixup_case2(node: N) do
+               if node.parent.is_red then insert_fixup_case3(node)
+       end
+
+       # Case 3: node, parent and uncle are red
+       # this is a LLr or RRr conflict
+       # we recolor recursively the tree to the root
+       private fun insert_fixup_case3(node: N) do
+               if node.uncle != null and node.uncle.is_red then
+                       node.parent.is_red = false
+                       node.uncle.is_red = false
+                       node.grandparent.is_red = true
+                       insert_fixup_case1(node.grandparent.as(not null))
+               else
+                       insert_fixup_case4(node)
+               end
+       end
+
+       # Case 4: node and parent are red, uncle is black
+       # this is a LRb or RLb conflict
+       # we rotate the tree to balance it
+       private fun insert_fixup_case4(node: N) do
+               if node == node.parent.right and node.parent == node.grandparent.left then
+                       rotate_left(node.parent.as(not null))
+                       node = node.left.as(not null)
+               else if node == node.parent.left and node.parent == node.grandparent.right then
+                       rotate_right(node.parent.as(not null))
+                       node = node.right.as(not null)
+               end
+               insert_fixup_case5(node)
+       end
+
+       # Case 5: node and parent are red, uncle is black
+       # this is a LLb or RRb conflict
+       # we rotate the tree to balance it
+       private fun insert_fixup_case5(node: N) do
+               node.parent.is_red = false
+               node.grandparent.is_red = true
+               if node == node.parent.left then
+                       rotate_right(node.grandparent.as(not null))
+               else
+                       rotate_left(node.grandparent.as(not null))
+               end
+       end
+
+       # TODO implement RBTree::delete
+       redef fun delete(key) is abstract
+
+       redef fun dot_down(node, f) do
+               if node.left != null then dot_down(node.left.as(not null), f)
+               f.write node.to_dot
+               if node.parent != null then f.write "\"{node.parent.as(not null)}\" -> \"{node}\"[dir=back];\n"
+               if node.right != null then dot_down(node.right.as(not null), f)
+       end
+end
+
+# RedBlackTree node (can be red or black)
+class RBTreeNode[K: Comparable, E]
+       super BinTreeNode[K, E]
+
+       redef type SELF: RBTreeNode[K, E]
+
+       # Is the node red?
+       private var is_red = true
+
+       redef fun to_dot do
+               if is_red then
+                       return "\"{self}\"[style=filled,fillcolor=red,fontcolor=white];\n"
+               else
+                       return "\"{self}\"[style=filled,fillcolor=black,fontcolor=white];\n"
+               end
+
+       end
+end
+
diff --git a/lib/trees/trees.nit b/lib/trees/trees.nit
new file mode 100644 (file)
index 0000000..93716b5
--- /dev/null
@@ -0,0 +1,20 @@
+# 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.
+
+# General module for tree data structures
+module trees
+
+import abstract_tree
+import bintree
+import rbtree
diff --git a/lib/union_find.nit b/lib/union_find.nit
new file mode 100644 (file)
index 0000000..0134eb2
--- /dev/null
@@ -0,0 +1,193 @@
+# 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.
+
+# union–find algorithm using an efficient disjoint-set data structure
+module union_find
+
+# Data structure to keeps track of elements partitioned into disjoint subsets
+#     var s = new DisjointSet[Int]
+#     s.add(1)
+#     s.add(2)
+#     assert not s.in_same_subset(1,2)
+#     s.union(1,2)
+#     assert s.in_same_subset(1,2)
+#
+# `in_same_subset` is transitive, reflexive and symetric
+#
+#     s.add(3)
+#     assert not s.in_same_subset(1,3)
+#     s.union(3,2)
+#     assert s.in_same_subset(1,3)
+#
+# Unkike theorical Disjoint-set data structures, the underling implementation is opaque
+# that makes the traditionnal `find` method unavailable for clients.
+# The methods `in_same_subset`, `to_partitions`, and their variations are offered instead.
+class DisjointSet[E: Object]
+       super SimpleCollection[E]
+
+       # The node in the hiearchical structure for each element
+       private var nodes = new HashMap[E, DisjointSetNode]
+
+       # Get the root node of an element
+       # require: `has(e)`
+       private fun find(e:E): DisjointSetNode
+       do
+               assert nodes.has_key(e)
+               var ne = nodes[e]
+               if ne.parent == ne then return ne
+               var res = nfind(ne)
+               nodes[e] = res
+               return res
+       end
+
+       # Get the root node of a node
+       # Use *path compression* to flatten the structure
+       # ENSURE: `result.parent == result`
+       private fun nfind(ne: DisjointSetNode): DisjointSetNode
+       do
+               var nf = ne.parent
+               if nf == ne then return ne
+               var ng = nfind(nf)
+               ne.parent = ng
+               return ng
+       end
+
+       # Is the element in the structure
+       #
+       #     var s = new DisjointSet[Int]
+       #     assert not s.has(1)
+       #     s.add(1)
+       #     assert s.has(1)
+       #     assert not s.has(2)
+       redef fun has(e: E): Bool
+       do
+               return nodes.has_key(e)
+       end
+
+       redef fun iterator do return nodes.keys.iterator
+
+       # Add a new element in the structure.
+       # Initially it is in its own disjoint subset
+       #
+       # ENSURE: `has(e)`
+       redef fun add(e:E)
+       do
+               if nodes.has_key(e) then return
+               var ne = new DisjointSetNode
+               nodes[e] = ne
+       end
+
+       # Are two elements in the same subset?
+       fun in_same_subset(e,f:E): Bool
+       do
+               return e == f or find(e) == find(f)
+       end
+
+       # Are all elements of `es` in the same subset?
+       #     var s = new DisjointSet[Int]
+       #     s.add_all([1,2,3,4,5,6])
+       #     s.union_all([1,2,3])
+       #     assert not s.all_in_same_subset([2,3,4])
+       #     s.union_all([1,4,5])
+       #     assert s.all_in_same_subset([2,3,4])
+       fun all_in_same_subset(es: Collection[E]): Bool
+       do
+               if es.is_empty then return true
+               var nf = find(es.first)
+               for e in es do
+                       var ne = find(e)
+                       if ne != nf then return false
+               end
+               return true
+       end
+
+       # Construct the current partitionning
+       #
+       #     var s = new DisjointSet[Int]
+       #     s.add_all([1,2,3,4,5,6])
+       #     s.union(1,2)
+       #     s.union(1,3)
+       #     s.union(4,5)
+       #     var p = s.to_partitions
+       #     assert p.length == 3
+       fun to_partitions: Collection[Set[E]]
+       do
+               return to_subpartition(self)
+       end
+
+       # Construct a partitionning on `es`, a subset of elements
+       #
+       #     var s = new DisjointSet[Int]
+       #     s.add_all([1,2,3,4,5,6])
+       #     s.union(1,2)
+       #     s.union(1,3)
+       #     s.union(4,5)
+       #     var p = s.to_subpartition([1,2,4])
+       #     assert p.length == 2
+       fun to_subpartition(es: Collection[E]): Collection[Set[E]]
+       do
+               var map = new HashMap[DisjointSetNode, Set[E]]
+               for e in es do
+                       var ne = find(e)
+                       var set = map.get_or_null(ne)
+                       if set == null then
+                               set = new HashSet[E]
+                               map[ne] = set
+                       end
+                       set.add(e)
+               end
+               return map.values
+       end
+
+       # Combine the subsets of `e` and `f`
+       # ENSURE: `in_same_subset(e,f)`
+       fun union(e,f:E)
+       do
+               var ne = find(e)
+               var nf = find(f)
+               if ne == nf then return
+
+               # merge them using *union by rank*
+               # attach the smaller tree to the root of the deeper tree
+               var er = ne.rank
+               var fr = nf.rank
+               if er < fr then
+                       ne.parent = nf
+                       nodes[e] = nf
+               else
+                       nf.parent = ne
+                       nodes[f] = ne
+                       if er == fr then
+                               # The only case where the deep is increased is when both are equals
+                               ne.rank = er+1
+                       end
+               end
+       end
+
+       # Combine the subsets of all elements of `es`
+       # ENSURE: `all_in_same_subset(cs)`
+       fun union_all(es:Collection[E])
+       do
+               if es.is_empty then return
+               var f = es.first
+               for e in es do union(e,f)
+       end
+end
+
+# A node in the hierarchical representation of subsets
+private class DisjointSetNode
+       # If parent == self then the node is a root
+       var parent: DisjointSetNode = self
+
+       # The rank to no desequilibrate the structure.
+       # The term rank is used instead of depth since
+       # path compression is used, see `DisjointSet::nfind`
+       var rank = 0
+end
index afaa93a..10c4a2e 100644 (file)
@@ -31,7 +31,6 @@ setlocal nocindent
 setlocal autoindent
 setlocal comments=:#
 setlocal indentkeys+==end,=else,=do,=var,0!,=then,=loop,=special,=class,=interface,=universal
-setlocal sw=8
 
 " Only define the function once.
 if exists("*GetNITIndent")
@@ -45,7 +44,7 @@ let s:outdent = '^\s*\(else\|then\|end\)\>'
 " At 0
 let s:no_indent = '^\s*\(class\|import\|special\)\>'
 
-let s:syng_strcom = '\<nit\%(String\|StringDelimiter\|Escape\|Comment\|Documentation\)\>'
+let s:syng_strcom = '\<NIT\(String\|StringDelimiter\|Escape\|Comment\|Documentation\)\>'
 
 " Check if the character at lnum:col is inside a string, comment, or is ascii.
 function s:IsInStringOrComment(lnum, col)
index 76db35d..8b68b53 100644 (file)
@@ -56,23 +56,25 @@ syn match NITClosure "!\h\w*"
 
 " Fallback highlight keywords
 syn match NITNull "\<\(null\)\>"
-syn match NITControl "\<\(init\|end\|not null\|not\|var\|do\|then\|else\|loop\)\>"
+syn match NITControl "\<\(init\|end\|not null\|not\|var\|do\|then\|else\|loop\|is\)\>"
 syn match NITKeyword "\<\(super\)\>"
 " Unmatchning error
 syn match Error "\<end\>"
 
 " Declarations, definitions and blocks
 syn region NITModuleDecl matchgroup=NITDefine start="\<\(import\|module\|package\)\>\s*" matchgroup=NONE end="\ze\(\s\|:\|(\|$\)"  oneline
-syn region NITClassBlock matchgroup=NITDefine start="\<\(class\|enum\|universal\|interface\|extern\)\>" matchgroup=NITDefine end="\<end\>" contains=ALL fold
+syn region NITClassBlock matchgroup=NITDefine start="\<\(class\|enum\|universal\|interface\|extern\)\>" matchgroup=NITDefine end="\<end\>" contains=ALLBUT,NITAnnotLine fold
 syn region NITFunctionDecl matchgroup=NITDefine start="\<fun\>\s*" matchgroup=NONE end="\ze\(\<do\>\|\s\|:\|(\|$\)"  oneline
 syn region NITTypeDecl matchgroup=NITDefine start="\<type\>\s*" matchgroup=NONE end="\ze\(\<do\>\|\s\|:\|(\|$\)"  oneline contained containedin=NITClassBlock
-syn region NITAttrDecl matchgroup=NITDefine start="\<var\>\s*\ze_" matchgroup=NONE end="\ze\(\<do\>\|\s\|:\|(\|$\)"  oneline contained containedin=NITClassBlock
+syn region NITAttrDecl matchgroup=NITDefine start="\<var\>\s*" matchgroup=NONE end="\ze\(\<do\>\|\s\|:\|(\|$\)"  oneline contained containedin=NITClassBlock
 syn region NITInitDecl matchgroup=NITDefine start="\<init\>\s*" matchgroup=NONE end="\ze\(\<do\>\|\s\|:\|(\|$\)"  oneline contained containedin=NITClassBlock
 syn match NITDefine "\<\(super\)\ze\s\+[A-Z]" contained containedin=NITClassBlock
 
-syn region NITStmtBlock matchgroup=NITControl start="\<\(do\|then\|else\|loop\)\>\ze\s*\(#\|$\)" matchgroup=NITControl end="^\s*\<\(end\|\zeelse\|\ze!\)\>" contains=ALLBUT,NITTypeDecl,NITAttrDecl,NITInitDecl
-syn region NITStmtBlock matchgroup=NITControl start="\<\(do\|then\|else\|loop\)\>" matchgroup=NITControl end="\<end\>" oneline
+syn region NITAnnotBlock matchgroup=NITControl start="\<is\>\ze\s*\(#\|$\)" matchgroup=NITControl end="\(\ze\<do\>\|\<end\>\)" transparent contains=ALL
+syn match NITAnnotLine "^\s*\zs\w\+" contained containedin=NITAnnotBlock
 
+syn region NITStmtBlock matchgroup=NITControl start="\<\(do\|then\|else\|loop\)\>\ze\s*\(#\|$\)" matchgroup=NITControl end="^\s*\<\(end\|\zeelse\|\ze!\)\>" contains=ALLBUT,NITTypeDecl,NITAttrDecl,NITInitDecl,NITAnnotLine
+syn region NITStmtBlock matchgroup=NITControl start="\<\(do\|then\|else\|loop\)\>" matchgroup=NITControl end="\<end\>" oneline
 if !exists("NIT_minlines")
        let NIT_minlines = 50
 endif
@@ -83,7 +85,7 @@ syn match  NITSharpBang       "\%^#!.*"
 syn match  NITComment  "#.*" contains=NITTodo
 
 " Keywords
-syn keyword NITKeyword  is abstract intern new
+syn keyword NITKeyword  abstract intern new
 syn keyword NITDefine   private public protected intrude readable writable redef
 syn keyword NITControl   if while for assert and or in as isa once break continue return abort
 syn keyword NITClass     nullable
@@ -100,6 +102,7 @@ hi def link NITTypeDecl                     Function
 hi def link NITAttrDecl                        Function
 hi def link NITInitDecl                        Function
 hi def link NITControl                 Statement
+hi def link NITAnnotLine               Statement
 hi def link NITLabel                   PreProc
 hi def link NITInclude                 Include
 hi def link NITNumber                  Number
index 1d9ddcf..4659036 100644 (file)
@@ -374,14 +374,14 @@ article .info .code {
 }\r
 \r
 .content section.concerns li {\r
-    margin-top: 20px;\r
+    margin-top: 10px;\r
 }\r
 \r
 .content section.concerns ul ul {\r
     padding-left: 20px;\r
 }\r
 \r
-.content section.concerns li li {\r
+.content section.concerns ul ul li {\r
     margin-top: 0;\r
 }\r
 \r
index 44cd139..efdfc3a 100644 (file)
@@ -1550,6 +1550,7 @@ redef class MMethodDef
        # Can the body be inlined?
        fun can_inline(v: VISITOR): Bool
        do
+               if is_abstract then return true
                var modelbuilder = v.compiler.modelbuilder
                if modelbuilder.mpropdef2npropdef.has_key(self) then
                        var npropdef = modelbuilder.mpropdef2npropdef[self]
@@ -1622,13 +1623,16 @@ redef class APropdef
        fun can_inline: Bool do return true
 end
 
-redef class AConcreteMethPropdef
+redef class AMethPropdef
        redef fun compile_to_c(v, mpropdef, arguments)
        do
-               for i in [0..mpropdef.msignature.arity[ do
-                       var variable = self.n_signature.n_params[i].variable.as(not null)
-                       v.assign(v.variable(variable), arguments[i+1])
+               if mpropdef.is_abstract then
+                       var cn = v.class_name_string(arguments.first)
+                       v.add("fprintf(stderr, \"Runtime error: Abstract method `%s` called on `%s`\", \"{mpropdef.mproperty.name.escape_to_c}\", {cn});")
+                       v.add_raw_abort
+                       return
                end
+
                # Call the implicit super-init
                var auto_super_inits = self.auto_super_inits
                if auto_super_inits != null then
@@ -1641,7 +1645,23 @@ redef class AConcreteMethPropdef
                                v.compile_callsite(auto_super_init, args)
                        end
                end
-               v.stmt(self.n_block)
+
+               var n_block = n_block
+               if n_block != null then
+                       for i in [0..mpropdef.msignature.arity[ do
+                               var variable = self.n_signature.n_params[i].variable.as(not null)
+                               v.assign(v.variable(variable), arguments[i+1])
+                       end
+                       v.stmt(n_block)
+               else if mpropdef.is_intern then
+                       compile_intern_to_c(v, mpropdef, arguments)
+               else if mpropdef.is_extern then
+                       if mpropdef.mproperty.is_init then
+                               compile_externinit_to_c(v, mpropdef, arguments)
+                       else
+                               compile_externmeth_to_c(v, mpropdef, arguments)
+                       end
+               end
        end
 
        redef fun can_inline
@@ -1653,10 +1673,8 @@ redef class AConcreteMethPropdef
                if nblock isa ABlockExpr and nblock.n_expr.length == 0 then return true
                return false
        end
-end
 
-redef class AInternMethPropdef
-       redef fun compile_to_c(v, mpropdef, arguments)
+       fun compile_intern_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable])
        do
                var pname = mpropdef.mproperty.name
                var cname = mpropdef.mclassdef.mclass.name
@@ -1889,10 +1907,8 @@ redef class AInternMethPropdef
                v.add("printf(\"NOT YET IMPLEMENTED {class_name}:{mpropdef} at {location.to_s}\\n\");")
                debug("Not implemented {mpropdef}")
        end
-end
 
-redef class AExternMethPropdef
-       redef fun compile_to_c(v, mpropdef, arguments)
+       fun compile_externmeth_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable])
        do
                var externname
                var nextern = self.n_extern
@@ -1921,10 +1937,8 @@ redef class AExternMethPropdef
                        v.ret(res)
                end
        end
-end
 
-redef class AExternInitPropdef
-       redef fun compile_to_c(v, mpropdef, arguments)
+       fun compile_externinit_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable])
        do
                var externname
                var nextern = self.n_extern
@@ -1999,11 +2013,11 @@ redef class AClassdef
                if mpropdef == self.mfree_init then
                        var super_inits = self.super_inits
                        if super_inits != null then
-                               assert arguments.length == 1
+                               var args_of_super = arguments
+                               if arguments.length > 1 then args_of_super = [arguments.first]
                                for su in super_inits do
-                                       v.send(su, arguments)
+                                       v.send(su, args_of_super)
                                end
-                               return
                        end
                        var recv = arguments.first
                        var i = 1
@@ -2020,15 +2034,6 @@ redef class AClassdef
        end
 end
 
-redef class ADeferredMethPropdef
-       redef fun compile_to_c(v, mpropdef, arguments) do
-               var cn = v.class_name_string(arguments.first)
-               v.add("fprintf(stderr, \"Runtime error: Abstract method `%s` called on `%s`\", \"{mpropdef.mproperty.name.escape_to_c}\", {cn});")
-               v.add_raw_abort
-       end
-       redef fun can_inline do return true
-end
-
 redef class AExpr
        # Try to compile self as an expression
        # Do not call this method directly, use `v.expr` instead
@@ -2560,7 +2565,7 @@ redef class ASuperExpr
                if callsite != null then
                        # Add additionnals arguments for the super init call
                        if args.length == 1 then
-                               for i in [0..callsite.mproperty.intro.msignature.arity[ do
+                               for i in [0..callsite.msignature.arity[ do
                                        args.add(v.frame.arguments[i+1])
                                end
                        end
index 60acc94..4052d20 100644 (file)
@@ -65,7 +65,7 @@ end
 class AndroidToolchain
        super MakefileToolchain
 
-       var android_project_root: String
+       var android_project_root: nullable String = null
 
        redef fun compile_dir
        do
@@ -76,6 +76,7 @@ class AndroidToolchain
 
        redef fun write_files(compiler, compile_dir, cfiles)
        do
+               var android_project_root = android_project_root.as(not null)
                var project = toolcontext.modelbuilder.android_project_for(compiler.mainmodule)
                var short_project_name = compiler.mainmodule.name
 
@@ -240,6 +241,7 @@ $(call import-module,android/native_app_glue)
 
        redef fun compile_c_code(compiler, compile_dir)
        do
+               var android_project_root = android_project_root.as(not null)
                # Compile C code (and thus Nit)
                toolcontext.exec_and_check(["ndk-build", "-s", "-j", "4", "-C", android_project_root])
 
index 8e210cc..c13fb36 100644 (file)
@@ -28,7 +28,7 @@ end
 
 private class AutoSuperInitPhase
        super Phase
-       redef fun process_npropdef(npropdef) do if npropdef isa AConcreteMethPropdef then npropdef.do_auto_super_init(toolcontext.modelbuilder)
+       redef fun process_npropdef(npropdef) do if npropdef isa AMethPropdef then npropdef.do_auto_super_init(toolcontext.modelbuilder)
 end
 
 private class AutoSuperInitVisitor
@@ -47,7 +47,7 @@ private class AutoSuperInitVisitor
 end
 
 
-redef class AConcreteMethPropdef
+redef class AMethPropdef
        # In case of constructor, the list of implicit auto super init constructors invoked (if needed)
        var auto_super_inits: nullable Array[CallSite] = null
 
index 0567a27..d7153e5 100644 (file)
@@ -46,7 +46,7 @@ private class CachedPhase
                # Do some validity checks and print errors if the annotation is used incorrectly
                var modelbuilder = toolcontext.modelbuilder
 
-               if not npropdef isa AConcreteMethPropdef then
+               if not npropdef isa AMethPropdef then
                        modelbuilder.error(npropdef, "Syntax error: only a function can be cached.")
                        return
                end
@@ -87,7 +87,7 @@ private class CachedPhase
                var real_mpropdef = new MMethodDef(mclassdef, new MMethod(mclassdef, "{name}<real>", private_visibility), location)
                real_mpropdef.msignature = mpropdef.msignature
                # FIXME: Again, if the engine require a real propdef even if it is empty
-               var real_npropdef = toolcontext.parse_propdef("fun real do end").as(AConcreteMethPropdef)
+               var real_npropdef = toolcontext.parse_propdef("fun real do end").as(AMethPropdef)
                associate_propdef(real_mpropdef, real_npropdef)
                # Note: the body is set at the last line of this function
 
diff --git a/src/coloring.nit b/src/coloring.nit
new file mode 100644 (file)
index 0000000..0b4532d
--- /dev/null
@@ -0,0 +1,392 @@
+# 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.
+
+module coloring
+
+import poset
+
+# Build a conflict graph from a POSet
+class POSetConflictGraph[E: Object]
+
+       # Core is composed by:
+       #  * elements that have mutiple direct parents
+       #  * parents of elements that have multiple direct parents
+       # REQUIRE: is_colored
+       var core = new HashSet[E]
+
+       # Border is composed by minimal elements of the core:
+       #  * that have multiple direct parents
+       #  * but whose subelements are all in single inheritance
+       # REQUIRE: is_colored
+       var border = new HashSet[E]
+
+       # The crown is composed by the elements that are:
+       #  * not part of the core nor the border
+       #  * are in single inheritance
+       # REQUIRE: is_colored
+       var crown = new HashSet[E]
+
+       # Conflict graph of the POSet
+       # Elements X and Y are in conflict if either:
+       #  * X and Y are the same element
+       #  * Y is a subelement of X
+       #  * X and Y have common sub elements
+       # REQUIRE: is_colored
+       var conflicts = new HashMap[E, Set[E]]
+
+       var poset: POSet[E]
+
+       init(poset: POSet[E]) do
+               self.poset = poset
+               extract_core
+               extract_border
+               extract_crown
+               compute_conflicts
+       end
+
+       # Compute the set of elements forming the core of the poset hierarchy.
+       private fun extract_core do
+               core.clear
+               for e in poset do
+                       if poset[e].direct_greaters.length > 1 then
+                               core.add_all(poset[e].greaters)
+                       end
+               end
+       end
+
+       # Compute the set of elements composing the border of the core
+       # Elements belonging to the `border` are removed from the `core`
+       private fun extract_border do
+               border.clear
+               for e in core do
+                       if not is_border(e) then continue
+                       border.add(e)
+               end
+               for e in border do core.remove(e)
+       end
+
+       private fun is_border(e: E): Bool do
+               for child in poset[e].direct_smallers do
+                       if core.has(child) then return false
+               end
+               return true
+       end
+
+       # Compute the set of elements belonging to the crown of the inheritance hierarchy.
+       private fun extract_crown do
+               crown.clear
+               for e in poset do
+                       if not core.has(e) and not border.has(e) then crown.add(e)
+               end
+       end
+
+       # Check for conflict in the core.
+       # Start from border and tag every ancestors
+       private fun compute_conflicts do
+               conflicts.clear
+               for e in border do add_conflicts(poset[e].greaters)
+       end
+
+       private fun add_conflict(e, o: E) do
+               if not conflicts.has_key(e) then conflicts[e] = new HashSet[E]
+               if not conflicts.has_key(o) then conflicts[o] = new HashSet[E]
+               conflicts[e].add(o)
+               conflicts[o].add(e)
+       end
+
+       private fun add_conflicts(es: Collection[E]) do
+               for e1 in es do
+                       for e2 in es do add_conflict(e1, e2)
+               end
+       end
+
+       # Used for debugging only
+       fun pretty_print do
+               #print "core: {core.join(" ")} ({core.length})"
+               #print "border: {border.join(" ")} ({border.length})"
+               #print "crown: {crown.join(" ")} ({crown.length})"
+               print "conflicts:"
+               for e, c in conflicts do print "  {e}: {c.join(" ")}"
+       end
+end
+
+# Colorize elements from a POSet
+# Two elements from a POSet cannot have the same color if they share common subelements
+#
+# Example:
+#       A
+#     / | \
+#    /  |  \
+#   B   C   D
+#   |  /|   |
+#   | / |   |
+#   |/  |   |
+#   E   F   G
+#   |
+#   H
+# Conflicts:
+#   A: {B, C, D, E, F, G, H}
+#   B: {A, C, E, H}
+#   C: {A, E, H, F}
+#   D: {A, G}
+#   E: {A, B, C, H}
+#   F: {A, C}
+#   G: {A, D}
+#   H: {A, B, C, E}
+# Possible colors:
+#   A:0, B:1, C: 2, D: 1, E: 3, F:3, G:2, H:4
+#
+# see:
+#      Ducournau, R. (2011).
+#      Coloring, a versatile technique for implementing object-oriented languages.
+#      Software: Practice and Experience, 41(6), 627–659.
+class POSetColorer[E: Object]
+
+       # Is the poset already colored?
+       var is_colored = false
+
+       # Resulting ids
+       # REQUIRE: is_colored
+       fun ids: Map[E, Int] do
+               assert is_colored
+               return ids_cache
+       end
+       private var ids_cache = new HashMap[E, Int]
+
+       # Resulting colors
+       # REQUIRE: is_colored
+       fun colors: Map[E, Int] do
+               assert is_colored
+               return colors_cache
+       end
+       private var colors_cache = new HashMap[E, Int]
+
+       # REQUIRE: is_colored
+       fun poset: POSet[E] do
+               assert is_colored
+               return poset_cache
+       end
+       private var poset_cache: POSet[E]
+
+       # REQUIRE: is_colored
+       fun conflicts: Map[E, Set[E]] do
+               assert is_colored
+               return conflicts_cache
+       end
+       private var conflicts_cache: Map[E, Set[E]]
+
+       private var graph: POSetConflictGraph[E]
+
+       init do end
+
+       # Start coloring on given POSet
+       fun colorize(poset: POSet[E]) do
+               poset_cache = poset
+               graph = new POSetConflictGraph[E](poset)
+               allocate_ids
+               compute_colors
+               conflicts_cache = graph.conflicts
+               is_colored = true
+       end
+
+       private fun allocate_ids do
+               ids_cache.clear
+               var elements = new HashSet[E].from(poset_cache.to_a)
+               for e in poset_cache.linearize(elements) do
+                       ids_cache[e] = ids_cache.length
+               end
+       end
+
+       # Colorize core, border and crown in that order
+       private fun compute_colors do
+               colors_cache.clear
+               colorize_core
+               colorize_set(graph.border)
+               colorize_set(graph.crown)
+       end
+
+       # Core elements cannot have the same color than:
+       #  * one of their parents
+       #  * one of their conflicting elements
+       private fun colorize_core do
+               for e in poset_cache.linearize(graph.core) do
+                       var color = min_color(e)
+                       var conflicts = graph.conflicts[e]
+                       while not is_color_free(color, conflicts) do
+                               color += 1
+                       end
+                       colors_cache[e] = color
+               end
+       end
+
+       # Other elements inherit color fron their direct parents
+       private fun colorize_set(set: Set[E]) do
+               for e in poset_cache.linearize(set) do colors_cache[e] = min_color(e)
+       end
+
+       # Get the next minimal color from direct parents
+       private fun min_color(e: E): Int do
+               var max_color = -1
+               for p in poset_cache[e].direct_greaters do
+                       if not colors_cache.has_key(p) then continue
+                       var color = colors_cache[p]
+                       if color > max_color then max_color = color
+               end
+               return max_color + 1
+       end
+
+       private fun is_color_free(color: Int, set: Collection[E]): Bool do
+               for e in set do
+                       if colors_cache.has_key(e) and colors_cache[e] == color then return false
+               end
+               return true
+       end
+
+       # Used for debugging only
+       fun pretty_print do
+               print "ids:"
+               for e, id in ids do print "  {e}: {id}"
+               print "colors:"
+               for e, c in colors do print "  {e}: {c}"
+       end
+end
+
+# Colorize a collection of buckets
+# Two elements cannot have the same color if they both appear in the same bucket
+# No coloring order is garantied
+#
+# Example:
+#      buckets[A] = {x1, x2}
+#   buckets[B] = {x1, x3, x4}
+#      buckets[C] = {x2, x3}
+# Conflicts:
+#      x1: {x2, x3, x4}
+#   x2: {x1, x3}
+#   x3: {x1, x2, x4}
+#   x4: {x1, x3}
+# Possible colors:
+#      x1: 0, x2: 1, x3: 2, x4: 1
+class BucketsColorer[H: Object, E: Object]
+       private var colors = new HashMap[E, Int]
+       private var conflicts = new HashMap[E, Set[E]]
+
+       init do end
+
+       # Start bucket coloring
+       fun colorize(buckets: Map[H, Set[E]]): Map[E, Int] do
+               compute_conflicts(buckets)
+               var min_color = 0
+               for holder, hbuckets in buckets do
+                       for bucket in hbuckets do
+                               if colors.has_key(bucket) then continue
+                               var color = min_color
+                               while not is_color_free(bucket, color) do
+                                       color += 1
+                               end
+                               colors[bucket] = color
+                               color = min_color
+                       end
+               end
+               return colors
+       end
+
+       private fun is_color_free(bucket: E, color: Int): Bool do
+               if conflicts.has_key(bucket) then
+                       for other in conflicts[bucket] do
+                               if colors.has_key(other) and colors[other] == color then return false
+                       end
+               end
+               return true
+       end
+
+       private fun compute_conflicts(buckets: Map[H, Set[E]]) do
+               conflicts.clear
+               for holder, hbuckets in buckets do
+                       for bucket in hbuckets do
+                               if not conflicts.has_key(bucket) then conflicts[bucket] = new HashSet[E]
+                               for obucket in hbuckets do
+                                       if obucket == bucket then continue
+                                       if not conflicts.has_key(obucket) then conflicts[obucket] = new HashSet[E]
+                                       conflicts[bucket].add(obucket)
+                                       conflicts[obucket].add(bucket)
+                               end
+                       end
+               end
+       end
+end
+
+# Colorize a collection of buckets using a poset and a conflict graph
+# Two elements cannot have the same color if they both appear in the same bucket
+# The use of a POSet hierarchy optimize the coloring
+# Buckets elements are colored using linearization order starting
+class POSetBucketsColorer[H: Object, E: Object]
+       private var colors = new HashMap[E, Int]
+       private var poset: POSet[H]
+       private var conflicts: Map[H, Set[H]]
+
+       init(poset: POSet[H], conflicts: Map[H, Set[H]]) do
+               self.poset = poset
+               self.conflicts = conflicts
+       end
+
+       # Colorize buckets using the POSet and conflict graph
+       fun colorize(buckets: Map[H, Set[E]]): Map[E, Int] do
+               colors.clear
+               for h in poset.linearize(buckets.keys) do
+                       var color = min_color(poset[h].direct_greaters, buckets)
+                       for bucket in buckets[h] do
+                               if colors.has_key(bucket) then continue
+                               while not is_color_free(color, h, buckets) do color += 1
+                               colors[bucket] = color
+                               color += 1
+                       end
+               end
+               return colors
+       end
+
+       # Get the next available color considering used colors by other buckets
+       private fun min_color(others: Collection[H], buckets: Map[H, Set[E]]): Int do
+               var min = -1
+               for holder in others do
+                       var color = max_color(holder, buckets)
+                       if color > min then min = color
+               end
+               return min + 1
+       end
+
+       # Return the max color used by a class
+       private fun max_color(holder: H, buckets: Map[H, Set[E]]): Int do
+               var max = -1
+               for bucket in buckets[holder] do
+                       if not colors.has_key(bucket) then continue
+                       var color = colors[bucket]
+                       if color > max then max = color
+               end
+               return max
+       end
+
+       # Check if the color is free for this holder
+       private fun is_color_free(color: Int, holder: H, buckets: Map[H, Set[E]]): Bool do
+               if not conflicts.has_key(holder) then return true
+               for conflict in conflicts[holder] do
+                       for bucket in buckets[conflict] do
+                               if not colors.has_key(bucket) then continue
+                               if colors[bucket] == color then return false
+                       end
+               end
+               return true
+       end
+end
+
+
index 249555c..65b1a22 100644 (file)
@@ -135,9 +135,9 @@ end
 class ExternCFunction
        super CFunction
 
-       var method: AExternPropdef
+       var method: AMethPropdef
 
-       init (method: AExternPropdef, mmodule: MModule)
+       init (method: AMethPropdef, mmodule: MModule)
        do
                self.method = method
 
index 2a9e7d4..5b2c0d7 100644 (file)
@@ -101,7 +101,7 @@ redef class AModule
        end
 end
 
-redef class AExternPropdef
+redef class AMethPropdef
        private var ffi_has_been_compiled = false
 
        # Compile the necessary wrapper around this extern method or constructor
index c51ea66..3b53826 100644 (file)
@@ -41,7 +41,7 @@ class FFILanguageAssignationPhase
 
        redef fun process_npropdef(npropdef)
        do
-               if npropdef isa AExternPropdef then
+               if npropdef isa AMethPropdef then
                        var code_block = npropdef.n_extern_code_block
                        if code_block != null then
                                verify_foreign_code_on_node( code_block )
@@ -111,8 +111,8 @@ class FFILanguage
        fun compile_module_block(block: AExternCodeBlock, ecc: CCompilationUnit, mmodule: MModule) is abstract
 
        # Generate wrapper code for this extern method
-       fun compile_extern_method(block: AExternCodeBlock, m: AExternPropdef,
-               ecc: CCompilationUnit, mmodule: MModule) is abstract
+       fun compile_extern_method(block: AExternCodeBlock, m: AMethPropdef,
+               ecc: CCompilationUnit, nmodule: MModule) is abstract
 
        # Generate wrapper code for this extern class
        fun compile_extern_class(block: AExternCodeBlock, m: AClassdef,
index 6172e47..5086beb 100644 (file)
@@ -168,7 +168,7 @@ class JavaLanguage
                mmodule.insert_compiler_options
 
                # Enable linking C callbacks to java native methods
-               mmodule.ensure_linking_callback_methods(ffi_ccu, mmodule.ffi_callbacks[self])
+               mmodule.ensure_linking_callback_methods(ffi_ccu.as(not null), mmodule.ffi_callbacks[self])
 
                # Java implementation code
                var java_file = mmodule.java_file
@@ -177,7 +177,7 @@ class JavaLanguage
                mmodule.ffi_files.add(extern_java_file)
        end
 
-       var ffi_ccu: CCompilationUnit # HACK
+       var ffi_ccu: nullable CCompilationUnit = null # HACK
 
        redef fun compile_callback(callback, mmodule, mainmodule, ccu)
        do
index 8331cd7..2ebf76d 100644 (file)
@@ -80,7 +80,7 @@ redef class MModule
        end
 end
 
-redef class AExternPropdef
+redef class AMethPropdef
        private fun compile_ffi_support_to_c(v: AbstractCompilerVisitor)
        do
                var mmodule = mpropdef.mclassdef.mmodule
@@ -97,6 +97,8 @@ redef class AExternPropdef
                amodule.ensure_compile_ffi_wrapper
                compile_ffi_method(mmodule)
 
+               assert self isa AExternPropdef
+
                # nitni - Compile missing callbacks
                mmodule.ensure_compile_nitni_base(v)
                var ccu = mmodule.nitni_ccu.as(not null)
@@ -126,10 +128,8 @@ redef class AExternPropdef
                # manage nitni callback set
                mmodule.foreign_callbacks.join(foreign_callbacks)
        end
-end
 
-redef class AExternMethPropdef
-       redef fun compile_to_c(v, mpropdef, arguments)
+       redef fun compile_externmeth_to_c(v, mpropdef, arguments)
        do
                var mmodule = mpropdef.mclassdef.mmodule
 
@@ -191,10 +191,8 @@ redef class AExternMethPropdef
 
                compile_ffi_support_to_c(v)
        end
-end
 
-redef class AExternInitPropdef
-       redef fun compile_to_c(v, mpropdef, arguments)
+       redef fun compile_externinit_to_c(v, mpropdef, arguments)
        do
                var mmodule = mpropdef.mclassdef.mmodule
 
index cd77425..c1ca4fb 100644 (file)
@@ -339,7 +339,7 @@ class Debugger
                if self.modelbuilder.mpropdef2npropdef.has_key(mpropdef) then
                        var npropdef = self.modelbuilder.mpropdef2npropdef[mpropdef]
                        self.parameter_check(npropdef, mpropdef, args)
-                       if npropdef isa AConcreteMethPropdef then
+                       if npropdef isa AMethPropdef then
                                return npropdef.rt_call(self, mpropdef, args)
                        else
                                print "Error, invalid propdef to call at runtime !"
@@ -1425,7 +1425,7 @@ class Debugger
 
 end
 
-redef class AConcreteMethPropdef
+redef class AMethPropdef
 
        # Same as call except it will copy local variables of the parent frame to the frame defined in this call.
        # Not supposed to be used by anyone else than the Debugger.
index 3424bef..5084b01 100644 (file)
@@ -29,6 +29,7 @@ class TplNitdocPage
        var content: Streamable writable
        var footer: nullable TplFooter writable
        var scripts = new Array[TplScript] # js scripts appended to body
+       init do end
 
        redef fun rendering do
                add "<!DOCTYPE html>"
@@ -226,6 +227,7 @@ class TplOverviewPage
        var text: nullable Streamable writable
        var graph: nullable TplGraph writable
        var modules = new Array[Streamable]
+       init do end
 
        redef fun rendering do
                add "<div class='content fullpage'>"
@@ -257,6 +259,7 @@ class TplSearchPage
        var modules = new Array[Streamable]
        var classes = new Array[Streamable]
        var props = new Array[Streamable]
+       init do end
 
        redef fun rendering do
                add "<div class='content fullpage'>"
@@ -311,6 +314,7 @@ class TplModulePage
        var graph: nullable TplGraph writable
        var intros = new Array[TplArticle]
        var redefs = new Array[TplArticle]
+       init do end
 
        redef fun rendering do
                add "<div class='content'>"
@@ -355,6 +359,8 @@ class TplClassPage
        var inits = new Array[TplArticle]
        var methods = new Array[Streamable]
 
+       init do end
+
        redef fun rendering do
                add "<div class='content'>"
                if title != null then
@@ -505,6 +511,8 @@ class TplArticle
        var subtitle: Template writable
        var content: nullable Template writable
 
+       init do end
+
        redef fun rendering do
                add "<article class='{classes.join(" ")}' id='{id}'>"
                add "<h3 class='signature'>"
@@ -533,6 +541,8 @@ class TplDefinition
        var location: nullable Streamable writable
        var github_area: nullable TplGithubArea writable
 
+       init do end
+
        redef fun rendering do
                add "<div class='description'>"
                if github_area != null then
@@ -616,6 +626,8 @@ class TplLink
        var text: String writable
        var title: nullable String writable
 
+       init do end
+
        redef fun rendering do
                add "<a href=\""
                add href
@@ -643,6 +655,7 @@ class TplConcernList
        var elts = new Array[TplConcernElt]
 
        redef fun rendering do
+               if elts.is_empty then return
                add "<ul>"
                for elt in elts do
                        add elt
@@ -659,6 +672,8 @@ class TplConcernListElt
        var name: String writable
        var comment: nullable String writable
 
+       init do end
+
        redef fun rendering do
                add "<li>"
                add "<a href=\"{anchor}\">{name}</a>"
@@ -676,6 +691,8 @@ class TplTopConcern
        var anchor: String writable
        var concern: TplLink writable
 
+       init do end
+
        redef fun rendering do
                add "<a id=\"{anchor}\"></a>"
                add "<h3 class=\"concern-toplevel\">Methods refined in "
@@ -692,6 +709,8 @@ class TplConcern
        var concern: TplLink writable
        var comment: nullable String writable
 
+       init do end
+
        redef fun rendering do
                add "<a id=\"{anchor}\"></a>"
                add "<p class=\"concern-doc\">"
diff --git a/src/layout_builders.nit b/src/layout_builders.nit
deleted file mode 100644 (file)
index f7dc388..0000000
+++ /dev/null
@@ -1,751 +0,0 @@
-# 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.
-
-# Table layout builders
-# Tables are used to implement objects mecanisms like:
-#  * message sending
-#  * attribute accessing
-#  * typing
-#  * resolution (for generic types)
-# This module provides various layout for object tables:
-#  * coloring
-#  * binary matrix
-#  * perfect hashing (and & mod operators)
-module layout_builders
-
-import abstract_compiler
-
-# Layouts
-
-# A layout is the result of computation by builders
-# it contains necessary informations for basic table creation
-class Layout[E: Object]
-       # Ids or each element
-       var ids: Map[E, Int] = new HashMap[E, Int]
-       # Fixed positions of each element in all tables
-       var pos: Map[E, Int] = new HashMap[E, Int]
-end
-
-# A PHLayout is used everywere the builder used perfect hashing
-# it adds masks and hashes informations to std layout
-class PHLayout[HOLDER: Object, E: Object]
-       super Layout[E]
-       # Masks used by hash function
-       var masks: Map[HOLDER, Int] = new HashMap[HOLDER, Int]
-       # Positions of each element for each tables
-       var hashes: Map[HOLDER, Map[E, Int]] = new HashMap[HOLDER, Map[E, Int]]
-end
-
-# Builders
-
-# TypingLayoutBuilder is used to build a layout for typing tables (by type or by class)
-interface TypingLayoutBuilder[E: Object]
-       # Build typing table layout
-       # elements: the set of elements (classes or types) used in typing tables
-       fun build_layout(elements: Set[E]): Layout[E] is abstract
-       # Get the poset used for table layout construction
-       # REQUIRE: build_layout
-       fun poset: nullable POSet[E] is abstract
-end
-
-# Layout builder dedicated to vft, attribute & VT tables
-interface PropertyLayoutBuilder[E: PropertyLayoutElement]
-       # Build table layout for attributes, methods and virtual types
-       # elements: the associative map between classes and properties to use in table layout
-       fun build_layout(elements: Map[MClass, Set[E]]): Layout[E] is abstract
-end
-
-# Used to create a common ancestors to MProperty and MPropDef
-# Required for polymorphic calls
-# FIXME: there should be a better way
-interface PropertyLayoutElement end
-
-redef class MProperty
-       super PropertyLayoutElement
-end
-
-redef class MPropDef
-       super PropertyLayoutElement
-end
-
-# For resolution tables (generics)
-interface ResolutionLayoutBuilder
-       # Build resolution table layout
-       # elements: association between classes and resolved types
-       fun build_layout(elements: Map[MClassType, Set[MType]]): Layout[MType] is abstract
-end
-
-# POSet builders
-
-# A POSet builder build a poset for a set of MType or MClass
-# the resulting poset is used by the layout builders
-private abstract class POSetBuilder[E: Object]
-       private var mmodule: MModule
-       init(mmodule: MModule) do self.mmodule = mmodule
-       # Build the poset from `elements`
-       private fun build_poset(elements: Set[E]): POSet[E] is abstract
-end
-
-# A TypingLayoutBuilder used for MType based typing
-# such as in separate compilers
-private class MTypePOSetBuilder
-       super POSetBuilder[MType]
-       redef fun build_poset(elements) do
-               var poset = new POSet[MType]
-               for e in elements do
-                       poset.add_node(e)
-                       for o in elements do
-                               if e == o then continue
-                               if e.is_subtype(mmodule, null, o) then
-                                       poset.add_edge(e, o)
-                               end
-                       end
-               end
-               return poset
-       end
-end
-
-# A TypingLayoutBuilder used for MClass based typing
-# such as in erased compilers or used in property coloring
-private class MClassPOSetBuilder
-       super POSetBuilder[MClass]
-       redef fun build_poset(elements) do return mmodule.flatten_mclass_hierarchy
-end
-
-# Matrice computers
-
-# Abstract layout builder for resolution tables using Binary Matrix (BM)
-abstract class TypingBMizer[E: Object]
-       super TypingLayoutBuilder[E]
-
-       private var mmodule: MModule
-       private var poset_builder: POSetBuilder[E]
-       private var poset_cache: nullable POSet[E]
-
-       private init(mmodule: MModule, poset_builder: POSetBuilder[E]) do
-               self.mmodule = mmodule
-               self.poset_builder = poset_builder
-       end
-
-       redef fun poset do return poset_cache
-
-       # Compute mtypes ids and position using BM
-       redef fun build_layout(elements: Set[E]): Layout[E] do
-               var result = new Layout[E]
-               var ids = new HashMap[E, Int]
-               poset_cache = poset_builder.build_poset(elements)
-               var lin = poset.to_a
-               poset.sort(lin)
-               for element in lin do
-                       ids[element] = ids.length
-               end
-               result.ids = ids
-               result.pos = ids
-               return result
-       end
-end
-
-# Layout builder for typing tables based on classes using Binary Matrix (BM)
-class MTypeBMizer
-       super TypingBMizer[MType]
-       init(mmodule: MModule) do super(mmodule, new MTypePOSetBuilder(mmodule))
-end
-
-# Layout builder for typing tables based on types using Binary Matrix (BM)
-class MClassBMizer
-       super TypingBMizer[MClass]
-       init(mmodule: MModule) do super(mmodule, new MClassPOSetBuilder(mmodule))
-end
-
-# Layout builder for resolution tables using Binary Matrix (BM)
-class ResolutionBMizer
-       super ResolutionLayoutBuilder
-
-       init do end
-
-       redef fun build_layout(elements) do
-               var result = new Layout[MType]
-               var ids = new HashMap[MType, Int]
-               var color = 0
-               for mclasstype, mclasstypes in elements do
-                       for element in mclasstypes do
-                               if ids.has_key(element) then continue
-                               ids[element] = color
-                               color += 1
-                       end
-               end
-               result.ids = ids
-               result.pos = ids
-               return result
-       end
-end
-
-# Abstract Layout builder for mproperties using Binary Matrix (BM)
-class MPropertyBMizer[E: PropertyLayoutElement]
-       super PropertyLayoutBuilder[E]
-
-       var mmodule: MModule
-
-       init(mmodule: MModule) do self.mmodule = mmodule
-
-       redef fun build_layout(elements) do
-               var result = new Layout[E]
-               var ids = new HashMap[E, Int]
-               var lin = new Array[MClass]
-               lin.add_all(elements.keys)
-               self.mmodule.linearize_mclasses(lin)
-               for mclass in lin do
-                       for mproperty in elements[mclass] do
-                               if ids.has_key(mproperty) then continue
-                               ids[mproperty] = ids.length
-                       end
-               end
-               result.pos = ids
-               return result
-       end
-end
-
-# Colorers
-
-# Abstract Layout builder for typing table using coloration (CL)
-abstract class TypingColorer[E: Object]
-       super TypingLayoutBuilder[E]
-
-       private var core: Set[E] = new HashSet[E]
-       private var crown: Set[E] = new HashSet[E]
-       private var border: Set[E] = new HashSet[E]
-       private var coloration_result: Map[E, Int] = new HashMap[E, Int]
-
-       private var mmodule: MModule
-       private var poset_builder: POSetBuilder[E]
-       private var poset_cache: nullable POSet[E]
-
-       private init(mmodule: MModule, poset_builder: POSetBuilder[E]) do
-               self.mmodule = mmodule
-               self.poset_builder = poset_builder
-       end
-
-       redef fun poset do return poset_cache
-
-       # Compute the layout with coloring
-       redef fun build_layout(elements: Set[E]): Layout[E] do
-               poset_cache = poset_builder.build_poset(elements)
-               var result = new Layout[E]
-               result.ids = compute_ids(elements)
-               result.pos = colorize(elements)
-               return result
-       end
-
-       private fun compute_ids(elements: Set[E]): Map[E, Int] do
-               var ids = new HashMap[E, Int]
-               for element in reverse_linearize(elements) do
-                       ids[element] = ids.length
-               end
-               return ids
-       end
-
-       private fun colorize(elements: Set[E]): Map[E, Int] do
-               tag_elements(elements)
-               build_conflicts_graph
-               colorize_elements(core)
-               colorize_elements(border)
-               colorize_elements(crown)
-               return coloration_result
-       end
-
-       # Colorize a collection of elements
-       private fun colorize_elements(elements: Set[E]) do
-               var min_color = 0
-
-               var lin = reverse_linearize(elements)
-               for element in lin do
-                       var color = min_color
-                       while not self.is_color_free(element, elements, color) do
-                               color += 1
-                       end
-                       coloration_result[element] = color
-                       color = min_color
-               end
-       end
-
-       # Check if a related element to the element already use the color
-       private fun is_color_free(element: E, elements: Set[E], color: Int): Bool do
-               if conflicts_graph.has_key(element) then
-                       for st in conflicts_graph[element] do
-                               if coloration_result.has_key(st) and coloration_result[st] == color then return false
-                       end
-               end
-               for st in self.poset[element].greaters do
-                       if st == element then continue
-                       if coloration_result.has_key(st) and coloration_result[st] == color then return false
-               end
-               return true
-       end
-
-       # Tag elements as core, crown or border
-       private fun tag_elements(elements: Set[E]) do
-               for element in elements do
-                       # Check if sub elements are all in single inheritance
-                       var all_subelements_si = true
-                       for subelem in self.poset[element].smallers do
-                               if self.poset[subelem].direct_greaters.length > 1 then
-                                       all_subelements_si = false
-                                       break
-                               end
-                       end
-
-                       # Tag as core, crown or border
-                       if self.poset[element].direct_greaters.length > 1 then
-                               core.add_all(self.poset[element].greaters)
-                               if all_subelements_si then
-                                       border.add(element)
-                               end
-                       else if not all_subelements_si then
-                               core.add_all(self.poset[element].greaters)
-                       else
-                               crown.add(element)
-                       end
-               end
-       end
-
-       # Conflicts graph of elements hierarchy (two types are in conflict if they have common subelements)
-       private fun build_conflicts_graph do
-               self.conflicts_graph = new HashMap[E, HashSet[E]]
-               var core = reverse_linearize(self.core)
-               for t in core do
-                       for i in self.linear_extension(t) do
-                               if t == i then continue
-
-                               var lin_i = self.linear_extension(i)
-
-                               for j in self.linear_extension(t) do
-                                       if i == j or j == t then continue
-                                       var lin_j = self.linear_extension(j)
-
-                                       var d_ij = lin_i - lin_j
-                                       var d_ji = lin_j - lin_i
-
-                                       for ed1 in d_ij do
-                                               if not conflicts_graph.has_key(ed1) then conflicts_graph[ed1] = new HashSet[E]
-                                               # add ed1 x ed2 to conflicts graph
-                                               for ed2 in d_ji do conflicts_graph[ed1].add(ed2)
-                                       end
-                                       for ed1 in d_ij do
-                                               if not conflicts_graph.has_key(ed1) then conflicts_graph[ed1] = new HashSet[E]
-                                               # add ed1 x ed2 to conflicts graph
-                                               for ed2 in d_ji do conflicts_graph[ed1].add(ed2)
-                                       end
-                               end
-                       end
-               end
-       end
-
-       private var conflicts_graph: nullable HashMap[E, Set[E]]
-
-       # cache for linear_extensions
-       private var linear_extensions_cache: Map[E, Array[E]] = new HashMap[E, Array[E]]
-
-       # Return a linear_extension of super_elements of the element
-       private fun linear_extension(element: E): Array[E] do
-               if not self.linear_extensions_cache.has_key(element) then
-                       var supers = new HashSet[E]
-                       supers.add_all(self.poset[element].greaters)
-                       self.linear_extensions_cache[element] = self.linearize(supers)
-               end
-               return self.linear_extensions_cache[element]
-       end
-
-       private fun reverse_linearize(elements: Set[E]): Array[E] do
-               var lin = new Array[E]
-               lin.add_all(elements)
-               poset.sort(lin)
-               return lin
-       end
-       private fun linearize(elements: Set[E]): Array[E] do return reverse_linearize(elements).reversed
-end
-
-# Layout builder for typing tables based on types using coloration (CL)
-class MTypeColorer
-       super TypingColorer[MType]
-       init(mmodule: MModule) do super(mmodule, new MTypePOSetBuilder(mmodule))
-end
-
-# Layout builder for typing tables based on classes using coloration (CL)
-class MClassColorer
-       super TypingColorer[MClass]
-       init(mmodule: MModule) do super(mmodule, new MClassPOSetBuilder(mmodule))
-end
-
-# Abstract Layout builder for properties tables using coloration (CL)
-class MPropertyColorer[E: PropertyLayoutElement]
-       super PropertyLayoutBuilder[E]
-
-       private var mmodule: MModule
-       private var class_colorer: MClassColorer
-       private var coloration_result: Map[E, Int] = new HashMap[E, Int]
-
-       init(mmodule: MModule, class_colorer: MClassColorer) do
-               self.mmodule = mmodule
-               self.class_colorer = class_colorer
-       end
-
-       # Compute mclasses ids and position using BM
-       redef fun build_layout(elements: Map[MClass, Set[E]]): Layout[E] do
-               var result = new Layout[E]
-               result.pos = self.colorize(elements)
-               return result
-       end
-
-       private fun colorize(elements: Map[MClass, Set[E]]): Map[E, Int] do
-               self.colorize_core(elements)
-               self.colorize_crown(elements)
-               return self.coloration_result
-       end
-
-       # Colorize properties of the core hierarchy
-       private fun colorize_core(elements: Map[MClass, Set[E]]) do
-               var min_color = 0
-               for mclass in self.class_colorer.core do
-                       var color = min_color
-                       # check last color used by parents
-                       color = max_color(color, mclass.in_hierarchy(mmodule).direct_greaters, elements)
-                       # check max color used in conflicts
-                       if self.class_colorer.conflicts_graph.has_key(mclass) then
-                               color = max_color(color, self.class_colorer.conflicts_graph[mclass], elements)
-                       end
-                       colorize_elements(elements[mclass], color)
-               end
-       end
-
-       # Colorize properties of the crown hierarchy
-       private fun colorize_crown(elements: Map[MClass, Set[E]]) do
-               for mclass in self.class_colorer.crown do
-                       var parents = new HashSet[MClass]
-                       if mmodule.flatten_mclass_hierarchy.has(mclass) then
-                               parents.add_all(mclass.in_hierarchy(mmodule).direct_greaters)
-                       end
-                       colorize_elements(elements[mclass], max_color(0, parents, elements))
-               end
-       end
-
-       # Colorize a collection of mproperties given a starting color
-       private fun colorize_elements(elements: Collection[E], start_color: Int) do
-               for element in elements do
-                       if self.coloration_result.has_key(element) then continue
-                       self.coloration_result[element] = start_color
-                       start_color += 1
-               end
-       end
-
-       private fun max_color(min_color: Int, mclasses: Collection[MClass], elements: Map[MClass, Set[E]]): Int do
-               var max_color = min_color
-
-               for mclass in mclasses do
-                       for mproperty in elements[mclass] do
-                               var color = min_color
-                               if self.coloration_result.has_key(mproperty) then
-                                       color = self.coloration_result[mproperty]
-                                       if color >= max_color then max_color = color + 1
-                               end
-                       end
-               end
-               return max_color
-       end
-end
-
-# Layout builder for resolution tables using coloration (CL)
-class ResolutionColorer
-       super ResolutionLayoutBuilder
-
-       private var coloration_result: Map[MType, Int] = new HashMap[MType, Int]
-
-       init do end
-
-       # Compute resolved types colors
-       redef fun build_layout(elements) do
-               self.build_conflicts_graph(elements)
-               var result = new Layout[MType]
-               result.ids = self.compute_ids(elements)
-               result.pos = self.colorize_elements(elements)
-               return result
-       end
-
-       private fun compute_ids(elements: Map[MClassType, Set[MType]]): Map[MType, Int] do
-               var ids = new HashMap[MType, Int]
-               var color = 0
-               for mclasstype, mclasstypes in elements do
-                       for element in mclasstypes do
-                               if ids.has_key(element) then continue
-                               ids[element] = color
-                               color += 1
-                       end
-               end
-               return ids
-       end
-
-       # Colorize a collection of elements
-       private fun colorize_elements(elements: Map[MClassType, Set[MType]]): Map[MType, Int] do
-               var min_color = 0
-               for mclasstype, mclasstypes in elements do
-                       for element in mclasstypes do
-                               if self.coloration_result.has_key(element) then continue
-                               var color = min_color
-                               while not self.is_color_free(element, color) do
-                                       color += 1
-                               end
-                               coloration_result[element] = color
-                               color = min_color
-                       end
-               end
-               return self.coloration_result
-       end
-
-       # Check if a related element to the element already use the color
-       private fun is_color_free(element: MType, color: Int): Bool do
-               if conflicts_graph.has_key(element) then
-                       for st in conflicts_graph[element] do
-                               if coloration_result.has_key(st) and coloration_result[st] == color then return false
-                       end
-               end
-               return true
-       end
-
-       # look for unanchored types generated by the same type
-       private fun build_conflicts_graph(elements: Map[MClassType, Set[MType]]) do
-               for mclasstype, mtypes in elements do
-                       for mtype in mtypes do
-                               for otype in mtypes do
-                                       if otype == mtype then continue
-                                       self.add_conflict(mtype, otype)
-                               end
-                       end
-               end
-       end
-
-       private var conflicts_graph: Map[MType, Set[MType]] = new HashMap[MType, Set[MType]]
-
-       private fun add_conflict(mtype: MType, otype: MType) do
-               if mtype == otype then return
-               if not self.conflicts_graph.has_key(mtype) then  self.conflicts_graph[mtype] = new HashSet[MType]
-               self.conflicts_graph[mtype].add(otype)
-               if not self.conflicts_graph.has_key(otype) then  self.conflicts_graph[otype] = new HashSet[MType]
-               self.conflicts_graph[otype].add(mtype)
-       end
-end
-
-# Perfect Hashing (PH)
-# T = type of holder
-# U = type of elements to hash
-private class PerfectHasher[T: Object, U: Object]
-
-       var operator: PHOperator
-
-       init do end
-
-       # Compute mask for each holders
-       fun compute_masks(conflicts: Map[T, Set[U]], ids: Map[U, Int]): Map[T, Int] do
-               var masks = new HashMap[T, Int]
-               for mclasstype, mtypes in conflicts do
-                       masks[mclasstype] = compute_mask(mtypes, ids)
-               end
-               return masks
-       end
-
-       private fun compute_mask(mtypes: Set[U], ids: Map[U, Int]): Int do
-               var mask = 0
-               loop
-                       var used = new List[Int]
-                       for mtype in mtypes do
-                               var res = operator.op(mask, ids[mtype])
-                               if used.has(res) then
-                                       break
-                               else
-                                       used.add(res)
-                               end
-                       end
-                       if used.length == mtypes.length then break
-                       mask += 1
-               end
-               return mask
-       end
-
-       # Compute hash for each element in each holder
-       fun compute_hashes(elements: Map[T, Set[U]], ids: Map[U, Int], masks: Map[T, Int]): Map[T, Map[U, Int]] do
-               var hashes = new HashMap[T, Map[U, Int]]
-               for mclasstype, mtypes in elements do
-                       var mask = masks[mclasstype]
-                       var inhashes = new HashMap[U, Int]
-                       for mtype in mtypes do
-                               inhashes[mtype] = operator.op(mask, ids[mtype])
-                       end
-                       hashes[mclasstype] = inhashes
-               end
-               return hashes
-       end
-end
-
-# Abstract operator used for perfect hashing
-abstract class PHOperator
-       # hash `id` using `mask`
-       fun op(mask: Int, id:Int): Int is abstract
-end
-
-# Hashing using modulo (MOD) operator
-# slower but compact
-class PHModOperator
-       super PHOperator
-       init do end
-       redef fun op(mask, id) do return mask % id
-end
-
-# Hashing using binary and (AND) operator
-# faster but sparse
-class PHAndOperator
-       super PHOperator
-       init do end
-       redef fun op(mask, id) do return mask.bin_and(id)
-end
-
-# Layout builder for typing tables using perfect hashing (PH)
-class TypingHasher[E: Object]
-       super PerfectHasher[E, E]
-       super TypingLayoutBuilder[E]
-
-       private var mmodule: MModule
-       private var poset_builder: POSetBuilder[E]
-       private var poset_cache: nullable POSet[E]
-
-       private init(mmodule: MModule, poset_builder: POSetBuilder[E], operator: PHOperator) do
-               self.operator = operator
-               self.mmodule = mmodule
-               self.poset_builder = poset_builder
-       end
-
-       redef fun build_layout(elements: Set[E]): PHLayout[E, E] do
-               poset_cache = poset_builder.build_poset(elements)
-               var result = new PHLayout[E, E]
-               var conflicts = self.build_conflicts(elements)
-               result.ids = self.compute_ids
-               result.masks = self.compute_masks(conflicts, result.ids)
-               result.hashes = self.compute_hashes(conflicts, result.ids, result.masks)
-               return result
-       end
-
-       # Ids start from 1 instead of 0
-       private fun compute_ids: Map[E, Int] do
-               var ids = new HashMap[E, Int]
-               var lin = poset.to_a
-               poset.sort(lin)
-               for e in lin do
-                       ids[e] = ids.length + 1
-               end
-               return ids
-       end
-
-       private fun build_conflicts(elements: Set[E]): Map[E, Set[E]] do
-               var conflicts = new HashMap[E, Set[E]]
-               for e in elements do
-                       var supers = new HashSet[E]
-                       supers.add_all(self.poset[e].greaters)
-                       supers.add(e)
-                       conflicts[e] = supers
-               end
-               return conflicts
-       end
-end
-
-# Layout builder for typing tables with types using perfect hashing (PH)
-class MTypeHasher
-       super TypingHasher[MType]
-       init(operator: PHOperator, mmodule: MModule) do super(mmodule, new MTypePOSetBuilder(mmodule), operator)
-end
-
-# Layout builder for typing tables with classes using perfect hashing (PH)
-class MClassHasher
-       super TypingHasher[MClass]
-       init(operator: PHOperator, mmodule: MModule) do super(mmodule, new MClassPOSetBuilder(mmodule), operator)
-end
-
-# Abstract layout builder for properties tables using perfect hashing (PH)
-class MPropertyHasher[E: PropertyLayoutElement]
-       super PerfectHasher[MClass, E]
-       super PropertyLayoutBuilder[E]
-
-       var mmodule: MModule
-
-       init(operator: PHOperator, mmodule: MModule) do
-               self.operator = operator
-               self.mmodule = mmodule
-       end
-
-       fun build_poset(mclasses: Set[MClass]): POSet[MClass] do
-               var poset = new POSet[MClass]
-               for e in mclasses do
-                       poset.add_node(e)
-                       for o in mclasses do
-                               if e == o or not mmodule.flatten_mclass_hierarchy.has(e) then continue
-                               if e.in_hierarchy(mmodule) < o then poset.add_edge(e, o)
-                       end
-               end
-               return poset
-       end
-
-       redef fun build_layout(elements) do
-               var result = new PHLayout[MClass, E]
-               var ids = new HashMap[E, Int]
-               var mclasses = new HashSet[MClass]
-               mclasses.add_all(elements.keys)
-               var poset = build_poset(mclasses)
-               var lin = poset.to_a
-               poset.sort(lin)
-               for mclass in lin.reversed do
-                       for mproperty in elements[mclass] do
-                               if ids.has_key(mproperty) then continue
-                               ids[mproperty] = ids.length + 1
-                       end
-               end
-               result.ids = ids
-               result.pos = ids
-               result.masks = self.compute_masks(elements, ids)
-               result.hashes = self.compute_hashes(elements, ids, result.masks)
-               return result
-       end
-end
-
-# Layout builder for resolution tables using perfect hashing (PH)
-class ResolutionHasher
-       super PerfectHasher[MClassType, MType]
-       super ResolutionLayoutBuilder
-
-       init(operator: PHOperator) do self.operator = operator
-
-       # Compute resolved types masks and hashes
-       redef fun build_layout(elements) do
-               var result = new PHLayout[MClassType, MType]
-               var ids = new HashMap[MType, Int]
-               var color = 1
-               for mclasstype, mclasstypes in elements do
-                       for element in mclasstypes do
-                               if ids.has_key(element) then continue
-                               ids[element] = color
-                               color += 1
-                       end
-               end
-               result.ids = ids
-               result.pos = ids
-               result.masks = self.compute_masks(elements, ids)
-               result.hashes = self.compute_hashes(elements, ids, result.masks)
-               return result
-       end
-end
index 47b0117..dbbec6d 100644 (file)
@@ -1472,6 +1472,15 @@ class MParameter
        # Is the parameter a vararg?
        var is_vararg: Bool
 
+       redef fun to_s
+       do
+               if is_vararg then
+                       return "{name}: {mtype}..."
+               else
+                       return "{name}: {mtype}"
+               end
+       end
+
        fun resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule, cleanup_virtual: Bool): MParameter
        do
                if not self.mtype.need_anchor then return self
@@ -1832,6 +1841,9 @@ class MMethodDef
 
        # Is the method definition intern?
        var is_intern writable = false
+
+       # Is the method definition extern?
+       var is_extern writable = false
 end
 
 # A local definition of an attribute
index b005ff4..56ff873 100644 (file)
@@ -105,41 +105,49 @@ redef class ModelBuilder
                                inhc = inhc2
                        end
                end
+
+               # Collect undefined attributes
+               var mparameters = new Array[MParameter]
+               var anode: nullable ANode = null
+               for npropdef in nclassdef.n_propdefs do
+                       if npropdef isa AAttrPropdef and npropdef.n_expr == null then
+                               if npropdef.mpropdef == null then return # Skip broken attribute
+                               var paramname = npropdef.mpropdef.mproperty.name.substring_from(1)
+                               var ret_type = npropdef.mpropdef.static_mtype
+                               if ret_type == null then return
+                               var mparameter = new MParameter(paramname, ret_type, false)
+                               mparameters.add(mparameter)
+                               if anode == null then anode = npropdef
+                       end
+               end
+               if anode == null then anode = nclassdef
+
                if combine.is_empty and inhc != null then
+                       if not mparameters.is_empty then
+                               self.error(anode,"Error: {mclassdef} cannot inherit constructors from {inhc} because there is attributes without initial values: {mparameters.join(", ")}")
+                               return
+                       end
+
                        # TODO: actively inherit the consturctor
                        self.toolcontext.info("{mclassdef} inherits all constructors from {inhc}", 3)
                        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
-                       nclassdef.super_inits = combine
-                       var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
-                       var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
-                       var mparameters = new Array[MParameter]
-                       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
-
-               # Collect undefined attributes
-               var mparameters = new Array[MParameter]
-               for npropdef in nclassdef.n_propdefs do
-                       if npropdef isa AAttrPropdef and npropdef.n_expr == null then
-                               if npropdef.mpropdef == null then return # Skip broken attribute
-                               var paramname = npropdef.mpropdef.mproperty.name.substring_from(1)
-                               var ret_type = npropdef.mpropdef.static_mtype
-                               if ret_type == null then return
-                               var mparameter = new MParameter(paramname, ret_type, false)
-                               mparameters.add(mparameter)
+                       if mparameters.is_empty and combine.length == 1 then
+                               # No need to create a local init, the inherited one is enough
+                               inhc = combine.first.intro_mclassdef.mclass
+                               mclassdef.mclass.inherit_init_from = inhc
+                               self.toolcontext.info("{mclassdef} inherits all constructors from {inhc}", 3)
+                               return
                        end
+                       nclassdef.super_inits = combine
                end
 
                var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
@@ -399,21 +407,23 @@ redef class AMethPropdef
 
        redef fun build_property(modelbuilder, nclassdef)
        do
-               var is_init = self isa AInitPropdef
+               var n_kwinit = n_kwinit
+               var n_kwnew = n_kwnew
+               var is_init = n_kwinit != null or n_kwnew != null
                var mclassdef = nclassdef.mclassdef.as(not null)
                var name: String
                var amethodid = self.n_methid
                var name_node: ANode
                if amethodid == null then
-                       if self isa AMainMethPropdef then
+                       if not is_init then
                                name = "main"
                                name_node = self
-                       else if self isa AConcreteInitPropdef then
+                       else if n_kwinit != null then
                                name = "init"
-                               name_node = self.n_kwinit
-                       else if self isa AExternInitPropdef then
+                               name_node = n_kwinit
+                       else if n_kwnew != null then
                                name = "init"
-                               name_node = self.n_kwnew
+                               name_node = n_kwnew
                        else
                                abort
                        end
@@ -436,7 +446,7 @@ redef class AMethPropdef
                        var mvisibility = new_property_visibility(modelbuilder, nclassdef, self.n_visibility)
                        mprop = new MMethod(mclassdef, name, mvisibility)
                        mprop.is_init = is_init
-                       mprop.is_new = self isa AExternInitPropdef
+                       mprop.is_new = n_kwnew != null
                        if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mprop) then return
                else
                        if n_kwredef == null then
@@ -555,6 +565,7 @@ redef class AMethPropdef
                mpropdef.msignature = msignature
                mpropdef.is_abstract = self isa ADeferredMethPropdef
                mpropdef.is_intern = self isa AInternMethPropdef
+               mpropdef.is_extern = self isa AExternPropdef
        end
 
        redef fun check_signature(modelbuilder, nclassdef)
index 3df0cce..e9d0a97 100644 (file)
@@ -591,23 +591,24 @@ redef class APropdef
        end
 end
 
-redef class AConcreteMethPropdef
+redef class AMethPropdef
+       super TablesCapable
 
        redef fun call(v, mpropdef, args)
        do
                var f = new Frame(self, self.mpropdef.as(not null), args)
-               call_commons(v, mpropdef, args, f)
+               var res = call_commons(v, mpropdef, args, f)
                v.frames.shift
                if v.returnmark == f then
                        v.returnmark = null
-                       var res = v.escapevalue
+                       res = v.escapevalue
                        v.escapevalue = null
                        return res
                end
-               return null
+               return res
        end
 
-       private fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame)
+       private fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
        do
                for i in [0..mpropdef.msignature.arity[ do
                        var variable = self.n_signature.n_params[i].variable
@@ -617,6 +618,11 @@ redef class AConcreteMethPropdef
 
                v.frames.unshift(f)
 
+               if mpropdef.is_abstract then
+                       v.fatal("Abstract method `{mpropdef.mproperty.name}` called on `{arguments.first.mtype}`")
+                       abort
+               end
+
                # Call the implicit super-init
                var auto_super_inits = self.auto_super_inits
                if auto_super_inits != null then
@@ -630,12 +636,15 @@ redef class AConcreteMethPropdef
                        end
                end
 
-               v.stmt(self.n_block)
+               if n_block != null then
+                       v.stmt(self.n_block)
+                       return null
+               else
+                       return intern_call(v, mpropdef, arguments)
+               end
        end
-end
 
-redef class AInternMethPropdef
-       redef fun call(v, mpropdef, args)
+       private fun intern_call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
        do
                var pname = mpropdef.mproperty.name
                var cname = mpropdef.mclassdef.mclass.name
@@ -673,6 +682,7 @@ redef class AInternMethPropdef
                else if pname == "sys" then
                        return v.mainobj
                else if cname == "Int" then
+                       var recvval = args[0].to_i
                        if pname == "unary -" then
                                return v.int_instance(-args[0].to_i)
                        else if pname == "+" then
@@ -703,6 +713,13 @@ redef class AInternMethPropdef
                                return v.int_instance(args[0].to_i.lshift(args[1].to_i))
                        else if pname == "rshift" then
                                return v.int_instance(args[0].to_i.rshift(args[1].to_i))
+                       else if pname == "rand" then
+                               var res = recvval.rand
+                               return v.int_instance(res)
+                       else if pname == "native_int_to_s" then
+                               return v.native_string_instance(recvval.to_s)
+                       else if pname == "strerror_ext" then
+                               return v.native_string_instance(recvval.strerror)
                        end
                else if cname == "Char" then
                        var recv = args[0].val.as(Char)
@@ -745,6 +762,36 @@ redef class AInternMethPropdef
                                return v.bool_instance(recv >= args[1].to_f)
                        else if pname == "to_i" then
                                return v.int_instance(recv.to_i)
+                       else if pname == "cos" then
+                               return v.float_instance(args[0].to_f.cos)
+                       else if pname == "sin" then
+                               return v.float_instance(args[0].to_f.sin)
+                       else if pname == "tan" then
+                               return v.float_instance(args[0].to_f.tan)
+                       else if pname == "acos" then
+                               return v.float_instance(args[0].to_f.acos)
+                       else if pname == "asin" then
+                               return v.float_instance(args[0].to_f.asin)
+                       else if pname == "atan" then
+                               return v.float_instance(args[0].to_f.atan)
+                       else if pname == "sqrt" then
+                               return v.float_instance(args[0].to_f.sqrt)
+                       else if pname == "exp" then
+                               return v.float_instance(args[0].to_f.exp)
+                       else if pname == "log" then
+                               return v.float_instance(args[0].to_f.log)
+                       else if pname == "pow" then
+                               return v.float_instance(args[0].to_f.pow(args[1].to_f))
+                       else if pname == "rand" then
+                               return v.float_instance(args[0].to_f.rand)
+                       else if pname == "abs" then
+                               return v.float_instance(args[0].to_f.abs)
+                       else if pname == "hypot_with" then
+                               return v.float_instance(args[0].to_f.hypot_with(args[1].to_f))
+                       else if pname == "is_nan" then
+                               return v.bool_instance(args[0].to_f.is_nan)
+                       else if pname == "is_inf_extern" then
+                               return v.bool_instance(args[0].to_f.is_inf != 0)
                        end
                else if cname == "NativeString" then
                        var recvval = args.first.val.as(Buffer)
@@ -783,6 +830,24 @@ redef class AInternMethPropdef
                                return null
                        else if pname == "atoi" then
                                return v.int_instance(recvval.to_i)
+                       else if pname == "file_exists" then
+                               return v.bool_instance(recvval.to_s.file_exists)
+                       else if pname == "file_mkdir" then
+                               recvval.to_s.mkdir
+                               return null
+                       else if pname == "file_chdir" then
+                               recvval.to_s.chdir
+                               return null
+                       else if pname == "file_realpath" then
+                               return v.native_string_instance(recvval.to_s.realpath)
+                       else if pname == "get_environ" then
+                               var txt = recvval.to_s.environ
+                               return v.native_string_instance(txt)
+                       else if pname == "system" then
+                               var res = sys.system(recvval.to_s)
+                               return v.int_instance(res)
+                       else if pname == "atof" then
+                               return v.float_instance(recvval.to_f)
                        end
                else if pname == "calloc_string" then
                        return v.native_string_instance("!" * args[1].to_i)
@@ -802,71 +867,20 @@ redef class AInternMethPropdef
                                recvval.copy(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
                                return null
                        end
-               else if pname == "calloc_array" then
-                       var recvtype = args.first.mtype.as(MClassType)
-                       var mtype: MType
-                       mtype = recvtype.supertype_to(v.mainmodule, recvtype, v.mainmodule.get_primitive_class("ArrayCapable"))
-                       mtype = mtype.arguments.first
-                       var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
-                       return new PrimitiveInstance[Array[Instance]](v.mainmodule.get_primitive_class("NativeArray").get_mtype([mtype]), val)
-               else if pname == "native_argc" then
-                       return v.int_instance(v.arguments.length)
-               else if pname == "native_argv" then
-                       var txt = v.arguments[args[1].to_i]
-                       return v.native_string_instance(txt)
-               end
-               fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
-               abort
-       end
-end
-
-redef class AbstractArray[E]
-       fun copy(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
-       do
-               self.copy_to(start, len, dest, new_start)
-       end
-end
-
-redef class AExternInitPropdef
-       redef fun call(v, mpropdef, args)
-       do
-               var pname = mpropdef.mproperty.name
-               var cname = mpropdef.mclassdef.mclass.name
-               if pname == "native_stdout" then
-                       return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, sys.stdout)
-               else if pname == "native_stdin" then
-                       return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, sys.stdin)
-               else if pname == "native_stderr" then
-                       return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, sys.stderr)
-               else if pname == "io_open_read" then
-                       var a1 = args[1].val.as(Buffer)
-                       return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, new IFStream.open(a1.to_s))
-               else if pname == "io_open_write" then
-                       var a1 = args[1].val.as(Buffer)
-                       return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, new OFStream.open(a1.to_s))
-               end
-               fatal(v, "NOT YET IMPLEMENTED extern init {mpropdef}")
-               abort
-       end
-end
-
-redef class AExternMethPropdef
-       super TablesCapable
-       redef fun call(v, mpropdef, args)
-       do
-               var pname = mpropdef.mproperty.name
-               var cname = mpropdef.mclassdef.mclass.name
-               if cname == "Int" then
-                       var recvval = args.first.val.as(Int)
-                       if pname == "rand" then
-                               var res = recvval.rand
-                               return v.int_instance(res)
-                       else if pname == "native_int_to_s" then
-                               return v.native_string_instance(recvval.to_s)
-                       else if pname == "strerror_ext" then
-                               return v.native_string_instance(recvval.strerror)
-                       end
                else if cname == "NativeFile" then
+                       if pname == "native_stdout" then
+                               return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, sys.stdout)
+                       else if pname == "native_stdin" then
+                               return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, sys.stdin)
+                       else if pname == "native_stderr" then
+                               return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, sys.stderr)
+                       else if pname == "io_open_read" then
+                               var a1 = args[1].val.as(Buffer)
+                               return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, new IFStream.open(a1.to_s))
+                       else if pname == "io_open_write" then
+                               var a1 = args[1].val.as(Buffer)
+                               return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, new OFStream.open(a1.to_s))
+                       end
                        var recvval = args.first.val
                        if pname == "io_write" then
                                var a1 = args[1].val.as(Buffer)
@@ -883,59 +897,18 @@ redef class AExternMethPropdef
                        else if pname == "address_is_null" then
                                return v.false_instance
                        end
-               else if cname == "NativeString" then
-                       var recvval = args.first.val.as(Buffer)
-                       if pname == "file_exists" then
-                               return v.bool_instance(recvval.to_s.file_exists)
-                       else if pname == "file_mkdir" then
-                               recvval.to_s.mkdir
-                               return null
-                       else if pname == "file_chdir" then
-                               recvval.to_s.chdir
-                               return null
-                       else if pname == "file_realpath" then
-                               return v.native_string_instance(recvval.to_s.realpath)
-                       else if pname == "get_environ" then
-                               var txt = recvval.to_s.environ
-                               return v.native_string_instance(txt)
-                       else if pname == "system" then
-                               var res = sys.system(recvval.to_s)
-                               return v.int_instance(res)
-                       else if pname == "atof" then
-                               return v.float_instance(recvval.to_f)
-                       end
-               else if cname == "Float" then
-                       if pname == "cos" then
-                               return v.float_instance(args[0].to_f.cos)
-                       else if pname == "sin" then
-                               return v.float_instance(args[0].to_f.sin)
-                       else if pname == "tan" then
-                               return v.float_instance(args[0].to_f.tan)
-                       else if pname == "acos" then
-                               return v.float_instance(args[0].to_f.acos)
-                       else if pname == "asin" then
-                               return v.float_instance(args[0].to_f.asin)
-                       else if pname == "atan" then
-                               return v.float_instance(args[0].to_f.atan)
-                       else if pname == "sqrt" then
-                               return v.float_instance(args[0].to_f.sqrt)
-                       else if pname == "exp" then
-                               return v.float_instance(args[0].to_f.exp)
-                       else if pname == "log" then
-                               return v.float_instance(args[0].to_f.log)
-                       else if pname == "pow" then
-                               return v.float_instance(args[0].to_f.pow(args[1].to_f))
-                       else if pname == "rand" then
-                               return v.float_instance(args[0].to_f.rand)
-                       else if pname == "abs" then
-                               return v.float_instance(args[0].to_f.abs)
-                       else if pname == "hypot_with" then
-                               return v.float_instance(args[0].to_f.hypot_with(args[1].to_f))
-                       else if pname == "is_nan" then
-                               return v.bool_instance(args[0].to_f.is_nan)
-                       else if pname == "is_inf_extern" then
-                               return v.bool_instance(args[0].to_f.is_inf != 0)
-                       end
+               else if pname == "calloc_array" then
+                       var recvtype = args.first.mtype.as(MClassType)
+                       var mtype: MType
+                       mtype = recvtype.supertype_to(v.mainmodule, recvtype, v.mainmodule.get_primitive_class("ArrayCapable"))
+                       mtype = mtype.arguments.first
+                       var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
+                       return new PrimitiveInstance[Array[Instance]](v.mainmodule.get_primitive_class("NativeArray").get_mtype([mtype]), val)
+               else if pname == "native_argc" then
+                       return v.int_instance(v.arguments.length)
+               else if pname == "native_argv" then
+                       var txt = v.arguments[args[1].to_i]
+                       return v.native_string_instance(txt)
                else if pname == "native_argc" then
                        return v.int_instance(v.arguments.length)
                else if pname == "native_argv" then
@@ -965,11 +938,24 @@ redef class AExternMethPropdef
                else if pname == "address_is_null" then
                        return v.false_instance
                end
-               fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
+               if mpropdef.is_intern then
+                       fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
+               else if mpropdef.is_extern then
+                       fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
+               else
+                       fatal(v, "NOT YET IMPLEMENTED <wat?> {mpropdef}")
+               end
                abort
        end
 end
 
+redef class AbstractArray[E]
+       fun copy(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
+       do
+               self.copy_to(start, len, dest, new_start)
+       end
+end
+
 redef class AAttrPropdef
        redef fun call(v, mpropdef, args)
        do
@@ -1008,25 +994,17 @@ redef class AAttrPropdef
        end
 end
 
-redef class ADeferredMethPropdef
-       redef fun call(v, mpropdef, args)
-       do
-               fatal(v, "Abstract method `{mpropdef.mproperty.name}` called on `{args.first.mtype}`")
-               abort
-       end
-end
-
 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
                var super_inits = self.super_inits
                if super_inits != null then
-                       assert args.length == 1
+                       var args_of_super = args
+                       if args.length > 1 then args_of_super = [args.first]
                        for su in super_inits do
-                               v.send(su, args)
+                               v.send(su, args_of_super)
                        end
-                       return null
                end
                var recv = args.first
                assert recv isa MutableInstance
@@ -1582,7 +1560,7 @@ redef class ASuperExpr
                if callsite != null then
                        # Add additionnals arguments for the super init call
                        if args.length == 1 then
-                               for i in [0..callsite.mproperty.intro.msignature.arity[ do
+                               for i in [0..callsite.msignature.arity[ do
                                        args.add(v.frame.arguments[i+1])
                                end
                        end
index 56c313f..7fd49a4 100644 (file)
@@ -792,8 +792,11 @@ class NitdocClass
        private fun mclass_intro_mpropdefs: Set[MPropDef] do
                var res = new HashSet[MPropDef]
                for mclassdef in mclass.mclassdefs do
-                       if mclassdef != mclass.intro then continue
+                       var owner = mclassdef.mmodule.public_owner
+                       if owner == null then owner = mclassdef.mmodule
                        for mpropdef in mclassdef.mpropdefs do
+                               if not mpropdef.is_intro then continue
+                               if owner != mclass.public_owner then continue
                                var mprop = mpropdef.mproperty
                                if mprop isa MMethod and mprop.is_init and mclass.is_abstract then continue
                                if mprop.visibility < ctx.min_visibility then continue
@@ -807,8 +810,10 @@ class NitdocClass
                var res = new HashSet[MPropDef]
                for mclassdef in mclass.mclassdefs do
                        if mclassdef == mclass.intro then continue
+                       var owner = mclassdef.mmodule.public_owner
+                       if owner == null then owner = mclassdef.mmodule
                        for mpropdef in mclassdef.mpropdefs do
-                               if mclassdef.mmodule.public_owner == mclass.public_owner then continue
+                               if owner == mclass.public_owner then continue
                                if mpropdef.mproperty.visibility < ctx.min_visibility then continue
                                res.add mpropdef
                        end
@@ -983,22 +988,23 @@ class NitdocClass
                        var stpl = new TplConcernList
                        for mmodule in mmodules do
                                # concerns list
-                               var mctpl = new TplConcernListElt
-                               mctpl.anchor = "#{mmodule.nitdoc_anchor}"
-                               mctpl.name = mmodule.nitdoc_name
-                               if mmodule.mdoc != null then
-                                       mctpl.comment = mmodule.mdoc.short_comment
+                               if mmodule != owner then
+                                       var mctpl = new TplConcernListElt
+                                       mctpl.anchor = "#{mmodule.nitdoc_anchor}"
+                                       mctpl.name = mmodule.nitdoc_name
+                                       if mmodule.mdoc != null then
+                                               mctpl.comment = mmodule.mdoc.short_comment
+                                       end
+                                       stpl.elts.add mctpl
+                                       # concern section
+                                       var cctpl = new TplConcern
+                                       cctpl.anchor = mmodule.nitdoc_anchor
+                                       cctpl.concern = mmodule.tpl_link
+                                       if mmodule.mdoc != null then
+                                               cctpl.comment = mmodule.mdoc.short_comment
+                                       end
+                                       mtpl.add cctpl
                                end
-                               stpl.elts.add mctpl
-                               # concern sectionm
-                               var cctpl = new TplConcern
-                               cctpl.anchor = mmodule.nitdoc_anchor
-                               cctpl.concern = mmodule.tpl_link
-                               if mmodule.mdoc != null then
-                                       cctpl.comment = mmodule.mdoc.short_comment
-                               end
-                               mtpl.add cctpl
-
                                var mprops = module_map[mmodule].to_a
                                prop_sorter.sort mprops
                                for mprop in mprops do mtpl.add tpl_mpropdef_article(mprop)
index 5f22329..85b2c1a 100644 (file)
@@ -27,11 +27,11 @@ var opt_full = new OptionBool("Process also imported modules", "--full")
 var opt_ast = new OptionBool("Generate specific HTML elements for each Node of the AST", "--ast")
 toolcontext.option_context.add_option(opt_fragment, opt_first_line, opt_last_line, opt_dir, opt_full)
 toolcontext.tooldescription = "Usage: nitlight [OPTION]... <file.nit>...\nGenerates HTML of highlited code from Nit source files."
+toolcontext.process_options(args)
 
 var model = new Model
 var modelbuilder = new ModelBuilder(model, toolcontext)
 
-toolcontext.process_options(args)
 var args = toolcontext.option_context.rest
 
 var mmodules = modelbuilder.parse(args)
index efe3667..6f85029 100644 (file)
@@ -268,7 +268,7 @@ end
 
 redef class AExternCall
        # Verify this explicit declaration of call from C and collect all relevant callbacks
-       fun verify_and_collect(npropdef: AExternPropdef, callback_set: ForeignCallbackSet,
+       fun verify_and_collect(npropdef: AMethPropdef, callback_set: ForeignCallbackSet,
                toolcontext: ToolContext) is abstract
 end
 
index 134d02a..0e0d345 100644 (file)
@@ -694,10 +694,9 @@ redef class MMethodDef
                if not mproperty.is_init then res.append("fun ")
                res.append(mproperty.to_console.bold)
                if msignature != null then res.append(msignature.to_console)
-               # FIXME: modifiers should be accessible via the model
-               #if self isa ADeferredMethPropdef then ret = "{ret} is abstract"
-               #if self isa AInternMethPropdef then ret = "{ret} is intern"
-               #if self isa AExternMethPropdef then ret = "{ret} is extern"
+               if is_abstract then res.append " is abstract"
+               if is_intern then res.append " is intern"
+               if is_extern then res.append " is extern"
                return res.to_s
        end
 end
index 6f60b77..edabf23 100644 (file)
@@ -179,11 +179,11 @@ abstract class Token
 
        # The previous token in the Lexer.
        # May have disapeared in the AST
-       var prev_token: nullable Token
+       var prev_token: nullable Token = null
 
        # The next token in the Lexer.
        # May have disapeared in the AST
-       var next_token: nullable Token
+       var next_token: nullable Token = null
 
        redef fun to_s: String do
                return "'{text}'"
@@ -620,6 +620,7 @@ class AModule
        readable var _n_imports: ANodes[AImport] = new ANodes[AImport](self)
        readable var _n_extern_code_blocks: ANodes[AExternCodeBlock] = new ANodes[AExternCodeBlock](self)
        readable var _n_classdefs: ANodes[AClassdef] = new ANodes[AClassdef](self)
+       init do end
 end
 
 # The declaration of the module with the documentation, name, and annotations
@@ -628,6 +629,7 @@ class AModuledecl
        readable writable var _n_doc: nullable ADoc = null
        readable writable var _n_kwmodule: TKwmodule
        readable writable var _n_name: AModuleName
+       init do end
 end
 
 # A import clause of a module
@@ -641,6 +643,7 @@ class AStdImport
        readable writable var _n_visibility: AVisibility
        readable writable var _n_kwimport: TKwimport
        readable writable var _n_name: AModuleName
+       init do end
 end
 
 # The special import clause of the kernel module. eg `import end`
@@ -649,6 +652,7 @@ class ANoImport
        readable writable var _n_visibility: AVisibility
        readable writable var _n_kwimport: TKwimport
        readable writable var _n_kwend: TKwend
+       init do end
 end
 
 # A visibility modifier
@@ -666,21 +670,26 @@ end
 class APrivateVisibility
        super AVisibility
        readable writable var _n_kwprivate: TKwprivate
+       init do end
 end
 class AProtectedVisibility
        super AVisibility
        readable writable var _n_kwprotected: TKwprotected
+       init do end
 end
 class AIntrudeVisibility
        super AVisibility
        readable writable var _n_kwintrude: TKwintrude
+       init do end
 end
 
 # A class definition
 # While most definition are `AStdClassdef`
 # There is tow special case of class definition
-abstract class AClassdef super Prod
+abstract class AClassdef
+       super Prod
        readable var _n_propdefs: ANodes[APropdef] = new ANodes[APropdef](self)
+       init do end
 end
 
 # A standard class definition with a name, superclasses and properties
@@ -696,6 +705,7 @@ class AStdClassdef
        readable var _n_superclasses: ANodes[ASuperclass] = new ANodes[ASuperclass](self)
        readable writable var _n_kwend: TKwend
        redef fun hot_location do return n_id.location
+       init do end
 end
 
 # The implicit class definition of the implicit main method
@@ -715,24 +725,29 @@ end
 class AConcreteClasskind
        super AClasskind
        readable writable var _n_kwclass: TKwclass
+       init do end
 end
 class AAbstractClasskind
        super AClasskind
        readable writable var _n_kwabstract: TKwabstract
        readable writable var _n_kwclass: TKwclass
+       init do end
 end
 class AInterfaceClasskind
        super AClasskind
        readable writable var _n_kwinterface: TKwinterface
+       init do end
 end
 class AEnumClasskind
        super AClasskind
        readable writable var _n_kwenum: TKwenum
+       init do end
 end
 class AExternClasskind
        super AClasskind
        readable writable var _n_kwextern: TKwextern
        readable writable var _n_kwclass: nullable TKwclass = null
+       init do end
 end
 
 # The definition of a formal generic parameter type. eg `X: Y`
@@ -741,6 +756,7 @@ class AFormaldef
        readable writable var _n_id: TClassid
        # The bound of the parameter type
        readable writable var _n_type: nullable AType = null
+       init do end
 end
 
 # A super-class. eg `super X`
@@ -748,20 +764,21 @@ class ASuperclass
        super Prod
        readable writable var _n_kwsuper: TKwsuper
        readable writable var _n_type: AType
+       init do end
 end
 
 # The definition of a property
 abstract class APropdef
        super Prod
        readable writable var _n_doc: nullable ADoc = null
+       readable writable var _n_kwredef: nullable TKwredef = null
+       readable writable var _n_visibility: nullable AVisibility = null
 end
 
 # A definition of an attribute
 # For historical reason, old-syle and new-style attributes use the same `ANode` sub-class
 class AAttrPropdef
        super APropdef
-       readable writable var _n_kwredef: nullable TKwredef = null
-       readable writable var _n_visibility: AVisibility
        readable writable var _n_kwvar: TKwvar
 
        # The identifier for an old-style attribute (null if new-style)
@@ -780,19 +797,29 @@ class AAttrPropdef
        do
                if n_id != null then return n_id.location else return n_id2.location
        end
+       init do end
 end
 
 # A definition of all kind of method (including constructors)
 abstract class AMethPropdef
        super APropdef
-       readable writable var _n_kwredef: nullable TKwredef = null
-       readable writable var _n_visibility: nullable AVisibility
+       readable writable var _n_kwmeth: nullable TKwmeth = null
+       readable writable var _n_kwinit: nullable TKwinit = null
+       readable writable var _n_kwnew: nullable TKwnew = null
        readable writable var _n_methid: nullable AMethid = null
-       readable writable var _n_signature: nullable ASignature
+       readable writable var _n_signature: nullable ASignature = null
+       readable writable var _n_block: nullable AExpr = null
+       readable writable var _n_extern: nullable TString = null
+       readable writable var _n_extern_calls: nullable AExternCalls = null
+       readable writable var _n_extern_code_block: nullable AExternCodeBlock = null
        redef fun hot_location
        do
                if n_methid != null then
                        return n_methid.location
+               else if n_kwinit != null then
+                       return n_kwinit.location
+               else if n_kwnew != null then
+                       return n_kwnew.location
                else
                        return location
                end
@@ -803,34 +830,26 @@ end
 # *deferred* is a old synonynmous of *abstract* that comes from PRM, that comes from Eiffel.
 class ADeferredMethPropdef
        super AMethPropdef
-       readable writable var _n_kwmeth: TKwmeth
 end
 
 # A method marked intern
 class AInternMethPropdef
        super AMethPropdef
-       readable writable var _n_kwmeth: TKwmeth
 end
 
 # A method of a constructor marked extern
 abstract class AExternPropdef
        super AMethPropdef
-       readable writable var _n_extern: nullable TString = null
-       readable writable var _n_extern_calls: nullable AExternCalls = null
-       readable writable var _n_extern_code_block: nullable AExternCodeBlock = null
 end
 
 # A method marked extern
 class AExternMethPropdef
        super AExternPropdef
-       readable writable var _n_kwmeth: TKwmeth
 end
 
 # A method with a body
 class AConcreteMethPropdef
        super AMethPropdef
-       readable writable var _n_kwmeth: nullable TKwmeth
-       readable writable var _n_block: nullable AExpr = null
 end
 
 # A constructor
@@ -842,15 +861,12 @@ end
 class AConcreteInitPropdef
        super AConcreteMethPropdef
        super AInitPropdef
-       readable writable var _n_kwinit: TKwinit
-       redef fun hot_location do return n_kwinit.location
 end
 
 # A constructor marked extern (defined with the `new` keyword)
 class AExternInitPropdef
        super AExternPropdef
        super AInitPropdef
-       readable writable var _n_kwnew: TKwnew
 end
 
 # The implicit main method
@@ -863,6 +879,7 @@ class AExternCalls
        super Prod
        readable writable var _n_kwimport: TKwimport
        readable var _n_extern_calls: ANodes[AExternCall] = new ANodes[AExternCall](self)
+       init do end
 end
 abstract class AExternCall
        super Prod
@@ -873,20 +890,24 @@ end
 class ALocalPropExternCall
        super APropExternCall
        readable writable var _n_methid: AMethid
+       init do end
 end
 class AFullPropExternCall
        super APropExternCall
        readable writable var _n_type: AType
        readable writable var _n_dot: nullable TDot = null
        readable writable var _n_methid: AMethid
+       init do end
 end
 class AInitPropExternCall
        super APropExternCall
        readable writable var _n_type: AType
+       init do end
 end
 class ASuperExternCall
        super AExternCall
        readable writable var _n_kwsuper: TKwsuper
+       init do end
 end
 abstract class ACastExternCall
        super AExternCall
@@ -897,12 +918,14 @@ class ACastAsExternCall
        readable writable var _n_dot: nullable TDot = null
        readable writable var _n_kwas: TKwas
        readable writable var _n_to_type: AType
+       init do end
 end
 class AAsNullableExternCall
        super ACastExternCall
        readable writable var _n_type: AType
        readable writable var _n_kwas: TKwas
        readable writable var _n_kwnullable: TKwnullable
+       init do end
 end
 class AAsNotNullableExternCall
        super ACastExternCall
@@ -910,16 +933,16 @@ class AAsNotNullableExternCall
        readable writable var _n_kwas: TKwas
        readable writable var _n_kwnot: TKwnot
        readable writable var _n_kwnullable: TKwnullable
+       init do end
 end
 
 # A definition of a virtual type
 class ATypePropdef
        super APropdef
-       readable writable var _n_kwredef: nullable TKwredef = null
-       readable writable var _n_visibility: AVisibility
        readable writable var _n_kwtype: TKwtype
        readable writable var _n_id: TClassid
        readable writable var _n_type: AType
+       init do end
 end
 
 # A `writable` or `readable` modifier
@@ -927,18 +950,21 @@ abstract class AAble
        super Prod
        readable writable var _n_visibility: nullable AVisibility = null
        readable writable var _n_kwredef: nullable TKwredef = null
+       init do end
 end
 
 # A `readable` modifier
 class AReadAble
        super AAble
        readable writable var _n_kwreadable: TKwreadable
+       init do end
 end
 
 # A `writable` modifier
 class AWriteAble
        super AAble
        readable writable var _n_kwwritable: TKwwritable
+       init do end
 end
 
 # The identifier of a method in a method declaration.
@@ -949,78 +975,96 @@ end
 class AIdMethid
        super AMethid
        readable writable var _n_id: TId
+       init do end
 end
 class APlusMethid
        super AMethid
        readable writable var _n_plus: TPlus
+       init do end
 end
 class AMinusMethid
        super AMethid
        readable writable var _n_minus: TMinus
+       init do end
 end
 class AStarMethid
        super AMethid
        readable writable var _n_star: TStar
+       init do end
 end
 class ASlashMethid
        super AMethid
        readable writable var _n_slash: TSlash
+       init do end
 end
 class APercentMethid
        super AMethid
        readable writable var _n_percent: TPercent
+       init do end
 end
 class AEqMethid
        super AMethid
        readable writable var _n_eq: TEq
+       init do end
 end
 class ANeMethid
        super AMethid
        readable writable var _n_ne: TNe
+       init do end
 end
 class ALeMethid
        super AMethid
        readable writable var _n_le: TLe
+       init do end
 end
 class AGeMethid
        super AMethid
        readable writable var _n_ge: TGe
+       init do end
 end
 class ALtMethid
        super AMethid
        readable writable var _n_lt: TLt
+       init do end
 end
 class AGtMethid
        super AMethid
        readable writable var _n_gt: TGt
+       init do end
 end
 class ALlMethid
        super AMethid
        readable writable var _n_ll: TLl
+       init do end
 end
 class AGgMethid
        super AMethid
        readable writable var _n_gg: TGg
+       init do end
 end
 class ABraMethid
        super AMethid
        readable writable var _n_obra: TObra
        readable writable var _n_cbra: TCbra
+       init do end
 end
 class AStarshipMethid
        super AMethid
        readable writable var _n_starship: TStarship
+       init do end
 end
 class AAssignMethid
        super AMethid
        readable writable var _n_id: TId
        readable writable var _n_assign: TAssign
+       init do end
 end
 class ABraassignMethid
        super AMethid
        readable writable var _n_obra: TObra
        readable writable var _n_cbra: TCbra
        readable writable var _n_assign: TAssign
+       init do end
 end
 
 # A signature in a method definition. eg `(x,y:X,z:Z):T`
@@ -1030,6 +1074,7 @@ class ASignature
        readable var _n_params: ANodes[AParam] = new ANodes[AParam](self)
        readable writable var _n_cpar: nullable TCpar = null
        readable writable var _n_type: nullable AType = null
+       init do end
 end
 
 # A parameter definition in a signature. eg `x:X`
@@ -1038,6 +1083,7 @@ class AParam
        readable writable var _n_id: TId
        readable writable var _n_type: nullable AType = null
        readable writable var _n_dotdotdot: nullable TDotdotdot = null
+       init do end
 end
 
 # A static type. eg `nullable X[Y]`
@@ -1050,6 +1096,7 @@ class AType
 
        # Type arguments for a generic type
        readable var _n_types: ANodes[AType] = new ANodes[AType](self)
+       init do end
 end
 
 # A label at the end of a block or in a break/continue statement. eg `label x`
@@ -1057,6 +1104,7 @@ class ALabel
        super Prod
        readable writable var _n_kwlabel: TKwlabel
        readable writable var _n_id: TId
+       init do end
 end
 
 # Expression and statements
@@ -1071,6 +1119,7 @@ class ABlockExpr
        super AExpr
        readable var _n_expr: ANodes[AExpr] = new ANodes[AExpr](self)
        readable writable var _n_kwend: nullable TKwend = null
+       init do end
 end
 
 # A declaration of a local variable. eg `var x: X = y`
@@ -1083,6 +1132,7 @@ class AVardeclExpr
 
        # The initial value, if any
        readable writable var _n_expr: nullable AExpr = null
+       init do end
 end
 
 # A `return` statement. eg `return x`
@@ -1090,12 +1140,14 @@ class AReturnExpr
        super AExpr
        readable writable var _n_kwreturn: nullable TKwreturn = null
        readable writable var _n_expr: nullable AExpr = null
+       init do end
 end
 
 # Something that has a label.
 abstract class ALabelable
        super Prod
        readable writable var _n_label: nullable ALabel = null
+       init do end
 end
 
 # A `break` statement.
@@ -1104,12 +1156,14 @@ class ABreakExpr
        super ALabelable
        readable writable var _n_kwbreak: TKwbreak
        readable writable var _n_expr: nullable AExpr = null
+       init do end
 end
 
 # An `abort` statement
 class AAbortExpr
        super AExpr
        readable writable var _n_kwabort: TKwabort
+       init do end
 end
 
 # A `continue` statement
@@ -1118,6 +1172,7 @@ class AContinueExpr
        super ALabelable
        readable writable var _n_kwcontinue: nullable TKwcontinue = null
        readable writable var _n_expr: nullable AExpr = null
+       init do end
 end
 
 # A `do` statement
@@ -1126,6 +1181,7 @@ class ADoExpr
        super ALabelable
        readable writable var _n_kwdo: TKwdo
        readable writable var _n_block: nullable AExpr = null
+       init do end
 end
 
 # A `if` statement
@@ -1135,6 +1191,7 @@ class AIfExpr
        readable writable var _n_expr: AExpr
        readable writable var _n_then: nullable AExpr = null
        readable writable var _n_else: nullable AExpr = null
+       init do end
 end
 
 # A `if` expression
@@ -1146,6 +1203,7 @@ class AIfexprExpr
        readable writable var _n_then: AExpr
        readable writable var _n_kwelse: TKwelse
        readable writable var _n_else: AExpr
+       init do end
 end
 
 # A `while` statement
@@ -1156,6 +1214,7 @@ class AWhileExpr
        readable writable var _n_expr: AExpr
        readable writable var _n_kwdo: TKwdo
        readable writable var _n_block: nullable AExpr = null
+       init do end
 end
 
 # A `loop` statement
@@ -1164,6 +1223,7 @@ class ALoopExpr
        super ALabelable
        readable writable var _n_kwloop: TKwloop
        readable writable var _n_block: nullable AExpr = null
+       init do end
 end
 
 # A `for` statement
@@ -1175,6 +1235,7 @@ class AForExpr
        readable writable var _n_expr: AExpr
        readable writable var _n_kwdo: TKwdo
        readable writable var _n_block: nullable AExpr = null
+       init do end
 end
 
 # An `assert` statement
@@ -1184,6 +1245,7 @@ class AAssertExpr
        readable writable var _n_id: nullable TId = null
        readable writable var _n_expr: AExpr
        readable writable var _n_else: nullable AExpr = null
+       init do end
 end
 
 # Whatever is a simple assignment. eg `= something`
@@ -1191,6 +1253,7 @@ abstract class AAssignFormExpr
        super AExpr
        readable writable var _n_assign: TAssign
        readable writable var _n_value: AExpr
+       init do end
 end
 
 # Whatever is a combined assignment. eg `+= something`
@@ -1198,12 +1261,14 @@ abstract class AReassignFormExpr
        super AExpr
        readable writable var _n_assign_op: AAssignOp
        readable writable var _n_value: AExpr
+       init do end
 end
 
 # A `once` expression. eg `once x`
 class AOnceExpr
        super AProxyExpr
        readable writable var _n_kwonce: TKwonce
+       init do end
 end
 
 # A polymorphic invocation of a method
@@ -1212,6 +1277,7 @@ abstract class ASendExpr
        super AExpr
        # The receiver of the method invocation
        readable writable var _n_expr: AExpr
+       init do end
 end
 
 # A binary operation on a method
@@ -1220,6 +1286,7 @@ abstract class ABinopExpr
        # The second operand of the operation
        # Note: the receiver (`n_expr`) is the first operand
        readable writable var _n_expr2: AExpr
+       init do end
 end
 
 # Something that is boolean expression
@@ -1232,6 +1299,7 @@ class AOrExpr
        super ABoolExpr
        readable writable var _n_expr: AExpr
        readable writable var _n_expr2: AExpr
+       init do end
 end
 
 # A `and` expression
@@ -1239,6 +1307,7 @@ class AAndExpr
        super ABoolExpr
        readable writable var _n_expr: AExpr
        readable writable var _n_expr2: AExpr
+       init do end
 end
 
 # A `or else` expression
@@ -1246,6 +1315,7 @@ class AOrElseExpr
        super ABoolExpr
        readable writable var _n_expr: AExpr
        readable writable var _n_expr2: AExpr
+       init do end
 end
 
 # A `implies` expression
@@ -1253,6 +1323,7 @@ class AImpliesExpr
        super ABoolExpr
        readable writable var _n_expr: AExpr
        readable writable var _n_expr2: AExpr
+       init do end
 end
 
 # A `not` expression
@@ -1260,6 +1331,7 @@ class ANotExpr
        super ABoolExpr
        readable writable var _n_kwnot: TKwnot
        readable writable var _n_expr: AExpr
+       init do end
 end
 
 # A `==` expression
@@ -1307,6 +1379,7 @@ class AIsaExpr
        super ABoolExpr
        readable writable var _n_expr: AExpr
        readable writable var _n_type: AType
+       init do end
 end
 
 # A `+` expression
@@ -1343,6 +1416,7 @@ end
 class AUminusExpr
        super ASendExpr
        readable writable var _n_minus: TMinus
+       init do end
 end
 
 # An explicit instantiation. eg `new T`
@@ -1354,6 +1428,7 @@ class ANewExpr
        # The name of the named-constructor, if any
        readable writable var _n_id: nullable TId = null
        readable writable var _n_args: AExprs
+       init do end
 end
 
 # Whatever is a old-style attribute access
@@ -1365,6 +1440,8 @@ abstract class AAttrFormExpr
 
        # The name of the attribute
        readable writable var _n_id: TAttrid
+
+       init do end
 end
 
 # The read of an attribute. eg `x._a`
@@ -1387,6 +1464,7 @@ abstract class ACallFormExpr
 
        # The arguments of the call
        readable writable var _n_args: AExprs
+       init do end
 end
 
 # A complex setter call (standard or brackets)
@@ -1430,6 +1508,7 @@ class ASuperExpr
        readable writable var _n_qualified: nullable AQualified = null
        readable writable var _n_kwsuper: TKwsuper
        readable writable var _n_args: AExprs
+       init do end
 end
 
 # A call to the `init` constructor.
@@ -1438,12 +1517,14 @@ class AInitExpr
        super ASendExpr
        readable writable var _n_kwinit: TKwinit
        readable writable var _n_args: AExprs
+       init do end
 end
 
 # Whatever looks-like a call of the brackets `[]` operator.
 abstract class ABraFormExpr
        super ASendExpr
        readable writable var _n_args: AExprs
+       init do end
 end
 
 # A call of the brackets operator. eg `x[y,z]`
@@ -1461,6 +1542,7 @@ end
 abstract class AVarFormExpr
        super AExpr
        readable writable var _n_id: TId
+       init do end
 end
 
 # A complex setter call of the bracket operator. eg `x[y,z]+=t`
@@ -1494,6 +1576,7 @@ abstract class ARangeExpr
        super AExpr
        readable writable var _n_expr: AExpr
        readable writable var _n_expr2: AExpr
+       init do end
 end
 
 # A closed literal range. eg `[x..y]`
@@ -1501,6 +1584,7 @@ class ACrangeExpr
        super ARangeExpr
        readable writable var _n_obra: TObra
        readable writable var _n_cbra: TCbra
+       init do end
 end
 
 # An open literal range. eg `[x..y[`
@@ -1508,18 +1592,21 @@ class AOrangeExpr
        super ARangeExpr
        readable writable var _n_obra: TObra
        readable writable var _n_cbra: TObra
+       init do end
 end
 
 # A literal array. eg. `[x,y,z]`
 class AArrayExpr
        super AExpr
        readable writable var _n_exprs: AExprs
+       init do end
 end
 
 # A read of `self` 
 class ASelfExpr
        super AExpr
        readable writable var _n_kwself: nullable TKwself
+       init do end
 end
 
 # When there is no explicit receiver, `self` is implicit
@@ -1531,16 +1618,19 @@ end
 class ATrueExpr
        super ABoolExpr
        readable writable var _n_kwtrue: TKwtrue
+       init do end
 end
 # A `false` boolean literal constant
 class AFalseExpr
        super ABoolExpr
        readable writable var _n_kwfalse: TKwfalse
+       init do end
 end
 # A `null` literal constant
 class ANullExpr
        super AExpr
        readable writable var _n_kwnull: TKwnull
+       init do end
 end
 # An integer literal
 class AIntExpr
@@ -1550,26 +1640,31 @@ end
 class ADecIntExpr
        super AIntExpr
        readable writable var _n_number: TNumber
+       init do end
 end
 # An integer literal in hexadecimal format
 class AHexIntExpr
        super AIntExpr
        readable writable var _n_hex_number: THexNumber
+       init do end
 end
 # A float literal
 class AFloatExpr
        super AExpr
        readable writable var _n_float: TFloat
+       init do end
 end
 # A character literal
 class ACharExpr
        super AExpr
        readable writable var _n_char: TChar
+       init do end
 end
 # A string literal
 abstract class AStringFormExpr
        super AExpr
        readable writable var _n_string: Token
+       init do end
 end
 
 # A simple string. eg. `"abc"`
@@ -1597,6 +1692,7 @@ end
 class ASuperstringExpr
        super AExpr
        readable var _n_exprs: ANodes[AExpr] = new ANodes[AExpr](self)
+       init do end
 end
 
 # A simple parenthesis. eg `(x)`
@@ -1604,12 +1700,14 @@ class AParExpr
        super AProxyExpr
        readable writable var _n_opar: TOpar
        readable writable var _n_cpar: TCpar
+       init do end
 end
 
 # Whatevej just contains (and mimic) an other expression
 abstract class AProxyExpr
        super AExpr
        readable writable var _n_expr: AExpr
+       init do end
 end
 
 # A type cast. eg `x.as(T)`
@@ -1620,6 +1718,7 @@ class AAsCastExpr
        readable writable var _n_opar: nullable TOpar = null
        readable writable var _n_type: AType
        readable writable var _n_cpar: nullable TCpar = null
+       init do end
 end
 
 # A as-not-null cast. eg `x.as(not null)`
@@ -1631,18 +1730,21 @@ class AAsNotnullExpr
        readable writable var _n_kwnot: TKwnot
        readable writable var _n_kwnull: TKwnull
        readable writable var _n_cpar: nullable TCpar = null
+       init do end
 end
 
 # A is-set check of old-style attributes. eg `isset x._a`
 class AIssetAttrExpr
        super AAttrFormExpr
        readable writable var _n_kwisset: TKwisset
+       init do end
 end
 
 # A list of expression separated with commas (arguments for instance)
 abstract class AExprs
        super Prod 
        readable var _n_exprs: ANodes[AExpr] = new ANodes[AExpr](self)
+       init do end
 end
 
 class ADebugTypeExpr
@@ -1651,6 +1753,7 @@ class ADebugTypeExpr
        readable writable var _n_kwtype: TKwtype
        readable writable var _n_expr: AExpr
        readable writable var _n_type: AType
+       init do end
 end
 
 # A simple list of expressions
@@ -1663,6 +1766,7 @@ class AParExprs
        super AExprs
        readable writable var _n_opar: TOpar
        readable writable var _n_cpar: TCpar
+       init do end
 end
 
 # A list of expressions enclosed in brackets
@@ -1670,6 +1774,7 @@ class ABraExprs
        super AExprs
        readable writable var _n_obra: TObra
        readable writable var _n_cbra: TCbra
+       init do end
 end
 
 # A complex assignment operator. eg `+=`
@@ -1679,10 +1784,12 @@ end
 class APlusAssignOp
        super AAssignOp
        readable writable var _n_pluseq: TPluseq
+       init do end
 end
 class AMinusAssignOp
        super AAssignOp
        readable writable var _n_minuseq: TMinuseq
+       init do end
 end
 
 class AModuleName
@@ -1690,22 +1797,26 @@ class AModuleName
        readable writable var _n_quad: nullable TQuad = null
        readable var _n_path: ANodes[TId] = new ANodes[TId](self)
        readable writable var _n_id: TId
+       init do end
 end
 class AInLanguage
        super Prod
        readable writable var _n_kwin: TKwin
        readable writable var _n_string: TString
+       init do end
 end
 class AExternCodeBlock
        super Prod
        readable writable var _n_in_language: nullable AInLanguage = null
        readable writable var _n_extern_code_segment: TExternCodeSegment
+       init do end
 end
 class AQualified
        super Prod
        readable writable var _n_quad: nullable TQuad = null
        readable var _n_id: ANodes[TId] = new ANodes[TId](self)
        readable writable var _n_classid: nullable TClassid = null
+       init do end
 end
 
 # A documentation of a definition
@@ -1713,6 +1824,7 @@ end
 class ADoc
        super Prod
        readable var _n_comment: ANodes[TComment] = new ANodes[TComment](self)
+       init do end
 end
 
 class AAnnotations
@@ -1721,6 +1833,7 @@ class AAnnotations
        readable writable var _n_opar: nullable TOpar = null
        readable var _n_items: ANodes[AAnnotation] = new ANodes[AAnnotation](self)
        readable writable var _n_cpar: nullable TCpar = null
+       init do end
 end
 class AAnnotation
        super Prod
@@ -1728,6 +1841,7 @@ class AAnnotation
        readable writable var _n_opar: nullable TOpar = null
        readable var _n_args: ANodes[AAtArg] = new ANodes[AAtArg](self)
        readable writable var _n_cpar: nullable TCpar = null
+       init do end
 end
 abstract class AAtArg
        super Prod
@@ -1735,10 +1849,12 @@ end
 class ATypeAtArg
        super AAtArg
        readable writable var _n_type: AType
+       init do end
 end
 class AExprAtArg
        super AAtArg
        readable writable var _n_expr: AExpr
+       init do end
 end
 class AAtAtArg
        super AAtArg
@@ -1746,6 +1862,7 @@ end
 abstract class AAtid
        super Prod
        readable writable var _n_id: Token
+       init do end
 end
 class AIdAtid
        super AAtid
index 9a6eec0..55ff3f7 100644 (file)
@@ -69,7 +69,7 @@ redef class ToolContext
        do
                var mod_string = "do\n{string}\nend"
                var nmodule = parse_module(mod_string)
-               var nblock = nmodule.n_classdefs.first.n_propdefs.first.as(AMainMethPropdef).n_block.as(ABlockExpr).n_expr.first.as(ADoExpr).n_block.as(not null)
+               var nblock = nmodule.n_classdefs.first.n_propdefs.first.as(AMethPropdef).n_block.as(ABlockExpr).n_expr.first.as(ADoExpr).n_block.as(not null)
                return nblock
        end
 
@@ -79,7 +79,7 @@ redef class ToolContext
        do
                var mod_string = "var dummy = \n{string}"
                var nmodule = parse_module(mod_string)
-               var nexpr = nmodule.n_classdefs.first.n_propdefs.first.as(AMainMethPropdef).n_block.as(ABlockExpr).n_expr.first.as(AVardeclExpr).n_expr.as(not null)
+               var nexpr = nmodule.n_classdefs.first.n_propdefs.first.as(AMethPropdef).n_block.as(ABlockExpr).n_expr.first.as(AVardeclExpr).n_expr.as(not null)
                return nexpr
        end
 
@@ -120,7 +120,7 @@ redef class ToolContext
                tree = (new Parser(lexer)).parse
                eof = tree.n_eof
                if not eof isa AError then
-                       var ntype = tree.n_base.n_classdefs.first.n_propdefs.first.as(AMainMethPropdef).n_block.as(ABlockExpr).n_expr.first.as(AVardeclExpr).n_type.n_types.first
+                       var ntype = tree.n_base.n_classdefs.first.n_propdefs.first.as(AMethPropdef).n_block.as(ABlockExpr).n_expr.first.as(AVardeclExpr).n_type.n_types.first
                        return ntype
                end
                error = eof
@@ -143,7 +143,7 @@ redef class ToolContext
                tree = (new Parser(lexer)).parse
                eof = tree.n_eof
                if not eof isa AError then
-                       var nexpr = tree.n_base.n_classdefs.first.n_propdefs.first.as(AMainMethPropdef).n_block.as(ABlockExpr).n_expr.first.as(AVardeclExpr).n_expr.as(AParExpr).n_expr
+                       var nexpr = tree.n_base.n_classdefs.first.n_propdefs.first.as(AMethPropdef).n_block.as(ABlockExpr).n_expr.first.as(AVardeclExpr).n_expr.as(AParExpr).n_expr
                        return nexpr
                end
                if eof.location > error.location then error = eof
@@ -156,7 +156,8 @@ redef class ToolContext
                tree = (new Parser(lexer)).parse
                eof = tree.n_eof
                if not eof isa AError then
-                       var nblock = tree.n_base.n_classdefs.first.n_propdefs.first.as(AMainMethPropdef).n_block.as(ABlockExpr).n_expr.first.as(ADoExpr).n_block.as(not null)
+                       var nblock = tree.n_base.n_classdefs.first.n_propdefs.first.as(AMethPropdef).n_block.as(ABlockExpr).n_expr.first.as(ADoExpr).n_block.as(ABlockExpr)
+                       nblock.n_kwend = null # drop injected token
                        return nblock
                end
                if eof.location > error.location then error = eof
index a40ca22..b2683c2 100644 (file)
@@ -203,6 +203,7 @@ class RapidTypeAnalysis
 
                while not todo.is_empty do
                        var mmethoddef = todo.shift
+                       var mmeth = mmethoddef.mproperty
                        #print "# visit {mmethoddef}"
                        var v = new RapidTypeVisitor(self, mmethoddef.mclassdef.bound_mtype, mmethoddef)
 
@@ -218,18 +219,18 @@ class RapidTypeAnalysis
                                v.add_monomorphic_send(vararg, self.modelbuilder.force_get_primitive_method(node, "with_native", vararg.mclass, self.mainmodule))
                        end
 
-
-                       for i in [0..mmethoddef.msignature.arity[ do
-                               var origtype = mmethoddef.mproperty.intro.msignature.mparameters[i].mtype
+                       var sig = mmethoddef.msignature.as(not null)
+                       var osig = mmeth.intro.msignature.as(not null)
+                       for i in [0..sig.arity[ do
+                               var origtype = osig.mparameters[i].mtype
                                if not origtype.need_anchor then continue # skip non covariant stuff
-                               var paramtype = mmethoddef.msignature.mparameters[i].mtype
-                               #paramtype = v.cleanup_type(paramtype).as(not null)
+                               var paramtype = sig.mparameters[i].mtype
                                add_cast(paramtype)
                        end
 
                        if not modelbuilder.mpropdef2npropdef.has_key(mmethoddef) then
                                # It is an init for a class?
-                               if mmethoddef.mproperty.name == "init" then
+                               if mmeth.name == "init" then
                                        var nclassdef = self.modelbuilder.mclassdef2nclassdef[mmethoddef.mclassdef]
                                        var super_inits = nclassdef.super_inits
                                        if super_inits != null then
@@ -247,27 +248,23 @@ class RapidTypeAnalysis
 
                        var npropdef = modelbuilder.mpropdef2npropdef[mmethoddef]
 
-                       if npropdef isa AConcreteMethPropdef then
+                       if npropdef isa AMethPropdef  then
                                var auto_super_inits = npropdef.auto_super_inits
                                if auto_super_inits != null then
                                        for auto_super_init in auto_super_inits do
                                                v.add_callsite(auto_super_init)
                                        end
                                end
-                       else if npropdef isa AInternMethPropdef or
-                         (npropdef isa AExternMethPropdef and npropdef.n_extern != null) then
+                       end
+
+                       if mmeth.is_new then
+                               v.add_type(v.receiver)
+                       else if mmethoddef.is_intern or mmethoddef.is_extern then
                                # UGLY: We force the "instantation" of the concrete return type if any
                                var ret = mmethoddef.msignature.return_mtype
                                if ret != null and ret isa MClassType and ret.mclass.kind != abstract_kind and ret.mclass.kind != interface_kind then
                                        v.add_type(ret)
                                end
-                       else if npropdef isa AExternMethPropdef then
-                               var nclassdef = npropdef.parent.as(AClassdef)
-                               v.enter_visit(npropdef)
-                       else if npropdef isa AExternInitPropdef then
-                               v.add_type(v.receiver)
-                       else
-
                        end
 
                        v.enter_visit(npropdef)
index f7863c6..fe9000c 100644 (file)
@@ -16,7 +16,7 @@
 module separate_compiler
 
 import abstract_compiler
-import layout_builders
+import coloring
 import rapid_type_analysis
 
 # Add separate compiler specific options
@@ -40,13 +40,7 @@ redef class ToolContext
        # --semi-global
        var opt_semi_global = new OptionBool("Enable all semi-global optimizations", "--semi-global")
        # --no-colo-dead-methods
-       var opt_no_colo_dead_methods = new OptionBool("Do not colorize dead methods", "--no-colo-dead-methods")
-       # --use-naive-coloring
-       var opt_bm_typing: OptionBool = new OptionBool("Colorize items incrementaly, used to simulate binary matrix typing", "--bm-typing")
-       # --use-mod-perfect-hashing
-       var opt_phmod_typing: OptionBool = new OptionBool("Replace coloration by perfect hashing (with mod operator)", "--phmod-typing")
-       # --use-and-perfect-hashing
-       var opt_phand_typing: OptionBool = new OptionBool("Replace coloration by perfect hashing (with and operator)", "--phand-typing")
+       var opt_colo_dead_methods = new OptionBool("Force colorization of dead methods", "--colo-dead-methods")
        # --tables-metrics
        var opt_tables_metrics: OptionBool = new OptionBool("Enable static size measuring of tables used for vft, typing and resolution", "--tables-metrics")
 
@@ -58,10 +52,7 @@ redef class ToolContext
                self.option_context.add_option(self.opt_no_union_attribute)
                self.option_context.add_option(self.opt_no_shortcut_equate)
                self.option_context.add_option(self.opt_inline_coloring_numbers, opt_inline_some_methods, opt_direct_call_monomorph, opt_skip_dead_methods, opt_semi_global)
-               self.option_context.add_option(self.opt_no_colo_dead_methods)
-               self.option_context.add_option(self.opt_bm_typing)
-               self.option_context.add_option(self.opt_phmod_typing)
-               self.option_context.add_option(self.opt_phand_typing)
+               self.option_context.add_option(self.opt_colo_dead_methods)
                self.option_context.add_option(self.opt_tables_metrics)
        end
 
@@ -163,10 +154,11 @@ class SeparateCompiler
        private var undead_types: Set[MType] = new HashSet[MType]
        private var live_unresolved_types: Map[MClassDef, Set[MType]] = new HashMap[MClassDef, HashSet[MType]]
 
-       private var type_layout: nullable Layout[MType]
-       private var resolution_layout: nullable Layout[MType]
-       protected var method_layout: nullable Layout[PropertyLayoutElement]
-       protected var attr_layout: nullable Layout[MAttribute]
+       private var type_ids: Map[MType, Int]
+       private var type_colors: Map[MType, Int]
+       private var opentype_colors: Map[MType, Int]
+       protected var method_colors: Map[PropertyLayoutElement, Int]
+       protected var attr_colors: Map[MAttribute, Int]
 
        init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: nullable RapidTypeAnalysis) do
                super(mainmodule, mmbuilder)
@@ -184,19 +176,7 @@ class SeparateCompiler
                # With resolution_table_table, all live type resolution are stored in a big table: resolution_table
                self.header.add_decl("struct type \{ int id; const char *name; int color; short int is_nullable; const struct types *resolution_table; int table_size; int type_table[]; \}; /* general C type representing a Nit type. */")
                self.header.add_decl("struct instance \{ const struct type *type; const struct class *class; nitattribute_t attrs[]; \}; /* general C type representing a Nit instance. */")
-
-               if modelbuilder.toolcontext.opt_phmod_typing.value or modelbuilder.toolcontext.opt_phand_typing.value then
-                       self.header.add_decl("struct types \{ int mask; const struct type *types[]; \}; /* a list types (used for vts, fts and unresolved lists). */")
-               else
-                       self.header.add_decl("struct types \{ int dummy; const struct type *types[]; \}; /* a list types (used for vts, fts and unresolved lists). */")
-               end
-
-               if modelbuilder.toolcontext.opt_phmod_typing.value then
-                       self.header.add_decl("#define HASH(mask, id) ((mask)%(id))")
-               else if modelbuilder.toolcontext.opt_phand_typing.value then
-                       self.header.add_decl("#define HASH(mask, id) ((mask)&(id))")
-               end
-
+               self.header.add_decl("struct types \{ int dummy; const struct type *types[]; \}; /* a list types (used for vts, fts and unresolved lists). */")
                self.header.add_decl("typedef struct instance val; /* general C type representing a Nit instance. */")
        end
 
@@ -279,30 +259,14 @@ class SeparateCompiler
 
        # colorize classe properties
        fun do_property_coloring do
-               var mclasses = new HashSet[MClass].from(modelbuilder.model.mclasses)
 
                var rta = runtime_type_analysis
 
                # Layouts
-               var method_layout_builder: PropertyLayoutBuilder[PropertyLayoutElement]
-               var attribute_layout_builder: PropertyLayoutBuilder[MAttribute]
-               #FIXME PH and BM layouts too slow for large programs
-               #if modelbuilder.toolcontext.opt_bm_typing.value then
-               #       method_layout_builder = new MMethodBMizer(self.mainmodule)
-               #       attribute_layout_builder = new MAttributeBMizer(self.mainmodule)
-               #else if modelbuilder.toolcontext.opt_phmod_typing.value then
-               #       method_layout_builder = new MMethodHasher(new PHModOperator, self.mainmodule)
-               #       attribute_layout_builder = new MAttributeHasher(new PHModOperator, self.mainmodule)
-               #else if modelbuilder.toolcontext.opt_phand_typing.value then
-               #       method_layout_builder = new MMethodHasher(new PHAndOperator, self.mainmodule)
-               #       attribute_layout_builder = new MAttributeHasher(new PHAndOperator, self.mainmodule)
-               #else
-
-               var class_layout_builder = new MClassColorer(self.mainmodule)
-               class_layout_builder.build_layout(mclasses)
-               method_layout_builder = new MPropertyColorer[PropertyLayoutElement](self.mainmodule, class_layout_builder)
-               attribute_layout_builder = new MPropertyColorer[MAttribute](self.mainmodule, class_layout_builder)
-               #end
+               var mclasses = new HashSet[MClass].from(modelbuilder.model.mclasses)
+               var poset = mainmodule.flatten_mclass_hierarchy
+               var colorer = new POSetColorer[MClass]
+               colorer.colorize(poset)
 
                # The dead methods, still need to provide a dead color symbol
                var dead_methods = new Array[MMethod]
@@ -315,7 +279,7 @@ class SeparateCompiler
                        mattributes[mclass] = new HashSet[MAttribute]
                        for mprop in self.mainmodule.properties(mclass) do
                                if mprop isa MMethod then
-                                       if modelbuilder.toolcontext.opt_no_colo_dead_methods.value and rta != null and not rta.live_methods.has(mprop) then
+                                       if not modelbuilder.toolcontext.opt_colo_dead_methods.value and rta != null and not rta.live_methods.has(mprop) then
                                                dead_methods.add(mprop)
                                                continue
                                        end
@@ -356,9 +320,10 @@ class SeparateCompiler
                end
 
                # methods coloration
-               self.method_layout = method_layout_builder.build_layout(mmethods)
-               self.method_tables = build_method_tables(mclasses, super_calls)
-               self.compile_color_consts(method_layout.pos)
+               var meth_colorer = new POSetBucketsColorer[MClass, PropertyLayoutElement](poset, colorer.conflicts)
+               method_colors = meth_colorer.colorize(mmethods)
+               method_tables = build_method_tables(mclasses, super_calls)
+               compile_color_consts(method_colors)
 
                # attribute null color to dead methods and supercalls
                for mproperty in dead_methods do
@@ -370,13 +335,13 @@ class SeparateCompiler
                end
 
                # attributes coloration
-               self.attr_layout = attribute_layout_builder.build_layout(mattributes)
-               self.attr_tables = build_attr_tables(mclasses)
-               self.compile_color_consts(attr_layout.pos)
+               var attr_colorer = new POSetBucketsColorer[MClass, MAttribute](poset, colorer.conflicts)
+               attr_colors = attr_colorer.colorize(mattributes)
+               attr_tables = build_attr_tables(mclasses)
+               compile_color_consts(attr_colors)
        end
 
        fun build_method_tables(mclasses: Set[MClass], super_calls: Set[MMethodDef]): Map[MClass, Array[nullable MPropDef]] do
-               var layout = self.method_layout
                var tables = new HashMap[MClass, Array[nullable MPropDef]]
                for mclass in mclasses do
                        var table = new Array[nullable MPropDef]
@@ -393,8 +358,8 @@ class SeparateCompiler
                                if parent == mclass then continue
                                for mproperty in self.mainmodule.properties(parent) do
                                        if not mproperty isa MMethod then continue
-                                       if not layout.pos.has_key(mproperty) then continue
-                                       var color = layout.pos[mproperty]
+                                       if not method_colors.has_key(mproperty) then continue
+                                       var color = method_colors[mproperty]
                                        if table.length <= color then
                                                for i in [table.length .. color[ do
                                                        table[i] = null
@@ -420,8 +385,8 @@ class SeparateCompiler
                        # then override with local properties
                        for mproperty in self.mainmodule.properties(mclass) do
                                if not mproperty isa MMethod then continue
-                               if not layout.pos.has_key(mproperty) then continue
-                               var color = layout.pos[mproperty]
+                               if not method_colors.has_key(mproperty) then continue
+                               var color = method_colors[mproperty]
                                if table.length <= color then
                                        for i in [table.length .. color[ do
                                                table[i] = null
@@ -444,7 +409,7 @@ class SeparateCompiler
                        end
                        # insert super calls in table according to receiver
                        for supercall in supercalls do
-                               var color = layout.pos[supercall]
+                               var color = method_colors[supercall]
                                if table.length <= color then
                                        for i in [table.length .. color[ do
                                                table[i] = null
@@ -459,7 +424,6 @@ class SeparateCompiler
        end
 
        fun build_attr_tables(mclasses: Set[MClass]): Map[MClass, Array[nullable MPropDef]] do
-               var layout = self.attr_layout
                var tables = new HashMap[MClass, Array[nullable MPropDef]]
                for mclass in mclasses do
                        var table = new Array[nullable MPropDef]
@@ -473,7 +437,7 @@ class SeparateCompiler
                                if parent == mclass then continue
                                for mproperty in self.mainmodule.properties(parent) do
                                        if not mproperty isa MAttribute then continue
-                                       var color = layout.pos[mproperty]
+                                       var color = attr_colors[mproperty]
                                        if table.length <= color then
                                                for i in [table.length .. color[ do
                                                        table[i] = null
@@ -490,7 +454,7 @@ class SeparateCompiler
                        # then override with local properties
                        for mproperty in self.mainmodule.properties(mclass) do
                                if not mproperty isa MAttribute then continue
-                               var color = layout.pos[mproperty]
+                               var color = attr_colors[mproperty]
                                if table.length <= color then
                                        for i in [table.length .. color[ do
                                                table[i] = null
@@ -509,29 +473,23 @@ class SeparateCompiler
 
        # colorize live types of the program
        private fun do_type_coloring: POSet[MType] do
+               # Collect types to colorize
+               var live_types = runtime_type_analysis.live_types
+               var live_cast_types = runtime_type_analysis.live_cast_types
                var mtypes = new HashSet[MType]
-               mtypes.add_all(self.runtime_type_analysis.live_types)
-               mtypes.add_all(self.runtime_type_analysis.live_cast_types)
+               mtypes.add_all(live_types)
+               mtypes.add_all(live_cast_types)
                for c in self.box_kinds.keys do
                        mtypes.add(c.mclass_type)
                end
 
-               # Typing Layout
-               var layout_builder: TypingLayoutBuilder[MType]
-               if modelbuilder.toolcontext.opt_bm_typing.value then
-                       layout_builder = new MTypeBMizer(self.mainmodule)
-               else if modelbuilder.toolcontext.opt_phmod_typing.value then
-                       layout_builder = new MTypeHasher(new PHModOperator, self.mainmodule)
-               else if modelbuilder.toolcontext.opt_phand_typing.value then
-                       layout_builder = new MTypeHasher(new PHAndOperator, self.mainmodule)
-               else
-                       layout_builder = new MTypeColorer(self.mainmodule)
-               end
-
-               # colorize types
-               self.type_layout = layout_builder.build_layout(mtypes)
-               var poset = layout_builder.poset.as(not null)
-               self.type_tables = self.build_type_tables(poset)
+               # Compute colors
+               var poset = poset_from_mtypes(mtypes)
+               var colorer = new POSetColorer[MType]
+               colorer.colorize(poset)
+               type_ids = colorer.ids
+               type_colors = colorer.colors
+               type_tables = build_type_tables(poset)
 
                # VT and FT are stored with other unresolved types in the big resolution_tables
                self.compile_resolution_tables(mtypes)
@@ -539,19 +497,27 @@ class SeparateCompiler
                return poset
        end
 
+       private fun poset_from_mtypes(mtypes: Set[MType]): POSet[MType] do
+               var poset = new POSet[MType]
+               for e in mtypes do
+                       poset.add_node(e)
+                       for o in mtypes do
+                               if e == o then continue
+                               if e.is_subtype(mainmodule, null, o) then
+                                       poset.add_edge(e, o)
+                               end
+                       end
+               end
+               return poset
+       end
+
        # Build type tables
        fun build_type_tables(mtypes: POSet[MType]): Map[MType, Array[nullable MType]] do
                var tables = new HashMap[MType, Array[nullable MType]]
-               var layout = self.type_layout
                for mtype in mtypes do
                        var table = new Array[nullable MType]
                        for sup in mtypes[mtype].greaters do
-                               var color: Int
-                               if layout isa PHLayout[MType, MType] then
-                                       color = layout.hashes[mtype][sup]
-                               else
-                                       color = layout.pos[sup]
-                               end
+                               var color = type_colors[sup]
                                if table.length <= color then
                                        for i in [table.length .. color[ do
                                                table[i] = null
@@ -584,18 +550,9 @@ class SeparateCompiler
                end
 
                # Compute the table layout with the prefered method
-               var resolution_builder: ResolutionLayoutBuilder
-               if modelbuilder.toolcontext.opt_bm_typing.value then
-                       resolution_builder = new ResolutionBMizer
-               else if modelbuilder.toolcontext.opt_phmod_typing.value then
-                       resolution_builder = new ResolutionHasher(new PHModOperator)
-               else if modelbuilder.toolcontext.opt_phand_typing.value then
-                       resolution_builder = new ResolutionHasher(new PHAndOperator)
-               else
-                       resolution_builder = new ResolutionColorer
-               end
-               self.resolution_layout = resolution_builder.build_layout(mtype2unresolved)
-               self.resolution_tables = self.build_resolution_tables(mtype2unresolved)
+               var colorer = new BucketsColorer[MType, MType]
+               opentype_colors = colorer.colorize(mtype2unresolved)
+               resolution_tables = self.build_resolution_tables(mtype2unresolved)
 
                # Compile a C constant for each collected unresolved type.
                # Either to a color, or to -1 if the unresolved type is dead (no live receiver can require it)
@@ -605,8 +562,8 @@ class SeparateCompiler
                end
                var all_unresolved_types_colors = new HashMap[MType, Int]
                for t in all_unresolved do
-                       if self.resolution_layout.pos.has_key(t) then
-                               all_unresolved_types_colors[t] = self.resolution_layout.pos[t]
+                       if opentype_colors.has_key(t) then
+                               all_unresolved_types_colors[t] = opentype_colors[t]
                        else
                                all_unresolved_types_colors[t] = -1
                        end
@@ -622,16 +579,10 @@ class SeparateCompiler
 
        fun build_resolution_tables(elements: Map[MClassType, Set[MType]]): Map[MClassType, Array[nullable MType]] do
                var tables = new HashMap[MClassType, Array[nullable MType]]
-               var layout = self.resolution_layout
                for mclasstype, mtypes in elements do
                        var table = new Array[nullable MType]
                        for mtype in mtypes do
-                               var color: Int
-                               if layout isa PHLayout[MClassType, MType] then
-                                       color = layout.hashes[mclasstype][mtype]
-                               else
-                                       color = layout.pos[mtype]
-                               end
+                               var color = opentype_colors[mtype]
                                if table.length <= color then
                                        for i in [table.length .. color[ do
                                                table[i] = null
@@ -668,7 +619,6 @@ class SeparateCompiler
        fun compile_type_to_c(mtype: MType)
        do
                assert not mtype.need_anchor
-               var layout = self.type_layout
                var is_live = mtype isa MClassType and runtime_type_analysis.live_types.has(mtype)
                var is_cast_live = runtime_type_analysis.live_cast_types.has(mtype)
                var c_name = mtype.c_name
@@ -683,7 +633,7 @@ class SeparateCompiler
 
                # type id (for cast target)
                if is_cast_live then
-                       v.add_decl("{layout.ids[mtype]},")
+                       v.add_decl("{type_ids[mtype]},")
                else
                        v.add_decl("-1, /*CAST DEAD*/")
                end
@@ -693,11 +643,7 @@ class SeparateCompiler
 
                # type color (for cast target)
                if is_cast_live then
-                       if layout isa PHLayout[MType, MType] then
-                               v.add_decl("{layout.masks[mtype]},")
-                       else
-                               v.add_decl("{layout.pos[mtype]},")
-                       end
+                       v.add_decl("{type_colors[mtype]},")
                else
                        v.add_decl("-1, /*CAST DEAD*/")
                end
@@ -733,7 +679,7 @@ class SeparateCompiler
                                if stype == null then
                                        v.add_decl("-1, /* empty */")
                                else
-                                       v.add_decl("{layout.ids[stype]}, /* {stype} */")
+                                       v.add_decl("{type_ids[stype]}, /* {stype} */")
                                end
                        end
                        v.add_decl("\},")
@@ -752,19 +698,13 @@ class SeparateCompiler
                        mclass_type = mtype.as(MClassType)
                end
 
-               var layout = self.resolution_layout
-
                # extern const struct resolution_table_X resolution_table_X
                self.provide_declaration("resolution_table_{mtype.c_name}", "extern const struct types resolution_table_{mtype.c_name};")
 
                # const struct fts_table_X fts_table_X
                var v = new_visitor
                v.add_decl("const struct types resolution_table_{mtype.c_name} = \{")
-               if layout isa PHLayout[MClassType, MType] then
-                       v.add_decl("{layout.masks[mclass_type]},")
-               else
-                       v.add_decl("0, /* dummy */")
-               end
+               v.add_decl("0, /* dummy */")
                v.add_decl("\{")
                for t in self.resolution_tables[mclass_type] do
                        if t == null then
@@ -775,7 +715,7 @@ class SeparateCompiler
                                # the value stored is tv.
                                var tv = t.resolve_for(mclass_type, mclass_type, self.mainmodule, true)
                                # FIXME: What typeids means here? How can a tv not be live?
-                               if self.type_layout.ids.has_key(tv) then
+                               if type_ids.has_key(tv) then
                                        v.require_declaration("type_{tv.c_name}")
                                        v.add_decl("&type_{tv.c_name}, /* {t}: {tv} */")
                                else
@@ -1476,11 +1416,7 @@ class SeparateCompilerVisitor
                        var recv = self.frame.arguments.first
                        var recv_type_info = self.type_info(recv)
                        self.require_declaration(mtype.const_color)
-                       if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
-                               return self.new_expr("NEW_{mtype.mclass.c_name}({recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {mtype.const_color})])", mtype)
-                       else
-                               return self.new_expr("NEW_{mtype.mclass.c_name}({recv_type_info}->resolution_table->types[{mtype.const_color}])", mtype)
-                       end
+                       return self.new_expr("NEW_{mtype.mclass.c_name}({recv_type_info}->resolution_table->types[{mtype.const_color}])", mtype)
                end
                compiler.undead_types.add(mtype)
                self.require_declaration("type_{mtype.c_name}")
@@ -1527,11 +1463,7 @@ class SeparateCompilerVisitor
                        hardening_live_open_type(mtype)
                        link_unresolved_type(self.frame.mpropdef.mclassdef, mtype)
                        self.require_declaration(mtype.const_color)
-                       if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
-                               self.add("{type_struct} = {recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {mtype.const_color})];")
-                       else
-                               self.add("{type_struct} = {recv_type_info}->resolution_table->types[{mtype.const_color}];")
-                       end
+                       self.add("{type_struct} = {recv_type_info}->resolution_table->types[{mtype.const_color}];")
                        if compiler.modelbuilder.toolcontext.opt_typing_test_metrics.value then
                                self.compiler.count_type_test_unresolved[tag] += 1
                                self.add("count_type_test_unresolved_{tag}++;")
@@ -1566,9 +1498,6 @@ class SeparateCompilerVisitor
                        self.add("\} else \{")
                end
                var value_type_info = self.type_info(value)
-               if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
-                       self.add("{cltype} = HASH({value_type_info}->color, {idtype});")
-               end
                self.add("if({cltype} >= {value_type_info}->table_size) \{")
                self.add("{res} = 0;")
                self.add("\} else \{")
@@ -1756,11 +1685,7 @@ class SeparateCompilerVisitor
                        var recv = self.frame.arguments.first
                        var recv_type_info = self.type_info(recv)
                        self.require_declaration(mtype.const_color)
-                       if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
-                               return self.new_expr("NEW_{mtype.mclass.c_name}({length}, {recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {mtype.const_color})])", mtype)
-                       else
-                               return self.new_expr("NEW_{mtype.mclass.c_name}({length}, {recv_type_info}->resolution_table->types[{mtype.const_color}])", mtype)
-                       end
+                       return self.new_expr("NEW_{mtype.mclass.c_name}({length}, {recv_type_info}->resolution_table->types[{mtype.const_color}])", mtype)
                end
                compiler.undead_types.add(mtype)
                self.require_declaration("type_{mtype.c_name}")
@@ -2006,10 +1931,14 @@ redef class MClass
        end
 end
 
+interface PropertyLayoutElement end
+
 redef class MProperty
+       super PropertyLayoutElement
        fun const_color: String do return "COLOR_{c_name}"
 end
 
 redef class MPropDef
+       super PropertyLayoutElement
        fun const_color: String do return "COLOR_{c_name}"
 end
index 4116d97..1942898 100644 (file)
@@ -67,7 +67,7 @@ redef class ModelBuilder
                                compiler.compile_class_to_c(mclass)
                        end
                end
-               compiler.compile_color_consts(compiler.vt_layout.pos)
+               compiler.compile_color_consts(compiler.vt_colors)
 
                # The main function of the C
                compiler.new_file("{mainmodule.name}.main")
@@ -91,30 +91,21 @@ end
 class SeparateErasureCompiler
        super SeparateCompiler
 
-       private var class_layout: nullable Layout[MClass]
-       protected var vt_layout: nullable Layout[MVirtualTypeProp]
+       private var class_ids: Map[MClass, Int]
+       private var class_colors: Map[MClass, Int]
+       protected var vt_colors: Map[MVirtualTypeProp, Int]
 
        init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: nullable RapidTypeAnalysis) do
                super
 
+               # Class coloring
                var mclasses = new HashSet[MClass].from(mmbuilder.model.mclasses)
-
-               var layout_builder: TypingLayoutBuilder[MClass]
-               var class_colorer = new MClassColorer(mainmodule)
-               if modelbuilder.toolcontext.opt_phmod_typing.value then
-                       layout_builder = new MClassHasher(new PHModOperator, mainmodule)
-                       class_colorer.build_layout(mclasses)
-               else if modelbuilder.toolcontext.opt_phand_typing.value then
-                       layout_builder = new MClassHasher(new PHAndOperator, mainmodule)
-                       class_colorer.build_layout(mclasses)
-               else if modelbuilder.toolcontext.opt_bm_typing.value then
-                       layout_builder = new MClassBMizer(mainmodule)
-                       class_colorer.build_layout(mclasses)
-               else
-                       layout_builder = class_colorer
-               end
-               self.class_layout = layout_builder.build_layout(mclasses)
-               self.class_tables = self.build_class_typing_tables(mclasses)
+               var poset = mainmodule.flatten_mclass_hierarchy
+               var colorer = new POSetColorer[MClass]
+               colorer.colorize(poset)
+               class_ids = colorer.ids
+               class_colors = colorer.colors
+               class_tables = self.build_class_typing_tables(mclasses)
 
                # lookup vt to build layout with
                var vts = new HashMap[MClass, Set[MVirtualTypeProp]]
@@ -128,13 +119,12 @@ class SeparateErasureCompiler
                end
 
                # vt coloration
-               var vt_coloring = new MPropertyColorer[MVirtualTypeProp](mainmodule, class_colorer)
-               var vt_layout = vt_coloring.build_layout(vts)
-               self.vt_tables = build_vt_tables(mclasses, vt_layout)
-               self.vt_layout = vt_layout
+               var vt_colorer = new POSetBucketsColorer[MClass, MVirtualTypeProp](poset, colorer.conflicts)
+               vt_colors = vt_colorer.colorize(vts)
+               vt_tables = build_vt_tables(mclasses)
        end
 
-       fun build_vt_tables(mclasses: Set[MClass], layout: Layout[MProperty]): Map[MClass, Array[nullable MPropDef]] do
+       fun build_vt_tables(mclasses: Set[MClass]): Map[MClass, Array[nullable MPropDef]] do
                var tables = new HashMap[MClass, Array[nullable MPropDef]]
                for mclass in mclasses do
                        var table = new Array[nullable MPropDef]
@@ -148,7 +138,7 @@ class SeparateErasureCompiler
                                if parent == mclass then continue
                                for mproperty in self.mainmodule.properties(parent) do
                                        if not mproperty isa MVirtualTypeProp then continue
-                                       var color = layout.pos[mproperty]
+                                       var color = vt_colors[mproperty]
                                        if table.length <= color then
                                                for i in [table.length .. color[ do
                                                        table[i] = null
@@ -165,7 +155,7 @@ class SeparateErasureCompiler
                        # then override with local properties
                        for mproperty in self.mainmodule.properties(mclass) do
                                if not mproperty isa MVirtualTypeProp then continue
-                               var color = layout.pos[mproperty]
+                               var color = vt_colors[mproperty]
                                if table.length <= color then
                                        for i in [table.length .. color[ do
                                                table[i] = null
@@ -185,7 +175,6 @@ class SeparateErasureCompiler
        # Build class tables
        fun build_class_typing_tables(mclasses: Set[MClass]): Map[MClass, Array[nullable MClass]] do
                var tables = new HashMap[MClass, Array[nullable MClass]]
-               var layout = self.class_layout
                for mclass in mclasses do
                        var table = new Array[nullable MClass]
                        var supers = new Array[MClass]
@@ -193,12 +182,7 @@ class SeparateErasureCompiler
                                supers = mclass.in_hierarchy(mainmodule).greaters.to_a
                        end
                        for sup in supers do
-                               var color: Int
-                               if layout isa PHLayout[MClass, MClass] then
-                                       color = layout.hashes[mclass][sup]
-                               else
-                                       color = layout.pos[sup]
-                               end
+                               var color = class_colors[sup]
                                if table.length <= color then
                                        for i in [table.length .. color[ do
                                                table[i] = null
@@ -217,19 +201,7 @@ class SeparateErasureCompiler
                self.header.add_decl("struct class \{ int id; const char *name; int box_kind; int color; const struct vts_table *vts_table; const struct type_table *type_table; nitmethod_t vft[]; \}; /* general C type representing a Nit class. */")
                self.header.add_decl("struct type_table \{ int size; int table[]; \}; /* colorized type table. */")
                self.header.add_decl("struct vts_entry \{ short int is_nullable; const struct class *class; \}; /* link (nullable or not) between the vts and is bound. */")
-
-               if self.vt_layout isa PHLayout[MClass, MVirtualTypeProp] then
-                       self.header.add_decl("struct vts_table \{ int mask; const struct vts_entry vts[]; \}; /* vts list of a C type representation. */")
-               else
-                       self.header.add_decl("struct vts_table \{ int dummy; const struct vts_entry vts[]; \}; /* vts list of a C type representation. */")
-               end
-
-               if modelbuilder.toolcontext.opt_phmod_typing.value then
-                       self.header.add_decl("#define HASH(mask, id) ((mask)%(id))")
-               else if modelbuilder.toolcontext.opt_phand_typing.value then
-                       self.header.add_decl("#define HASH(mask, id) ((mask)&(id))")
-               end
-
+               self.header.add_decl("struct vts_table \{ int dummy; const struct vts_entry vts[]; \}; /* vts list of a C type representation. */")
                self.header.add_decl("typedef struct instance \{ const struct class *class; nitattribute_t attrs[1]; \} val; /* general C type representing a Nit instance. */")
        end
 
@@ -257,15 +229,10 @@ class SeparateErasureCompiler
 
                # Build class vft
                v.add_decl("const struct class class_{c_name} = \{")
-               v.add_decl("{self.class_layout.ids[mclass]},")
+               v.add_decl("{class_ids[mclass]},")
                v.add_decl("\"{mclass.name}\", /* class_name_string */")
                v.add_decl("{self.box_kind_of(mclass)}, /* box_kind */")
-               var layout = self.class_layout
-               if layout isa PHLayout[MClass, MClass] then
-                       v.add_decl("{layout.masks[mclass]},")
-               else
-                       v.add_decl("{layout.pos[mclass]},")
-               end
+               v.add_decl("{class_colors[mclass]},")
                if not is_dead then
                        if build_class_vts_table(mclass) then
                                v.require_declaration("vts_table_{c_name}")
@@ -307,7 +274,7 @@ class SeparateErasureCompiler
                        if msuper == null then
                                v.add_decl("-1, /* empty */")
                        else
-                               v.add_decl("{self.class_layout.ids[msuper]}, /* {msuper} */")
+                               v.add_decl("{self.class_ids[msuper]}, /* {msuper} */")
                        end
                end
                v.add_decl("\}")
@@ -383,12 +350,7 @@ class SeparateErasureCompiler
 
                var v = new_visitor
                v.add_decl("const struct vts_table vts_table_{mclass.c_name} = \{")
-               if self.vt_layout isa PHLayout[MClass, MVirtualTypeProp] then
-                       #TODO redo this when PHPropertyLayoutBuilder will be implemented
-                       #v.add_decl("{vt_masks[mclass]},")
-               else
-                       v.add_decl("0, /* dummy */")
-               end
+               v.add_decl("0, /* dummy */")
                v.add_decl("\{")
 
                for vt in self.vt_tables[mclass] do
@@ -570,11 +532,7 @@ class SeparateErasureCompilerVisitor
                        var entry = self.get_name("entry")
                        self.add("struct vts_entry {entry};")
                        self.require_declaration(mtype.mproperty.const_color)
-                       if self.compiler.as(SeparateErasureCompiler).vt_layout isa PHLayout[MClass, MVirtualTypeProp] then
-                               self.add("{entry} = {recv_ptr}vts_table->vts[HASH({recv_ptr}vts_table->mask, {mtype.mproperty.const_color})];")
-                       else
-                               self.add("{entry} = {recv_ptr}vts_table->vts[{mtype.mproperty.const_color}];")
-                       end
+                       self.add("{entry} = {recv_ptr}vts_table->vts[{mtype.mproperty.const_color}];")
                        self.add("{cltype} = {entry}.class->color;")
                        self.add("{idtype} = {entry}.class->id;")
                        if maybe_null and accept_null == "0" then
@@ -598,9 +556,6 @@ class SeparateErasureCompilerVisitor
                        self.add("{res} = {accept_null};")
                        self.add("\} else \{")
                end
-               if self.compiler.as(SeparateErasureCompiler).class_layout isa PHLayout[MClass, MClass] then
-                       self.add("{cltype} = HASH({class_ptr}color, {idtype});")
-               end
                self.add("if({cltype} >= {class_ptr}type_table->size) \{")
                self.add("{res} = 0;")
                self.add("\} else \{")
index 9cae36f..92a1c6a 100644 (file)
@@ -79,16 +79,6 @@ private class TypeVisitor
                return res
        end
 
-       # Retrieve the signature of a `MMethodDef` resolved for a specific call.
-       # This method is an helper to symplify the query on the model.
-       #
-       # Note: `for_self` indicates if the reciever is self or not.
-       # If yes, virtual types are not resolved.
-       fun resolve_signature_for(mmethoddef: MMethodDef, recv: MType, for_self: Bool): MSignature
-       do
-               return self.resolve_for(mmethoddef.msignature.as(not null), recv, for_self).as(MSignature)
-       end
-
        # Check that `sub` is a subtype of `sup`.
        # If `sub` is not a valud suptype, then display an error on `node` an return null.
        # If `sub` is a safe subtype of `sup` then return `sub`.
@@ -260,7 +250,8 @@ private class TypeVisitor
                end
 
 
-               var msignature = self.resolve_signature_for(mpropdef, recvtype, recv_is_self)
+               var msignature = mpropdef.msignature.as(not null)
+               msignature = resolve_for(msignature, recvtype, recv_is_self).as(MSignature)
 
                var erasure_cast = false
                var rettype = mpropdef.msignature.return_mtype
@@ -479,17 +470,17 @@ redef class APropdef
        var selfvariable: nullable Variable
 end
 
-redef class AConcreteMethPropdef
+redef class AMethPropdef
        redef fun do_typing(modelbuilder: ModelBuilder)
        do
+               var nblock = self.n_block
+               if nblock == null then return
+
                var nclassdef = self.parent.as(AClassdef)
                var mpropdef = self.mpropdef.as(not null)
                var v = new TypeVisitor(modelbuilder, nclassdef, mpropdef)
                self.selfvariable = v.selfvariable
 
-               var nblock = self.n_block
-               if nblock == null then return
-
                var mmethoddef = self.mpropdef.as(not null)
                for i in [0..mmethoddef.msignature.arity[ do
                        var mtype = mmethoddef.msignature.mparameters[i].mtype
@@ -1455,7 +1446,8 @@ redef class ASuperExpr
                # FIXME: covariance of return type in linear extension?
                var superprop = superprops.first
 
-               var msignature = v.resolve_signature_for(superprop, recvtype, true)
+               var msignature = superprop.msignature.as(not null)
+               msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
                var args = self.n_args.to_a
                if args.length > 0 then
                        v.check_signature(self, args, mproperty.name, msignature)
@@ -1501,7 +1493,9 @@ redef class ASuperExpr
                        return
                end
 
-               var msignature = v.resolve_signature_for(superprop, recvtype, true)
+               var msignature = 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)
                self.callsite = callsite
 
diff --git a/tests/base_init_combine.nit b/tests/base_init_combine.nit
new file mode 100644 (file)
index 0000000..e30298f
--- /dev/null
@@ -0,0 +1,60 @@
+# 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 1.output
+end
+
+class B
+       init do 2.output
+end
+
+class C
+       super A
+       super B
+
+       init do 3.output
+end
+
+class D
+       super A
+       super B
+
+       var i: Int
+end
+
+class E
+       super A
+       super B
+
+       var i: Int
+       init(i: Int) do
+               self.i = i
+               i.output
+       end
+end
+
+class F
+       super E
+       #alt1# var z: Int
+end
+
+var a = new A
+var b = new B
+var c = new C
+var d = new D(4)
+var e = new E(5)
+var f = new F(6)
index ca5debe..ae42bee 100644 (file)
@@ -32,6 +32,7 @@ class WakeUpNode
                _scheduler.add_event(self, d)
        end
        var _scheduler: Scheduler
+       init do end
 end
 
 class NodeSource
index 75feb69..e589ec7 100644 (file)
@@ -15,9 +15,9 @@
 # limitations under the License.
 
 class A
-       var _a: Int
+       var _a: Int = 1
 end
 class B
        super A
-       redef var _a: Object
+       redef var _a: Object = 2
 end
index e1ba289..4050a44 100644 (file)
@@ -2,4 +2,3 @@ init_inherit
 init_linext
 inline
 test_json
-pep8analysis_args
index ed1c634..1368f63 100644 (file)
@@ -2,5 +2,4 @@ init_inherit
 init_linext
 inline
 nitg
-test_json
 mnit
index e1ba289..4050a44 100644 (file)
@@ -2,4 +2,3 @@ init_inherit
 init_linext
 inline
 test_json
-pep8analysis_args
diff --git a/tests/sav/base_init_combine.res b/tests/sav/base_init_combine.res
new file mode 100644 (file)
index 0000000..d210e23
--- /dev/null
@@ -0,0 +1,13 @@
+1
+2
+1
+2
+3
+1
+2
+1
+2
+5
+1
+2
+6
diff --git a/tests/sav/base_init_combine_alt1.res b/tests/sav/base_init_combine_alt1.res
new file mode 100644 (file)
index 0000000..5759dba
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_combine_alt1.nit:52,6: Error: base_init_combine_alt1#F cannot inherit constructors from E because there is attributes without initial values: z: Int
index 8ac105d..4b258f9 100644 (file)
@@ -1 +1 @@
-alt/base_init_simple_alt1.nit:15,8--11: Error: No property B::init3 is inherited. Remove the redef keyword to define a new property.
+alt/base_init_simple_alt1.nit:15,13--17: Error: No property B::init3 is inherited. Remove the redef keyword to define a new property.
diff --git a/tests/sav/test_json.res b/tests/sav/test_json.res
deleted file mode 100644 (file)
index 146e88b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{"int":"1234","float":"0.123","str":"str","null": null}
-{"int":1234,"float":0.123400,"str":"str","null":null}
-{"arr":"123","obj":"{"int":"123","float":"-234.45"}"}
-{"arr":[1,2,3],"obj":{"int":123,"float":-234.449997}}
-{"arr":"12.3str","obj":"{"int":"123","float":"-234.45"}"}
-{"arr":[1,2.300000,null,"str"],"obj":{"int":123,"float":-234.449997}}
index b6f1b43..ae5bfb0 100644 (file)
@@ -55,12 +55,7 @@ same paragraph</p><p>Other paragraph with <code class="nitcode"><span class="nit
 but long
 bullet</li></ul><pre class="nitcode"><span class="nitcode"><span class="nc_k"></span><span class="nc_i">some</span>
 <span class="nc_i">block</span>
-<span class="nc_k"></span>some
-block
 </span></pre><p>a first example</p><pre class="nitcode"><span class="nitcode"><span class="nc_k"></span><span class="nc_k">assert</span> <span class="nc_l">1</span> <span class="nc_o">+</span> <span class="nc_l">1</span> <span class="nc_o">==</span> <span class="nc_l">2</span>
-<span class="nc_k"></span>assert 1 + 1 == 2
 </span></pre><p>and a last example to illustrate the <code class="nitcode"><span class="nitcode"><span class="nc_i">to_s</span></span></code> method on <code class="nitcode"><span class="nitcode"><span class="nc_k"></span><span class="nc_v nc_i"></span><span class="nc_t"></span><span class="nc_t">A</span></span></code>.</p><pre class="nitcode"><span class="nitcode"><span class="nc_k"></span><span class="nc_k">var</span> <span class="nc_v nc_i">a</span> = <span class="nc_k">new</span> <span class="nc_t">A</span>
 <span class="nc_k">assert</span> <span class="nc_i">a</span><span class="nc_o">.</span><span class="nc_i">to_s</span> <span class="nc_o">==</span> <span class="nc_s">&quot;A&quot;</span>
-<span class="nc_k"></span>var a = new A
-assert a.to_s == &quot;A&quot;
 </span></pre></div></body></html>
\ No newline at end of file
index 16b4a6c..dc855e5 100644 (file)
@@ -9,7 +9,6 @@
         AImplicitSelfExpr 1,7
         TId "world" 1,7--11
         AListExprs 1,11
-  TKwend "" 1,1--0
 --> AStringExpr 1,1--13
   TString "\"hello world\"" 1,1--13
 --> ABlockExpr 1,1--0
@@ -25,7 +24,6 @@
       AImplicitSelfExpr 1,15
       TId "p" 1,15
       AListExprs 1,15
-  TKwend "" 1,1--0
 --> AModule 1,1--12
   ATopClassdef 1,1--12
     AConcreteMethPropdef 1,1--12
@@ -53,7 +51,6 @@
         TId "p" 2,1
         AListExprs 2,1
       TKwend "end" 3,1--3
-  TKwend "" 1,1--0
 --> ... ... ... ... AModule 1,1--5,3
   ATopClassdef 1,1--5,3
     AConcreteMethPropdef 1,1--5,3
diff --git a/tests/test_json.nit b/tests/test_json.nit
deleted file mode 100644 (file)
index fadb6cc..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
-#
-# 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.
-
-module test_json
-
-import json
-
-redef class HashMap[K,V]
-       redef fun to_s
-       do
-               var es = new Array[String]
-               for k, v in self do
-                       if v != null then
-                               es.add( "\"{k}\":\"{v}\"" )
-                       else
-                               es.add( "\"{k}\": null" )
-                       end
-               end
-               return "\{{es.join(",")}\}"
-       end
-end
-
-redef class String
-       fun parse_and_display
-       do
-               var json_map = json_to_object
-               if json_map != null then
-                       print json_map
-                       print json_map.to_json.replace(" ","")
-
-                       # only available for libjson0 v0.10
-                       # print json_map.to_pretty_json
-               else
-                       print "Conversion to json failed."
-               end
-       end
-end
-
-fun print_usage do print "Usage: json input.json"
-
-if args.length == 1 then
-       var input_path = args.first
-       var input_file = new IFStream.open( input_path )
-       var input_text = input_file.read_all
-       input_file.close
-
-       input_text.parse_and_display
-else
-       var s = "\{\"int\":1234, \"float\":0.1234, \"str\":\"str\", \"null\":null\}"
-       s.parse_and_display
-
-       s = "\{\"arr\":[1,2,3], \"obj\":\{\"int\":123, \"float\":-234.45\}\}"
-       s.parse_and_display
-
-       s = "\{\"arr\":[1,2.3,null,\"str\"], \"obj\":\{\"int\":123, \"float\":-234.45\}\}"
-       s.parse_and_display
-end
similarity index 56%
rename from tests/test_simple_json_reader.nit
rename to tests/test_json_static.nit
index f38cbaa..b510725 100644 (file)
@@ -1,4 +1,20 @@
-import simple_json_reader
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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 json::static
 
 redef class HashMap[K,V]
        redef fun to_s do return "<HashMap {join(", ", ": ")}>"