Merge: Opportunity
authorJean Privat <jean@pryen.org>
Wed, 12 Nov 2014 03:14:30 +0000 (22:14 -0500)
committerJean Privat <jean@pryen.org>
Wed, 12 Nov 2014 03:14:30 +0000 (22:14 -0500)
Added 2 features to Opportunity, namely the maybe option and the count for the answers, as well as a visual hint for the best answer.

Also fixed a few bugs, some Update statements were wrong.

Pull-Request: #885
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Jean Privat <jean@pryen.org>

204 files changed:
Makefile
benchmarks/bench_strings.sh
benchmarks/strings/chain_concat.nit
benchmarks/strings/iteration_bench.nit
benchmarks/strings/substr_bench.nit
c_src/Makefile
c_src/nith.mk
contrib/neo_doxygen/Makefile [new file with mode: 0644]
contrib/neo_doxygen/gen-all.sh [new file with mode: 0755]
contrib/neo_doxygen/gen-one.sh [new file with mode: 0755]
contrib/neo_doxygen/sh-lib/errors.sh [new file with mode: 0644]
contrib/neo_doxygen/src/doxml/compounddef.nit [new file with mode: 0644]
contrib/neo_doxygen/src/doxml/doc.nit [new file with mode: 0644]
contrib/neo_doxygen/src/doxml/doxml.nit [new file with mode: 0644]
contrib/neo_doxygen/src/doxml/entitydef.nit [new file with mode: 0644]
contrib/neo_doxygen/src/doxml/language_specific.nit [new file with mode: 0644]
contrib/neo_doxygen/src/doxml/listener.nit [new file with mode: 0644]
contrib/neo_doxygen/src/doxml/memberdef.nit [new file with mode: 0644]
contrib/neo_doxygen/src/model/class_compound.nit [new file with mode: 0644]
contrib/neo_doxygen/src/model/graph.nit [new file with mode: 0644]
contrib/neo_doxygen/src/model/linked_text.nit [new file with mode: 0644]
contrib/neo_doxygen/src/model/location.nit [new file with mode: 0644]
contrib/neo_doxygen/src/model/member.nit [new file with mode: 0644]
contrib/neo_doxygen/src/model/model.nit [new file with mode: 0644]
contrib/neo_doxygen/src/model/module_compound.nit [new file with mode: 0644]
contrib/neo_doxygen/src/model/type_entity.nit [new file with mode: 0644]
contrib/neo_doxygen/src/neo_doxygen.nit [new file with mode: 0644]
contrib/nitester/src/nitester.nit
contrib/online_ide/sources/nit/pnacl_nit.nit
contrib/pep8analysis/Makefile
contrib/sort_downloads/src/sort_downloads.nit
doc/advanced_options [deleted file]
examples/pnacl/converter/Makefile
examples/pnacl/converter/README
lib/ai/examples/puzzle.nit
lib/buffered_ropes.nit [new file with mode: 0644]
lib/bufferized_ropes.nit [deleted file]
lib/cartesian.nit [new file with mode: 0644]
lib/combinations.nit [new file with mode: 0644]
lib/console.nit
lib/html/html.nit
lib/java/java.nit
lib/jvm.nit
lib/more_collections.nit
lib/neo4j/curl_json.nit
lib/neo4j/json_store.nit [new file with mode: 0644]
lib/neo4j/neo4j.nit
lib/opts.nit
lib/ordered_tree.nit
lib/perfect_hashing.nit
lib/poset.nit
lib/ropes_debug.nit
lib/splay_ropes.nit [deleted file]
lib/sqlite3/native_sqlite3.nit
lib/standard/collection/abstract_collection.nit
lib/standard/collection/array.nit
lib/standard/collection/hash_collection.nit
lib/standard/collection/list.nit
lib/standard/collection/range.nit
lib/standard/file.nit
lib/standard/math.nit
lib/standard/queue.nit
lib/standard/ropes.nit
lib/standard/standard.nit
lib/standard/stream.nit
lib/standard/string.nit
lib/standard/string_search.nit
lib/string_experimentations/utf8_noindex.nit
misc/jenkins/nitester-wrapper.sh [new file with mode: 0755]
misc/jenkins/unitrun.sh
share/man/.gitignore [new file with mode: 0644]
share/man/Makefile
share/man/README.md
share/man/man1/nitc.1 [new symlink]
share/man/nit.md
share/man/nitdbg_client.md [new file with mode: 0644]
share/man/nitdoc.md
share/man/nitg.md
share/man/nitlight.md
share/man/nitls.md
share/man/nitmetrics.md
share/man/nitpick.md
share/man/nitpretty.md
share/man/nitserial.md
share/man/nitunit.md
share/man/nitx.md
src/c_tools.nit
src/compiler/abstract_compiler.nit
src/compiler/android_platform.nit
src/compiler/coloring.nit
src/compiler/compiler_ffi.nit
src/compiler/global_compiler.nit
src/compiler/separate_compiler.nit
src/compiler/separate_erasure_compiler.nit
src/doc/doc_model.nit
src/doc/doc_pages.nit
src/doc/doc_templates.nit
src/doc/model_ext.nit [new file with mode: 0644]
src/ffi/c.nit
src/ffi/c_compiler_options.nit
src/ffi/cpp.nit
src/ffi/ffi.nit
src/ffi/ffi_base.nit
src/ffi/java.nit
src/ffi/pkgconfig.nit
src/frontend/cached.nit
src/frontend/div_by_zero.nit
src/frontend/serialization_phase.nit
src/frontend/simple_misc_analysis.nit
src/interpreter/debugger.nit
src/interpreter/naive_interpreter.nit
src/literal.nit
src/location.nit
src/metrics/generate_hierarchies.nit
src/model/mmodule.nit
src/model/model.nit
src/model/model_base.nit
src/model/model_viz.nit
src/model/mproject.nit
src/modelbuilder.nit
src/modelize/modelize_property.nit
src/neo.nit
src/nit.nit
src/nitni/nitni_utilities.nit
src/nitunit.nit
src/nitx.nit
src/parser/lexer_work.nit
src/parser/parser_nodes.nit
src/parser/parser_work.nit
src/parser_util.nit
src/phase.nit
src/rapid_type_analysis.nit
src/semantize/auto_super_init.nit
src/semantize/flow.nit
src/semantize/local_var_init.nit
src/semantize/scope.nit
src/semantize/typing.nit
src/testing/testing_doc.nit
src/testing/testing_suite.nit
src/toolcontext.nit
src/transform.nit
src/vm.nit
tests/base_new.nit
tests/bench_string_append.nit
tests/example_procedural_string.nit
tests/example_string.nit
tests/listfull.sh
tests/nit.args
tests/sav/base_error_new_abstract.res
tests/sav/base_error_new_interface.res
tests/sav/base_new.res
tests/sav/base_new_alt5.res
tests/sav/base_new_alt6.res
tests/sav/base_new_alt7.res
tests/sav/base_new_alt8.res
tests/sav/bench_string_append_alt1.res [new file with mode: 0644]
tests/sav/error_needed_method_alt2.res
tests/sav/example_procedural_string_alt1.res [new file with mode: 0644]
tests/sav/example_string_alt1.res [new file with mode: 0644]
tests/sav/nitdoc_args1.res
tests/sav/nitg-e/fixme/base_conflict_submodule_name.res [deleted file]
tests/sav/nitg-e/fixme/base_conflict_submodule_name_alt1.res [deleted file]
tests/sav/nitg-e/fixme/base_conflict_submodule_name_alt2.res [deleted file]
tests/sav/nitg-g/fixme/base_conflict_submodule_name.res [deleted file]
tests/sav/nitg-g/fixme/base_conflict_submodule_name_alt1.res [deleted file]
tests/sav/nitg-g/fixme/base_conflict_submodule_name_alt2.res [deleted file]
tests/sav/nitg-s/fixme/base_conflict_submodule_name.res [deleted file]
tests/sav/nitg-s/fixme/base_conflict_submodule_name_alt1.res [deleted file]
tests/sav/nitg-s/fixme/base_conflict_submodule_name_alt2.res [deleted file]
tests/sav/nitg-sg/fixme/base_conflict_submodule_name.res [deleted file]
tests/sav/nitg-sg/fixme/base_conflict_submodule_name_alt1.res [deleted file]
tests/sav/nitg-sg/fixme/base_conflict_submodule_name_alt2.res [deleted file]
tests/sav/nitmetrics_args1.res
tests/sav/nitunit_args1.res
tests/sav/puzzle_args1.res
tests/sav/splay_test.res [deleted file]
tests/sav/string_trim_alt1.res [new file with mode: 0644]
tests/sav/test_ffi_c_duplicated_callback_a.res [new file with mode: 0644]
tests/sav/test_ffi_c_duplicated_callback_b.res [new file with mode: 0644]
tests/sav/test_ffi_cpp_duplicated_callback_a.res [new file with mode: 0644]
tests/sav/test_ffi_cpp_duplicated_callback_b.res [new file with mode: 0644]
tests/sav/test_new_native_alt1.res
tests/sav/test_ropes.res
tests/sav/test_ropes_alt1.res [deleted file]
tests/sav/test_ropes_alt2.res [deleted file]
tests/sav/test_string_long_alt1.res [new file with mode: 0644]
tests/sav/test_to_upper_lower_buffer_alt1.res [new file with mode: 0644]
tests/sav/test_toolcontext_args1.res
tests/sav/test_toolcontext_args2.res
tests/shootout_nsieve.nit
tests/splay_test.nit [deleted file]
tests/string_trim.nit
tests/test_arr_tos_ropes.nit
tests/test_ffi_c_duplicated_callback_a.nit [new file with mode: 0644]
tests/test_ffi_c_duplicated_callback_b.nit [new file with mode: 0644]
tests/test_ffi_cpp_duplicated_callback_a.nit [new file with mode: 0644]
tests/test_ffi_cpp_duplicated_callback_b.nit [new file with mode: 0644]
tests/test_ffi_java_global.nit [new file with mode: 0644]
tests/test_flatrope.nit
tests/test_ropes.nit
tests/test_string_long.nit
tests/test_text.nit
tests/test_to_upper_lower_buffer.nit
tests/tests.sh

index 636e0ce..326d49b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -66,12 +66,16 @@ doc/nitc/index.html: bin/nitdoc bin/nitls
                --piwik-tracker "pratchett.info.uqam.ca/piwik/" \
                --piwik-site-id "3"
 
+man:
+       $(MAKE) -C share/man
+
 clean:
        rm -rf -- .nit_compile 2> /dev/null || true
        rm -rf -- doc/stdlib doc/nitc || true
        cd c_src; make clean
        cd src; make clean
        cd tests; make clean
+       cd share/man; make clean
        for m in $(PROGS); do \
                $(MAKE) clean -C "$$m"; \
                test -d $$m/.nit_compile && rm -r $$m/.nit_compile; \
index c327d58..0bb13a7 100755 (executable)
@@ -54,7 +54,7 @@ function bench_array()
                echo "*** Benching Array.to_s performance ***"
        fi
 
-       ../bin/nitg --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_rope.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+       ../bin/nitg --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_flatstr.nit -m ../lib/standard/ropes.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
 
        prepare_res arr_tos_ropes.out arr_tos_ropes ropes
        if $verbose; then
@@ -67,6 +67,19 @@ function bench_array()
                bench_command $i ropes$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
        done
 
+       ../bin/nitg --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_flatstr.nit -m ../lib/standard/ropes.nit -m ../lib/buffered_ropes.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
+       prepare_res arr_tos_buf_ropes.out arr_tos_buf_ropes buffered_ropes
+       if $verbose; then
+               echo "Buffered Ropes :"
+       fi
+       for i in `seq 1 "$3"`; do
+               if $verbose; then
+                       echo "String length = $i, Concats/loop = $1, Loops = $2"
+               fi
+               bench_command $i buf_ropes$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
+       done
+
        ../bin/nitg --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_flatstr.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
 
        prepare_res arr_tos_flat.out arr_tos_flat flatstring
@@ -110,7 +123,7 @@ function bench_array()
 
        prepare_res arr_tos_man_buf.out arr_tos_man_buf flatbuf_with_capacity
        if $verbose; then
-               echo "Memmove :"
+               echo "FlatBuffer.with_capacity :"
        fi
        for i in `seq 1 "$3"`; do
                if $verbose; then
@@ -119,25 +132,30 @@ function bench_array()
                bench_command $i flatbuf_with_capacity$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
        done
 
+       ../bin/nitg --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_rope_buf.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
+       prepare_res arr_tos_rope_buf.out arr_tos_rope_buf ropebuf
+       if $verbose; then
+               echo "RopeBuffer :"
+       fi
+       for i in `seq 1 "$3"`; do
+               if $verbose; then
+                       echo "String length = $i, Concats/loop = $1, Loops = $2"
+               fi
+               bench_command $i ropebuf$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
+       done
+
        plot array_tos.gnu
 }
 
 function bench_concat()
 {
-       if $verbose; then
-               echo "*** Benching concat performance ***"
-       fi
+       ../bin/nitg --global ./strings/chain_concat.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+       ../bin/nitg --global ./strings/utf_chain_concat.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
 
-       prepare_res concat_ropes.out concat_ropes ropes
        if $verbose; then
-               echo "Ropes :"
+               echo "*** Benching concat performance ***"
        fi
-       for i in `seq 1 "$1"`; do
-               if $verbose; then
-                       echo "String length = $i, Concats/loop = $2, Loops = $3"
-               fi
-               bench_command $i ropes$i ./chain_concat -m rope --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
-       done
 
        prepare_res concat_flat.out concat_flat flatstring
        if $verbose; then
@@ -172,37 +190,57 @@ function bench_concat()
                bench_command $i flatstr_utf8_noindex$i ./utf_chain_concat -m flatstr_utf8_noindex --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
        done
 
-       plot concat.gnu
-}
+       ../bin/nitg --global ./strings/chain_concat.nit -m ../lib/standard/ropes.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
 
-function bench_iteration()
-{
+       prepare_res concat_ropes.out concat_ropes ropes
        if $verbose; then
-               echo "*** Benching iteration performance ***"
+               echo "Ropes :"
        fi
+       for i in `seq 1 "$1"`; do
+               if $verbose; then
+                       echo "String length = $i, Concats/loop = $2, Loops = $3"
+               fi
+               bench_command $i ropes$i ./chain_concat -m flatstr --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+       done
 
-       prepare_res iter_ropes_iter.out iter_ropes_iter ropes_iter
+       ../bin/nitg --global ./strings/chain_concat.nit -m ../lib/standard/ropes.nit -m ../lib/buffered_ropes.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
+       prepare_res concat_buf_ropes.out concat_buf_ropes buffered_ropes
        if $verbose; then
-               echo "Ropes by iterator :"
+               echo "buffered ropes :"
        fi
        for i in `seq 1 "$1"`; do
                if $verbose; then
-                       echo "String base length = $1, Concats (depth of the rope) = $i, Loops = $3"
+                       echo "string length = $i, concats/loop = $2, loops = $3"
                fi
-               bench_command $i ropes_iter$i ./iteration_bench -m rope --iter-mode iterator --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i buf_ropes$i ./chain_concat -m flatstr --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
        done
 
-       prepare_res iter_ropes_index.out iter_ropes_index ropes_index
+       ../bin/nitg --global ./strings/chain_cct_ropebuf.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
+       prepare_res cct_buf_ropes.out cct_buf_ropes cctbuf_ropes
        if $verbose; then
-               echo "Ropes by index :"
+               echo "buffered ropes :"
        fi
        for i in `seq 1 "$1"`; do
                if $verbose; then
-                       echo "String base length = $1, Concats (depth of the rope) = $i, Loops = $3"
+                       echo "string length = $i, concats/loop = $2, loops = $3"
                fi
-               bench_command $i ropes_index$i ./iteration_bench -m rope --iter-mode index --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i cctbuf_ropes$i ./chain_cct_ropebuf --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
        done
 
+       plot concat.gnu
+}
+
+function bench_iteration()
+{
+       if $verbose; then
+               echo "*** Benching iteration performance ***"
+       fi
+
+       ../bin/nitg --global ./strings/iteration_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+       ../bin/nitg --global ./strings/utf_iteration_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
        prepare_res iter_flat_iter.out iter_flat_iter flatstring_iter
        if $verbose; then
                echo "FlatStrings by iterator :"
@@ -269,26 +307,66 @@ function bench_iteration()
                bench_command $i flatstr_index_utf8_noindex$i ./utf_iteration_bench -m flatstr_utf8_noindex --iter-mode index --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
        done
 
-       plot iter.gnu
-}
+       ../bin/nitg --global ./strings/iteration_bench.nit -m ../lib/standard/ropes.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
 
-function bench_substr()
-{
+       prepare_res iter_ropes_iter.out iter_ropes_iter ropes_iter
        if $verbose; then
-               echo "*** Benching substring performance ***"
+               echo "Ropes by iterator :"
        fi
+       for i in `seq 1 "$1"`; do
+               if $verbose; then
+                       echo "String base length = $1, Concats (depth of the rope) = $i, Loops = $3"
+               fi
+               bench_command $i ropes_iter$i ./iteration_bench -m flatstr --iter-mode iterator --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+       done
 
-       prepare_res substr_ropes.out substr_ropes ropes
+       prepare_res iter_ropes_index.out iter_ropes_index ropes_index
        if $verbose; then
-               echo "Ropes :"
+               echo "Ropes by index :"
        fi
        for i in `seq 1 "$1"`; do
                if $verbose; then
-                       echo "String length = $i, loops = $2, Loops = $3"
+                       echo "String base length = $1, Concats (depth of the rope) = $i, Loops = $3"
+               fi
+               bench_command $i ropes_index$i ./iteration_bench -m flatstr --iter-mode index --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+       done
+
+       ../bin/nitg --global ./strings/iteration_bench.nit -m ../lib/standard/ropes.nit -m ../lib/buffered_ropes.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
+       prepare_res iter_buf_ropes_iter.out iter_buf_ropes_iter buf_ropes_iter
+       if $verbose; then
+               echo "Buffered Ropes by iterator :"
+       fi
+       for i in `seq 1 "$1"`; do
+               if $verbose; then
+                       echo "String base length = $1, Concats (depth of the rope) = $i, Loops = $3"
+               fi
+               bench_command $i buf_ropes_iter$i ./iteration_bench -m flatstr --iter-mode iterator --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+       done
+
+       prepare_res iter_buf_ropes_index.out iter_buf_ropes_index buf_ropes_index
+       if $verbose; then
+               echo "Buffered Ropes by index :"
+       fi
+       for i in `seq 1 "$1"`; do
+               if $verbose; then
+                       echo "String base length = $1, Concats (depth of the rope) = $i, Loops = $3"
                fi
-               bench_command $i ropes$i ./substr_bench -m rope --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i buf_ropes_index$i ./iteration_bench -m flatstr --iter-mode index --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
        done
 
+       plot iter.gnu
+}
+
+function bench_substr()
+{
+       if $verbose; then
+               echo "*** Benching substring performance ***"
+       fi
+
+       ../bin/nitg --global ./strings/substr_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+       ../bin/nitg --global ./strings/utf_substr_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
        prepare_res substr_flat.out substr_flat flatstring
        if $verbose; then
                echo "FlatStrings :"
@@ -322,6 +400,31 @@ function bench_substr()
                bench_command $i flatstring_utf8_noindex$i ./utf_substr_bench -m flatstr_utf8_noindex --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
        done
 
+       ../bin/nitg --global ./strings/substr_bench.nit -m ../lib/standard/ropes.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
+       prepare_res substr_ropes.out substr_ropes ropes
+       if $verbose; then
+               echo "Ropes :"
+       fi
+       for i in `seq 1 "$1"`; do
+               if $verbose; then
+                       echo "String length = $i, loops = $2, Loops = $3"
+               fi
+               bench_command $i ropes$i ./substr_bench -m flatstr --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+       done
+
+       ../bin/nitg --global ./strings/substr_bench.nit -m ../lib/standard/ropes.nit -m ../lib/buffered_ropes.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+
+       prepare_res substr_buf_ropes.out substr_buf_ropes buf_ropes
+       if $verbose; then
+               echo "Buffered Ropes :"
+       fi
+       for i in `seq 1 "$1"`; do
+               if $verbose; then
+                       echo "String length = $i, loops = $2, Loops = $3"
+               fi
+               bench_command $i buf_ropes$i ./substr_bench -m flatstr --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+       done
        plot substr.gnu
 }
 
@@ -340,17 +443,6 @@ if test $# -ne 4; then
        exit
 fi
 
-if $verbose; then
-       echo "Compiling"
-fi
-
-../bin/nitg --global ./strings/chain_concat.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-../bin/nitg --global ./strings/utf_chain_concat.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-../bin/nitg --global ./strings/iteration_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-../bin/nitg --global ./strings/utf_iteration_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-../bin/nitg --global ./strings/substr_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-../bin/nitg --global ./strings/utf_substr_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-
 case "$1" in
        iter) shift; bench_iteration $@ ;;
        cct) shift; bench_concat $@ ;;
index 35466f9..a45075f 100644 (file)
@@ -25,18 +25,6 @@ do
        end
 end
 
-fun bench_rope(str_size: Int, nb_ccts: Int, loops: Int)
-do
-       var lft = "a" * str_size
-
-       for i in [0..loops] do
-               var str: String = new RopeString.from(lft)
-               for j in [0..nb_ccts] do
-                       str += lft
-               end
-       end
-end
-
 fun bench_flatbuf(str_size: Int, nb_ccts: Int, loops: Int)
 do
        var lft = "a" * str_size
@@ -51,7 +39,7 @@ do
 end
 
 var opts = new OptionContext
-var mode = new OptionEnum(["rope", "flatstr", "flatbuf"], "Mode", -1, "-m")
+var mode = new OptionEnum(["flatstr", "flatbuf"], "Mode", -1, "-m")
 var nb_ccts = new OptionInt("Number of concatenations per loop", -1, "--ccts")
 var loops = new OptionInt("Number of loops to be done", -1, "--loops")
 var strlen = new OptionInt("Length of the base string", -1, "--strlen")
@@ -67,10 +55,8 @@ end
 var modval = mode.value
 
 if modval == 0 then
-       bench_rope(strlen.value, nb_ccts.value, loops.value)
-else if modval == 1 then
        bench_flatstr(strlen.value, nb_ccts.value, loops.value)
-else if modval == 2 then
+else if modval == 1 then
        bench_flatbuf(strlen.value, nb_ccts.value, loops.value)
 else
        opts.usage
index a8047d2..0e36c49 100644 (file)
@@ -13,39 +13,6 @@ module iteration_bench
 
 import opts
 
-fun bench_rope_iter(nb_cct: Int, loops: Int, strlen: Int)
-do
-       var a = "a" * strlen
-       var x:String = new RopeString.from(a)
-       for i in [0 .. nb_cct] do x += a
-       var cnt = 0
-       var c: Char
-       while cnt != loops do
-               for i in x do
-                       c = i
-               end
-               cnt += 1
-       end
-end
-
-fun bench_rope_index(nb_cct: Int, loops: Int, strlen: Int)
-do
-       var a = "a" * strlen
-       var x:String = new RopeString.from(a)
-       for i in [0 .. nb_cct] do x += a
-       var cnt = 0
-       var c: Char
-       var pos = 0
-       while cnt != loops do
-               pos = 0
-               while pos < x.length do
-                       c = x[pos]
-                       pos += 1
-               end
-               cnt += 1
-       end
-end
-
 fun bench_flatstr_iter(nb_cct: Int, loops: Int, strlen: Int)
 do
        var a = "a" * strlen
@@ -113,7 +80,7 @@ do
 end
 
 var opts = new OptionContext
-var mode = new OptionEnum(["rope", "flatstr", "flatbuf"], "Mode", -1, "-m")
+var mode = new OptionEnum(["flatstr", "flatbuf"], "Mode", -1, "-m")
 var access_mode = new OptionEnum(["iterator", "index"], "Iteration mode", -1, "--iter-mode")
 var nb_ccts = new OptionInt("Number of concatenations done to the string (in the case of the rope, this will increase its depth)", -1, "--ccts")
 var loops = new OptionInt("Number of loops to be done", -1, "--loops")
@@ -132,15 +99,6 @@ var iterval = access_mode.value
 
 if modval == 0 then
        if iterval == 0 then
-               bench_rope_iter(nb_ccts.value, loops.value, strlen.value)
-       else if iterval == 1 then
-               bench_rope_index(nb_ccts.value, loops.value, strlen.value)
-       else
-               opts.usage
-               exit(-1)
-       end
-else if modval == 1 then
-       if iterval == 0 then
                bench_flatstr_iter(nb_ccts.value, loops.value, strlen.value)
        else if iterval == 1 then
                bench_flatstr_index(nb_ccts.value, loops.value, strlen.value)
@@ -148,7 +106,7 @@ else if modval == 1 then
                opts.usage
                exit(-1)
        end
-else if modval == 2 then
+else if modval == 1 then
        if iterval == 0 then
                bench_flatbuf_iter(nb_ccts.value, loops.value, strlen.value)
        else if iterval == 1 then
index 5021e66..effb9ec 100644 (file)
@@ -13,18 +13,6 @@ module substr_bench
 
 import opts
 
-fun bench_rope(nb_cct: Int, loops: Int, strlen: Int)
-do
-       var a = "a" * strlen
-       var x:String = new RopeString.from(a)
-       for i in [0 .. nb_cct] do x += a
-       var cnt = 0
-       while cnt != loops do
-               x.substring(0,5)
-               cnt += 1
-       end
-end
-
 fun bench_flatstr(nb_cct: Int, loops: Int, strlen: Int)
 do
        var a = "a" * strlen
@@ -50,7 +38,7 @@ do
 end
 
 var opts = new OptionContext
-var mode = new OptionEnum(["rope", "flatstr", "flatbuf"], "Mode", -1, "-m")
+var mode = new OptionEnum(["flatstr", "flatbuf"], "Mode", -1, "-m")
 var nb_ccts = new OptionInt("Number of concatenations done to the string (in the case of the rope, this will increase its depth)", -1, "--ccts")
 var loops = new OptionInt("Number of loops to be done", -1, "--loops")
 var strlen = new OptionInt("Length of the base string", -1, "--strlen")
@@ -66,10 +54,8 @@ end
 var modval = mode.value
 
 if modval == 0 then
-       bench_rope(nb_ccts.value, loops.value, strlen.value)
-else if modval == 1 then
        bench_flatstr(nb_ccts.value, loops.value, strlen.value)
-else if modval == 2 then
+else if modval == 1 then
        bench_flatbuf(nb_ccts.value, loops.value, strlen.value)
 else
        opts.usage
index 40131db..b7e5ab8 100644 (file)
@@ -3,7 +3,7 @@ CXX = ccache c++
 CFLAGS = -g -O2 -Wno-unused-value -Wno-switch
 CINCL = 
 LDFLAGS ?= 
-LDLIBS  ?= -lm `pkg-config --libs bdw-gc` 
+LDLIBS  ?= -lm 
 
 NEED_LIBUNWIND := YesPlease
 uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
@@ -296,41 +296,49 @@ nith.types.4.o: nith.types.4.c
 nith.types.5.o: nith.types.5.c
        $(CC) $(CFLAGS) $(CINCL) -c -o nith.types.5.o nith.types.5.c
 
+# does pkg-config exists?
+ifneq ($(shell which pkg-config >/dev/null; echo $$?), 0)
+$(error "Command `pkg-config` not found. Please install it")
+endif
+# Check for library bdw-gc
+ifneq ($(shell pkg-config --exists 'bdw-gc'; echo $$?), 0)
+$(error "pkg-config: package bdw-gc is not found.")
+endif
 time_nit.extern.o: time_nit.c
-       $(CC) $(CFLAGS)  -c -o time_nit.extern.o time_nit.c
+       $(CC) $(CFLAGS)   -c -o time_nit.extern.o time_nit.c
 
 string_nit.extern.o: string_nit.c
-       $(CC) $(CFLAGS)  -c -o string_nit.extern.o string_nit.c
+       $(CC) $(CFLAGS)   -c -o string_nit.extern.o string_nit.c
 
 file_nit.extern.o: file_nit.c
-       $(CC) $(CFLAGS)  -c -o file_nit.extern.o file_nit.c
+       $(CC) $(CFLAGS)   -c -o file_nit.extern.o file_nit.c
 
 exec_nit.extern.o: exec_nit.c
-       $(CC) $(CFLAGS)  -c -o exec_nit.extern.o exec_nit.c
+       $(CC) $(CFLAGS)   -c -o exec_nit.extern.o exec_nit.c
 
 tables_nit.extern.o: tables_nit.c
-       $(CC) $(CFLAGS)  -c -o tables_nit.extern.o tables_nit.c
+       $(CC) $(CFLAGS)   -c -o tables_nit.extern.o tables_nit.c
 
 c_functions_hash.extern.o: c_functions_hash.c
-       $(CC) $(CFLAGS)  -c -o c_functions_hash.extern.o c_functions_hash.c
+       $(CC) $(CFLAGS)   -c -o c_functions_hash.extern.o c_functions_hash.c
 
 gc_chooser.extern.o: gc_chooser.c
        $(CC) $(CFLAGS) -DWITH_LIBGC `pkg-config --cflags bdw-gc` -c -o gc_chooser.extern.o gc_chooser.c
 
 string._ffi.extern.o: string._ffi.c
-       $(CC) $(CFLAGS)  -c -o string._ffi.extern.o string._ffi.c
+       $(CC) $(CFLAGS)   -c -o string._ffi.extern.o string._ffi.c
 
 string._nitni.extern.o: string._nitni.c
-       $(CC) $(CFLAGS)  -c -o string._nitni.extern.o string._nitni.c
+       $(CC) $(CFLAGS)   -c -o string._nitni.extern.o string._nitni.c
 
 kernel._ffi.extern.o: kernel._ffi.c
-       $(CC) $(CFLAGS)  -c -o kernel._ffi.extern.o kernel._ffi.c
+       $(CC) $(CFLAGS)   -c -o kernel._ffi.extern.o kernel._ffi.c
 
 kernel._nitni.extern.o: kernel._nitni.c
-       $(CC) $(CFLAGS)  -c -o kernel._nitni.extern.o kernel._nitni.c
+       $(CC) $(CFLAGS)   -c -o kernel._nitni.extern.o kernel._nitni.c
 
 nitg: nith.classes.1.o nith.classes.2.o nith.classes.3.o nith.classes.4.o nith.classes.5.o nith.classes.6.o nith.classes.7.o nith.main.1.o nith.sep.1.o modelize_property.sep.1.o modelize_property.sep.2.o modelize_class.sep.1.o modelbuilder.sep.1.o model.sep.1.o model.sep.2.o mmodule.sep.1.o location.sep.1.o string.sep.1.o string.sep.2.o math.sep.1.o kernel.sep.1.o abstract_collection.sep.1.o list.sep.1.o array.sep.1.o sorter.sep.1.o hash_collection.sep.1.o environ.sep.1.o file.sep.1.o stream.sep.1.o string_search.sep.1.o time.sep.1.o exec.sep.1.o mproject.sep.1.o model_base.sep.1.o more_collections.sep.1.o poset.sep.1.o mdoc.sep.1.o phase.sep.1.o toolcontext.sep.1.o opts.sep.1.o version.sep.1.o template.sep.1.o parser.sep.1.o parser.sep.2.o parser.sep.3.o parser.sep.4.o parser.sep.5.o parser.sep.6.o parser_prod.sep.1.o parser_prod.sep.2.o parser_prod.sep.3.o parser_prod.sep.4.o parser_prod.sep.5.o lexer.sep.1.o parser_nodes.sep.1.o lexer_work.sep.1.o tables.sep.1.o parser_work.sep.1.o annotation.sep.1.o literal.sep.1.o transform.sep.1.o astbuilder.sep.1.o typing.sep.1.o typing.sep.2.o typing.sep.3.o local_var_init.sep.1.o flow.sep.1.o scope.sep.1.o astvalidation.sep.1.o auto_super_init.sep.1.o rapid_type_analysis.sep.1.o separate_erasure_compiler.sep.1.o separate_erasure_compiler.sep.2.o separate_compiler.sep.1.o separate_compiler.sep.2.o separate_compiler.sep.3.o separate_compiler.sep.4.o separate_compiler.sep.5.o abstract_compiler.sep.1.o abstract_compiler.sep.2.o abstract_compiler.sep.3.o abstract_compiler.sep.4.o abstract_compiler.sep.5.o platform.sep.1.o c_tools.sep.1.o mixin.sep.1.o coloring.sep.1.o nith.types.1.o nith.types.2.o nith.types.3.o nith.types.4.o nith.types.5.o time_nit.extern.o string_nit.extern.o file_nit.extern.o exec_nit.extern.o tables_nit.extern.o c_functions_hash.extern.o gc_chooser.extern.o string._ffi.extern.o string._nitni.extern.o kernel._ffi.extern.o kernel._nitni.extern.o
-       $(CC) $(LDFLAGS) -o nitg nith.classes.1.o nith.classes.2.o nith.classes.3.o nith.classes.4.o nith.classes.5.o nith.classes.6.o nith.classes.7.o nith.main.1.o nith.sep.1.o modelize_property.sep.1.o modelize_property.sep.2.o modelize_class.sep.1.o modelbuilder.sep.1.o model.sep.1.o model.sep.2.o mmodule.sep.1.o location.sep.1.o string.sep.1.o string.sep.2.o math.sep.1.o kernel.sep.1.o abstract_collection.sep.1.o list.sep.1.o array.sep.1.o sorter.sep.1.o hash_collection.sep.1.o environ.sep.1.o file.sep.1.o stream.sep.1.o string_search.sep.1.o time.sep.1.o exec.sep.1.o mproject.sep.1.o model_base.sep.1.o more_collections.sep.1.o poset.sep.1.o mdoc.sep.1.o phase.sep.1.o toolcontext.sep.1.o opts.sep.1.o version.sep.1.o template.sep.1.o parser.sep.1.o parser.sep.2.o parser.sep.3.o parser.sep.4.o parser.sep.5.o parser.sep.6.o parser_prod.sep.1.o parser_prod.sep.2.o parser_prod.sep.3.o parser_prod.sep.4.o parser_prod.sep.5.o lexer.sep.1.o parser_nodes.sep.1.o lexer_work.sep.1.o tables.sep.1.o parser_work.sep.1.o annotation.sep.1.o literal.sep.1.o transform.sep.1.o astbuilder.sep.1.o typing.sep.1.o typing.sep.2.o typing.sep.3.o local_var_init.sep.1.o flow.sep.1.o scope.sep.1.o astvalidation.sep.1.o auto_super_init.sep.1.o rapid_type_analysis.sep.1.o separate_erasure_compiler.sep.1.o separate_erasure_compiler.sep.2.o separate_compiler.sep.1.o separate_compiler.sep.2.o separate_compiler.sep.3.o separate_compiler.sep.4.o separate_compiler.sep.5.o abstract_compiler.sep.1.o abstract_compiler.sep.2.o abstract_compiler.sep.3.o abstract_compiler.sep.4.o abstract_compiler.sep.5.o platform.sep.1.o c_tools.sep.1.o mixin.sep.1.o coloring.sep.1.o nith.types.1.o nith.types.2.o nith.types.3.o nith.types.4.o nith.types.5.o time_nit.extern.o string_nit.extern.o file_nit.extern.o exec_nit.extern.o tables_nit.extern.o c_functions_hash.extern.o gc_chooser.extern.o string._ffi.extern.o string._nitni.extern.o kernel._ffi.extern.o kernel._nitni.extern.o $(LDLIBS)
+       $(CC) $(LDFLAGS) -o nitg nith.classes.1.o nith.classes.2.o nith.classes.3.o nith.classes.4.o nith.classes.5.o nith.classes.6.o nith.classes.7.o nith.main.1.o nith.sep.1.o modelize_property.sep.1.o modelize_property.sep.2.o modelize_class.sep.1.o modelbuilder.sep.1.o model.sep.1.o model.sep.2.o mmodule.sep.1.o location.sep.1.o string.sep.1.o string.sep.2.o math.sep.1.o kernel.sep.1.o abstract_collection.sep.1.o list.sep.1.o array.sep.1.o sorter.sep.1.o hash_collection.sep.1.o environ.sep.1.o file.sep.1.o stream.sep.1.o string_search.sep.1.o time.sep.1.o exec.sep.1.o mproject.sep.1.o model_base.sep.1.o more_collections.sep.1.o poset.sep.1.o mdoc.sep.1.o phase.sep.1.o toolcontext.sep.1.o opts.sep.1.o version.sep.1.o template.sep.1.o parser.sep.1.o parser.sep.2.o parser.sep.3.o parser.sep.4.o parser.sep.5.o parser.sep.6.o parser_prod.sep.1.o parser_prod.sep.2.o parser_prod.sep.3.o parser_prod.sep.4.o parser_prod.sep.5.o lexer.sep.1.o parser_nodes.sep.1.o lexer_work.sep.1.o tables.sep.1.o parser_work.sep.1.o annotation.sep.1.o literal.sep.1.o transform.sep.1.o astbuilder.sep.1.o typing.sep.1.o typing.sep.2.o typing.sep.3.o local_var_init.sep.1.o flow.sep.1.o scope.sep.1.o astvalidation.sep.1.o auto_super_init.sep.1.o rapid_type_analysis.sep.1.o separate_erasure_compiler.sep.1.o separate_erasure_compiler.sep.2.o separate_compiler.sep.1.o separate_compiler.sep.2.o separate_compiler.sep.3.o separate_compiler.sep.4.o separate_compiler.sep.5.o abstract_compiler.sep.1.o abstract_compiler.sep.2.o abstract_compiler.sep.3.o abstract_compiler.sep.4.o abstract_compiler.sep.5.o platform.sep.1.o c_tools.sep.1.o mixin.sep.1.o coloring.sep.1.o nith.types.1.o nith.types.2.o nith.types.3.o nith.types.4.o nith.types.5.o time_nit.extern.o string_nit.extern.o file_nit.extern.o exec_nit.extern.o tables_nit.extern.o c_functions_hash.extern.o gc_chooser.extern.o string._ffi.extern.o string._nitni.extern.o kernel._ffi.extern.o kernel._nitni.extern.o $(LDLIBS) `pkg-config --libs bdw-gc`
 
 clean:
        rm nith.classes.1.o nith.classes.2.o nith.classes.3.o nith.classes.4.o nith.classes.5.o nith.classes.6.o nith.classes.7.o nith.main.1.o nith.sep.1.o modelize_property.sep.1.o modelize_property.sep.2.o modelize_class.sep.1.o modelbuilder.sep.1.o model.sep.1.o model.sep.2.o mmodule.sep.1.o location.sep.1.o string.sep.1.o string.sep.2.o math.sep.1.o kernel.sep.1.o abstract_collection.sep.1.o list.sep.1.o array.sep.1.o sorter.sep.1.o hash_collection.sep.1.o environ.sep.1.o file.sep.1.o stream.sep.1.o string_search.sep.1.o time.sep.1.o exec.sep.1.o mproject.sep.1.o model_base.sep.1.o more_collections.sep.1.o poset.sep.1.o mdoc.sep.1.o phase.sep.1.o toolcontext.sep.1.o opts.sep.1.o version.sep.1.o template.sep.1.o parser.sep.1.o parser.sep.2.o parser.sep.3.o parser.sep.4.o parser.sep.5.o parser.sep.6.o parser_prod.sep.1.o parser_prod.sep.2.o parser_prod.sep.3.o parser_prod.sep.4.o parser_prod.sep.5.o lexer.sep.1.o parser_nodes.sep.1.o lexer_work.sep.1.o tables.sep.1.o parser_work.sep.1.o annotation.sep.1.o literal.sep.1.o transform.sep.1.o astbuilder.sep.1.o typing.sep.1.o typing.sep.2.o typing.sep.3.o local_var_init.sep.1.o flow.sep.1.o scope.sep.1.o astvalidation.sep.1.o auto_super_init.sep.1.o rapid_type_analysis.sep.1.o separate_erasure_compiler.sep.1.o separate_erasure_compiler.sep.2.o separate_compiler.sep.1.o separate_compiler.sep.2.o separate_compiler.sep.3.o separate_compiler.sep.4.o separate_compiler.sep.5.o abstract_compiler.sep.1.o abstract_compiler.sep.2.o abstract_compiler.sep.3.o abstract_compiler.sep.4.o abstract_compiler.sep.5.o platform.sep.1.o c_tools.sep.1.o mixin.sep.1.o coloring.sep.1.o nith.types.1.o nith.types.2.o nith.types.3.o nith.types.4.o nith.types.5.o time_nit.extern.o string_nit.extern.o file_nit.extern.o exec_nit.extern.o tables_nit.extern.o c_functions_hash.extern.o gc_chooser.extern.o string._ffi.extern.o string._nitni.extern.o kernel._ffi.extern.o kernel._nitni.extern.o 2>/dev/null
index db97fe4..b7e5ab8 100644 (file)
@@ -3,7 +3,7 @@ CXX = ccache c++
 CFLAGS = -g -O2 -Wno-unused-value -Wno-switch
 CINCL = 
 LDFLAGS ?= 
-LDLIBS  ?= -lm -lgc 
+LDLIBS  ?= -lm 
 
 NEED_LIBUNWIND := YesPlease
 uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
@@ -296,41 +296,49 @@ nith.types.4.o: nith.types.4.c
 nith.types.5.o: nith.types.5.c
        $(CC) $(CFLAGS) $(CINCL) -c -o nith.types.5.o nith.types.5.c
 
+# does pkg-config exists?
+ifneq ($(shell which pkg-config >/dev/null; echo $$?), 0)
+$(error "Command `pkg-config` not found. Please install it")
+endif
+# Check for library bdw-gc
+ifneq ($(shell pkg-config --exists 'bdw-gc'; echo $$?), 0)
+$(error "pkg-config: package bdw-gc is not found.")
+endif
 time_nit.extern.o: time_nit.c
-       $(CC) $(CFLAGS)  -c -o time_nit.extern.o time_nit.c
+       $(CC) $(CFLAGS)   -c -o time_nit.extern.o time_nit.c
 
 string_nit.extern.o: string_nit.c
-       $(CC) $(CFLAGS)  -c -o string_nit.extern.o string_nit.c
+       $(CC) $(CFLAGS)   -c -o string_nit.extern.o string_nit.c
 
 file_nit.extern.o: file_nit.c
-       $(CC) $(CFLAGS)  -c -o file_nit.extern.o file_nit.c
+       $(CC) $(CFLAGS)   -c -o file_nit.extern.o file_nit.c
 
 exec_nit.extern.o: exec_nit.c
-       $(CC) $(CFLAGS)  -c -o exec_nit.extern.o exec_nit.c
+       $(CC) $(CFLAGS)   -c -o exec_nit.extern.o exec_nit.c
 
 tables_nit.extern.o: tables_nit.c
-       $(CC) $(CFLAGS)  -c -o tables_nit.extern.o tables_nit.c
+       $(CC) $(CFLAGS)   -c -o tables_nit.extern.o tables_nit.c
 
 c_functions_hash.extern.o: c_functions_hash.c
-       $(CC) $(CFLAGS)  -c -o c_functions_hash.extern.o c_functions_hash.c
+       $(CC) $(CFLAGS)   -c -o c_functions_hash.extern.o c_functions_hash.c
 
 gc_chooser.extern.o: gc_chooser.c
-       $(CC) $(CFLAGS) -DWITH_LIBGC -c -o gc_chooser.extern.o gc_chooser.c
+       $(CC) $(CFLAGS) -DWITH_LIBGC `pkg-config --cflags bdw-gc` -c -o gc_chooser.extern.o gc_chooser.c
 
 string._ffi.extern.o: string._ffi.c
-       $(CC) $(CFLAGS)  -c -o string._ffi.extern.o string._ffi.c
+       $(CC) $(CFLAGS)   -c -o string._ffi.extern.o string._ffi.c
 
 string._nitni.extern.o: string._nitni.c
-       $(CC) $(CFLAGS)  -c -o string._nitni.extern.o string._nitni.c
+       $(CC) $(CFLAGS)   -c -o string._nitni.extern.o string._nitni.c
 
 kernel._ffi.extern.o: kernel._ffi.c
-       $(CC) $(CFLAGS)  -c -o kernel._ffi.extern.o kernel._ffi.c
+       $(CC) $(CFLAGS)   -c -o kernel._ffi.extern.o kernel._ffi.c
 
 kernel._nitni.extern.o: kernel._nitni.c
-       $(CC) $(CFLAGS)  -c -o kernel._nitni.extern.o kernel._nitni.c
+       $(CC) $(CFLAGS)   -c -o kernel._nitni.extern.o kernel._nitni.c
 
 nitg: nith.classes.1.o nith.classes.2.o nith.classes.3.o nith.classes.4.o nith.classes.5.o nith.classes.6.o nith.classes.7.o nith.main.1.o nith.sep.1.o modelize_property.sep.1.o modelize_property.sep.2.o modelize_class.sep.1.o modelbuilder.sep.1.o model.sep.1.o model.sep.2.o mmodule.sep.1.o location.sep.1.o string.sep.1.o string.sep.2.o math.sep.1.o kernel.sep.1.o abstract_collection.sep.1.o list.sep.1.o array.sep.1.o sorter.sep.1.o hash_collection.sep.1.o environ.sep.1.o file.sep.1.o stream.sep.1.o string_search.sep.1.o time.sep.1.o exec.sep.1.o mproject.sep.1.o model_base.sep.1.o more_collections.sep.1.o poset.sep.1.o mdoc.sep.1.o phase.sep.1.o toolcontext.sep.1.o opts.sep.1.o version.sep.1.o template.sep.1.o parser.sep.1.o parser.sep.2.o parser.sep.3.o parser.sep.4.o parser.sep.5.o parser.sep.6.o parser_prod.sep.1.o parser_prod.sep.2.o parser_prod.sep.3.o parser_prod.sep.4.o parser_prod.sep.5.o lexer.sep.1.o parser_nodes.sep.1.o lexer_work.sep.1.o tables.sep.1.o parser_work.sep.1.o annotation.sep.1.o literal.sep.1.o transform.sep.1.o astbuilder.sep.1.o typing.sep.1.o typing.sep.2.o typing.sep.3.o local_var_init.sep.1.o flow.sep.1.o scope.sep.1.o astvalidation.sep.1.o auto_super_init.sep.1.o rapid_type_analysis.sep.1.o separate_erasure_compiler.sep.1.o separate_erasure_compiler.sep.2.o separate_compiler.sep.1.o separate_compiler.sep.2.o separate_compiler.sep.3.o separate_compiler.sep.4.o separate_compiler.sep.5.o abstract_compiler.sep.1.o abstract_compiler.sep.2.o abstract_compiler.sep.3.o abstract_compiler.sep.4.o abstract_compiler.sep.5.o platform.sep.1.o c_tools.sep.1.o mixin.sep.1.o coloring.sep.1.o nith.types.1.o nith.types.2.o nith.types.3.o nith.types.4.o nith.types.5.o time_nit.extern.o string_nit.extern.o file_nit.extern.o exec_nit.extern.o tables_nit.extern.o c_functions_hash.extern.o gc_chooser.extern.o string._ffi.extern.o string._nitni.extern.o kernel._ffi.extern.o kernel._nitni.extern.o
-       $(CC) $(LDFLAGS) -o nitg nith.classes.1.o nith.classes.2.o nith.classes.3.o nith.classes.4.o nith.classes.5.o nith.classes.6.o nith.classes.7.o nith.main.1.o nith.sep.1.o modelize_property.sep.1.o modelize_property.sep.2.o modelize_class.sep.1.o modelbuilder.sep.1.o model.sep.1.o model.sep.2.o mmodule.sep.1.o location.sep.1.o string.sep.1.o string.sep.2.o math.sep.1.o kernel.sep.1.o abstract_collection.sep.1.o list.sep.1.o array.sep.1.o sorter.sep.1.o hash_collection.sep.1.o environ.sep.1.o file.sep.1.o stream.sep.1.o string_search.sep.1.o time.sep.1.o exec.sep.1.o mproject.sep.1.o model_base.sep.1.o more_collections.sep.1.o poset.sep.1.o mdoc.sep.1.o phase.sep.1.o toolcontext.sep.1.o opts.sep.1.o version.sep.1.o template.sep.1.o parser.sep.1.o parser.sep.2.o parser.sep.3.o parser.sep.4.o parser.sep.5.o parser.sep.6.o parser_prod.sep.1.o parser_prod.sep.2.o parser_prod.sep.3.o parser_prod.sep.4.o parser_prod.sep.5.o lexer.sep.1.o parser_nodes.sep.1.o lexer_work.sep.1.o tables.sep.1.o parser_work.sep.1.o annotation.sep.1.o literal.sep.1.o transform.sep.1.o astbuilder.sep.1.o typing.sep.1.o typing.sep.2.o typing.sep.3.o local_var_init.sep.1.o flow.sep.1.o scope.sep.1.o astvalidation.sep.1.o auto_super_init.sep.1.o rapid_type_analysis.sep.1.o separate_erasure_compiler.sep.1.o separate_erasure_compiler.sep.2.o separate_compiler.sep.1.o separate_compiler.sep.2.o separate_compiler.sep.3.o separate_compiler.sep.4.o separate_compiler.sep.5.o abstract_compiler.sep.1.o abstract_compiler.sep.2.o abstract_compiler.sep.3.o abstract_compiler.sep.4.o abstract_compiler.sep.5.o platform.sep.1.o c_tools.sep.1.o mixin.sep.1.o coloring.sep.1.o nith.types.1.o nith.types.2.o nith.types.3.o nith.types.4.o nith.types.5.o time_nit.extern.o string_nit.extern.o file_nit.extern.o exec_nit.extern.o tables_nit.extern.o c_functions_hash.extern.o gc_chooser.extern.o string._ffi.extern.o string._nitni.extern.o kernel._ffi.extern.o kernel._nitni.extern.o $(LDLIBS)
+       $(CC) $(LDFLAGS) -o nitg nith.classes.1.o nith.classes.2.o nith.classes.3.o nith.classes.4.o nith.classes.5.o nith.classes.6.o nith.classes.7.o nith.main.1.o nith.sep.1.o modelize_property.sep.1.o modelize_property.sep.2.o modelize_class.sep.1.o modelbuilder.sep.1.o model.sep.1.o model.sep.2.o mmodule.sep.1.o location.sep.1.o string.sep.1.o string.sep.2.o math.sep.1.o kernel.sep.1.o abstract_collection.sep.1.o list.sep.1.o array.sep.1.o sorter.sep.1.o hash_collection.sep.1.o environ.sep.1.o file.sep.1.o stream.sep.1.o string_search.sep.1.o time.sep.1.o exec.sep.1.o mproject.sep.1.o model_base.sep.1.o more_collections.sep.1.o poset.sep.1.o mdoc.sep.1.o phase.sep.1.o toolcontext.sep.1.o opts.sep.1.o version.sep.1.o template.sep.1.o parser.sep.1.o parser.sep.2.o parser.sep.3.o parser.sep.4.o parser.sep.5.o parser.sep.6.o parser_prod.sep.1.o parser_prod.sep.2.o parser_prod.sep.3.o parser_prod.sep.4.o parser_prod.sep.5.o lexer.sep.1.o parser_nodes.sep.1.o lexer_work.sep.1.o tables.sep.1.o parser_work.sep.1.o annotation.sep.1.o literal.sep.1.o transform.sep.1.o astbuilder.sep.1.o typing.sep.1.o typing.sep.2.o typing.sep.3.o local_var_init.sep.1.o flow.sep.1.o scope.sep.1.o astvalidation.sep.1.o auto_super_init.sep.1.o rapid_type_analysis.sep.1.o separate_erasure_compiler.sep.1.o separate_erasure_compiler.sep.2.o separate_compiler.sep.1.o separate_compiler.sep.2.o separate_compiler.sep.3.o separate_compiler.sep.4.o separate_compiler.sep.5.o abstract_compiler.sep.1.o abstract_compiler.sep.2.o abstract_compiler.sep.3.o abstract_compiler.sep.4.o abstract_compiler.sep.5.o platform.sep.1.o c_tools.sep.1.o mixin.sep.1.o coloring.sep.1.o nith.types.1.o nith.types.2.o nith.types.3.o nith.types.4.o nith.types.5.o time_nit.extern.o string_nit.extern.o file_nit.extern.o exec_nit.extern.o tables_nit.extern.o c_functions_hash.extern.o gc_chooser.extern.o string._ffi.extern.o string._nitni.extern.o kernel._ffi.extern.o kernel._nitni.extern.o $(LDLIBS) `pkg-config --libs bdw-gc`
 
 clean:
        rm nith.classes.1.o nith.classes.2.o nith.classes.3.o nith.classes.4.o nith.classes.5.o nith.classes.6.o nith.classes.7.o nith.main.1.o nith.sep.1.o modelize_property.sep.1.o modelize_property.sep.2.o modelize_class.sep.1.o modelbuilder.sep.1.o model.sep.1.o model.sep.2.o mmodule.sep.1.o location.sep.1.o string.sep.1.o string.sep.2.o math.sep.1.o kernel.sep.1.o abstract_collection.sep.1.o list.sep.1.o array.sep.1.o sorter.sep.1.o hash_collection.sep.1.o environ.sep.1.o file.sep.1.o stream.sep.1.o string_search.sep.1.o time.sep.1.o exec.sep.1.o mproject.sep.1.o model_base.sep.1.o more_collections.sep.1.o poset.sep.1.o mdoc.sep.1.o phase.sep.1.o toolcontext.sep.1.o opts.sep.1.o version.sep.1.o template.sep.1.o parser.sep.1.o parser.sep.2.o parser.sep.3.o parser.sep.4.o parser.sep.5.o parser.sep.6.o parser_prod.sep.1.o parser_prod.sep.2.o parser_prod.sep.3.o parser_prod.sep.4.o parser_prod.sep.5.o lexer.sep.1.o parser_nodes.sep.1.o lexer_work.sep.1.o tables.sep.1.o parser_work.sep.1.o annotation.sep.1.o literal.sep.1.o transform.sep.1.o astbuilder.sep.1.o typing.sep.1.o typing.sep.2.o typing.sep.3.o local_var_init.sep.1.o flow.sep.1.o scope.sep.1.o astvalidation.sep.1.o auto_super_init.sep.1.o rapid_type_analysis.sep.1.o separate_erasure_compiler.sep.1.o separate_erasure_compiler.sep.2.o separate_compiler.sep.1.o separate_compiler.sep.2.o separate_compiler.sep.3.o separate_compiler.sep.4.o separate_compiler.sep.5.o abstract_compiler.sep.1.o abstract_compiler.sep.2.o abstract_compiler.sep.3.o abstract_compiler.sep.4.o abstract_compiler.sep.5.o platform.sep.1.o c_tools.sep.1.o mixin.sep.1.o coloring.sep.1.o nith.types.1.o nith.types.2.o nith.types.3.o nith.types.4.o nith.types.5.o time_nit.extern.o string_nit.extern.o file_nit.extern.o exec_nit.extern.o tables_nit.extern.o c_functions_hash.extern.o gc_chooser.extern.o string._ffi.extern.o string._nitni.extern.o kernel._ffi.extern.o kernel._nitni.extern.o 2>/dev/null
diff --git a/contrib/neo_doxygen/Makefile b/contrib/neo_doxygen/Makefile
new file mode 100644 (file)
index 0000000..ed82923
--- /dev/null
@@ -0,0 +1,30 @@
+# 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.
+
+NITG=../../bin/nitg
+NITG_FLAGS=--dir bin
+NEO4J_DIR=/var/lib/neo4j
+
+.PHONY: bin reset-neo
+
+# Compile the tool.
+bin:
+       mkdir -p bin
+       ../../bin/nitg --dir bin src/neo_doxygen.nit
+
+# Reset the local graph.
+reset-neo:
+       sudo -u neo4j "${NEO4J_DIR}/bin/neo4j" stop \
+       && sudo -u neo4j rm -rf "${NEO4J_DIR}/data/graph.db" \
+       && sudo -u neo4j "${NEO4J_DIR}/bin/neo4j" start
diff --git a/contrib/neo_doxygen/gen-all.sh b/contrib/neo_doxygen/gen-all.sh
new file mode 100755 (executable)
index 0000000..b43ceab
--- /dev/null
@@ -0,0 +1,36 @@
+#! /bin/bash
+
+# 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.
+
+# ./gen-all.sh <source_language> <directory>
+#
+# Document all projects in the specified directory.
+#
+# Projects are direct sub-directories of the specified directory.
+# Every project directory must contain a `.nx_config` file.
+# Also, every project must include the Doxygen XML output in its `doxygen/xml`
+# directory.
+
+NEO_DOXYGEN="${PWD}/bin/neo_doxygen"
+NX="${PWD}/../../bin/nx"
+
+for dir in "$2"/*; do
+       if [ -d "$dir" ]; then
+               if [ -f "$dir/.nx_config" ]; then
+                       # Note: gen-one.sh already prints errors.
+                       ./gen-one.sh "$1" "$dir" || exit
+               fi
+       fi
+done
diff --git a/contrib/neo_doxygen/gen-one.sh b/contrib/neo_doxygen/gen-one.sh
new file mode 100755 (executable)
index 0000000..2621c8d
--- /dev/null
@@ -0,0 +1,38 @@
+#! /bin/bash
+
+# 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.
+
+# ./gen-one.sh <source_language> <directory>
+#
+# Document the project in the specified directory.
+#
+# The project name is the basename of the specified directory.
+# The project directory must contain a `.nx_config` file.
+# Also, the directory must include the Doxygen XML output in its `doxygen/xml`
+# subdirectory.
+
+NEO_DOXYGEN="${PWD}/bin/neo_doxygen"
+NX="${PWD}/../../bin/nx"
+dir=$2
+
+. sh-lib/errors.sh
+
+echo "$0: Documenting \"${dir##*/}\"..."
+pushd "$dir"
+try "$NEO_DOXYGEN" --src-lang "$1" --dest http://localhost:7474 -- "${dir##*/}" "$dir/doxygen/xml"
+try echo "$0: [done] neo_doxygen"
+try "$NX" neo doc "${dir##*/}"
+try echo "$0: [done] nx"
+popd
diff --git a/contrib/neo_doxygen/sh-lib/errors.sh b/contrib/neo_doxygen/sh-lib/errors.sh
new file mode 100644 (file)
index 0000000..dc5335b
--- /dev/null
@@ -0,0 +1,46 @@
+#! /bin/bash
+
+# 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.
+
+# Error handling.
+
+# The program’s name.
+prog_name=$0
+
+# Run the specified command and exit in case of error.
+function try {
+       "$@"
+       local status=$?
+       if [ $status -ne 0 ]; then
+               >&2 echo "${prog_name}: Error: \`$1\` failed with exit status ${status}."
+               trace
+               exit "$status"
+       fi
+       return 0
+}
+
+# Print the stack trace.
+function trace {
+       local frame=0
+       >&2 caller $frame
+       local has_next=$?
+       while [ $has_next = 0 ]; do
+               ((frame++));
+               >&2 caller $frame
+               has_next=$?
+       done
+       >&2 echo "---"
+       return 0
+}
diff --git a/contrib/neo_doxygen/src/doxml/compounddef.nit b/contrib/neo_doxygen/src/doxml/compounddef.nit
new file mode 100644 (file)
index 0000000..4cd42ca
--- /dev/null
@@ -0,0 +1,167 @@
+# 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.
+
+# `compounddef` element reading.
+module doxml::compounddef
+
+import memberdef
+import more_collections
+
+# Processes the content of a `compounddef` element.
+class CompoundDefListener
+       super EntityDefListener
+
+       var compound: Compound is writable, noinit
+       private var memberdef: MemberDefListener is noinit
+       private var param_listener: TypeParamListener is noinit
+
+       # Default attributes for members in the current section.
+       private var member_defaults: MemberDefaults is noinit
+
+       # For each section kind, default attributes for member in that section.
+       private var section_kinds: DefaultMap[String, MemberDefaults] is noinit
+
+
+       # Attributes of the current `<basecompoundref>` element.
+
+       private var refid = ""
+       private var prot = ""
+       private var virt = ""
+
+
+       init do
+               super
+               var defaults = new MemberDefaults("public", false, false)
+
+               memberdef = new MemberDefListener(reader, self)
+               param_listener = new TypeParamListener(reader, self)
+
+               member_defaults = defaults
+               section_kinds = new DefaultMap[String, MemberDefaults](defaults)
+
+               section_kinds["public-type"] = defaults
+               section_kinds["public-func"] = defaults
+               section_kinds["public-attrib"] = defaults
+               section_kinds["public-slot"] = defaults
+               defaults = new MemberDefaults("public", true, false)
+               section_kinds["public-static-func"] = defaults
+               section_kinds["public-static-attrib"] = defaults
+
+               defaults = new MemberDefaults("protected", false, false)
+               section_kinds["protected-type"] = defaults
+               section_kinds["protected-func"] = defaults
+               section_kinds["protected-attrib"] = defaults
+               section_kinds["protected-slot"] = defaults
+               defaults = new MemberDefaults("protected", true, false)
+               section_kinds["protected-static-func"] = defaults
+               section_kinds["protected-static-attrib"] = defaults
+
+               defaults = new MemberDefaults("package", false, false)
+               section_kinds["package-type"] = defaults
+               section_kinds["package-func"] = defaults
+               section_kinds["package-attrib"] = defaults
+               defaults = new MemberDefaults("package", true, false)
+               section_kinds["package-static-func"] = defaults
+               section_kinds["package-static-attrib"] = defaults
+
+               defaults = new MemberDefaults("private", false, false)
+               section_kinds["private-type"] = defaults
+               section_kinds["private-func"] = defaults
+               section_kinds["private-attrib"] = defaults
+               section_kinds["private-slot"] = defaults
+               defaults = new MemberDefaults("private", true, false)
+               section_kinds["private-static-func"] = defaults
+               section_kinds["private-static-attrib"] = defaults
+
+               defaults = new MemberDefaults("public", true, true)
+               section_kinds["related"] = defaults
+               section_kinds["user-defined"] = defaults
+       end
+
+       redef fun entity: Entity do return compound
+
+       redef fun start_dox_element(local_name: String, atts: Attributes) do
+               if ["compoundname", "innerclass", "innernamespace"].has(local_name) then
+                       text.listen_until(dox_uri, local_name)
+                       if ["innerclass", "innernamespace"].has(local_name) then
+                               refid = get_required(atts, "refid")
+                       end
+               else if "basecompoundref" == local_name then
+                       refid = get_optional(atts, "refid", "")
+                       prot = get_optional(atts, "prot", "")
+                       virt = get_optional(atts, "virt", "")
+                       text.listen_until(dox_uri, local_name)
+               else if "memberdef" == local_name then
+                       read_member(atts)
+               else if local_name == "sectiondef" then
+                       member_defaults = section_kinds[get_required(atts, "kind")]
+                       if member_defaults.is_special then
+                               super # TODO
+                       end
+               else if "param" == local_name then
+                       param_listener.listen_until(dox_uri, local_name)
+               else if "templateparamlist" != local_name then
+                       super
+               end
+       end
+
+       redef fun end_dox_element(local_name: String) do
+               if local_name == "compoundname" then
+                       compound.full_name = text.to_s
+               else if local_name == "innerclass" then
+                       compound.declare_class(refid, text.to_s)
+               else if local_name == "innernamespace" then
+                       compound.declare_namespace(refid, text.to_s)
+               else if "memberdef" == local_name then
+                       if not (memberdef.member isa UnknownMember) then
+                               compound.declare_member(memberdef.member)
+                       end
+               else if local_name == "basecompoundref" then
+                       compound.declare_super(refid, text.to_s, prot, virt)
+               else if "param" == local_name and compound isa ClassCompound then
+                       compound.as(ClassCompound).add_type_parameter(param_listener.parameter)
+               else
+                       super
+               end
+       end
+
+       private fun read_member(atts: Attributes) do
+               var kind = get_required(atts, "kind")
+
+               create_member(kind)
+               memberdef.member.model_id = get_required(atts, "id")
+               memberdef.member.visibility = get_optional(atts, "prot",
+                               member_defaults.visibility)
+       end
+
+       private fun create_member(kind: String) do
+               if kind == "variable" then
+                       memberdef.member = new Attribute(compound.graph)
+               else if kind == "function" then
+                       memberdef.member = new Method(compound.graph)
+               else
+                       memberdef.member = new UnknownMember(compound.graph)
+                       noop.listen_until(dox_uri, "memberdef")
+                       return
+               end
+               memberdef.listen_until(dox_uri, "memberdef")
+       end
+end
+
+# Default attributes for members in the current section.
+private class MemberDefaults
+       var visibility: String
+       var is_static: Bool
+       var is_special: Bool
+end
diff --git a/contrib/neo_doxygen/src/doxml/doc.nit b/contrib/neo_doxygen/src/doxml/doc.nit
new file mode 100644 (file)
index 0000000..84a880d
--- /dev/null
@@ -0,0 +1,30 @@
+# 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.
+
+# Documentation reading.
+module doxml::doc
+
+import listener
+
+# Processes documentation.
+class DocListener
+       super TextListener
+
+       var doc: JsonArray = new JsonArray is writable
+
+       redef fun end_listening do
+               super
+               doc.add(to_s)
+       end
+end
diff --git a/contrib/neo_doxygen/src/doxml/doxml.nit b/contrib/neo_doxygen/src/doxml/doxml.nit
new file mode 100644 (file)
index 0000000..280334a
--- /dev/null
@@ -0,0 +1,89 @@
+# 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.
+
+# Doxygen’s XML documents reading.
+module doxml
+
+import compounddef
+
+# Reader for XML documents whose the schema is `compound.xsd`.
+class CompoundFileReader
+       super DoxmlListener
+
+       # The project graph.
+       var model: ProjectGraph
+
+       # The language-specific strategies to use.
+       redef var source_language: SourceLanguage
+
+       private var reader: XMLReader = new XophonReader
+       private var compounddef: CompoundDefListener is noinit
+       private var noop: NoopListener is noinit
+
+       init do
+               compounddef = new CompoundDefListener(reader, self)
+               noop = new NoopListener(reader, self)
+       end
+
+       redef fun graph do return model
+
+       # Read the document at the specified path.
+       fun read(path: String) do
+               reader.content_handler = self
+               reader.parse_file(path)
+               compounddef.compound = new UnknownCompound(model)
+       end
+
+       redef fun start_dox_element(local_name: String, atts: Attributes) do
+               if local_name == "compounddef" then
+                       read_compound(atts)
+               else if "doxygen" != local_name then
+                       noop.listen_until(dox_uri, local_name)
+               end
+       end
+
+       private fun read_compound(atts: Attributes) do
+               var kind = get_required(atts, "kind")
+
+               create_compound(kind)
+               # TODO Make all values of `kind` and `visibility` compatible with the Nit meta-model.
+               if get_bool(atts, "final") then
+                       kind = "final {kind}"
+               end
+               if get_bool(atts, "sealed") then
+                       kind = "sealed {kind}"
+               end
+               if get_bool(atts, "abstract") then
+                       kind = "abstract {kind}"
+               end
+               compounddef.compound.kind = kind
+               compounddef.compound.model_id = get_required(atts, "id")
+               compounddef.compound.visibility = get_optional(atts, "prot", "")
+       end
+
+       private fun create_compound(kind: String) do
+               if kind == "file" then
+                       compounddef.compound = new FileCompound(model)
+               else if kind == "namespace" then
+                       compounddef.compound = new Namespace(model)
+               else if kind == "class" or kind == "interface" or kind == "enum" then
+                       compounddef.compound = new ClassCompound(model)
+               else
+                       compounddef.compound = new UnknownCompound(model)
+                       noop.listen_until(dox_uri, "compounddef")
+                       return
+               end
+               compounddef.listen_until(dox_uri, "compounddef")
+       end
+end
diff --git a/contrib/neo_doxygen/src/doxml/entitydef.nit b/contrib/neo_doxygen/src/doxml/entitydef.nit
new file mode 100644 (file)
index 0000000..6c11a6c
--- /dev/null
@@ -0,0 +1,129 @@
+# 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.
+
+# Common SAX listeners for entity definitions.
+module doxml::entitydef
+
+import doc
+
+# Processes the content of an entity definition.
+abstract class EntityDefListener
+       super StackableListener
+
+       # The inner `TextListener`.
+       protected var text: TextListener is noinit
+
+       # The inner `DocListener`.
+       protected var doc: DocListener is noinit
+
+       # The inner `NoopListener`.
+       protected var noop: NoopListener is noinit
+
+       init do
+               super
+               text = new TextListener(reader, self)
+               doc = new DocListener(reader, self)
+               noop = new NoopListener(reader, self)
+       end
+
+       # The current entity.
+       protected fun entity: Entity is abstract
+
+       redef fun start_dox_element(local_name: String, atts: Attributes) do
+               if ["briefdescription", "detaileddescription", "inbodydescription"].has(local_name) then
+                       doc.doc = entity.doc
+                       doc.listen_until(dox_uri, local_name)
+               else if "location" == local_name then
+                       entity.location = get_location(atts)
+               else
+                       noop.listen_until(dox_uri, local_name)
+               end
+       end
+
+       redef fun end_listening do
+               super
+               entity.put_in_graph
+       end
+
+       # Parse the attributes of a `location` element.
+       protected fun get_location(atts: Attributes): Location do
+               var location = new Location
+
+               location.path = atts.value_ns("", "bodyfile") or else atts.value_ns("", "file")
+               # Doxygen may indicate `[generated]`.
+               if "[generated]" == location.path then location.path = null
+               var line_start = atts.value_ns("", "bodystart") or else atts.value_ns("", "line") or else null
+               if line_start != null then location.line_start = line_start.to_i
+               var line_end = atts.value_ns("", "bodyend")
+               if line_end != null then location.line_end = line_end.to_i
+               var column_start = atts.value_ns("", "column")
+               if column_start != null then location.column_start = column_start.to_i
+               if location.line_start == location.line_end then
+                       location.column_end = location.column_start
+               end
+               return location
+       end
+end
+
+# Processes the content of a `<param>` element.
+abstract class ParamListener[T: Parameter]
+       super EntityDefListener
+
+       # The current parameter.
+       var parameter: T is noinit
+
+       private var type_listener: TypeListener is noinit
+
+       init do
+               super
+               type_listener = new TypeListener(reader, self)
+       end
+
+       redef fun entity do return parameter
+
+       redef fun listen_until(uri, local_name) do
+               super
+               parameter = create_parameter
+       end
+
+       # Create a new parameter.
+       protected fun create_parameter: T is abstract
+
+       redef fun start_dox_element(local_name: String, atts: Attributes) do
+               if "declname" == local_name then
+                       text.listen_until(dox_uri, local_name)
+               else if "type" == local_name then
+                       type_listener.listen_until(dox_uri, local_name)
+               else
+                       super
+               end
+       end
+
+       redef fun end_dox_element(local_name: String) do
+               if "declname" == local_name then
+                       parameter.name = text.to_s
+               else if "type" == local_name then
+                       source_language.apply_parameter_type(parameter, type_listener.linked_text)
+               else
+                       super
+               end
+       end
+end
+
+# Processes the content of a `<param>` element in a `<templateparamlist>` element.
+class TypeParamListener
+       super ParamListener[TypeParameter]
+
+       redef fun create_parameter do return new TypeParameter(graph)
+end
diff --git a/contrib/neo_doxygen/src/doxml/language_specific.nit b/contrib/neo_doxygen/src/doxml/language_specific.nit
new file mode 100644 (file)
index 0000000..bbc6410
--- /dev/null
@@ -0,0 +1,180 @@
+# 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.
+
+# Handle language-specific parts of the importation.
+module doxml::language_specific
+
+import model
+
+# Various importation logics that depend on the project’s language.
+abstract class SourceLanguage
+
+       # Apply the information deduced from `type_text` to `member`.
+       #
+       # `type_text` is the content of the `<type>` element.
+       fun apply_member_type(member: Member, type_text: RawType) do
+               if type_text["text"] != null then
+                       member.static_type = type_text
+               end
+       end
+
+       # Apply the information deduced from `type_text` to `parameter`.
+       #
+       # `type_text` is the content of the `<type>` element.
+       fun apply_parameter_type(parameter: Parameter, type_text: RawType) do
+               if type_text["text"] != null then
+                       parameter.static_type = type_text
+               end
+       end
+
+       # Extract the specified keyword at the beginning of the specified text.
+       #
+       # If the keyword is at the beginning of the specified text, return `true`
+       # and remove the keyword. Else, return false.
+       #
+       # Used to extract some keywords that Doxygen puts in the type.
+       #
+       #     class DummySource
+       #       super JavaSource
+       #     #
+       #       fun test(text: LinkedText, keyword: String): Bool do
+       #               return extract_keyword(text, keyword)
+       #       end
+       #     end
+       #     #
+       #     var text = new RawType(new ProjectGraph(""))
+       #     var dummy = new DummySource
+       #     var res: Bool
+       #     #
+       #     text.add_part("abstract final", "")
+       #     res = dummy.test(text, "static")
+       #     assert not res
+       #     res = dummy.test(text, "abstract")
+       #     assert res
+       #     assert "final" == text["text"].as(JsonArray).first
+       #     res = dummy.test(text, "final")
+       #     assert res
+       #     assert text["text"] == null
+       #     res = dummy.test(text, "abstract")
+       #     assert not res
+       protected fun extract_keyword(text: LinkedText, keyword: String): Bool do
+               var text_array = text["text"]
+               if text_array == null then return false
+               assert text_array isa JsonArray
+               if text_array.is_empty then return false
+
+               var content = text_array.first.as(String).l_trim
+               var link = text.links.first
+               var found = false
+
+               if link == null and content.has_prefix(keyword) then
+                       if keyword.length == content.length then
+                               content = ""
+                               found = true
+                       else if content.chars[keyword.length] <= ' ' then
+                               content = content.substring_from(keyword.length).l_trim
+                               found = true
+                       end
+                       if "" == content then
+                               text.shift_part
+                       else if found then
+                               text.set_part(0, content, "")
+                       end
+               end
+               return found
+       end
+
+       # Extract the specified suffix in the specified text.
+       #
+       # If the suffix is at the end of the specified text, return `true`
+       # and remove the suffix. Else, return false.
+       #
+       # Used to extract stuff like `...` that Doxygen puts in the type.
+       #
+       #     class DummySource
+       #       super JavaSource
+       #     #
+       #       fun test(text: LinkedText, s: String): Bool do
+       #               return extract_suffix(text, s)
+       #       end
+       #     end
+       #     #
+       #     var text = new RawType(new ProjectGraph(""))
+       #     var dummy = new DummySource
+       #     var res: Bool
+       #     #
+       #     text.add_part("Object...+++", "")
+       #     res = dummy.test(text, "...")
+       #     assert not res
+       #     res = dummy.test(text, "+++")
+       #     assert res
+       #     assert "Object..." == text["text"].as(JsonArray).first
+       #     res = dummy.test(text, "...")
+       #     assert res
+       #     assert "Object" == text["text"].as(JsonArray).first
+       protected fun extract_suffix(text: LinkedText, suffix: String): Bool do
+               var text_array = text["text"]
+               if text_array == null then return false
+               assert text_array isa JsonArray
+               if text_array.is_empty then return false
+
+               var content = text_array.last.as(String).r_trim
+               var link = text.links.first
+               var found = false
+
+               if link == null and content.has_suffix(suffix) then
+                       content = content.substring(0, content.length - suffix.length).r_trim
+                       if "" == content then
+                               text.pop_part
+                       else
+                               text.set_part(0, content, "")
+                       end
+                       return true
+               else
+                       return false
+               end
+       end
+end
+
+# The default importation logics.
+#
+# Do nothing special.
+class DefaultSource
+       super SourceLanguage
+end
+
+# Importation logics for Java.
+class JavaSource
+       super SourceLanguage
+
+       redef fun apply_member_type(member, type_text) do
+               # For abstract members, Doxygen put `abstract` at the beginning of the type.
+               # We assume that Doxygen do not put annotations in the type (it seems to
+               # be the case).
+               member.is_abstract = extract_keyword(type_text, "abstract")
+               # TODO final
+               # TODO void
+               # TODO Avoid using `RawType` when possible. Only use `RawType` as a fallback.
+               super
+       end
+
+       redef fun apply_parameter_type(parmeter, type_text) do
+               # We assume that Doxygen do not put annotations in the type (it seems to
+               # be the case).
+               # TODO final
+               # TODO Avoid using `RawType` when possible. Only use `RawType` as a fallback.
+               parmeter.is_vararg = extract_suffix(type_text, "...")
+               super
+       end
+end
diff --git a/contrib/neo_doxygen/src/doxml/listener.nit b/contrib/neo_doxygen/src/doxml/listener.nit
new file mode 100644 (file)
index 0000000..26de0d2
--- /dev/null
@@ -0,0 +1,281 @@
+# 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.
+
+# Basic SAX listeners.
+module doxml::listener
+
+import saxophonit
+import model
+import language_specific
+
+# Common abstractions for SAX listeners reading XML documents generated by Doxygen.
+abstract class DoxmlListener
+       super ContentHandler
+
+       # The locator setted by calling `document_locator=`.
+       protected var locator: nullable SAXLocator = null
+
+       # The project graph.
+       fun graph: ProjectGraph is abstract
+
+       # The language-specific strategies to use.
+       fun source_language: SourceLanguage is abstract
+
+       redef fun document_locator=(locator: SAXLocator) do
+               self.locator = locator
+       end
+
+       protected fun dox_uri: String do return ""
+
+       redef fun start_element(uri: String, local_name: String, qname: String,
+                       atts: Attributes) do
+               super
+               if uri != dox_uri then return # None of our business.
+               start_dox_element(local_name, atts)
+       end
+
+       # Process the start of an element in the Doxygen’s namespace.
+       #
+       # See `ContentHandler.start_element` for the description of the parameters.
+       protected fun start_dox_element(local_name: String, atts: Attributes) do end
+
+       redef fun end_element(uri: String, local_name: String, qname: String) do
+               super
+               if uri != dox_uri then return # None of our business.
+               end_dox_element(local_name)
+       end
+
+       # Process the end of an element in the Doxygen’s namespace.
+       #
+       # See `ContentHandler.start_element` for the description of the parameters.
+       protected fun end_dox_element(local_name: String) do end
+
+       protected fun get_bool(atts: Attributes, local_name: String): Bool do
+               return get_optional(atts, local_name, "no") == "yes"
+       end
+
+       # Get the value of an optional attribute.
+       #
+       # Parameters:
+       #
+       # * `atts`: attribute list.
+       # * `local_name`: local name of the attribute.
+       # * `default`: value to return when the specified attribute is not found.
+       protected fun get_optional(atts: Attributes, local_name: String,
+                       default: String): String do
+               return atts.value_ns(dox_uri, local_name) or else default
+       end
+
+       # Get the value of an required attribute.
+       #
+       # Parameters:
+       #
+       # * `atts`: attribute list.
+       # * `local_name`: local name of the attribute.
+       protected fun get_required(atts: Attributes, local_name: String): String do
+               var value = atts.value_ns(dox_uri, local_name)
+               if value == null then
+                       throw_error("The `{local_name}` attribute is required.")
+                       return ""
+               else
+                       return value
+               end
+       end
+
+       redef fun end_document do
+               locator = null
+       end
+
+       # Throw an error with the specified message by prepending the current location.
+       protected fun throw_error(message: String) do
+               var e: SAXParseException
+
+               if locator != null then
+                       e = new SAXParseException.with_locator(message, locator.as(not null))
+               else
+                       e = new SAXParseException(message)
+               end
+               e.throw
+       end
+end
+
+# A `DoxmlListener` that read only a part of a document.
+#
+# Temporary redirect events to itself until it ends processing its part.
+abstract class StackableListener
+       super DoxmlListener
+
+       # The associated reader.
+       var reader: XMLReader
+
+       # The parent listener.
+       var parent: DoxmlListener
+
+       # Namespace’s IRI of the element at the root of the part to process.
+       private var root_uri: String = ""
+
+       # Local name of the element at the root of the part to process.
+       private var root_local_name: String = ""
+
+       # The number of open element of the same type than the root of the part to process.
+       private var depth = 0
+
+       # The project graph.
+       private var p_graph: ProjectGraph is noinit
+
+       # The language-specific strategies to use.
+       private var p_source: SourceLanguage is noinit
+
+
+       init do
+               super
+               p_graph = parent.graph
+               p_source = parent.source_language
+       end
+
+       redef fun graph do return p_graph
+       redef fun source_language do return p_source
+
+       # Temporary redirect events to itself until the end of the specified element.
+       fun listen_until(uri: String, local_name: String) do
+               root_uri = uri
+               root_local_name = local_name
+               depth = 1
+               reader.content_handler = self
+               locator = parent.locator
+       end
+
+       redef fun start_element(uri: String, local_name: String, qname: String,
+                       atts: Attributes) do
+               super
+               if uri == root_uri and local_name == root_local_name then
+                       depth += 1
+               end
+       end
+
+       redef fun end_element(uri: String, local_name: String, qname: String) do
+               super
+               if uri == root_uri and local_name == root_local_name then
+                       depth -= 1
+                       if depth <= 0 then
+                               end_listening
+                               parent.end_element(uri, local_name, qname)
+                       end
+               end
+       end
+
+       # Reset the reader’s listener to the parent.
+       fun end_listening do
+               reader.content_handler = parent
+               locator = null
+       end
+
+       redef fun end_document do
+               end_listening
+       end
+end
+
+# A SAX listener that skips any event except the end of the part to process.
+#
+# Used to skip an entire element.
+class NoopListener
+       super StackableListener
+end
+
+# Concatenates any text node found.
+class TextListener
+       super StackableListener
+
+       protected var buffer: Buffer = new FlatBuffer
+       private var sp: Bool = false
+
+       redef fun listen_until(uri: String, local_name: String) do
+               buffer.clear
+               sp = false
+               super
+       end
+
+       redef fun characters(str: String) do
+               if sp then
+                       if buffer.length > 0 then buffer.append(" ")
+                       sp = false
+               end
+               buffer.append(str)
+       end
+
+       redef fun ignorable_whitespace(str: String) do
+               sp = true
+       end
+
+       # Flush the buffer.
+       protected fun flush_buffer: String do
+               var s = buffer.to_s
+
+               buffer.clear
+               sp = false
+               return s
+       end
+
+       redef fun to_s do return buffer.to_s
+end
+
+# Processes a content of type `linkedTextType`.
+abstract class LinkedTextListener[T: LinkedText]
+       super TextListener
+
+       # The read text.
+       var linked_text: T is noinit
+
+       private var refid = ""
+
+       # Create a new instance of `T`.
+       protected fun create_linked_text: T is abstract
+
+       redef fun listen_until(uri: String, local_name: String) do
+               linked_text = create_linked_text
+               refid = ""
+               super
+       end
+
+       redef fun start_dox_element(local_name: String, atts: Attributes) do
+               super
+               push_part
+               if "ref" == local_name then refid = get_required(atts, "refid")
+       end
+
+       redef fun end_dox_element(local_name: String) do
+               super
+               push_part
+               if "ref" == local_name then refid = ""
+       end
+
+       private fun push_part do
+               var s = flush_buffer
+
+               if not s.is_empty then
+                       linked_text.add_part(s, refid)
+               end
+       end
+
+       redef fun to_s do return linked_text.to_s
+end
+
+# Processes the content of a `<type>` element.
+class TypeListener
+       super LinkedTextListener[RawType]
+
+       private var raw_type: RawType is noinit
+
+       redef fun create_linked_text do return new RawType(graph)
+end
diff --git a/contrib/neo_doxygen/src/doxml/memberdef.nit b/contrib/neo_doxygen/src/doxml/memberdef.nit
new file mode 100644 (file)
index 0000000..5249404
--- /dev/null
@@ -0,0 +1,70 @@
+# 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.
+
+# `memberdef` element reading.
+module doxml::memberdef
+
+import entitydef
+
+# Processes the content of a `<memberdef>` element.
+class MemberDefListener
+       super EntityDefListener
+
+       # The current member.
+       var member: Member is writable, noinit
+
+       private var type_listener: TypeListener is noinit
+       private var param_listener: MemberParamListener is noinit
+
+       init do
+               super
+               type_listener = new TypeListener(reader, self)
+               param_listener = new MemberParamListener(reader, self)
+       end
+
+       redef fun entity do return member
+
+       redef fun start_dox_element(local_name: String, atts: Attributes) do
+               if "name" == local_name then
+                       text.listen_until(dox_uri, local_name)
+               else if "reimplements" == local_name then
+                       member.reimplement(get_required(atts, "refid"))
+               else if "type" == local_name then
+                       type_listener.listen_until(dox_uri, local_name)
+               else if "param" == local_name then
+                       param_listener.listen_until(dox_uri, local_name)
+               else
+                       super
+               end
+       end
+
+       redef fun end_dox_element(local_name: String) do
+               if "name" == local_name then
+                       member.name = text.to_s
+               else if "type" == local_name then
+                       source_language.apply_member_type(member, type_listener.linked_text)
+               else if "param" == local_name then
+                       member.add_parameter(param_listener.parameter)
+               else
+                       super
+               end
+       end
+end
+
+# Processes the content of a `<param>` element in a `<memberdef>` element.
+class MemberParamListener
+       super ParamListener[MemberParameter]
+
+       redef fun create_parameter do return new MemberParameter(graph)
+end
diff --git a/contrib/neo_doxygen/src/model/class_compound.nit b/contrib/neo_doxygen/src/model/class_compound.nit
new file mode 100644 (file)
index 0000000..7663c0a
--- /dev/null
@@ -0,0 +1,230 @@
+# 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.
+
+# Nodes for classes.
+module model::class_compound
+
+import graph
+import member
+import type_entity
+
+# A class.
+class ClassCompound
+       super Compound
+
+       # The corresponding type.
+       #
+       # In the case of a generic class, defines bounds for type parameters.
+       var class_type: ClassType is noinit
+
+       # The definition.
+       var class_def: ClassDef is noinit
+
+       init do
+               super
+               class_type = new ClassType(graph)
+               class_type.class_compound = self
+               class_def = new ClassDef(graph, self)
+               self.labels.add("MClass")
+               kind = "class"
+               visibility = "public"
+       end
+
+       # Return the number of type parameters.
+       fun arity: Int do return class_type.arity
+
+       redef fun name=(name: String) do
+               super
+               class_type.name = name
+               class_def.name = name
+       end
+
+       redef fun full_name=(full_name: String) do
+               super
+               class_type.full_name = full_name
+               class_def.full_name = full_name
+       end
+
+       redef fun parent_name=(parent_name: String) do
+               super
+               class_type.parent_name = parent_name
+               class_def.parent_name = parent_name
+       end
+
+       redef fun location=(location: nullable Location) do
+               super
+               class_def.location = location
+       end
+
+       redef fun set_mdoc do
+               super
+               class_def["mdoc"] = doc
+       end
+
+       redef fun declare_super(id: String, name: String, prot: String, virt: String) do
+               class_def.declare_super(id, name, prot, virt)
+       end
+
+       redef fun declare_member(member: Member) do
+               class_def.declare_member(member)
+       end
+
+       # Append the specified type parameter.
+       fun add_type_parameter(parameter: TypeParameter) do
+               class_type.arguments.add(parameter)
+       end
+
+       redef fun put_in_graph do
+               super
+               class_type.put_in_graph
+               class_def.put_in_graph
+       end
+
+       redef fun put_edges do
+               super
+               graph.add_edge(self, "CLASSTYPE", class_type)
+               if arity > 0 then
+                       var names = new JsonArray
+
+                       for p in class_type.arguments do
+                               names.add(p.name)
+                       end
+                       self["parameter_names"] = names
+               end
+       end
+end
+
+# The `MClassDef` node of a class.
+class ClassDef
+       super CodeBlock
+
+       var class_compound: ClassCompound
+       var supers: SimpleCollection[String] = new Array[String]
+       var members: SimpleCollection[Member] = new Array[Member]
+
+       init do
+               super
+               self.labels.add("MClassDef")
+               self["is_intro"] = true
+       end
+
+       fun declare_super(id: String, name: String, prot: String, virt: String) do
+               # TODO prot, virt, name
+               if "" != id then
+                       supers.add(id)
+               end
+       end
+
+       fun declare_member(member: Member) do
+               var full_name = self["full_name"]
+
+               if full_name != null then
+                       member.parent_name = full_name.to_s
+               end
+               members.add(member)
+       end
+
+       redef fun full_name=(full_name: String) do
+               super
+               for m in members do
+                       m.parent_name = full_name
+               end
+       end
+
+       redef fun parent_name=(parent_name: String) do
+               super
+               for m in members do
+                       m.parent_name = full_name
+               end
+       end
+
+       redef fun put_edges do
+               super
+               graph.add_edge(self, "BOUNDTYPE", class_compound.class_type)
+               graph.add_edge(self, "MCLASS", class_compound)
+               for s in supers do
+                       graph.add_edge(self, "INHERITS", graph.by_id[s].as(ClassCompound).class_type)
+               end
+               for m in members do
+                       if m.is_intro then
+                               var intro = m.introducer.as(not null)
+                               graph.add_edge(self, "INTRODUCES", intro)
+                               graph.add_edge(intro, "INTRO_CLASSDEF", self)
+                       end
+                       graph.add_edge(self, "DECLARES", m)
+               end
+       end
+end
+
+# A type defined by a class.
+class ClassType
+       super TypeEntity
+
+       # The associated class.
+       #
+       # You may use this attribute or `class_compound_id` to specify the class.
+       var class_compound: nullable ClassCompound = null is writable
+
+       # The `model_id` of the associated class.
+       #
+       # You may use this attribute or `class_compound` to specify the class.
+       var class_compound_id: String = "" is writable
+
+       # The type arguments or the type parameters.
+       var arguments = new Array[TypeEntity]
+
+       init do
+               super
+               self.labels.add("MClassType")
+       end
+
+       # Return the number of arguments.
+       fun arity: Int do return arguments.length
+
+       fun is_generic: Bool do return arity > 0
+
+       redef fun put_in_graph do
+               super
+               if is_generic then
+                       self.labels.add("MGenericType")
+               else
+                       var i = self.labels.index_of("MGenericType")
+                       if i >= 0 then self.labels.remove_at(i)
+               end
+       end
+
+       redef fun put_edges do
+               var cls = class_compound
+
+               if cls == null and class_compound_id != "" then
+                       cls = graph.by_id[class_compound_id].as(ClassCompound)
+               end
+               assert cls != null
+
+               super
+               graph.add_edge(self, "CLASS", cls)
+               assert cls.arity == self.arity
+               for i in [0..arguments.length[ do
+                       var a = arguments[i]
+                       if cls.class_type != self then
+                               a.name = cls.class_type.arguments[i].name
+                       end
+                       if a isa TypeParameter then
+                               a.rank = i
+                               graph.add_edge(a, "CLASS", cls)
+                       end
+                       graph.add_edge(self, "ARGUMENT", a)
+               end
+       end
+end
diff --git a/contrib/neo_doxygen/src/model/graph.nit b/contrib/neo_doxygen/src/model/graph.nit
new file mode 100644 (file)
index 0000000..e14d817
--- /dev/null
@@ -0,0 +1,293 @@
+# 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.
+
+# Graphs and basic entities.
+module model::graph
+
+import neo4j
+import location
+
+# A Neo4j graph.
+class NeoGraph
+       var all_nodes: SimpleCollection[NeoNode] = new Array[NeoNode]
+       var all_edges: SimpleCollection[NeoEdge] = new Array[NeoEdge]
+
+       # Add a relationship between two nodes.
+       #
+       # Parameters are the same than for the constructor of `NeoEdge`.
+       fun add_edge(from: NeoNode, rel_type: String, to: NeoNode) do
+               all_edges.add(new NeoEdge(from, rel_type, to))
+       end
+end
+
+# The project’s graph.
+class ProjectGraph
+       super NeoGraph
+
+       # The node reperesenting the project.
+       #
+       # Once the project’s graph is initialized, this node must not be edited.
+       var project: NeoNode = new NeoNode
+
+       # Entities by `model_id`.
+       var by_id: Map[String, Entity] = new HashMap[String, Entity]
+
+       # Initialize a new project graph using the specified project name.
+       #
+       # The specified name will label all nodes of the project’s graph.
+       init(name: String) do
+               project.labels.add(name)
+               project.labels.add("MEntity")
+               project.labels.add("MProject")
+               project["name"] = name
+               all_nodes.add(project)
+
+               var root = new RootNamespace(self)
+               root.put_in_graph
+               by_id[""] = root
+       end
+
+       # Request to all nodes in the graph to add their related edges.
+       fun put_edges do
+               add_edge(project, "ROOT", by_id[""])
+               for n in all_nodes do
+                       if n isa Entity then
+                               n.put_edges
+                       end
+               end
+       end
+end
+
+# A model’s entity.
+#
+# In practice, this is the base class of every node in a `ProjectGraph`.
+abstract class Entity
+       super NeoNode
+
+       # Graph that will embed the entity.
+       var graph: ProjectGraph
+
+       # ID of the entity in the model.
+       #
+       # Is empty for entities without an ID.
+       var model_id: String = "" is writable
+
+       # Associated documentation.
+       var doc: JsonArray = new JsonArray is writable
+
+       init do
+               self.labels.add(graph.project["name"].to_s)
+               self.labels.add("MEntity")
+       end
+
+       # The short (unqualified) name.
+       #
+       # May be also set by `full_name=`.
+       fun name=(name: String) do
+               self["name"] = name
+       end
+
+       # The short (unqualified) name.
+       fun name: String do
+               var name = self["name"]
+               assert name isa String
+               return name
+       end
+
+       # Include the documentation of `self` in the graph.
+       protected fun set_mdoc do
+               self["mdoc"] = doc
+       end
+
+       # The namespace separator of Nit/C++.
+       fun ns_separator: String do return "::"
+
+       # The name separator used when calling `full_name=`.
+       fun name_separator: String do return ns_separator
+
+       # The full (qualified) name.
+       #
+       # Also set `name` using `name_separator`.
+       fun full_name=(full_name: String) do
+               var m: nullable Match = full_name.search_last(name_separator)
+
+               self["full_name"] = full_name
+               if m == null then
+                       name = full_name
+               else
+                       name = full_name.substring_from(m.after)
+               end
+       end
+
+       # The full (qualified) name.
+       fun full_name: String do
+               var full_name = self["full_name"]
+               assert full_name isa String
+               return full_name
+       end
+
+       # Set the full name using the current name and the specified parent name.
+       fun parent_name=(parent_name: String) do
+               self["full_name"] = parent_name + name_separator + self["name"].as(not null).to_s
+       end
+
+       # Set the location of the entity in the source code.
+       fun location=(location: nullable Location) do
+               self["location"] = location
+       end
+
+       # Put the entity in the graph.
+       #
+       # Called by the loader when it has finished to read the entity.
+       fun put_in_graph do
+               if doc.length > 0 then
+                       set_mdoc
+               end
+               graph.all_nodes.add(self)
+               if model_id != "" then graph.by_id[model_id] = self
+       end
+
+       # Put the related edges in the graph.
+       #
+       # This method is called on each node by `ProjectGraph.put_edges`.
+       #
+       # Note: Even at this step, the entity may modify its own attributes and
+       # inner entities’ ones because some values are only known once the entity
+       # know its relationships with the rest of the graph.
+       fun put_edges do end
+end
+
+# An entity whose the location is mandatory.
+abstract class CodeBlock
+       super Entity
+
+       init do
+               self["location"] = new Location
+       end
+
+       redef fun location=(location: nullable Location) do
+               if location == null then
+                       super(new Location)
+               else
+                       super
+               end
+       end
+end
+
+# A compound.
+#
+# Usually corresponds to a `<compounddef>` element in of the XML output of
+# Doxygen.
+abstract class Compound
+       super Entity
+
+       # Set the declared visibility (the proctection) of the compound.
+       fun visibility=(visibility: String) do
+               self["visibility"] = visibility
+       end
+
+       # Set the specific kind of the compound.
+       fun kind=(kind: String) do
+               self["kind"] = kind
+       end
+
+       # Declare an inner namespace.
+       #
+       # Parameters:
+       #
+       # * `id`: `model_id` of the inner namespace. May be empty.
+       # * `name`: string identifying the inner namespace. May be empty.
+       fun declare_namespace(id: String, name: String) do end
+
+       # Declare an inner class.
+       #
+       # Parameters:
+       #
+       # * `id`: `model_id` of the inner class. May be empty.
+       # * `name`: string identifying the inner class. May be empty.
+       fun declare_class(id: String, name: String) do end
+
+       # Declare a base compound (usually, a base class).
+       #
+       # Parameters:
+       #
+       # * `id`: `model_id` of the base compound. May be empty.
+       # * `name`: string identifying the base compound. May be empty.
+       # * `prot`: visibility (proctection) of the relationship.
+       # * `virt`: level of virtuality of the relationship.
+       fun declare_super(id: String, name: String, prot: String, virt: String) do end
+end
+
+# An unrecognized compound.
+#
+# Used to simplify the handling of ignored entities.
+class UnknownCompound
+       super Compound
+
+       redef fun put_in_graph do end
+       redef fun put_edges do end
+end
+
+# A namespace.
+#
+# Corresponds to a group in Nit.
+class Namespace
+       super Compound
+
+       # Inner namespaces (IDs).
+       #
+       # Left empty for the root namespace.
+       var inner_namespaces: SimpleCollection[String] = new Array[String]
+
+       init do
+               super
+               self.labels.add("MGroup")
+       end
+
+       redef fun declare_namespace(id: String, name: String) do
+               inner_namespaces.add(id)
+       end
+
+       redef fun put_edges do
+               super
+               graph.add_edge(self, "PROJECT", graph.project)
+               if self["name"] == self["full_name"] and self["full_name"] != "" then
+                       # The root namespace does not know its children.
+                       var root = graph.by_id[""]
+                       graph.add_edge(self, "PARENT", root)
+                       graph.add_edge(root, "NESTS", self)
+               end
+               for ns in inner_namespaces do
+                       var node = graph.by_id[ns]
+                       graph.add_edge(node, "PARENT", self)
+                       graph.add_edge(self, "NESTS", node)
+               end
+       end
+end
+
+# The root namespace of a `ProjectGraph`.
+#
+# This the only entity in the graph whose `model_id` is really `""`.
+# Added automatically at the initialization of a `ProjectGraph`.
+class RootNamespace
+       super Namespace
+
+       init do
+               super
+               self["full_name"] = ""
+               self["name"] = graph.project["name"]
+       end
+
+       redef fun declare_namespace(id: String, name: String) do end
+end
diff --git a/contrib/neo_doxygen/src/model/linked_text.nit b/contrib/neo_doxygen/src/model/linked_text.nit
new file mode 100644 (file)
index 0000000..bfdf6a5
--- /dev/null
@@ -0,0 +1,164 @@
+# 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 text with links.
+module model::linked_text
+
+import graph
+
+# A text with links.
+abstract class LinkedText
+       super Entity
+
+       # All link in the text.
+       #
+       # Do not edit directly.
+       var links: Sequence[nullable Link] = new Array[nullable Link]
+
+       # Remove all the parts.
+       fun clear_parts do
+               self["text"] = null
+               links.clear
+       end
+
+       # Remove the first part.
+       fun shift_part do
+               var text = self["text"]
+               assert text isa JsonArray
+               text.shift
+               links.shift
+               if text.is_empty then
+                       self["text"] = null
+               end
+       end
+
+       # Remove the last part.
+       fun pop_part do
+               var text = self["text"]
+               assert text isa JsonArray
+               text.pop
+               links.pop
+               if text.is_empty then
+                       self["text"] = null
+               end
+       end
+
+       # Remove the part at the specified index.
+       fun remove_part_at(index: Int) do
+               var text = self["text"]
+               assert text isa JsonArray
+               text.remove_at(index)
+               links.remove_at(index)
+               if text.is_empty then
+                       self["text"] = null
+               end
+       end
+
+       # Change a part of text.
+       #
+       # Parameters:
+       #
+       # * `index` : the index of the part.
+       # * `content` : textual content.
+       # * `refid` : `model_id` of the linked entity or `""`.
+       fun set_part(index: Int, content: String, refid: String) do
+               var text = self["text"]
+               assert text isa JsonArray
+               text[index] = content
+               if not refid.is_empty then
+                       links[index] = create_link(links.length, refid)
+               else
+                       links[index] = null
+               end
+       end
+
+       # Append a part of text.
+       #
+       # Parameters:
+       #
+       # * `content` : textual content.
+       # * `refid` : `model_id` of the linked entity or `""`.
+       fun add_part(content: String, refid: String) do
+               var text = self["text"]
+
+               if text == null then
+                       text = new JsonArray
+                       self["text"] = text
+               end
+               assert text isa JsonArray
+               text.add(content)
+               if not refid.is_empty then
+                       links.add(create_link(links.length, refid))
+               else
+                       links.add(null)
+               end
+       end
+
+       # Create a link to the specified entity.
+       protected fun create_link(rank:Int, refid: String): Link is abstract
+
+       redef fun to_s do
+               var text = self["text"]
+
+               if text isa JsonArray then
+                       return text.join("")
+               else
+                       return "UNDEFINED"
+               end
+       end
+
+       redef fun put_in_graph do
+               super
+               for link in links do
+                       if link isa Link then
+                               link.put_in_graph
+                       end
+               end
+       end
+
+       redef fun put_edges do
+               super
+               for i in [0..links.length[ do
+                       var link = links[i]
+                       if link isa Link then
+                               link["rank"] = i
+                               graph.add_edge(self, "LINK", link)
+                       end
+               end
+       end
+end
+
+# A link.
+abstract class Link
+       super Entity
+
+       # * `refid` : `model_id` of the linked entity.
+       var refid: String
+
+       init do
+               super
+               self["rank"] = -1
+       end
+
+       redef fun put_edges do
+               graph.add_edge(self, "TARGET", graph.by_id[refid])
+       end
+
+       # Specify the rank (index) of the parameter in the signature.
+       #
+       # Called by `LinkedText.put_edges`.
+       private fun rank=(rank: Int) do
+               self["rank"] = rank
+       end
+end
diff --git a/contrib/neo_doxygen/src/model/location.nit b/contrib/neo_doxygen/src/model/location.nit
new file mode 100644 (file)
index 0000000..8652577
--- /dev/null
@@ -0,0 +1,37 @@
+# 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.
+
+# This module is used to model locations in source files.
+module location
+
+import neo4j
+
+# A location inside a source file.
+class Location
+       super Jsonable
+
+       var path: nullable String = null is writable
+       var line_start: Int = 1 is writable
+       var line_end: Int = 1 is writable
+       var column_start: Int = 1 is writable
+       var column_end: Int = 1 is writable
+
+       redef fun to_s: String do
+               var file_part = "/dev/null:"
+               if path != null and path.length > 0 then file_part = "{path.as(not null)}:"
+               return "{file_part}{line_start},{column_start}--{line_end},{column_end}"
+       end
+
+       redef fun to_json do return to_s.to_json
+end
diff --git a/contrib/neo_doxygen/src/model/member.nit b/contrib/neo_doxygen/src/model/member.nit
new file mode 100644 (file)
index 0000000..f29892e
--- /dev/null
@@ -0,0 +1,288 @@
+# 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.
+
+# Members.
+module model::member
+
+import graph
+import type_entity
+
+# A member.
+abstract class Member
+       super CodeBlock
+
+       # The node used to represent the `MProperty` node.
+       #
+       # Only defined if `self` is at the root of a reimplementation graph, and
+       # only once `put_in_graph` is called.
+       var introducer: nullable MemberIntroducer = null
+
+       # Members that this member redefines/reimplements.
+       var reimplemented: SimpleCollection[String] = new Array[String]
+
+       init do
+               super
+               self.labels.add("MPropDef")
+       end
+
+       # Set the static type.
+       fun static_type=(static_type: nullable TypeEntity) is abstract
+
+       # Get the static type.
+       fun static_type: nullable TypeEntity is abstract
+
+       # Append the specified parameter to the signature.
+       fun add_parameter(parameter: MemberParameter) do end
+
+       # Append a member that is reimplemeneted by `self`.
+       fun reimplement(parent: String) do
+               reimplemented.add(parent)
+       end
+
+       # Does this member introduce the property?
+       fun is_intro: Bool do
+               return reimplemented.length <= 0
+       end
+
+       redef fun put_in_graph do
+               super
+               self["is_intro"] = is_intro
+               if is_intro then
+                       var visibility = self["visibility"]
+                       var full_name = self["full_name"]
+                       var name = self["name"]
+
+                       introducer = create_introducer
+                       if full_name isa String then
+                               introducer.full_name = full_name
+                       else if name isa String then
+                               introducer.name = name
+                       end
+                       if visibility isa String then
+                               introducer.visibility = visibility
+                       end
+                       introducer.put_in_graph
+               end
+       end
+
+       redef fun put_edges do
+               super
+               var intro = resolve_introducer
+
+               assert intro != null
+               graph.add_edge(self, "DEFINES", intro)
+       end
+
+       # Set the visibility.
+       fun visibility=(visibility: String) do
+               self["visibility"] = visibility
+               if introducer != null then
+                       introducer.as(not null).visibility = visibility
+               end
+       end
+
+       redef fun name=(name: String) do
+               super
+               if introducer != null then
+                       introducer.as(not null).name = name
+               end
+       end
+
+       redef fun full_name=(full_name: String) do
+               super
+               if introducer != null then
+                       introducer.as(not null).full_name = full_name
+               end
+       end
+
+       redef fun parent_name=(parent_name: String) do
+               super
+               if introducer != null then
+                       introducer.as(not null).parent_name = parent_name
+               end
+       end
+
+       # Is the member abstract?
+       fun is_abstract=(is_abstract: Bool) do
+               self["is_abstract"] = is_abstract
+       end
+
+       # Create an instance of `MemberIntroducer` that will be linked to `self`.
+       protected fun create_introducer: MemberIntroducer is abstract
+
+       # Find the nearest reimplementation root.
+       #
+       #     var g = new ProjectGraph("foo")
+       #     var m1 = new Attribute(g)
+       #     var m2 = new Attribute(g)
+       #     var m3 = new Attribute(g)
+       #     #
+       #     m1.model_id = "1"
+       #     m1.put_in_graph
+       #     m2.reimplement("1")
+       #     m2.put_in_graph
+       #     assert m1.resolve_introducer == m1.introducer
+       #     assert m2.resolve_introducer == m1.introducer
+       #     #
+       #     m3.model_id = "3"
+       #     m3.reimplement("3")
+       #     m3.put_in_graph
+       #     assert m3.resolve_introducer == null
+       fun resolve_introducer: nullable MemberIntroducer do
+               if introducer == null then
+                       var member_queue = new List[String]
+                       var visited = new HashSet[Member]
+                       var member: Member
+
+                       member_queue.add_all(reimplemented)
+                       while not member_queue.is_empty do
+                               member = graph.by_id[member_queue.shift].as(Member)
+                               if visited.has(member) then
+                                       return null
+                               else if member.is_intro then
+                                       return member.introducer
+                               else
+                                       visited.add(member)
+                                       member_queue.add_all(member.reimplemented)
+                               end
+                       end
+                       return null
+               else
+                       return introducer
+               end
+       end
+end
+
+# An unrecognized member.
+#
+# Used to simplify the handling of ignored entities.
+class UnknownMember
+       super Member
+
+       redef fun put_in_graph do end
+       redef fun put_edges do end
+end
+
+class Method
+       super Member
+
+       # The method’s signature.
+       var signature: Signature is noinit, writable
+
+       init do
+               super
+               self.labels.add("MMethodDef")
+               self["is_intern"] = false # TODO
+               self["is_extern"] = false # TODO
+               signature = new Signature(graph)
+               is_abstract = false
+       end
+
+       # Set the return type.
+       redef fun static_type=(static_type: nullable TypeEntity) do
+               signature.return_type = static_type
+       end
+
+       # Get the return type.
+       redef fun static_type: nullable TypeEntity do return signature.return_type
+
+       redef fun add_parameter(parameter: MemberParameter) do
+               signature.parameters.add(parameter)
+       end
+
+       redef fun create_introducer: MemberIntroducer do
+               return new MethodIntroducer(graph)
+       end
+
+       redef fun put_in_graph do
+               super
+               signature.put_in_graph
+       end
+
+       redef fun put_edges do
+               super
+               graph.add_edge(self, "SIGNATURE", signature)
+       end
+end
+
+class Attribute
+       super Member
+
+       # The declared type.
+       redef var static_type: nullable TypeEntity = null is writable
+
+       init do
+               super
+               self.labels.add("MAttributeDef")
+       end
+
+       redef fun create_introducer: MemberIntroducer do
+               return new AttributeIntroducer(graph)
+       end
+
+       redef fun put_in_graph do
+               super
+               if static_type != null then
+                       static_type.as(not null).put_in_graph
+               end
+       end
+
+       redef fun put_edges do
+               super
+               if static_type != null then
+                       graph.add_edge(self, "TYPE", static_type.as(not null))
+               end
+       end
+end
+
+# The `MProperty` node of a root of a reimplementation graph.
+abstract class MemberIntroducer
+       super Entity
+
+       init do
+               super
+               self.labels.add("MProperty")
+               self["visibility"] = "public"
+       end
+
+       fun visibility=(visibility: String) do
+               self["visibility"] = visibility
+       end
+end
+
+# A `MProperty` node for a method.
+class MethodIntroducer
+       super MemberIntroducer
+
+       init do
+               super
+               self.labels.add("MMethod")
+               self["is_init"] = false # TODO
+       end
+end
+
+# A `MProperty` node for an attribute.
+class AttributeIntroducer
+       super MemberIntroducer
+
+       init do
+               super
+               self.labels.add("MAttribute")
+       end
+end
+
+redef class Compound
+       # Append the specified member.
+       fun declare_member(member: Member) do end
+end
diff --git a/contrib/neo_doxygen/src/model/model.nit b/contrib/neo_doxygen/src/model/model.nit
new file mode 100644 (file)
index 0000000..d3c2af9
--- /dev/null
@@ -0,0 +1,23 @@
+# 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.
+
+# The model used to populate the Neo4j graph.
+module model
+
+import location
+import linked_text
+import graph
+import class_compound
+import module_compound
+import member
diff --git a/contrib/neo_doxygen/src/model/module_compound.nit b/contrib/neo_doxygen/src/model/module_compound.nit
new file mode 100644 (file)
index 0000000..6629cc7
--- /dev/null
@@ -0,0 +1,139 @@
+# 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.
+
+# Nodes for modules and files.
+module model::module_compound
+
+import graph
+import class_compound
+
+# A source file.
+#
+# Creates one modules by inner namespace. The full name of the modules begin
+# with the namespace’s full name, and end with the unqualified name of the file,
+# without the extension.
+class FileCompound
+       super Compound
+       super CodeBlock
+
+       # Mapping between inner namespace’s names and corresponding modules.
+       private var inner_namespaces: Map[String, Module] = new HashMap[String, Module]
+
+       # The last component of the path, without the extension.
+       #
+       # Used as the unqualified name of the modules.
+       private var basename: String = ""
+
+       init do
+               super
+       end
+
+       redef fun name_separator: String do return "/"
+
+       redef fun location=(location: nullable Location) do
+               super
+               if location != null and location.path != null then
+                       full_name = location.path.as(not null)
+               end
+               for m in inner_namespaces.values do m.location = location
+       end
+
+       redef fun name=(name: String) do
+               # Example: `MyClass.java`
+               super
+               var match = name.search_last(".")
+
+               if match == null then
+                       basename = name
+               else
+                       basename = name.substring(0, match.from)
+               end
+               # Update the modules’ name.
+               for ns, m in inner_namespaces do
+                       m.full_name = "{ns}{ns_separator}{basename}"
+               end
+       end
+
+       redef fun declare_namespace(id: String, name: String) do
+               var m: Module
+
+               if inner_namespaces.keys.has(name) then
+                       m = inner_namespaces[name]
+                       if id != "" then m.parent = id
+               else
+                       m = new Module(graph)
+                       m.full_name = "{name}{ns_separator}{basename}"
+                       m.parent = id
+                       m.location = self["location"].as(nullable Location)
+                       inner_namespaces[name] = m
+               end
+       end
+
+       redef fun declare_class(id: String, name: String) do
+               var match = name.search_last(ns_separator)
+               var ns_name: String
+               var m: Module
+
+               if match == null then
+                       ns_name = ""
+               else
+                       ns_name = name.substring(0, match.from)
+               end
+               if inner_namespaces.keys.has(ns_name) then
+                       m = inner_namespaces[ns_name]
+               else
+                       declare_namespace("", ns_name)
+                       m = inner_namespaces[ns_name]
+               end
+               m.declare_class(id, name)
+       end
+
+       redef fun put_in_graph do
+               # Do not add `self` to the Neo4j graph...
+               # ... but add its modules...
+               for m in inner_namespaces.values do m.put_in_graph
+               # ... and add `self` to the index.
+               if model_id != "" then graph.by_id[model_id] = self
+       end
+end
+
+# A module.
+class Module
+       super Compound
+       super CodeBlock
+
+       # The `model_id` of the parent namespace.
+       var parent: String = "" is writable
+
+       # The classes defined in the module.
+       var inner_classes: SimpleCollection[String] = new Array[String]
+
+       init do
+               super
+               self.labels.add("MModule")
+       end
+
+       redef fun declare_class(id: String, name: String) do
+               inner_classes.add(id)
+       end
+
+       redef fun put_edges do
+               graph.add_edge(graph.by_id[parent], "DECLARES", self)
+               for c in inner_classes do
+                       var node = graph.by_id[c].as(ClassCompound)
+                       graph.add_edge(self, "INTRODUCES", node)
+                       graph.add_edge(self, "DEFINES", node.class_def)
+               end
+       end
+end
diff --git a/contrib/neo_doxygen/src/model/type_entity.nit b/contrib/neo_doxygen/src/model/type_entity.nit
new file mode 100644 (file)
index 0000000..d8ea8c0
--- /dev/null
@@ -0,0 +1,166 @@
+# 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.
+
+# Typing and parameters.
+module model::type_entity
+
+import graph
+import linked_text
+
+# Base class of all types and signatures.
+abstract class TypeEntity
+       super Entity
+
+       init do
+               super
+               self.labels.add("MType")
+       end
+end
+
+# A type parameter or a type argument.
+#
+# Note : The class relationship and the rank are set by `MClassType.put_edges`.
+class TypeParameter
+       super TypeEntity
+       super Parameter
+
+       init do
+               super
+               self.labels.add("MParameterType")
+       end
+end
+
+
+# A type described by a text.
+class RawType
+       super TypeEntity
+       super LinkedText
+
+       init do
+               super
+               self.labels.add("MRawType")
+       end
+
+       redef fun create_link(rank, refid) do return new TypeLink(graph, refid)
+end
+
+# A link in a `RawType`.
+class TypeLink
+       super Link
+
+       init do
+               super
+               self.labels.add("MTypePart")
+       end
+end
+
+
+# A signature of a method.
+class Signature
+       super TypeEntity
+
+       # The parameters.
+       var parameters = new Array[MemberParameter]
+
+       # The static type of the returned value.
+       var return_type: nullable TypeEntity = null is writable
+
+       init do
+               super
+               self.labels.add("MSignature")
+       end
+
+       redef fun put_in_graph do
+               super
+               if return_type isa TypeEntity then
+                       return_type.as(TypeEntity).put_in_graph
+               end
+               for p in parameters do
+                       p.put_in_graph
+               end
+       end
+
+       redef fun put_edges do
+               super
+               if parameters.length > 0 then
+                       var names = new JsonArray
+
+                       for i in [0..parameters.length[ do
+                               var p = parameters[i]
+                               p.rank = i
+                               names.add(p.name)
+                               graph.add_edge(self, "PARAMETER", p)
+                       end
+                       self["parameter_names"] = names
+               end
+               if return_type != null then
+                       graph.add_edge(self, "RETURNTYPE", return_type.as(not null))
+               end
+       end
+end
+
+# A parameter or an argument.
+abstract class Parameter
+       super Entity
+
+       # The static type of the parameter.
+       var static_type: nullable TypeEntity = null is writable
+
+       init do
+               super
+               self["is_vararg"] = false
+               self["rank"] = -1
+       end
+
+       # Is the parameter a “vararg”?
+       fun is_vararg=(is_vararg: Bool) do
+               self["is_vararg"] = is_vararg
+       end
+
+       # Is the parameter a “vararg”?
+       fun is_vararg: Bool do
+               var value = self["is_vararg"]
+               assert value isa Bool
+               return value
+       end
+
+       # Set the rank (index) of the parameter in the signature.
+       fun rank=(rank: Int) do
+               self["rank"] = rank
+       end
+
+       redef fun put_in_graph do
+               super
+               if static_type != null then
+                       static_type.as(not null).put_in_graph
+               end
+       end
+
+       redef fun put_edges do
+               super
+               graph.add_edge(self, "TYPE", static_type.as(not null))
+       end
+end
+
+# A parameter of a member.
+#
+# Note : The rank are set by `Signature.put_edges`.
+class MemberParameter
+       super Parameter
+
+       init do
+               super
+               self.labels.add("MParameter")
+       end
+end
diff --git a/contrib/neo_doxygen/src/neo_doxygen.nit b/contrib/neo_doxygen/src/neo_doxygen.nit
new file mode 100644 (file)
index 0000000..f26dfc2
--- /dev/null
@@ -0,0 +1,306 @@
+# 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.
+
+# Doxygen XML to Neo4j.
+#
+# Converts a Doxygen XML output into a model in Neo4j that is readable by the
+# `nx` tool.
+module neo_doxygen
+
+import model
+import doxml
+import console
+import opts
+
+# An importation task.
+class NeoDoxygenJob
+       var client: Neo4jClient
+       var model: ProjectGraph is noinit
+
+       # How many operation can be executed in one batch?
+       private var batch_max_size = 1000
+
+       private var save_cursor: String = (new TermSaveCursor).to_s
+
+       # Escape control sequence to reset the current line.
+       private var reset_line: String = "{new TermRestoreCursor}{new TermEraseDisplayDown}"
+
+       # Generate a graph from the specified project model.
+       #
+       # Parameters:
+       #
+       # * `name`: project name.
+       # * `dir`: Doxygen XML output directory path.
+       # * `source`: The language-specific logics to use.
+       fun load_project(name: String, dir: String, source: SourceLanguage) do
+               check_name name
+               model = new ProjectGraph(name)
+               # TODO Let the user select the language.
+               var reader = new CompoundFileReader(model, source)
+               # Queue for sub-directories.
+               var directories = new Array[String]
+
+               if dir.length > 1 and dir.chars.last == "/" then
+                       dir = dir.substring(0, dir.length - 1)
+               end
+               sys.stdout.write save_cursor
+               loop
+                       for f in dir.files do
+                               var path = dir/f
+                               if path.file_stat.is_dir then
+                                       directories.push(path)
+                               else if f.has_suffix(".xml") and f != "index.xml" then
+                                       print "{reset_line}Reading {path}..."
+                                       reader.read(path)
+                               end
+                       end
+                       if directories.length <= 0 then break
+                       dir = directories.pop
+               end
+               print "{reset_line}Reading... Done."
+       end
+
+       # Check the project’s name.
+       private fun check_name(name: String) do
+               assert name_valid: not name.chars.first.is_upper else
+                       sys.stderr.write("{sys.program_name}: The project’s name must not" +
+                                       " begin with an upper case letter. Got `{name}`.\n")
+               end
+               var query = new CypherQuery.from_string("match n where \{name\} in labels(n) return count(n)")
+               query.params["name"] = name
+               var data = client.cypher(query).as(JsonObject)["data"]
+               var result = data.as(JsonArray).first.as(JsonArray).first.as(Int)
+               assert name_unused: result == 0 else
+                       sys.stderr.write("{sys.program_name}: The label `{name}` is already" +
+                       " used in the specified graph.\n")
+               end
+       end
+
+       # Save the graph.
+       fun save do
+               print "Linking nodes...{save_cursor}"
+               model.put_edges
+               print "{reset_line} Done."
+               var nodes = model.all_nodes
+               print "Saving {nodes.length} nodes...{save_cursor}"
+               push_all(nodes)
+               var edges = model.all_edges
+               print "Saving {edges.length} edges...{save_cursor}"
+               push_all(edges)
+       end
+
+       # Save `neo_entities` in the database using batch mode.
+       private fun push_all(neo_entities: Collection[NeoEntity]) do
+               var batch = new NeoBatch(client)
+               var len = neo_entities.length
+               var sum = 0
+               var i = 1
+
+               for nentity in neo_entities do
+                       batch.save_entity(nentity)
+                       if i == batch_max_size then
+                               do_batch(batch)
+                               sum += batch_max_size
+                               print("{reset_line} {sum * 100 / len}%")
+                               batch = new NeoBatch(client)
+                               i = 1
+                       else
+                               i += 1
+                       end
+               end
+               do_batch(batch)
+               print("{reset_line} Done.")
+       end
+
+       # Execute `batch` and check for errors.
+       #
+       # Abort if `batch.execute` returns errors.
+       private fun do_batch(batch: NeoBatch) do
+               var errors = batch.execute
+               if not errors.is_empty then
+                       for e in errors do sys.stderr.write("{sys.program_name}: {e}\n")
+                       exit(1)
+               end
+       end
+end
+
+# The main class.
+class NeoDoxygenCommand
+
+       # Invalid arguments
+       var e_usage = 64
+
+       # Available options for `--src-lang`.
+       var sources = new HashMap[String, SourceLanguage]
+
+       # The synopsis.
+       var synopsis: String = "[--dest <url>] [--src-lang <lang>]\n" +
+                       "    [--] <project_name> <doxml_dir>"
+
+       # The synopsis for the help page.
+       var help_synopsis = "[-h|--help]"
+
+       # The default destination.
+       var default_dest = "http://localhost:7474"
+
+       # Processes the options.
+       var option_context = new OptionContext
+
+       # The `--src-lang` option.
+       var opt_src_lang: OptionEnum is noinit
+
+       # The `--dest` option.
+       var opt_dest: OptionString is noinit
+
+       # The `-h|--help` option.
+       var opt_help: OptionBool is noinit
+
+       init do
+               sources["any"] = new DefaultSource
+               sources["java"] = new JavaSource
+
+               var prefix = new OptionText("""
+{{{"NAME".bold}}}
+  {{{sys.program_name}}} — Doxygen XML to Neo4j.
+
+{{{"SYNOPSIS".bold}}}
+  {{{sys.program_name}}} {{{synopsis}}}
+  {{{sys.program_name}}} {{{help_synopsis}}}
+
+{{{"DESCRIPTION".bold}}}
+  Convert a Doxygen XML output into a model in Neo4j that is readable by the
+  `nx` tool.
+
+{{{"ARGUMENTS".bold}}}
+  <project_name>  The internal name of the project. Must the same name as the
+                  one specified to the `nx` tool. Must not begin by an upper
+                  case letter.
+
+  <doxml_dir>     The directory where the XML documents generated by Doxygen are
+                  located.
+
+{{{"OPTIONS".bold}}}
+""")
+               option_context.add_option(prefix)
+
+               opt_dest = new OptionString("The URL of the destination graph. `{default_dest}` by default.",
+                               "--dest")
+               opt_dest.default_value = default_dest
+               option_context.add_option(opt_dest)
+
+               var keys = new Array[String].from(sources.keys)
+               opt_src_lang = new OptionEnum(keys,
+                               "The programming language to assume when processing chunk in the declarations left as-is by Doxygen. Use `any` (the default) to disable any language-specific processing.",
+                               keys.index_of("any"), "--src-lang")
+               option_context.add_option(opt_src_lang)
+
+               opt_help = new OptionBool("Show the help (this page).",
+                               "-h", "--help")
+               option_context.add_option(opt_help)
+       end
+
+       # Start the application.
+       fun main: Int do
+               if args.is_empty then
+                       show_help
+                       return e_usage
+               end
+               option_context.parse(args)
+
+               var errors = option_context.get_errors
+               var rest = option_context.rest
+
+               if errors.is_empty and not opt_help.value and rest.length != 2 then
+                       errors.add "Unexpected number of additional arguments. Expecting 2; got {rest.length}."
+               end
+               if not errors.is_empty then
+                       for e in errors do print_error(e)
+                       show_usage
+                       return e_usage
+               end
+               if opt_help.value then
+                       show_help
+                       return 0
+               end
+
+               var source = sources[opt_src_lang.value_name]
+               var dest = opt_dest.value
+               var project_name = rest[0]
+               var dir = rest[1]
+               var neo = new NeoDoxygenJob(new Neo4jClient(dest or else default_dest))
+
+               neo.load_project(project_name, dir, source)
+               neo.save
+               return 0
+       end
+
+       # Show the help.
+       fun show_help do
+               option_context.usage
+       end
+
+       # Show the usage.
+       fun show_usage do
+               sys.stderr.write "Usage: {sys.program_name} {synopsis}\n"
+               sys.stderr.write "For details, run `{sys.program_name} --help`.\n"
+       end
+
+       # Print an error.
+       fun print_error(e: String) do
+               sys.stderr.write "{sys.program_name}: {e}\n"
+       end
+end
+
+# Add handling of multi-line descriptions.
+#
+# Note: The algorithm is naive and do not handle internationalisation and
+# escape sequences.
+redef class Option
+
+       redef fun pretty(off) do
+               var s = super
+
+               if s.length > 80 and off < 80 then
+                       var column_length = 80 - off
+                       var left = 0
+                       var right = 80
+                       var buf = new FlatBuffer
+                       var prefix = "\n{" " * off}"
+
+                       loop
+                               while right > left and s.chars[right] != ' ' do
+                                       right -= 1
+                               end
+                               if left == right then
+                                       buf.append s.substring(left, column_length)
+                                       right += column_length
+                               else
+                                       buf.append s.substring(left, right - left)
+                                       right += 1
+                               end
+                               buf.append prefix
+                               left = right
+                               right += column_length
+                               if right >= s.length then break
+                       end
+                       buf.append s.substring_from(left)
+                       buf.append "\n"
+                       return buf.to_s
+               else
+                       return "{s}\n"
+               end
+       end
+end
+
+exit((new NeoDoxygenCommand).main)
index 5edfe22..37b5594 100644 (file)
@@ -62,7 +62,7 @@ abstract class Processor
        var done_tag: Tag = 5.tag
 
        # Number of tasks within each task assignation with `task_tag`
-       var tasks_per_packet = 4
+       var tasks_per_packet = 1
 
        # Run the main logic of this node
        fun run is abstract
@@ -163,10 +163,8 @@ abstract class Processor
        # Gather and registar all tasks
        fun create_tasks
        do
-               var c = 0
-               for engine in engines do for prog in test_programs do
+               for prog in test_programs do for engine in engines do
                        tasks.add new Task(engine, prog)
-                       c += 1
                end
        end
 end
@@ -250,6 +248,8 @@ class Controller
                                        if res == 5 then result.fail = true
                                        if res == 6 then result.soso = true
                                        if res == 7 then result.skip = true
+                                       if res == 8 then result.todo = true
+                                       if res == 9 then result.skip_exec = true
                                        if res == 0 then result.unknown = true
 
                                        results.add result
@@ -305,6 +305,8 @@ class Controller
                print "* {results.fixmes.length} fixmes"
                print "* {results.sosos.length} sosos"
                print "* {results.skips.length} skips"
+               print "* {results.todos.length} todos"
+               print "* {results.skip_execs.length} skip execs"
                print "* {results.unknowns.length} unknowns (bug in tests.sh or nitester)"
        end
 
@@ -332,12 +334,12 @@ class Worker
        # Output file directory
        var out_dir = "/dev/shm/nit_out{rank}" is lazy
 
+       # Directory to store the xml files produced for Jenkins
+       var xml_dir = "~/jenkins_xml/"
+
        # Output file of the `tests.sh` script
        var tests_sh_out = "/dev/shm/nit_local_out{rank}" is lazy
 
-       # Path to the local copy of the Nit repository
-       var nit_copy_dir = "/dev/shm/nit{rank}/" is lazy
-
        # Source Nit repository, must be already updated and `make` before execution
        var nit_source_dir = "~/nit"
 
@@ -362,7 +364,6 @@ class Worker
        fun setup
        do
                if verbose > 0 then sys.system "hostname"
-               sys.system "git clone {nit_source_dir} {nit_copy_dir}"
        end
 
        # Clean up the testing environment
@@ -372,7 +373,6 @@ class Worker
        do
                if comp_dir.file_exists then comp_dir.rmdir
                if out_dir.file_exists then out_dir.rmdir
-               if nit_copy_dir.file_exists then nit_copy_dir.rmdir
                if tests_sh_out.file_exists then tests_sh_out.file_delete
        end
 
@@ -395,17 +395,17 @@ class Worker
                                # Receive tasks to execute
                                mpi.recv_into(task_buffer, 0, 1, status.source, status.tag, comm_world)
                                var first_id = task_buffer[0]
-                               for task_id in [first_id .. first_id + tasks_per_packet] do
+                               for task_id in [first_id .. first_id + tasks_per_packet[ do
 
                                        # If id is over all known tasks, stop right here
                                        if task_id >= tasks.length then break
                                        var task = tasks[task_id]
 
                                        # Command line to execute test
-                                       var cmd = "XMLDIR={out_dir} ERRLIST={out_dir}/errlist TMPDIR={out_dir} " +
+                                       var cmd = "XMLDIR={xml_dir} ERRLIST={out_dir}/errlist TMPDIR={out_dir} " +
                                                "CCACHE_DIR={ccache_dir} CCACHE_TEMPDIR={ccache_dir} CCACHE_BASEDIR={comp_dir} " +
-                                               "./tests.sh --compdir {comp_dir} --outdir {out_dir} -o \"--make-flags '-j1'\"" +
-                                               " --node --engine {task.engine} {nit_copy_dir / "tests" / task.test_program} > {tests_sh_out}"
+                                               "./tests.sh --compdir {comp_dir} --outdir {out_dir} " +
+                                               " --node --engine {task.engine} {task.test_program} > {tests_sh_out}"
 
                                        # Execute test
                                        sys.system cmd
@@ -446,6 +446,8 @@ class Worker
                                                if line.has("[======= fail") then res = 5
                                                if line.has("[======= soso") then res = 6
                                                if line.has("[skip]") then res = 7
+                                               if line.has("[todo]") then res = 8
+                                               if line.has("[skip exec]") then res = 9
 
                                                if res == null then
                                                        res = 0
@@ -552,9 +554,15 @@ class Result
        # Is `self` result a _soso_?
        var soso = false
 
-       # Is `self` skipped test?
+       # Has `self` been skipped?
        var skip = false
 
+       # Is `self` TODO?
+       var todo = false
+
+       # Has the execution of `self` been skipped?
+       var skip_exec = false
+
        # Is `self` an unknown result, probably an error
        var unknown = false
 
@@ -566,6 +574,10 @@ class Result
                if ok_empty then err = "0k"
                if fixme then err = "fixme"
                if fail then err = "fail"
+               if soso then err = "soso"
+               if skip then err = "skip"
+               if todo then err = "todo"
+               if skip_exec then err = "skip_exec"
 
                return "{task} arg{arg} alt{alt} => {err}"
        end
@@ -582,6 +594,8 @@ class ResultSet
        var fails = new HashSet[Result]
        var sosos = new HashSet[Result]
        var skips = new HashSet[Result]
+       var todos = new HashSet[Result]
+       var skip_execs = new HashSet[Result]
        var unknowns = new HashSet[Result]
 
        # TODO remove
@@ -596,6 +610,8 @@ class ResultSet
                if result.fail then fails.add result
                if result.soso then sosos.add result
                if result.skip then skips.add result
+               if result.todo then todos.add result
+               if result.skip_exec then skip_execs.add result
                if result.unknown then unknowns.add result
 
                super
index 477c79f..d50b84a 100644 (file)
@@ -57,7 +57,7 @@ end
 
 redef class ToolContext
        # We don't need 'the compute_nit_dir'.
-       redef fun compute_nit_dir: nullable String
+       redef fun compute_nit_dir
        do
                return "/pnacl"
        end
index 6829411..c2f2669 100644 (file)
@@ -1,6 +1,6 @@
 bin/pep8analysis:
        mkdir -p bin
-       ../../bin/nitg --global -o bin/pep8analysis src/pep8analysis.nit
+       ../../bin/nitg -o bin/pep8analysis src/pep8analysis.nit
 
 doc/index.html:
        ../../bin/nitdoc src/pep8analysis.nit
index 65db74f..6b849c9 100755 (executable)
@@ -85,7 +85,7 @@ end
 class PatternWithDir
        super BM_Pattern
 
-       var dir: String
+       var dir: String is noinit
 
        init with_dir(motif, dir: String)
        do
diff --git a/doc/advanced_options b/doc/advanced_options
deleted file mode 100644 (file)
index 814f81b..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-* GC **************************************************************************
-
-Nit programs can dynamically select a GC at runtime. Just set NIT_GC_OPTION envvar.
-Set it to "help" to list available GC at the begin of the program.
-
index 06318b6..aee71e8 100644 (file)
@@ -1,5 +1,5 @@
 default: 
-       ../../../bin/nitg --global converter.nit
+       ../../../bin/nitg --semi-global converter.nit
 
 HTTPD_PY := python $(NACL_SDK_ROOT)/tools/httpd.py
 serve:
index 220bc8d..fa70fff 100644 (file)
@@ -5,9 +5,9 @@ Steps to make the example work :
 2. Declare the environment variable NACL_SDK_ROOT as the root of the target platform within the SDK (ex: ~/nacl_sdk/pepper_34/) :
        $ export NACL_SDK_ROOT=/path/to/nacl_sdk/pepper_[your_version]
 
-3. Compile the Nit code with: `nitg --global converter.nit` or `make`.
+3. Compile the Nit code with: `nitg --semi-global converter.nit` or `make`.
 
-You must use the '--global' option. Some features in the standard library are not supported by the NaCL platform, the global compiler do not try to compile them.
+You must use the '--semi-global' (or `--global`) option. Some features in the standard library are not supported by the NaCL platform, the global compiler do not try to compile them.
 
 4. Start a local server using: `make serve`.
 
index 782fee6..d07c1be 100644 (file)
@@ -285,6 +285,6 @@ for arg in args do
                break
        end
 
-       print "Solved, after looking at {r.steps} positions during {c.lapse}"
+       print "Solved, after looking at {r.steps} positions"
        pb.print_plan(r.plan)
 end
diff --git a/lib/buffered_ropes.nit b/lib/buffered_ropes.nit
new file mode 100644 (file)
index 0000000..b287871
--- /dev/null
@@ -0,0 +1,353 @@
+# 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.
+
+# Ropes with a special kind of Leaves that act similar to a `Buffer`
+#
+# When using this module, re-allocations are limited by the introduction
+# of a larger-than-necessary buffered area for the native part of a `String`
+# in an append-only fashion.
+#
+# Concretely, when concatenating two small strings of length `n` + `m` < `maxlen`
+# What happens is that a `maxlen` byte buffer is allocated, ready to receive more
+# bytes a posteriori without necessarily reallocating a new byte array.
+#
+# Theoretically, this should lower the number of concatenations
+# and reallocations when concatenating `String` objects.
+module buffered_ropes
+
+intrude import standard::ropes
+
+# Hidden buffer, used to simulate a `FlatBuffer` on a short string.
+#
+# This is to be used by low-level APIs because of its lack of
+# safety, if you use it, make sure you know what you are doing !
+#
+# Practically, it is the underlying representation of a `Leaf` in
+# the `Rope` block, its advantage is that it saves a bit more space
+# for future concatenations, without risking to overwrite previously
+# used space, making it suitable for Strings.
+#
+# Note for future use : Should there be parallel capacity in Nit at
+# some point, this is NOT thread safe !
+private class ManualBuffer
+       var ns: NativeString is noinit
+       # Current position in the `NativeString`
+       #
+       # It is used by the clients of `ManualBuffer` as a guard
+       # to detect if the concatenation in the `ManualBuffer`
+       # is safe or not.
+       #
+       # i.e. :
+       # Say we have two strings `x` and `y` referencing the
+       # same `ManualBuffer` `b`, `y` is the concatenation of
+       # `x` and another string.
+       #
+       # If we try to concatenate a `String` `z` to `x`, a new
+       # `ManualBuffer` will be created since `pos` and `x.length`
+       # do not match.
+       #
+       # However, if we concatenate the same `String` to `y`,
+       # the contents of `z` will be copied to the `ManualBuffer`.
+       var pos = 0
+
+       init do ns = new NativeString(maxlen)
+
+       fun [](i: Int): Char do return ns[i]
+end
+
+# Simple implementation of the iterator on Substrings for `Leaf`
+#
+# Basically just returns `self` encapsulated in a `FlatString`.
+private class LeafSubstrings
+       super IndexedIterator[Text]
+
+       var str: String
+       var avail = true
+
+       init(l: Leaf) do str = new FlatString.with_infos(l.buf.ns, l.length, 0, l.length - 1)
+
+       redef fun is_ok do return avail
+
+       redef fun next do avail = false
+
+       redef fun index do return 0
+
+       redef fun item do return str
+end
+
+# Leaf of a `Rope`, used as a buffered area for speedy concatenation.
+private class Leaf
+       super RopeString
+
+       private var buf: ManualBuffer
+       private var bns: NativeString is noinit
+       redef var length: Int is noinit
+
+       redef fun empty do return new Leaf(new ManualBuffer)
+
+       redef fun to_cstring do
+               var len = length
+               var ns = new NativeString(len + 1)
+               ns[len] = '\0'
+               buf.ns.copy_to(ns, len, 0, 0)
+               return ns
+       end
+
+       redef fun substrings do return new LeafSubstrings(self)
+
+       redef fun [](i) do return buf[i]
+
+       init do
+               bns = buf.ns
+               length = buf.pos
+       end
+
+       redef fun output do new FlatString.with_infos(buf.ns, length, 0, length - 1).output
+
+       redef fun to_upper do
+               var x = new ManualBuffer
+               var nns = x.ns
+               var ns = bns
+               var mlen = length
+               for i in [0..mlen[ do
+                       nns[i] = ns[i].to_upper
+               end
+               x.pos = mlen - 1
+               return new Leaf(x)
+       end
+
+       redef fun to_lower do
+               var x = new ManualBuffer
+               var nns = x.ns
+               var ns = bns
+               var mlen = length
+               for i in [0..mlen[ do
+                       nns[i] = ns[i].to_lower
+               end
+               x.pos = mlen - 1
+               return new Leaf(x)
+       end
+
+       redef fun reversed do
+               var x = new ManualBuffer
+               var nns = x.ns
+               var ns = bns
+               var mlen = length
+               var j = mlen - 1
+               for i in [0 .. mlen[ do
+                       nns[j] = ns[i]
+                       j -= 1
+               end
+               x.pos = mlen - 1
+               return new Leaf(x)
+       end
+
+       redef fun substring(from, len) do
+               return new FlatString.with_infos(buf.ns, len, from, from + len - 1)
+       end
+
+       redef fun insert_at(s, pos) do
+               var l = substring(0, pos)
+               var r = substring_from(pos)
+               return l + s + r
+       end
+
+       redef fun +(o) do
+               var s = o.to_s
+               var slen = s.length
+               var mlen = length
+               if slen == 0 then return self
+               if mlen == 0 then return s
+               var nlen = mlen + slen
+               if nlen > maxlen then return new Concat(self, s)
+               if s isa FlatString then
+                       var bpos = buf.pos
+                       var sits = s.items
+                       if bpos == mlen then
+                               sits.copy_to(buf.ns, slen, s.index_from, bpos)
+                               buf.pos = bpos + slen
+                               return new Leaf(buf)
+                       else
+                               var b = new ManualBuffer
+                               var nbns = b.ns
+                               bns.copy_to(nbns, mlen, 0, 0)
+                               sits.copy_to(nbns, slen, s.index_from, mlen)
+                               b.pos = nlen
+                               return new Leaf(b)
+                       end
+               else if s isa Leaf then
+                       var bpos = buf.pos
+                       var sbns = s.bns
+                       if bpos == mlen then
+                               sbns.copy_to(bns, slen, 0, bpos)
+                               buf.pos += slen
+                               return new Leaf(buf)
+                       else
+                               var b = new ManualBuffer
+                               var nbns = b.ns
+                               bns.copy_to(nbns, mlen, 0, 0)
+                               sbns.copy_to(nbns, slen, 0, mlen)
+                               b.pos = nlen
+                               return new Leaf(b)
+                       end
+               else if s isa Concat then
+                       if not s.left isa Concat then
+                               return new Concat(self + s.left, s.right)
+                       end
+                       return new Concat(self, s)
+               else
+                       var bpos = buf.pos
+                       var b = buf
+                       if bpos != mlen then
+                               b = new ManualBuffer
+                               bns.copy_to(b.ns, mlen, 0, 0)
+                       end
+                       for i in s.chars do
+                               bns[bpos] = i
+                               bpos += 1
+                       end
+                       return new Leaf(b)
+               end
+       end
+end
+
+redef class Concat
+       redef fun to_cstring do
+               var len = length
+               var ns = new NativeString(len + 1)
+               ns[len] = '\0'
+               var off = 0
+               for i in substrings do
+                       var ilen = i.length
+                       if i isa FlatString then
+                               i.items.copy_to(ns, ilen, i.index_from, off)
+                       else if i isa Leaf then
+                               i.buf.ns.copy_to(ns, ilen, 0, off)
+                       else
+                               abort
+                       end
+                       off += ilen
+               end
+               return ns
+       end
+
+       redef fun +(o) do
+               var s = o.to_s
+               var mlen = length
+               var slen = s.length
+               if s isa FlatString then
+                       var r = right
+                       var rlen = r.length
+                       if rlen + slen > maxlen then return new Concat(left, new Concat(r, s))
+                       return new Concat(left, r + s)
+               else if s isa Concat then
+                       return new Concat(self, s)
+               else if s isa Leaf then
+                       var r = right
+                       var rlen = r.length
+                       if rlen + slen > maxlen then return new Concat(left, new Concat(r, s))
+                       return new Concat(left, r + s)
+               else
+                       abort
+               end
+       end
+end
+
+redef class FlatString
+       redef fun +(o) do
+               var s = o.to_s
+               var slen = s.length
+               var mlen = length
+               if slen == 0 then return self
+               if mlen == 0 then return s
+               if s isa FlatString then
+                       if slen + mlen > maxlen then return new Concat(self, s)
+                       var mits = items
+                       var sifrom = s.index_from
+                       var mifrom = index_from
+                       var sits = s.items
+                       var b = new ManualBuffer
+                       var bns = b.ns
+                       mits.copy_to(bns, mlen, mifrom, 0)
+                       sits.copy_to(bns, slen, sifrom, mlen)
+                       b.pos = mlen + slen
+                       return new Leaf(b)
+               else if s isa Concat then
+                       var sl = s.left
+                       var sllen = sl.length
+                       if sllen + mlen > maxlen then return new Concat(self, s)
+                       return new Concat(sl + self, s.right)
+               else if s isa Leaf then
+                       if slen + mlen > maxlen then return new Concat(self, s)
+                       var mits = items
+                       var mifrom = index_from
+                       var sb = s.buf
+                       var b = new ManualBuffer
+                       var bns = b.ns
+                       items.copy_to(bns, mlen, mifrom, 0)
+                       sb.ns.copy_to(bns, slen, 0, mlen)
+                       b.pos = mlen + slen
+                       return new Leaf(b)
+               else
+                       abort
+               end
+       end
+end
+
+redef class Array[E]
+
+       # Fast implementation
+       redef fun to_s do
+               var l = length
+               if l == 0 then return ""
+               if l == 1 then if self[0] == null then return "" else return self[0].to_s
+               var its = _items
+               var na = new NativeArray[String](l)
+               var i = 0
+               var sl = 0
+               var mypos = 0
+               while i < l do
+                       var itsi = its[i]
+                       if itsi == null then
+                               i += 1
+                               continue
+                       end
+                       var tmp = itsi.to_s
+                       sl += tmp.length
+                       na[mypos] = tmp
+                       i += 1
+                       mypos += 1
+               end
+               var ns = new NativeString(sl + 1)
+               ns[sl] = '\0'
+               i = 0
+               var off = 0
+               while i < mypos do
+                       var tmp = na[i]
+                       var tpl = tmp.length
+                       if tmp isa FlatString then
+                               tmp.items.copy_to(ns, tpl, tmp.index_from, off)
+                               off += tpl
+                       else
+                               for j in tmp.substrings do
+                                       var slen = j.length
+                                       if j isa FlatString then
+                                               j.items.copy_to(ns, slen, j.index_from, off)
+                                       else if j isa Leaf then
+                                               j.buf.ns.copy_to(ns, slen, 0, off)
+                                       end
+                                       off += slen
+                               end
+                       end
+                       i += 1
+               end
+               return ns.to_s_with_length(sl)
+       end
+end
diff --git a/lib/bufferized_ropes.nit b/lib/bufferized_ropes.nit
deleted file mode 100644 (file)
index 18cfa4c..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-# 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 if 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 as a part of
-# another product.
-
-# Introduces ropes with buffered leaves
-module bufferized_ropes
-
-import standard
-intrude import standard::ropes
-
-# Leaf containing a FlatBuffer to optimize concatenation operations
-private class BufferLeaf
-       super Leaf
-
-       init(val: FlatBuffer) do
-               self.str = val
-               length = str.length
-       end
-
-end
-
-redef class Concat
-       redef fun to_leaf
-       do
-               if left == null then
-                       if right == null then return new StringLeaf("".as(FlatString))
-                       return right.to_leaf
-               end
-               if right == null then return left.as(not null).to_leaf
-               if left.length + right.length < buf_len then
-                       var b = new FlatBuffer.with_capacity(buf_len)
-                       b.append(left.to_leaf.str)
-                       b.append(right.to_leaf.str)
-                       return new BufferLeaf(b)
-               else
-                       var b = new FlatBuffer.with_capacity(left.length + right.length)
-                       b.append(left.to_leaf.str)
-                       b.append(right.to_leaf.str)
-                       return new StringLeaf(b.lazy_to_s(b.length))
-               end
-       end
-end
-
-redef class FlatText
-
-       # Creates a substring, only without any copy overhead for Buffers
-       # The call to lazy_substring ensures the creation of a FlatString, which is required for Leaves.
-       private fun lazy_substring(from: Int, length: Int): FlatString is abstract
-
-       # Same as substring_from, but without copy of the data for Buffers.
-       private fun lazy_substring_from(from: Int): FlatString is abstract
-end
-
-redef class FlatBuffer
-
-       # Same as to_s, only will not copy self before returning a String.
-       private fun lazy_to_s(len: Int): FlatString
-       do
-               return new FlatString.with_infos(items, len, 0, length - 1)
-       end
-
-       redef fun lazy_substring(from,length)
-       do
-               return new FlatString.with_infos(items, length, from, from + length - 1)
-       end
-
-       redef fun lazy_substring_from(from)
-       do
-               var newlen = length - from
-               return new FlatString.with_infos(items, newlen, from, from + newlen - 1)
-       end
-
-end
-
-redef class FlatString
-
-       redef fun lazy_substring(from, len) do return substring(from,len).as(FlatString)
-
-       redef fun lazy_substring_from(from) do return substring_from(from).as(FlatString)
-
-end
-
-redef class Rope
-
-       # Empty Rope
-       init do root = new BufferLeaf(new FlatBuffer.with_capacity(buf_len))
-
-end
-
-redef class RopeString
-
-       init from(s: String) do
-               if s.length < buf_len then
-                       var b = new FlatBuffer.with_capacity(buf_len)
-                       b.append(s)
-                       root = new BufferLeaf(b)
-               else
-                       if s isa RopeString then root = s.root else root = new StringLeaf(s.as(FlatString))
-               end
-       end
-
-       redef fun +(o) do return insert_at(o.to_s, length)
-
-       # Inserts a String `str` at position `pos`
-       redef fun insert_at(str, pos)
-       do
-               if str.length == 0 then return self
-
-               assert pos >= 0 and pos <= length
-
-               if pos == length then
-                       var r = root
-                       if r isa BufferLeaf then
-                               var b = r.str.as(FlatBuffer)
-                               if r.length + str.length < b.capacity then
-                                       b.append(str)
-                                       return new RopeString.from_root(new BufferLeaf(b))
-                               end
-                       end
-               end
-
-               var path = node_at(pos)
-
-               var cct: RopeNode
-
-               if path.offset == path.leaf.length then
-                       cct = build_node_len_offset(path, str)
-               else if path.offset == 0 then
-                       cct = build_node_zero_offset(path, str)
-               else
-                       cct = build_node_other(path,str)
-               end
-
-               if path.stack.is_empty then return new RopeString.from_root(cct)
-
-               var tmp = path.stack.pop
-               var last_concat: Concat
-
-               if tmp.left then
-                       last_concat = new Concat(cct,tmp.node.right.as(not null))
-               else
-                       last_concat = new Concat(tmp.node.left.as(not null), cct)
-               end
-
-               for i in path.stack.reverse_iterator do
-                       var nod: Concat
-                       if i.left then
-                               nod = new Concat(last_concat, i.node.right.as(not null))
-                       else
-                               nod = new Concat(i.node.left.as(not null), last_concat)
-                       end
-                       last_concat = nod
-               end
-
-               return new RopeString.from_root(last_concat)
-       end
-
-       redef fun substring(pos, len)
-       do
-               if pos < 0 then
-                       len += pos
-                       pos = 0
-               end
-
-               if pos + len > length then len = length - pos
-
-               if len <= 0 then return new RopeString
-
-               var path = node_at(pos)
-
-               var lf = path.leaf
-               var offset = path.offset
-
-               var s: FlatString
-               if lf isa StringLeaf then
-                       s = lf.str.as(FlatString)
-               else
-                       s = lf.str.as(FlatBuffer).lazy_to_s(lf.length)
-               end
-
-               if path.leaf.str.length - offset > len then
-                       lf = new StringLeaf(s.substring(offset,len).as(FlatString))
-               else
-                       lf = new StringLeaf(s.substring_from(offset).as(FlatString))
-               end
-
-               var nod: RopeNode = lf
-
-               if lf.length == len then return new RopeString.from_root(lf)
-
-               var lft: nullable RopeNode
-               var rht: nullable RopeNode
-
-               for i in path.stack.reverse_iterator do
-                       if i.right then continue
-                       lft = nod
-                       rht = i.node.right
-                       nod = new Concat(lft, rht)
-               end
-
-               var ret = new RopeString
-               ret.root = nod
-
-               path = ret.node_at(len-1)
-
-               offset = path.offset
-
-               lf = path.leaf
-
-               if lf isa StringLeaf then
-                       s = lf.str.as(FlatString)
-               else
-                       s = lf.str.as(FlatBuffer).lazy_to_s(lf.length)
-               end
-
-               nod = new StringLeaf(s.substring(0, offset+1).as(FlatString))
-
-               for i in path.stack.reverse_iterator do
-                       if i.left then continue
-                       rht = nod
-                       lft = i.node.left
-                       nod = new Concat(lft, rht)
-               end
-
-               ret.root = nod
-
-               return ret
-       end
-
-       private fun build_node_zero_offset(path: Path, s: String): RopeNode
-       do
-               var finlen = path.leaf.length + s.length
-               if finlen <= buf_len then
-                       var b = new FlatBuffer.with_capacity(buf_len)
-                       b.append(s)
-                       b.append(path.leaf.str)
-                       if finlen == buf_len then return new StringLeaf(b.lazy_to_s(finlen))
-                       return new BufferLeaf(b)
-               end
-               var rht = path.leaf
-               var lft: RopeNode
-               if s isa FlatString then
-                       if s.length > buf_len then
-                               lft = new StringLeaf(s)
-                       else
-                               var b = new FlatBuffer
-                               b.append(s)
-                               lft = new BufferLeaf(b)
-                       end
-               else
-                       lft = s.as(RopeString).root
-               end
-               return new Concat(lft, rht)
-       end
-
-       private fun build_node_len_offset(path: Path, s: String): RopeNode
-       do
-               var leaf = path.leaf
-               if leaf isa BufferLeaf then
-                       if s.length > buf_len then
-                               if s isa FlatString then
-                                       return new Concat(leaf, new StringLeaf(s))
-                               else
-                                       return new Concat(leaf, s.as(Rope).root)
-                               end
-                       end
-                       var finlen = leaf.length + s.length
-                       var buf = leaf.str.as(FlatBuffer)
-                       var cap = buf.capacity
-                       # Meaning the buffer was modified elsewhere
-                       # Therefore, we create a new one
-                       if leaf.length != buf.length then
-                               var b = new FlatBuffer.with_capacity(buf_len)
-                               b.append(buf.lazy_to_s(leaf.length))
-                               buf = b
-                       end
-                       if finlen <= cap then
-                               buf.append(s)
-                               if finlen == buf_len then return new StringLeaf(buf.lazy_to_s(finlen))
-                               return new BufferLeaf(buf)
-                       else
-                               var l_len = finlen - cap
-                               buf.append(s.substring(0,l_len))
-                               var b2 = new FlatBuffer.with_capacity(buf_len)
-                               b2.append(s.substring_from(l_len))
-                               var left_leaf = new StringLeaf(buf.lazy_to_s(buf.length))
-                               var right_leaf = new BufferLeaf(b2)
-                               var cct = new Concat(left_leaf, right_leaf)
-                               return cct
-                       end
-               else
-                       var lft = leaf
-                       var rht: RopeNode
-                       if s.length >= buf_len then
-                               if s isa FlatString then rht = new StringLeaf(s) else rht = s.as(Rope).root
-                       else
-                               var buf = new FlatBuffer.with_capacity(buf_len)
-                               buf.append(s)
-                               rht = new BufferLeaf(buf)
-                       end
-                       return new Concat(lft,rht)
-               end
-       end
-
-       private fun build_node_other(path: Path,str: String): RopeNode
-       do
-               var lf = path.leaf
-               var s: FlatString
-               if lf isa BufferLeaf then
-                       var b = lf.str.as(FlatBuffer)
-                       s = b.lazy_to_s(lf.length)
-               else
-                       s = lf.str.as(FlatString)
-               end
-               var l_str = s.lazy_substring(0, path.offset)
-               var r_str = s.lazy_substring_from(path.offset)
-               if s.length + str.length < buf_len then
-                       var buf = new FlatBuffer.with_capacity(buf_len)
-                       buf.append(l_str)
-                       buf.append(str)
-                       buf.append(r_str)
-                       return new BufferLeaf(buf)
-               end
-               var child: RopeNode
-               if str isa FlatString then child = new StringLeaf(str) else child = str.as(Rope).root
-               var l_cct = new Concat(new StringLeaf(l_str), child)
-               var r_cct = new Concat(l_cct, new StringLeaf(r_str))
-               return r_cct
-       end
-
-end
-
-redef class SubstringsIterator
-
-       # Compute the bounds of the current substring and makes the substring
-       redef fun make_substring
-       do
-               var l = nodes.item
-               var s = l.str
-               var min = 0
-               var length = l.length
-               if nodes.index < pos then
-                       min = pos - nodes.index
-               end
-               substring = s.lazy_substring(min, length)
-       end
-
-end
-
-redef class ReverseSubstringsIterator
-
-       redef fun make_substring
-       do
-               var l = leaves.item
-               var s = l.str
-               if pos > (leaves.index + l.length - 1) then return
-               str = s.lazy_substring(0, (pos - leaves.index + 1))
-       end
-
-end
-
-# Default size of a buffer in a rope leaf.
-fun buf_len: Int do return 200
-
diff --git a/lib/cartesian.nit b/lib/cartesian.nit
new file mode 100644 (file)
index 0000000..7090050
--- /dev/null
@@ -0,0 +1,181 @@
+# 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.
+
+# Cartesian products on heterogeneous collections.
+#
+# This module is a proof-of-concept to propose memory-efficient views on collections.
+#
+# This is a specific alternative to `combinations`, that focuses only highly efficient
+# Cartesian products between collections of different types.
+#
+#    Collection[Int] X Collection[String] -> Collection[(Int,String)]
+#
+# However, in Nit, there in no native *tuple* type.
+# So we need a first building block, a pair.
+
+# A simple read-only pair of two elements `e` and `f`.
+class Pair[E, F]
+       # The first element of the pair
+       var e: E
+
+       # The second element of the pair
+       var f: F
+
+       # The parenthesized notation.
+       #
+       # ~~~
+       # var p = new Pair[Int, String](1, "hello")
+       # assert p.to_s == "(1,hello)"
+       # ~~~
+       redef fun to_s
+       do
+               var es = e or else ""
+               var fs = f or else ""
+               return "({es},{fs})"
+       end
+
+       # Untyped pair equality.
+       #
+       # ~~~
+       # var p1 = new Pair[Object, Object](1, 2)
+       # var p2 = new Pair[Int, Int](1, 2)
+       # var p3 = new Pair[Int, Int](1, 3)
+       #
+       # assert p1 == p2
+       # assert p2 != p3
+       # ~~~
+       #
+       # Untyped because we want that `p1 == p2` above.
+       # So the method just ignores the real types of `E` and `F`.
+       redef fun ==(o) do return o isa Pair[nullable Object, nullable Object] and e == o.e and f == o.f
+
+       redef fun hash do return e.hash * 13 + f.hash * 27 # Magic numbers are magic!
+end
+
+# A view of a Cartesian-product collection over two collections.
+#
+# A Cartesian product over two collections is just a collection of pairs.
+# Therefore, this view *contains* all the pairs of elements constructed by associating each
+# element of the first collection to each element of the second collection.
+#
+# However the view is memory-efficient and the pairs are created only when needed.
+#
+# A simple Cartesian product
+# ~~~~
+# var c1 = [1,2]
+# var c2 = ["a","b","c"]
+# var c12 = new Cartesian[Int,String](c1, c2)
+# assert c12.length    == 6
+# assert c12.join(";") == "(1,a);(1,b);(1,c);(2,a);(2,b);(2,c)" # All the 6 pairs
+# ~~~~
+#
+# Note: because it is a view, changes on the base collections are reflected on the view.
+#
+# E.g. c12 is a view on c1 and c2, so if c1 changes, then c12 "changes".
+# ~~~~
+# assert c2.pop        == "c"
+# assert c12.length    == 4
+# assert c12.join(";") == "(1,a);(1,b);(2,a);(2,b)" # All the 4 remaining pairs
+# ~~~~
+#
+# Cartesian objects are collections, so can be used to build another Cartesian object.
+# ~~~~
+# var c3 = [1000..2000[
+# var c123 = new Cartesian[Pair[Int,String],Int](c12, c3)
+# assert c123.length   == 4000
+# ~~~~
+#
+# All methods of Collection are inherited, it is so great!
+#
+# E.g. search elements?
+# ~~~~
+# var p12 = new Pair[Int,String](2,"b")
+# assert c12.has(p12)      == true
+# var p123 = new Pair[Pair[Int, String], Int](p12, 1500)
+# var p123bis = new Pair[Pair[Int, String], Int](p12, 0)
+# assert c123.has(p123)    == true
+# assert c123.has(p123bis) == false
+# ~~~~
+class Cartesian[E, F]
+       super Collection[Pair[E,F]]
+
+       # The first collection
+       var ce: Collection[E]
+
+       # The second collection
+       var cf: Collection[F]
+
+       redef fun length do return ce.length * cf.length # optional, but so efficient...
+
+       redef fun iterator do return new CartesianIterator[E,F](self)
+
+       # Returns a new Cartesian where the first collection is the second.
+       # Because the full collection is virtual, the operation is cheap!
+       fun swap: Cartesian[F, E] do return new Cartesian[F, E](cf, ce)
+end
+
+# An iterator over a `Cartesian`-product collection.
+class CartesianIterator[E,F]
+       super Iterator[Pair[E,F]]
+
+       # The associated Cartesian-product collection.
+       var collection: Cartesian[E,F]
+
+       # The iterator over the first collection of the Cartesian product.
+       # Will be used only once.
+       private var ice: Iterator[E] is noinit
+
+       # The iterator over the second collection of the Cartesian product.
+       # Will be used once for each element of the first collection.
+       private var icf: Iterator[F] is noinit
+
+       init do
+               # Initialize each iterator
+               ice = collection.ce.iterator
+               icf = collection.cf.iterator
+       end
+
+       redef fun is_ok do return ice.is_ok and icf.is_ok
+
+       redef fun item do
+               # We lazily create the pair here
+               var res = item_cache
+               if res == null then
+                       res = new Pair[E,F](ice.item, icf.item)
+                       item_cache = res
+               end
+               return res
+       end
+
+       # Cached pair created by `item` and cleared by `next`.
+       private var item_cache: nullable Pair[E,F] = null
+
+       redef fun next do
+               # Next item in the second iterator
+               icf.next
+               if not icf.is_ok then
+                       # If it is over, then reset it and advance the first iterator
+                       icf = collection.cf.iterator
+                       ice.next
+               end
+               # Reset the cache
+               item_cache = null
+       end
+
+       # First member of `item`.
+       #
+       # This method shortcut the allocation of a `Pair`, thus should be more time and memory efficient.
+       fun item_e: E do return ice.item
+
+       # Second member of `item`.
+       #
+       # This method shortcut the allocation of a `Pair`, thus should be more time and memory efficient.
+       fun item_f: E do return icf.item
+end
diff --git a/lib/combinations.nit b/lib/combinations.nit
new file mode 100644 (file)
index 0000000..4076c03
--- /dev/null
@@ -0,0 +1,439 @@
+# 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.
+
+# Cartesian products, combinations and permutation on collections.
+#
+# This module offers memory-efficient views on combinatoric collections.
+# Methods of the views create objects only when needed.
+# Moreover, produced objects during iterations are free to be collected and
+# their memory reused.
+#
+# This enable these views and method to works with very combinatoric large collections.
+#
+# When small combinatoric views need to be kept in memory (for fast access by example).
+# The `Collection::to_a` method and other related factories can be used to transform
+# the combinatoric views into extensive collections,
+module combinations
+
+redef class Collection[E]
+       # Cartesian product, over `r` times `self`.
+       #
+       # See `CartesianCollection` for details.
+       #
+       # FIXME: Cannot be used if RTA is enabled. So `niti` or `--erasure` only.
+       fun product(r: Int): Collection[SequenceRead[E]]
+       do
+               return new CartesianCollection[E]([self]*r)
+       end
+
+       # All `r`-length permutations on self (all possible ordering) without repeated elements.
+       #
+       # See `CartesianCollection` for details.
+       #
+       # FIXME: Cannot be used if RTA is enabled. So `niti` or `--erasure` only.
+       fun permutations(r: Int): Collection[SequenceRead[E]]
+       do
+               var res = new CombinationCollection[E](self, r)
+               res.are_sorted = false
+               res.are_unique = true
+               return res
+       end
+
+       # All `r`-length combinations on self (in same order) without repeated elements.
+       #
+       # See `CartesianCollection` for details.
+       #
+       # FIXME: Cannot be used if RTA is enabled. So `niti` or `--erasure` only.
+       fun combinations(r: Int): Collection[SequenceRead[E]]
+       do
+               var res = new CombinationCollection[E](self, r)
+               res.are_sorted = true
+               res.are_unique = true
+               return res
+       end
+
+       # All `r`-length combination on self (in same order) with repeated elements.
+       #
+       # See `CartesianCollection` for details.
+       #
+       # FIXME: Cannot be used if RTA is enabled. So `niti` or `--erasure` only.
+       fun combinations_with_replacement(r: Int): Collection[SequenceRead[E]]
+       do
+               var res = new CombinationCollection[E](self, r)
+               res.are_sorted = true
+               res.are_unique = false
+               return res
+       end
+end
+
+# A view of a Cartesian-product collection over homogeneous collections.
+#
+# Therefore, this view *generates* all the sequences of elements constructed by associating
+# en element for each one of the original collections.
+#
+# It is equivalent to doing nesting `for` for each collection.
+#
+# ~~~~
+# var xs = [1, 2, 3]
+# var ys = [8, 9]
+# var xys = new CartesianCollection[Int]([xs, ys])
+# assert xys.length == 6
+# assert xys.to_a == [[1,8], [1,9], [2,8], [2,9], [3,8], [3,9]]
+# ~~~~
+#
+# The pattern of the generate sequences produces a lexicographical order.
+#
+# Because it is a generator, it is memory-efficient and the sequences are created only when needed.
+#
+# Note: because it is a view, changes on the base collections are reflected on the view.
+#
+# ~~~~
+# assert xs.pop == 3
+# assert ys.pop == 9
+# assert xys.to_a == [[1,8], [2,8]]
+# ~~~~
+class CartesianCollection[E]
+       super Collection[SequenceRead[E]]
+
+       # The base collections used to generate the sequences.
+       var collections: SequenceRead[Collection[E]]
+
+       redef fun length
+       do
+               var res = 1
+               for c in collections do res = res * c.length
+               return res
+       end
+
+       redef fun iterator do return new CartesianIterator[E](self)
+end
+
+private class CartesianIterator[E]
+       super Iterator[SequenceRead[E]]
+       var collection: CartesianCollection[E]
+
+       # The array of iterations that will be increased in the lexicographic order.
+       private var iterators = new Array[Iterator[E]]
+
+       init
+       do
+               for c in collection.collections do
+                       var it = c.iterator
+                       iterators.add it
+                       if not it.is_ok then is_ok = false
+               end
+       end
+
+       redef var is_ok = true
+
+       redef fun item
+       do
+               var len = iterators.length
+               var res = new Array[E].with_capacity(len)
+               for i in [0..len[ do
+                       var it = iterators[i]
+                       res.add(it.item)
+               end
+               return res
+       end
+
+       redef fun next
+       do
+               var rank = iterators.length - 1
+
+               # Odometer-like increment starting from the last iterator
+               loop
+                       var it = iterators[rank]
+                       it.next
+                       if it.is_ok then return
+
+                       # The iterator if over
+                       if rank == 0 then
+                               # It it is the first, then the whole thing is over
+                               is_ok = false
+                               return
+                       end
+
+                       # If not, restart the iterator and increment the previous one
+                       # (like a carry)
+                       iterators[rank] = collection.collections[rank].iterator
+                       rank -= 1
+               end
+       end
+end
+
+# A view of some combinations over a base collections.
+#
+# This view *generates* some combinations and permutations on a collection.
+#
+# By default, the generated sequences are combinations:
+#
+#   * each sequence has a length of `repeat`
+#   * elements are in sorted order (see `are_sorted` for details)
+#   * no repeated element (see `are_unique` for details)
+#
+# ~~~~
+# var xs = [1, 2, 3]
+# var cxs = new CombinationCollection[Int](xs, 2)
+# assert cxs.length == 3
+# assert cxs.to_a == [[1,2], [1,3], [2,3]]
+# ~~~~
+#
+# Other kind of combinations can be generated by tweaking the attributes `are_sorted` and `are_unique`.
+#
+# * for permutation:
+#
+# ~~~~
+# cxs.are_sorted = false
+# cxs.are_unique = true
+# assert cxs.length == 6
+# assert cxs.to_a == [[1,2], [1,3], [2,1], [2,3], [3,1], [3,2]]
+# ~~~~
+#
+# * for combinations with replacement:
+#
+# ~~~~
+# cxs.are_sorted = true
+# cxs.are_unique = false
+# assert cxs.length == 6
+# assert cxs.to_a == [[1,1], [1,2], [1,3], [2,2], [2,3], [3,3]]
+# ~~~~
+#
+# * for product:
+#
+# ~~~~
+# cxs.are_sorted = false
+# cxs.are_unique = false
+# assert cxs.length == 9
+# assert cxs.to_a == [[1,1], [1,2], [1,3], [2,1], [2,2], [2,3], [3,1], [3,2], [3,3]]
+# ~~~~
+#
+# However, in the last case, a faster alternative is to use `CartesianCollection`:
+#
+# ~~~~
+# var cp = new CartesianCollection[Int]([xs] * 2)
+# assert cp.to_a == cxs.to_a
+# ~~~~
+#
+# As seen in the examples, the patterns of the generated sequences produce a lexicographical order.
+#
+# Because it is a generator, it is memory-efficient and the sequences are created only when needed.
+#
+# Note: because it is a view, changes on the base collection are reflected on the view.
+#
+# ~~~~
+# assert xs.pop == 3
+# cxs.are_sorted = true
+# cxs.are_unique = true
+# assert cxs.to_a == [[1,2]]
+# ~~~~
+class CombinationCollection[E]
+       super Collection[SequenceRead[E]]
+
+       # The base collection used to generate the sequences.
+       var collection: Collection[E]
+
+       # The maximum length of each generated sequence.
+       var repeat: Int
+
+       init
+       do
+               assert repeat >= 0
+       end
+
+       # Are the elements in the generated sequences sorted?
+       # Default `true`.
+       #
+       # When `true`, the original order is preserved.
+       #
+       # Elements are compared by their order in the base collection,
+       # not by their intrinsic value or comparability.
+       #
+       # ~~~~
+       # var xs = [1, 1, 2]
+       # var cxs = new CombinationCollection[Int](xs, 2)
+       # cxs.are_sorted = true
+       # assert cxs.to_a == [[1,1], [1,2], [1, 2]]
+       # cxs.are_sorted = false
+       # assert cxs.to_a == [[1,1], [1,2], [1, 1], [1, 2], [2, 1], [2, 1]]
+       # ~~~~
+       var are_sorted = true is writable
+
+       # Are the element in the generated sequence unique?
+       # Default `true`.
+       #
+       # When `true`, an element cannot be reused in the same sequence (no replacement).
+       #
+       # Elements are distinguished by their order in the base collection,
+       # not by their intrinsic value or equality.
+       #
+       # ~~~~
+       # var xs = [1, 1, 2]
+       # var cxs = new CombinationCollection[Int](xs, 2)
+       # cxs.are_unique = true
+       # assert cxs.to_a == [[1,1], [1,2], [1, 2]]
+       # cxs.are_unique = false
+       # assert cxs.to_a == [[1,1], [1,1], [1,2], [1,1], [1,2], [2,2]]
+       # ~~~~
+       var are_unique = true is writable
+
+       redef fun length
+       do
+               var n = collection.length
+               if are_unique then
+                       if repeat > n then
+                               return 0
+                       end
+                       if are_sorted then
+                               return n.factorial / repeat.factorial
+                       else
+                               return n.factorial / (n-repeat).factorial
+                       end
+               else
+                       if are_sorted then
+                               return (n+repeat-1).factorial / repeat.factorial / (n-1).factorial
+                       else
+                               return n ** repeat
+                       end
+               end
+       end
+
+       redef fun iterator do
+               return new CombinationIterator[E](self)
+       end
+end
+
+private class CombinationIterator[E]
+       super Iterator[SequenceRead[E]]
+       var product: CombinationCollection[E]
+
+       private var iterators = new Array[Iterator[E]]
+       private var indices = new Array[Int]
+
+       var are_sorted: Bool is noinit
+       var are_unique: Bool is noinit
+
+       init
+       do
+               are_sorted = product.are_sorted
+               are_unique = product.are_unique
+
+               for rank in [0..product.repeat[ do
+                       reset_iterator(rank)
+               end
+       end
+
+       redef var is_ok = true
+
+       redef fun item
+       do
+               var len = product.repeat
+               var res = new Array[E].with_capacity(len)
+               for i in [0..len[ do
+                       var it = iterators[i]
+                       res.add(it.item)
+               end
+               return res
+       end
+
+       redef fun next
+       do
+               var rank = product.repeat - 1
+
+               loop
+                       var it = iterators[rank]
+
+                       if are_unique and not are_sorted then
+                               var idx = indices[rank] + 1
+                               it.next
+                               var adv = next_free(rank, idx)
+                               for i in [idx..adv[ do it.next
+                               indices[rank] = adv
+                       else
+                               it.next
+                               indices[rank] += 1
+                       end
+
+                       if it.is_ok then break
+                       if rank == 0 then
+                               is_ok = false
+                               return
+                       end
+                       rank -= 1
+               end
+
+               for r in [rank+1..product.repeat[ do
+                       reset_iterator(r)
+               end
+       end
+
+       private fun next_free(rank: Int, start: Int): Int
+       do
+               loop
+                       for i in [0..rank[ do
+                               if indices[i] == start then
+                                       start += 1
+                                       continue label
+                               end
+                       end
+                       break label
+               end label
+               return start
+       end
+
+       private fun reset_iterator(rank: Int): Iterator[E]
+       do
+               var it = product.collection.iterator
+               iterators[rank] = it
+               var skip = 0
+
+               if (not are_sorted and not are_unique) or rank == 0 then
+                       # DO NOTHING
+               else if are_sorted and are_unique then
+                       skip = indices[rank-1] + 1
+               else if are_sorted then
+                       skip = indices[rank-1]
+               else
+                       skip = next_free(rank, 0)
+               end
+
+               for i in [0..skip[ do it.next
+               indices[rank] = skip
+               if not it.is_ok then is_ok = false
+               return it
+       end
+
+       fun need_skip: Bool
+       do
+               if not are_sorted and not are_unique then
+                       return false
+               else if are_sorted and are_unique then
+                       var max = -1
+                       for i in indices do
+                               if i <= max then return true
+                               max = i
+                       end
+                       return false
+               else if are_sorted then
+                       var max = -1
+                       for i in indices do
+                               if i < max then return true
+                               max = i
+                       end
+                       return false
+               else
+                       # are_unique
+                       for i in indices do
+                               if indices.count(i) > 1 then return true
+                       end
+                       return false
+               end
+       end
+end
index 04dcb6e..e922a84 100644 (file)
@@ -19,9 +19,162 @@ module console
 abstract class TermEscape
        # The US-ASCII ESC character.
        protected fun esc: Char do return 27.ascii
+
+       # The Control Sequence Introducer (CSI).
+       protected fun csi: String do return "{esc}["
+end
+
+# Abstract class of the ANSI/VT100 escape sequences for directional moves.
+abstract class TermDirectionalMove
+       super TermEscape
+
+       # The length of the move.
+       var magnitude: Int = 1 is protected writable
+
+       redef fun to_s do
+               if magnitude == 1 then return "{csi}{code}"
+               return "{csi}{magnitude}{code}"
+       end
+
+       # The code of the command.
+       protected fun code: String is abstract
+end
+
+# ANSI/VT100 code to move the cursor up by `magnitude` rows (CUU).
+class TermMoveUp
+       super TermDirectionalMove
+
+       init do end
+
+       # Move by the specified number of cells.
+       init by(magnitude: Int) do self.magnitude = magnitude
+
+       redef fun code do return "A"
+end
+
+# ANSI/VT100 code to move the cursor down by `magnitude` rows (CUD).
+class TermMoveDown
+       super TermDirectionalMove
+
+       init do end
+
+       # Move by the specified number of cells.
+       init by(magnitude: Int) do self.magnitude = magnitude
+
+       redef fun code do return "B"
+end
+
+# ANSI/VT100 code to move the cursor foward by `magnitude` columns (CUF).
+class TermMoveFoward
+       super TermDirectionalMove
+
+       init do end
+
+       # Move by the specified number of cells.
+       init by(magnitude: Int) do self.magnitude = magnitude
+
+       redef fun code do return "C"
+end
+
+# ANSI/VT100 code to move the cursor backward by `magnitude` columns (CUB).
+class TermMoveBackward
+       super TermDirectionalMove
+
+       init do end
+
+       # Move by the specified number of cells.
+       init by(magnitude: Int) do self.magnitude = magnitude
+
+       redef fun code do return "D"
+end
+
+# ANSI/VT100 code to move the cursor at the specified position (CUP).
+class TermMove
+       super TermEscape
+
+       # Vertical position.
+       #
+       # 1 is the top.
+       var row: Int = 1
+
+       # Horizontal position.
+       #
+       # 1 is the left.
+       var column: Int = 1
+
+       init do end
+
+       # Move at the specified position.
+       #
+       # (1, 1) is the top-left corner of the display.
+       init at(row: Int, column: Int) do
+               self.row = row
+               self.column = column
+       end
+
+       redef fun to_s do
+               if row == 1 then
+                       if column == 1 then return "{csi}H"
+                       return "{csi};{column}H"
+               else
+                       if column == 1 then return "{csi}{row}H"
+                       return "{csi}{row};{column}H"
+               end
+       end
+end
+
+# ANSI/VT100 code to clear from the cursor to the end of the screen (ED 0).
+class TermEraseDisplayDown
+       super TermEscape
+       redef fun to_s do return "{csi}J"
+end
+
+# ANSI/VT100 code to clear from the cursor to the beginning of the screen (ED 1).
+class TermEraseDisplayUp
+       super TermEscape
+       redef fun to_s do return "{csi}1J"
+end
+
+# ANSI/VT100 code to clear the entire display and move the cursor to the top left of screen (ED 2).
+#
+# Note: Some terminals always move the cursor when the screen is cleared. So we
+# force this behaviour to ensure interoperability of the code.
+class TermClearDisplay
+       super TermEscape
+       redef fun to_s do return "{csi}2J{csi}H"
+end
+
+# ANSI/VT100 code to erase anything after the cursor in the line (EL 0).
+class TermEraseLineFoward
+       super TermEscape
+       redef fun to_s do return "{csi}K"
+end
+
+# ANSI/VT100 code to erase anything before the cursor in the line (EL 1).
+class TermEraseLineBackward
+       super TermEscape
+       redef fun to_s do return "{csi}1K"
+end
+
+# ANSI/VT100 code to clear everything in the current line (EL 2).
+class TermClearLine
+       super TermEscape
+       redef fun to_s do return "{csi}2K"
+end
+
+# ANSI/VT100 code to save the current cursor position (SCP).
+class TermSaveCursor
+       super TermEscape
+       redef fun to_s do return "{csi}s"
+end
+
+# ANSI/VT100 code to restore the current cursor position (RCP).
+class TermRestoreCursor
+       super TermEscape
+       redef fun to_s do return "{csi}u"
 end
 
-# ANSI/VT100 code to switch character attributes (SGR).
+# ANSI/VT100 code to change character look (SGR).
 #
 # By default, resets everything to the terminal’s defaults.
 #
@@ -46,7 +199,7 @@ class TermCharFormat
                attributes.add_all(format.attributes)
        end
 
-       redef fun to_s: String do return "{esc}[{attributes.join(";")}m"
+       redef fun to_s: String do return "{csi}{attributes.join(";")}m"
 
        # Apply the specified SGR and return `self`.
        private fun apply(sgr: String): TermCharFormat do
index 4fc8530..f58bdf6 100644 (file)
@@ -60,7 +60,7 @@ class HTMLPage
 
        # Add a raw html string
        # add_html("<a href='#top'>top</a>")
-       fun add_html(html: String) do current.add(new HTMLRaw(html))
+       fun add_html(html: String) do current.add(new HTMLRaw("", html))
 
        # Open a html tag
        # open("ul")
@@ -89,8 +89,7 @@ class HTMLTag
 
        # HTML tagname: 'div' for <div></div>
        var tag: String
-       init(tag: String) do
-               self.tag = tag
+       init do
                self.is_void = (once ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"]).has(tag)
        end
 
@@ -98,7 +97,7 @@ class HTMLTag
        #
        #     assert (new HTMLTag("img")).is_void    == true
        #     assert (new HTMLTag("p")).is_void      == false
-       var is_void: Bool
+       var is_void: Bool is noinit
 
        init with_attrs(tag: String, attrs: Map[String, String]) do
                self.tag = tag
@@ -237,7 +236,7 @@ class HTMLTag
        #     assert p.write_to_string      ==  "<p>Hello<br/>World!</p>"
        # Text is escaped see: standard::String::html_escape
        fun append(txt: String): HTMLTag do
-               add(new HTMLRaw(txt.html_escape))
+               add(new HTMLRaw("", txt.html_escape))
                return self
        end
 
@@ -250,7 +249,7 @@ class HTMLTag
        #
        # Note: the HTML in insered as it, no verification is done.
        fun add_raw_html(txt: String): HTMLTag do
-               add(new HTMLRaw(txt))
+               add(new HTMLRaw("", txt))
                return self
        end
 
@@ -327,6 +326,5 @@ private class HTMLRaw
        super HTMLTag
 
        private var content: String
-       init(content: String) do self.content = content
        redef fun render_in(res) do res.add content
 end
index d9d1f27..389c6f6 100644 (file)
@@ -38,7 +38,7 @@ redef class Sys
        private var jvm_cache: nullable JavaVM = null
        private var jni_env_cache: nullable JniEnv = null
 
-       # Default Java Virtual Machine to use (will be instanciated using
+       # Default Java Virtual Machine to use (will be instantiated using
        # `create_default_jvm` if not already set)
        fun jvm: JavaVM
        do
@@ -59,13 +59,13 @@ redef class Sys
        # Sets the current default JNI env (use with `jvm=`)
        fun jni_env=(jni_env: JniEnv) do jni_env_cache = jni_env
 
-       # Called by `jvm` and `jni_env` to instanciate a Java Virual Machine.
+       # Called by `jvm` and `jni_env` to instantiate a Java Virtual Machine.
        # Used mostly for the FFI with Java.
        protected fun create_default_jvm
        do
                var builder = new JavaVMBuilder
 
-               # By default, look for Java classes in a jar file the same dir as the executable
+               # By default, look for Java classes in a jar file the same directory as the executable
                builder.options.add "-Djava.class.path={sys.program_name}.jar"
 
                var jvm = builder.create_jvm
@@ -79,7 +79,7 @@ redef class Sys
        fun load_jclass(name: NativeString): JClass import jni_env `{
                JNIEnv *nit_ffi_jni_env = Sys_jni_env(recv);
 
-               // retreive the implementation Java class
+               // retrieve the implementation Java class
                jclass java_class = (*nit_ffi_jni_env)->FindClass(nit_ffi_jni_env, name);
                if (java_class == NULL) {
                        fprintf(stderr, "Nit FFI with Java error: failed to load class.\\n");
@@ -135,6 +135,7 @@ redef class NativeString
 end
 
 redef class Text
+       # Get `self` as a `JavaString`
        fun to_java_string: JavaString do return to_cstring.to_java_string
 end
 
@@ -177,4 +178,26 @@ redef extern class JavaObject
        private fun pop_from_local_frame_with_env(jni_env: JniEnv): SELF `{
                return (*jni_env)->PopLocalFrame(jni_env, recv);
        `}
+
+       # Is `self` null in Java?
+       #
+       # Since Java type system doesn't have the same `nullable` concept as Nit's,
+       # the two systems are not directly compatible. Any Nit instances of
+       # `JavaObject` may hold a Java null.
+       #
+       # To benefit from the safer type system of Nit, it is recommended to check
+       # the return of all extern methods implemented in Java to ensure the value
+       # is not a Java null. In case it is, you should replace it by a normal Nit
+       # `null`.
+       fun is_java_null: Bool in "Java" `{ return recv == null; `}
+
+       # `JavaString` representation of `self` using Java's `toString`
+       fun to_java_string: JavaString in "Java" `{ return recv.toString(); `}
+
+       # Use Java's `toString` for any `JavaObject`
+       redef fun to_s
+       do
+               if is_java_null then return super
+               return to_java_string.to_s
+       end
 end
index 4337d9e..56080a5 100644 (file)
@@ -19,8 +19,8 @@
 #
 # See: http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/jniTOC.html
 module jvm is
-       c_compiler_option("-I $(JAVA_HOME)/include/")
-       c_linker_option("-L $(JNI_LIB_PATH) -ljvm")
+       c_compiler_option "-I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux/"
+       c_linker_option "-L $(JNI_LIB_PATH) -ljvm"
 end
 
 in "C Header" `{
index 50117cf..bd441a1 100644 (file)
@@ -110,3 +110,13 @@ class HashMap3[K1: Object, K2: Object, K3: Object, V]
                level2[k2, k3] = v
        end
 end
+
+# A map with a default value.
+class DefaultMap[K: Object, V]
+       super HashMap[K, V]
+
+       # The default value.
+       var default: V
+
+       redef fun provide_default_value(key) do return default
+end
index f1a1da8..dc5c8ac 100644 (file)
@@ -50,6 +50,7 @@ abstract class JsonCurlRequest
                headers = new HeaderMap
                headers["Accept"] = "application/json; charset=UTF-8"
                headers["Transfer-Encoding"] = "chunked"
+               headers["X-Stream"] = "true"
                if auth != null then
                        headers["Authorization"] = "token {auth.to_s}"
                end
@@ -95,7 +96,7 @@ abstract class JsonCurlRequest
                end
 
                var err_hook = execute_hook
-           if err_hook != null then return err_hook
+               if err_hook != null then return err_hook
 
                var err_resp = perform
                if err_resp != null then return err_resp
diff --git a/lib/neo4j/json_store.nit b/lib/neo4j/json_store.nit
new file mode 100644 (file)
index 0000000..49e055c
--- /dev/null
@@ -0,0 +1,199 @@
+# 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.
+
+# Uses JSON as a storage medium for a Neo4j subgraph.
+module neo4j::json_store
+
+import neo4j
+private import template
+
+# A Neo4j graph that uses as a storage medium.
+#
+# The graph is stored as a JSON object with the following properties:
+#
+# * `"nodes"`: An array with all nodes. Each node is an object with the
+# following properties:
+#      * `"id"`: The ID (`Int`) that uniquely identifies the node in the current
+#      graph.
+#      * `"labels"`: An array of all applied labels.
+#      * `"properties"`: An object mapping each defined property to its value.
+# * `"links"`: An array with all relationships. Each relationship is an object
+# with the following properties:
+#      * `"type"`: The type (`String`) of the relationship.
+#      * `"properties"`: An object mapping each defined property to its value.
+#      * `"from"`: The ID (`Int`) of the source node.
+#      * `"to"`: The ID (`Int`) of the destination node.
+#
+# TODO Refine the graph API instead when it will be available.
+class JsonGraph
+       super Jsonable
+
+       # All nodes in the graph.
+       var nodes: SimpleCollection[NeoNode] = new Array[NeoNode]
+
+       # All relationships in the graph.
+       var links: SimpleCollection[NeoEdge] = new Array[NeoEdge]
+
+       # Create an empty graph.
+       init do end
+
+       # Retrieve the graph from the specified JSON value.
+       #
+       #     var graph = new JsonGraph
+       #     var a = new NeoNode
+       #     a.labels.add "Foo"
+       #     a["answer"] = 42
+       #     a["Ultimate question of"] = new JsonArray.from(["life",
+       #               "the Universe", "and Everything."])
+       #     graph.nodes.add a
+       #     var b = new NeoNode
+       #     b.labels.add "Foo"
+       #     b.labels.add "Bar"
+       #     graph.nodes.add b
+       #     graph.links.add new NeoEdge(a, "BAZ", b)
+       #     #
+       #     graph = new JsonGraph.from_json(graph.to_json)
+       #     assert 1 == graph.links.length
+       #     for link in graph.links do
+       #       assert "BAZ" == link.rel_type
+       #       assert a.labels == link.from.labels
+       #       for k, v in a.properties do assert v == link.from.properties[k]
+       #       assert b.labels == link.to.labels
+       #       for k, v in b.properties do assert v == link.to.properties[k]
+       #     end
+       #     assert 2 == graph.nodes.length
+       init from_json(t: Text) do
+               from_json_object(t.to_jsonable.as(JsonObject))
+       end
+
+       # Retrieve the graph from the specified JSON object.
+       init from_json_object(o: JsonObject) do
+               var node_by_id = new HashMap[Int, NeoNode]
+               var nodes = o["nodes"].as(JsonArray)
+               for json_node in nodes do
+                       assert json_node isa JsonObject
+                       var node = new NeoNode.from_json_object(json_node)
+                       node_by_id[json_node["id"].as(Int)] = node
+                       self.nodes.add node
+               end
+               var links = o["links"].as(JsonArray)
+               for json_link in links do
+                       assert json_link isa JsonObject
+                       var from = node_by_id[json_link["from"].as(Int)]
+                       var to = node_by_id[json_link["to"].as(Int)]
+                       var rel_type = json_link["type"].as(String)
+                       var json_properties = json_link["properties"].as(JsonObject)
+                       var link = new NeoEdge(from, rel_type, to)
+                       link.properties.recover_with(json_properties)
+                       self.links.add link
+               end
+       end
+
+       redef fun to_json do
+               var t = new Template
+               t.add "\{\"nodes\":["
+               var i = 0
+               for n in nodes do
+                       if i > 0 then t.add ","
+                       t.add n.to_json
+                       i += 1
+               end
+               t.add "],\"links\":["
+               i = 0
+               for link in links do
+                       if i > 0 then t.add ","
+                       t.add link.to_json
+                       i += 1
+               end
+               t.add "]\}"
+               return t.write_to_string
+       end
+end
+
+# Make `NeoNode` `Jsonable`.
+redef class NeoNode
+       super Jsonable
+
+       # Retrieve the node from the specified JSON value.
+       #
+       # Note: Here, the `"id"` is optional and ignored.
+       #
+       # SEE: `JsonGraph`
+       #
+       #     var node = new NeoNode.from_json("""
+       #     {
+       #       "labels": ["foo", "Bar"],
+       #       "properties": {
+       #               "baz": 42
+       #       }
+       #     }
+       #     """)
+       #     assert ["foo", "Bar"] == node.labels
+       #     assert 42 == node["baz"]
+       init from_json(t: Text) do
+               from_json_object(t.to_jsonable.as(JsonObject))
+       end
+
+       # Retrieve the node from the specified JSON value.
+       #
+       # Note: Here, the `"id"` is optional and ignored.
+       #
+       # SEE: `JsonGraph`
+       init from_json_object(o: JsonObject) do
+               init
+               var labels = o["labels"].as(JsonArray)
+               for lab in labels do self.labels.add(lab.as(String))
+               var json_properties = o["properties"].as(JsonObject)
+               properties.recover_with(json_properties)
+       end
+
+       # Get the JSON representation of `self`.
+       #
+       # SEE: `JsonGraph`
+       redef fun to_json do
+               var t = new Template
+               t.add "\{\"id\":"
+               t.add object_id.to_json
+               t.add ",\"labels\":["
+               var i = 0
+               for lab in labels do
+                       if i > 0 then t.add ","
+                       t.add lab.to_json
+                       i += 1
+               end
+               t.add "],\"properties\":"
+               t.add properties.to_json
+               t.add "}"
+               return t.write_to_string
+       end
+
+       redef fun to_s do return to_json
+end
+
+# Make `NeoEdge` `Jsonable`.
+redef class NeoEdge
+       super Jsonable
+
+       redef fun to_json do
+               var t = new Template
+               t.add "\{\"type\":"
+               t.add rel_type.to_json
+               t.add ",\"properties\":"
+               t.add properties.to_json
+               t.add ",\"from\":"
+               t.add from.object_id.to_json
+               t.add ",\"to\":"
+               t.add to.object_id.to_json
+               t.add "}"
+               return t.write_to_string
+       end
+
+       redef fun to_s do return to_json
+end
index 6629b80..b84a60b 100644 (file)
@@ -300,7 +300,7 @@ class Neo4jClient
        # Perform a `CypherQuery`
        # see: CypherQuery
        fun cypher(query: CypherQuery): Jsonable do
-               return post("{cypher_url}", query.to_json)
+               return post("{cypher_url}", query.to_rest)
        end
 
        # GET JSON data from `url`
@@ -436,8 +436,8 @@ class CypherQuery
                return self
        end
 
-       # Translate the query to JSON
-       fun to_json: JsonObject do
+       # Translate the query to the body of a corresponding Neo4j REST request.
+       fun to_rest: JsonObject do
                var obj = new JsonObject
                obj["query"] = query
                if not params.is_empty then
@@ -446,7 +446,7 @@ class CypherQuery
                return obj
        end
 
-       redef fun to_s do return to_json.to_s
+       redef fun to_s do return to_rest.to_s
 end
 
 # The fundamental units that form a graph are nodes and relationships.
@@ -546,9 +546,6 @@ abstract class NeoEntity
 
        # Is the property `key` set?
        fun has_key(key: String): Bool do return properties.has_key(key)
-
-       # Translate `self` to JSON
-       fun to_json: JsonObject do return properties
 end
 
 # Nodes are used to represent entities stored in base.
@@ -595,7 +592,7 @@ class NeoNode
                var tpl = new FlatBuffer
                tpl.append "\{"
                tpl.append "labels: [{labels.join(", ")}],"
-               tpl.append "data: {to_json}"
+               tpl.append "data: {properties.to_json}"
                tpl.append "\}"
                return tpl.write_to_string
        end
@@ -743,7 +740,8 @@ class NeoEdge
        # Get edge type
        fun rel_type: nullable String do return internal_type
 
-       redef fun to_json do
+       # Get the JSON body of a REST request that create the relationship.
+       private fun to_rest: JsonObject do
                var obj = new JsonObject
                if to.is_linked then
                        obj["to"] = to.url
@@ -891,7 +889,7 @@ class NeoBatch
                else
                        job.to = "\{{edge.from.batch_id.to_s}\}/relationships"
                end
-               job.body = edge.to_json
+               job.body = edge.to_rest
        end
 
        # Create multiple edges
@@ -902,7 +900,7 @@ class NeoBatch
                var request = new JsonPOST(client.batch_url, client.curl)
                # request.headers["X-Stream"] = "true"
                var json_jobs = new JsonArray
-               for job in jobs.values do json_jobs.add job.to_json
+               for job in jobs.values do json_jobs.add job.to_rest
                request.data = json_jobs
                var response = request.execute
                var res = client.parse_response(response)
@@ -1003,7 +1001,7 @@ class NeoJob
        var body: nullable Jsonable = null
 
        # JSON formated job
-       fun to_json: JsonObject do
+       fun to_rest: JsonObject do
                var job = new JsonObject
                job["id"] = id
                job["method"] = method
index c088325..5e36142 100644 (file)
@@ -282,6 +282,14 @@ class OptionContext
                parse_intern(it)
        end
 
+       # Must all option be given before the first argument?
+       #
+       # When set to `false` (the default), options of the command line are
+       # all parsed until the end of the list of arguments or until "--" is met (in this case "--" is discarded).
+       #
+       # When set to `true` options are parsed until the first non-option is met.
+       var options_before_rest = false is writable
+
        # Parse the command line
        protected fun parse_intern(it: Iterator[String])
        do
@@ -319,6 +327,10 @@ class OptionContext
                                        else
                                                rest.add(it.item)
                                                it.next
+                                               if options_before_rest then
+                                                       rest.add_all(it.to_a)
+                                                       parseargs = false
+                                               end
                                        end
                                end
                        end
index 91f8e63..34ca522 100644 (file)
@@ -158,9 +158,7 @@ private class OrderedTreeIterator[E: Object]
 
        var iterators = new Array[Iterator[E]]
 
-       init(tree: OrderedTree[E]) do
-               self.tree = tree
-
+       init do
                if not tree.is_empty then
                        iterators.add tree.roots.iterator
                end
index 1a74641..9221116 100644 (file)
@@ -26,7 +26,7 @@ class Perfecthashing
        # A null value represents the upper bound of identifier
        private var interval = new List[Couple[nullable Int, nullable Int]]
 
-       # An array used as a temporary Hashtable for 
+       # An array used as a temporary Hashtable for
        # checking there is no collision between identifiers
        private var tempht = new Array[nullable Int]
 
@@ -36,9 +36,9 @@ class Perfecthashing
                # By default, all identifiers are available
                interval.push(new Couple[nullable Int, nullable Int](1, null))
        end
-       
+
        # Returns a mask composed by discriminants bits
-       # for these given identifiers 
+       # for these given identifiers
        # The mask + 1 value is the size of the hastable to create
        fun phand(ids: Array[Int]): Int
        do
@@ -59,7 +59,7 @@ class Perfecthashing
                mask = orMask.bin_xor(andMask)
 
                # Re-initialize the hashtable with null values
-               for i in [0..mask+1] do tempht[i] = null
+               for i in [0..(mask+1)] do tempht[i] = null
 
                # Optimize the already computed mask
                var newmask = 0
@@ -67,7 +67,7 @@ class Perfecthashing
                while i != 0 do
                        if mask.getbit(i) == 1 then
                                newmask = mask.bin_xor(1.lshift(i))
-                               
+
                                # If there is no collision, replace the old mask
                                if phandp(ids, newmask) then
                                        mask = newmask
@@ -92,7 +92,7 @@ class Perfecthashing
                                tempht[hv] = mask
                        end
                end
-       
+
                return true
        end
 
@@ -121,6 +121,9 @@ class Perfecthashing
                end
 
                # Resetting hashtable
+               for j in [0..(mask+1)] do tempht[j] = null
+
+               # Set the temporary hashtable for `compute_least_free_ids`
                phandp(ids, mask)
 
                # Fill the given array with n free identifiers
@@ -155,7 +158,7 @@ class Perfecthashing
                                # Tests if this id is free for this mask
                                var hv = i.bin_and(mask)
 
-                               # If the hashtable if full, push an empty item 
+                               # If the hashtable if full, push an empty item
                                if hv >= tempht.length then
                                        tempht.push(null)
                                end
@@ -163,7 +166,7 @@ class Perfecthashing
                                if tempht[hv] != mask then
                                        found = true
                                        id = i
-                               end     
+                               end
                                i = i + 1
                        end
 
@@ -179,7 +182,7 @@ class Perfecthashing
                        else
                                inter.item.first += 1
                        end
-               else 
+               else
                        if id != inter.item.first and id != inter.item.second then
                                # We need to split in two this interval
                                var last = inter.item.second
index 7a26f90..9549e48 100644 (file)
@@ -126,28 +126,40 @@ class POSet[E: Object]
                return fe.dtos.has(t)
        end
 
-       # Display the POSet in a gaphical windows.
-       # Graphviz with a working -Txlib is expected.
-       # Used fo debugging.
-       fun show_dot
+       # Write the POSet as a graphviz digraph.
+       #
+       # Nodes are identified with their `to_s`.
+       # Edges are unlabeled.
+       fun write_dot(f: OStream)
        do
-               var f = new OProcess("dot", "-Txlib")
-               #var f = stdout
                f.write "digraph \{\n"
                for x in elements.keys do
-                       f.write "\"{x}\";\n"
+                       var xstr = x.to_s.escape_to_dot
+                       f.write "\"{xstr}\";\n"
                        var xe = self.elements[x]
                        for y in xe.dtos do
+                               var ystr = y.to_s.escape_to_dot
                                if self.has_edge(y,x) then
-                                       f.write "\"{x}\" -> \"{y}\"[dir=both];\n"
+                                       f.write "\"{xstr}\" -> \"{ystr}\"[dir=both];\n"
                                else
-                                       f.write "\"{x}\" -> \"{y}\";\n"
+                                       f.write "\"{xstr}\" -> \"{ystr}\";\n"
                                end
                        end
                end
                f.write "\}\n"
-               #f.close
-               #f.wait
+       end
+
+       # Display the POSet in a graphical windows.
+       # Graphviz with a working -Txlib is expected.
+       #
+       # See `write_dot` for details.
+       fun show_dot
+       do
+               var f = new OProcess("dot", "-Txlib")
+               f.write "\}\n"
+               write_dot(f)
+               f.close
+               f.wait
        end
 
        # Compare two elements in an arbitrary total order.
index a122a02..da40da1 100644 (file)
 # Exposes methods for debugging ropes when needed.
 module ropes_debug
 
-intrude import ::standard::ropes
-import ::standard
+import standard
+intrude import standard::ropes
 
-redef class Rope
+redef class Text
        # Writes self as a dot file on the hard drive
-       fun to_dot(filepath: String): String is abstract
-end
+       private fun internal_to_dot: String is abstract
 
-redef class RopeNode
-       # Generates a dot string
-       fun to_dot(s: String): String is abstract
+       fun to_dot: String do
+               return "digraph g \{\n" + internal_to_dot + "\}\n"
+       end
 end
 
-redef class Leaf
-       redef fun to_dot(s): String
+redef class Concat
+       redef fun internal_to_dot: String
        do
-               s += "n{object_id} [label = \"{str}\" shape = rect];\n"
-               s += "n{str.object_id} -> n{object_id} [label = \"contains\"];\n"
-               s = str.to_dot(s)
+               var s = "n{object_id} [label = {length}];\n"
+               s += "n{object_id} -> n{left.object_id} [label = \"left\"];\n"
+               s += left.internal_to_dot
+               s += "n{object_id} -> n{right.object_id} [label = \"right\"];\n"
+               s += right.internal_to_dot
                return s
        end
 end
 
-redef class Concat
-       redef fun to_dot(s): String
+redef class RopeBuffer
+       redef fun internal_to_dot: String
        do
-               s += "n{object_id} [label = {length}];\n"
-               if left != null then
-                       s += "n{object_id} -> n{left.object_id} [label = \"left\"];\n"
-                       s = left.to_dot(s)
-               end
-               if right != null then
-                       s += "n{object_id} -> n{right.object_id} [label = \"right\"];\n"
-                       s = right.to_dot(s)
-               end
+               var s = "n{object_id} [label = {length}];\n"
+               s += "n{object_id} -> n{str.object_id} [label = \"str\"];\n"
+               s += str.internal_to_dot
+               s += "n{object_id} -> n{ns.object_id} [label = \"ns\"];\n"
+               s += "n{ns.object_id}[label = \"NativeString\", content=\"{ns.to_s_with_length(rpos)}\"];\n"
                return s
        end
 end
 
-redef class FlatText
-       fun to_dot(s: String): String is abstract
-end
-
 redef class FlatString
-       redef fun to_dot(s: String): String
+       redef fun internal_to_dot: String
        do
-               return s + "n{object_id} [label=\"FlatString\\nindex_from = {index_from}\\nindex_to = {index_to}\\nNativeString = {items.to_s_with_length(items.cstring_length)}\"];\n"
+               return "n{object_id} [label=\"FlatString\\nindex_from = {index_from}\\nindex_to = {index_to}\\nNativeString = {items.to_s_with_length(items.cstring_length)}\"];\n"
        end
 end
 
 redef class FlatBuffer
-       redef fun to_dot(s: String): String
+       redef fun internal_to_dot: String
        do
-               return s + "n{object_id} [label=\"FlatBuffer\\length = {length}\\ncapacity = {capacity}\\nitems = {items.to_s_with_length(items.cstring_length)}\"];\n"
+               return "n{object_id} [label=\"FlatBuffer\\length = {length}\\ncapacity = {capacity}\\nitems = {items.to_s_with_length(items.cstring_length)}\"];\n"
        end
 end
 
-redef class RopeString
-       redef fun to_dot(filepath: String)
-       do
-               var of = new OFStream.open(filepath)
-               var ret: String = new RopeString.from("digraph g \{\n")
-               ret = root.to_dot(ret).as(RopeString)
-               ret += "\}\n"
-               ret.write_to(of)
-               of.close
-               return ret
-       end
-end
-
-
diff --git a/lib/splay_ropes.nit b/lib/splay_ropes.nit
deleted file mode 100644 (file)
index e167ce7..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-# 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.
-
-# Introduces a self-balancing method on Rope, using a Splay Tree
-module splay_ropes
-
-import standard
-intrude import standard::ropes
-
-redef class Rope
-
-       # Performs a Left rotation on node `x`
-       # Since a Rope does not have any notion of parent in its node, they need to be passed as arguments if available.
-       private fun left_rotate(r: Concat): Concat
-       do
-               var rr = r.right.as(Concat)
-               var rl = r.left
-               var pl = rr.left
-               var pr = rr.right
-               var nr = new Concat(rl, pl)
-               var np = new Concat(nr, pr)
-               return np
-       end
-
-       # Performs a Right rotation on node `r`
-       # Since a Rope does not have any notion of parent in its node, they need to be passed as arguments if available.
-       private fun right_rotate(r: Concat): Concat
-       do
-               var rl = r.left.as(Concat)
-               var rr = r.right
-               var pr = rl.right
-               var pl = rl.left
-               var nr = new Concat(pr, rr)
-               var np = new Concat(pl, nr)
-               return np
-       end
-
-       # Performs a Splay operation on a complete path
-       # The last node of the path will become the root.
-       private fun splay(path: Path): nullable Concat
-       do
-               var st = path.stack
-               if st.is_empty then return null
-               var cct = st.pop.node
-               while not st.is_empty do
-                       var tmp = st.pop
-                       var nod: Concat
-                       if tmp.left then
-                               nod = new Concat(cct, tmp.node.right)
-                               cct = right_rotate(nod)
-                       else
-                               nod = new Concat(tmp.node.left, cct)
-                               cct = left_rotate(nod)
-                       end
-               end
-               return cct
-       end
-end
-
-redef class RopeString
-
-       # Inserts a String `str` at position `pos`
-       redef fun insert_at(str, pos)
-       do
-               if str.length == 0 then return self
-               if self.length == 0 then return new RopeString.from(str)
-
-               assert pos >= 0 and pos <= length
-
-               var path = node_at(pos)
-
-               var last_concat: Concat
-
-               if path.offset == 0 then
-                       if str isa FlatString then
-                               last_concat = new Concat(new StringLeaf(str), path.leaf)
-                       else
-                               last_concat = new Concat(str.as(RopeString).root, path.leaf)
-                       end
-               else if path.offset == path.leaf.length then
-                       if str isa FlatString then
-                               last_concat = new Concat(path.leaf, new StringLeaf(str))
-                       else
-                               last_concat = new Concat(path.leaf, str.as(RopeString).root)
-                       end
-               else
-                       var s = path.leaf.str
-                       var l_half = s.substring(0, s.length - path.offset)
-                       var r_half = s.substring_from(s.length - path.offset)
-                       var cct: Concat
-                       var ll = new StringLeaf(l_half.as(FlatString))
-                       if str isa FlatString then
-                               cct = new Concat(ll, new StringLeaf(str))
-                       else
-                               cct = new Concat(ll, str.as(RopeString).root)
-                       end
-                       last_concat = new Concat(cct, new StringLeaf(r_half.as(FlatString)))
-               end
-
-               var st = path.stack
-
-               if st.is_empty then return new RopeString.from_root(last_concat)
-
-               var tmp = st.pop
-
-               if tmp.left then
-                       var n = tmp.node.right
-                       var r = new Concat(last_concat, n)
-                       st.push(new PathElement(r))
-               else
-                       var n = tmp.node.left
-                       var r = new Concat(n, last_concat)
-                       st.push(new PathElement(r))
-               end
-
-               return new RopeString.from_root(splay(path).as(not null))
-       end
-
-end
-
index da93820..6419ea8 100644 (file)
@@ -153,7 +153,16 @@ extern class NativeSqlite3 `{sqlite3 *`}
        fun destroy do close
 
        # Close this connection
-       fun close `{ sqlite3_close_v2(recv); `}
+       fun close `{
+#if SQLITE_VERSION_NUMBER >= 3007014
+               sqlite3_close_v2(recv);
+#else
+               // A program using the older version should not rely on the garbage-collector
+               // to close its connections. They must be closed manually after the associated
+               // prepare statements have been finalized.
+               sqlite3_close(recv);
+#endif
+       `}
 
        # Execute a SQL statement
        fun exec(sql: String): Sqlite3Code import String.to_cstring `{
index 843f8eb..a439ec1 100644 (file)
@@ -194,9 +194,6 @@ class Container[E]
 
        redef fun iterator do return new ContainerIterator[E](self)
 
-       # Create a new instance with a given initial value.
-       init(e: E) do item = e
-
        # The stored item
        var item: E is writable
 end
@@ -208,8 +205,6 @@ private class ContainerIterator[E]
 
        redef fun next do is_ok = false
 
-       init(c: Container[E]) do _container = c
-
        redef var is_ok: Bool = true
 
        private var container: Container[E]
@@ -950,8 +945,6 @@ private class CoupleMapIterator[K: Object, V]
        end
 
        private var iter: Iterator[Couple[K,V]]
-
-       init(i: Iterator[Couple[K,V]]) do _iter = i
 end
 
 # Some tools ###################################################################
@@ -964,11 +957,4 @@ class Couple[F, S]
 
        # The second element of the couple.
        var second: S is writable
-
-       # Create a new instance with a first and a second object.
-       init(f: F, s: S)
-       do
-               first = f
-               second = s
-       end
 end
index 70e0b94..7d710bd 100644 (file)
@@ -394,6 +394,26 @@ class Array[E]
                res.append(other)
                return res
        end
+
+       # Repetition of arrays.
+       #
+       # returns a new array built by concatenating `self` `repeat` times.
+       #
+       #    var a = [1,2,3]
+       #    assert (a * 0).is_empty
+       #    assert a * 1  ==  [1,2,3]
+       #    assert a * 2  ==  [1,2,3,1,2,3]
+       #    assert (a * 10).length  ==  30
+       fun *(repeat: Int): Array[E]
+       do
+               assert repeat >= 0
+               var res = new Array[E].with_capacity(length * repeat)
+               while repeat > 0 do
+                       res.add_all(self)
+                       repeat -= 1
+               end
+               return res
+       end
 end
 
 # An `Iterator` on `AbstractArray`
@@ -408,12 +428,6 @@ private class ArrayIterator[E]
 
        redef fun next do _index += 1
 
-       init(a: AbstractArrayRead[E])
-       do
-               _array = a
-               _index = 0
-       end
-
        redef var index = 0
 
        private var array: AbstractArrayRead[E]
@@ -426,10 +440,9 @@ private class ArrayReverseIterator[E]
 
        redef fun next do _index -= 1
 
-       init(a: AbstractArrayRead[E])
+       init
        do
-               _array = a
-               _index = a.length - 1
+               _index = _array.length - 1
        end
 end
 
@@ -496,8 +509,6 @@ private class ArraySetIterator[E: Object]
 
        redef fun item: E do return _iter.item
 
-       init(iter: ArrayIterator[E]) do _iter = iter
-
        private var iter: ArrayIterator[E]
 end
 
index 7c90189..6490024 100644 (file)
@@ -197,10 +197,6 @@ private abstract class HashNode[K: Object]
        private var prev_item: nullable N = null
        private var prev_in_bucklet: nullable N = null
        private var next_in_bucklet: nullable N = null
-       init(k: K)
-       do
-               _key = k
-       end
 end
 
 # A map implemented with a hash table.
@@ -346,12 +342,6 @@ private class HashMapNode[K: Object, V]
        super HashNode[K]
        redef type N: HashMapNode[K, V]
        private var value: V
-
-       init(k: K, v: V)
-       do
-               super(k)
-               _value = v
-       end
 end
 
 class HashMapIterator[K: Object, V]
@@ -386,12 +376,12 @@ class HashMapIterator[K: Object, V]
        private var map: HashMap[K, V]
 
        # The current node
-       private var node: nullable HashMapNode[K, V]
+       private var node: nullable HashMapNode[K, V] = null
 
-       init(map: HashMap[K, V])
+       init
        do
                _map = map
-               _node = map._first_item
+               _node = _map._first_item
        end
 end
 
@@ -452,11 +442,6 @@ end
 private class HashSetNode[E: Object]
        super HashNode[E]
        redef type N: HashSetNode[E]
-
-       init(e: E)
-       do
-               _key = e
-       end
 end
 
 private class HashSetIterator[E: Object]
@@ -479,12 +464,11 @@ private class HashSetIterator[E: Object]
        private var set: HashSet[E]
 
        # The position in the internal map storage
-       private var node: nullable HashSetNode[E]
+       private var node: nullable HashSetNode[E] = null
 
-       init(set: HashSet[E])
+       init
        do
-               _set = set
-               _node = set._first_item
+               _node = _set._first_item
        end
 end
 
index f80e176..49fb693 100644 (file)
@@ -289,21 +289,19 @@ class ListIterator[E]
        end
 
        # Build a new iterator for `list`.
-       private init(list: List[E])
+       init
        do
-               _list = list
-               _node = list._head
-               _index = 0
+               _node = _list._head
        end
 
        # The current list
        private var list: List[E]
 
        # The current node of the list
-       private var node: nullable ListNode[E]
+       private var node: nullable ListNode[E] = null
 
        # The index of the current node
-       redef var index
+       redef var index = 0
 
        # Remove the current item
        fun delete
@@ -327,9 +325,9 @@ private class ListReverseIterator[E]
                _index -= 1
        end
 
-       private init(list: List[E])
+       init
        do
-               _list = list
+               var list = _list
                _node = list._tail
                _index = list.length
        end
@@ -338,14 +336,10 @@ end
 # Linked nodes that constitute a linked list.
 private class ListNode[E]
        super Container[E]
-       init(i: E)
-       do 
-               item = i
-       end
 
        # The next node.
-       var next: nullable ListNode[E]
+       var next: nullable ListNode[E] = null
 
        # The previous node.
-       var prev: nullable ListNode[E]
+       var prev: nullable ListNode[E] = null
 end
index 31ffaa2..a79f218 100644 (file)
@@ -77,16 +77,15 @@ private class IteratorRange[E: Discrete]
        # Iterator on ranges.
        super Iterator[E]
        private var range: Range[E]
-       redef var item
+       redef var item is noinit
 
        redef fun is_ok do return _item < _range.after
        
        redef fun next do _item = _item.successor(1)
        
-       init(r: Range[E])
+       init
        do
-               _range = r
-               _item = r.first
+               _item = _range.first
        end
 end
 
index 30e48e3..fb89882 100644 (file)
@@ -94,8 +94,6 @@ class IFStream
                end
        end
 
-       private init do end
-       private init without_file do end
 end
 
 # File output stream
@@ -142,9 +140,6 @@ class OFStream
                self.path = path
                _is_writable = true
        end
-       
-       private init do end
-       private init without_file do end
 end
 
 ###############################################################################
@@ -152,7 +147,7 @@ end
 class Stdin
        super IFStream
 
-       private init do
+       init do
                _file = new NativeFile.native_stdin
                path = "/dev/stdin"
                prepare_buffer(1)
@@ -163,7 +158,7 @@ end
 
 class Stdout
        super OFStream
-       private init do
+       init do
                _file = new NativeFile.native_stdout
                path = "/dev/stdout"
                _is_writable = true
@@ -172,7 +167,7 @@ end
 
 class Stderr
        super OFStream
-       private init do
+       init do
                _file = new NativeFile.native_stderr
                path = "/dev/stderr"
                _is_writable = true
index a2e0966..5a980aa 100644 (file)
@@ -83,6 +83,34 @@ redef class Int
        #
        #    assert not 13.is_even
        fun is_odd: Bool do return not is_even
+
+       # Returns the `self` raised to the power of `e`.
+       #
+       #    assert 2 ** 3 == 8
+       fun **(e: Int): Int
+       do
+               return self.to_f.pow(e.to_f).to_i
+       end
+
+       # The factorial of `self` (aka `self!`)
+       #
+       # Returns `1 * 2 * 3 * ... * self-1 * self`
+       #
+       #    assert 0.factorial == 1  # by convention for an empty product
+       #    assert 1.factorial == 1
+       #    assert 4.factorial == 24
+       #    assert 9.factorial == 362880
+       fun factorial: Int
+       do
+               assert self >= 0
+               var res = 1
+               var n = self
+               while n > 0 do
+                       res = res * n
+                       n -= 1
+               end
+               return res
+       end
 end
 
 redef class Float
index ceab407..ff2ee0d 100644 (file)
@@ -232,8 +232,6 @@ class MinHeap[E: Object]
                init(default_comparator)
        end
 
-       init(comparator: Comparator) do self.comparator = comparator
-
        redef fun is_empty do return items.is_empty
        redef fun length do return items.length
        redef fun iterator do return items.iterator
index ad97500..c4915fd 100644 (file)
-# This file is part of NIT ( http://www.nitlanguage.org ).
+# 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 if 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 as a part of
-# another product.
-
-# Nit implementation of the Ropes (see Ropes : An Alternative to Strings,
-# SOFTWARE - PRACTICE AND EXPERIENCE, VOL. 25(12), 1315 - 1330 (DECEMBER 1995)
-# Hans. J Boehm, Russ Atkinson and Michael Plass)
+# 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
 #
-# A rope is a kind of string but instead of being flat, it relies on a binary tree structure to store data.
+#     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.
+
+# Tree-based representation of a String.
+#
+# Ropes are a data structure introduced in a 1995 paper from
+# Hans J. Boehm, Russ Atkinson and Michael Plass.
+# See : `Ropes : an Alternative to Strings`, `Software - Practice and Experience,
+# Vol. 25(12), 1315-1330 (December 1995)`.
+#
+# The implementation developed here provides an automatic change
+# of data structure depending on the length of the leaves.
+#
+# The length from which a `Rope` is built from a `flat` string
+# if defined at top-level (see `maxlen`) and can be redefined by clients
+# depending on their needs (e.g. if you need to bench the speed of
+# the creation of concat nodes, lower the size of maxlen).
+#
+# A Rope as defined in the original paper is a Tree made of concatenation
+# nodes and containing `Flat` (that is Array-based) strings as Leaves.
+#
+# Example :
+#
+# `            Concat                   `
+# `          /        \                 `
+# `    Concat          Concat           `
+# `   /      \        /      \          `
+# `"My"     " Name"  " is"   " Simon."  `
+#
+# Note that the above example is not representative of the actual implementation
+# of `Ropes`, since short leaves are merged to keep the rope at an acceptable
+# height (hence, this rope here might actually be a `FlatString` !).
 module ropes
 
 intrude import string
 
-# Used when searching for a particular node
-# Returns the path to the node from the root of the rope
-# Also, the node and the offset for seeked position in the rope
-private class Path
-       # Leaf found
-       var leaf: Leaf
-       # Offset in leaf
-       var offset: Int
-       # Stack of the nodes traversed, and the path used
-       var stack: List[PathElement]
-end
+# Maxlen is the maximum length of a Leaf node
+#
+# When concatenating two leaves, if `new_length` > `maxlen`,
+# A `Concat` node is created instead
+#
+# Its purpose is to limit the depth of the `Rope` (this
+# improves performance when accessing/iterating).
+fun maxlen: Int do return 64
 
-# An element for a Path, has the concat node and whether or not
-# left or right child was visited.
-private class PathElement
-       # Visited node
-       var node: Concat
-       # Was the left child visited ?
-       var left = false
-       # Was the right child visited ?
-       var right = false
+# String using a tree-based representation with leaves as `FlatStrings`
+private abstract class Rope
+       super Text
 end
 
-# A node for a Rope
-private abstract class RopeNode
-       # Length of the node
-       var length = 0
+private abstract class RopeString
+       super Rope
+       super String
 
-       # Transforms the current node to a Leaf.
-       # This might be costly to invoke since this produces a FlatString concatenation.
-       # Can be used internally to limit the growth of the Rope when working with small leaves.
-       fun to_leaf: Leaf is abstract
+       redef fun chars is cached do return new RopeChars(self)
 end
 
-# Node that represents a concatenation between two nodes (of any RopeNode type)
+# Node that represents a concatenation between two `String`
 private class Concat
-       super RopeNode
+       super RopeString
+
+       redef var length: Int
+
+       redef fun substrings do return new RopeSubstrings(self)
+
+       redef fun empty do return ""
+
+       redef fun to_cstring is cached do
+               var len = length
+               var ns = new NativeString(len + 1)
+               ns[len] = '\0'
+               var off = 0
+               for i in substrings do
+                       var ilen = i.length
+                       i.as(FlatString).items.copy_to(ns, ilen, i.as(FlatString).index_from, off)
+                       off += ilen
+               end
+               return ns
+       end
 
        # Left child of the node
-       var left: nullable RopeNode
+       var left: String
        # Right child of the node
-       var right: nullable RopeNode
+       var right: String
 
-       init(l: nullable RopeNode, r: nullable RopeNode)
-       do
+       init(l: String, r: String) do
                left = l
                right = r
-               if l != null then length += l.length
-               if r != null then length += r.length
+               length = l.length + r.length
        end
 
-       redef fun to_leaf
-       do
-               if left == null then
-                       if right == null then return new StringLeaf("".as(FlatString))
-                       return right.to_leaf
-               end
-               if right == null then return left.as(not null).to_leaf
-               return new StringLeaf((left.to_leaf.str.as(FlatString) + right.to_leaf.str.as(FlatString)).as(FlatString))
+       redef fun output do
+               left.output
+               right.output
        end
-end
-
-# Leaf of a Rope, contains a FlatString
-private abstract class Leaf
-       super RopeNode
-
-       # Encapsulated FlatString in the leaf node
-       var str: FlatText
-
-end
 
-private class StringLeaf
-       super Leaf
+       redef fun iterator do return new RopeIter(self)
 
-       init(val: FlatString) do
-               self.str = val
-               length = str.length
+       redef fun *(i) do
+               var x: String = self
+               for j in [1 .. i[ do x += self
+               return x
        end
 
-       redef fun to_leaf do return self
-end
-
-# Used as a cache when using indexed access to a substring in the Rope
-private class LeafCache
-       # Cached leaf
-       var leaf: Leaf
-       # Position in Rope
-       var pos: Int
-end
-
-# Basic structure, binary tree with a root node.
-#
-# Also shared services by subsequent implementations.
-abstract class Rope
-       super Text
-
-       # Root node, entry point of a Rope.
-       private var root: RopeNode is noinit
-
-       # Cached version of self as a flat String
-       private var str_representation: nullable NativeString = null
-
-       private var leaf_cache: nullable LeafCache = null
-
-       # Empty Rope
-       init do root = new StringLeaf("".as(FlatString))
-
-       # Creates a new Rope with `s` as root
-       init from(s: String) do
-               if s isa RopeString then root = s.root else root = new StringLeaf(s.as(FlatString))
+       redef fun [](i) do
+               var llen = left.length
+               if i >= llen then return right[i - llen]
+               return left[i]
        end
 
-       private init from_root(r: RopeNode)
-       do
-               root = r
+       redef fun substring(from, len) do
+               var llen = left.length
+               if from < llen then
+                       if from + len < llen then return left.substring(from,len)
+                       var lsublen = llen - from
+                       return left.substring_from(from) + right.substring(0, len - lsublen)
+               else
+                       return right.substring(from - llen, len)
+               end
        end
 
-       redef fun length do return root.length
-
-       # Iterator on the nodes of the rope, in forward postfix order
-       private fun postfix(from: Int): Postfix do return new Postfix.from(self, from)
-
-       # Iterator on the leaves of the rope, forward order
-       private fun leaves(from: Int): LeavesIterator do return new LeavesIterator(self, from)
+       redef fun reversed do return new Concat(right.reversed, left.reversed)
 
-       # Iterator on the substrings from 0, in forward order
-       redef fun substrings do return new SubstringsIterator(self, 0)
-
-       # Iterator on the substrings, starting at position `from`, in forward order
-       fun substrings_from(from: Int): IndexedIterator[Text] do return new SubstringsIterator(self, from)
-
-       # Iterator on the nodes of the rope, in backwards postfix order
-       private fun reverse_postfix(from: Int): ReversePostfix do return new ReversePostfix.from(self, from)
-
-       # Iterator on the leaves of the rope, backwards order
-       private fun reverse_leaves(from: Int): ReverseLeavesIterator do return new ReverseLeavesIterator(self,from)
+       redef fun insert_at(s, pos) do
+               if pos > left.length then
+                       return left + right.insert_at(s, pos - left.length)
+               end
+               return left.insert_at(s, pos) + right
+       end
 
-       # Iterator on the substrings, in reverse order
-       fun reverse_substrings: IndexedIterator[Text] do return new ReverseSubstringsIterator(self, length-1)
+       redef fun to_upper do return new Concat(left.to_upper, right.to_upper)
 
-       # Iterator on the substrings, in reverse order, starting iteration at position `from`
-       fun reverse_substrings_from(from: Int): IndexedIterator[Text] do return new ReverseSubstringsIterator(self, from)
+       redef fun to_lower do return new Concat(left.to_lower, right.to_lower)
 
-       redef fun output
-       do
-               for i in substrings do
-                       i.output
+       redef fun +(o) do
+               var s = o.to_s
+               var mlen = length
+               var slen = s.length
+               if s isa Concat then
+                       return new Concat(self, s)
+               else
+                       var r = right
+                       var rlen = r.length
+                       if rlen + slen > maxlen then return new Concat(left, new Concat(r, s))
+                       return new Concat(left, r + s)
                end
        end
+end
 
-       redef fun to_cstring
-       do
-               if str_representation != null then return str_representation.as(not null)
+# Mutable `Rope`, optimized for concatenation operations
+#
+# A `RopeBuffer` is an efficient way of building a `String` when
+# concatenating small strings.
+#
+# It does concatenations in an optimized way by having a
+# mutable part and an immutable part built by efficiently
+# concatenating strings in chain.
+#
+# Every concatenation operation is done by copying a string to
+# the mutable part and flushing it when full.
+#
+# However, when a long string is appended to the `Buffer`,
+# the concatenation is done at it would be in a `Rope`.
+class RopeBuffer
+       super Rope
+       super Buffer
 
-               var native_final_str = calloc_string(length + 1)
+       redef fun chars: Sequence[Char] is cached do return new RopeBufferChars(self)
 
-               native_final_str[length] = '\0'
+       # The final string being built on the fly
+       private var str: String is noinit
 
-               if self.length == 0 then
-                       str_representation = native_final_str
-                       return native_final_str
-               end
+       # Current concatenation buffer
+       private var ns: NativeString is noinit
 
-               var offset = 0
+       # Next available (e.g. unset) character in the `Buffer`
+       private var rpos = 0
 
-               for i in substrings do
-                       var str = i.flatten
-                       if str isa FlatString then str.items.copy_to(native_final_str, str.length, str.index_from, offset)
-                       offset += i.length
-               end
+       # Keeps track of the buffer's currently dumped part
+       #
+       # This might happen if for instance, a String was being
+       # built by concatenating small parts of string and suddenly
+       # a long string (length > maxlen) is appended.
+       private var dumped: Int is noinit
 
-               str_representation = native_final_str
+       # Length of the complete rope
+       redef var length = 0
 
-               return native_final_str
-       end
+       # Length of the mutable part
+       #
+       # Is also used as base to compute the size of the next
+       # mutable native string (`ns`)
+       private var buf_size: Int is noinit
 
-       # Path to the Leaf for `position`
-       private fun node_at(position: Int): Path
-       do
-               assert position >= 0 and position <= length
-               if position == length then
-                       var st = new List[PathElement]
-                       stack_to_end(root,st)
-                       if not st.is_empty then
-                               var lst = st.last
-                               var lf = lst.node.right
-                               if lf != null then
-                                       return new Path(lf.as(Leaf), lf.length, st)
-                               else
-                                       lf = lst.node.left
-                                       return new Path(lf.as(Leaf), lf.length, st)
-                               end
-                       else
-                               return new Path(root.as(Leaf), length, st)
-                       end
-               end
-               return get_node_from(root, 0, position, new List[PathElement])
-       end
-
-       # Special case for when the required pos is length
-       private fun stack_to_end(nod: RopeNode, st: List[PathElement])
-       do
-               if nod isa Leaf then return
-               var n = nod.as(Concat)
-               var r = n.right
-               var ele = new PathElement(n)
-               ele.right = true
-               st.push(ele)
-               if r != null then
-                       stack_to_end(r, st)
-               end
-               return
-       end
+       redef fun substrings: Iterator[String] do return new RopeBufSubstringIterator(self)
 
-       # Builds the path to Leaf at position `seek_pos`
-       private fun get_node_from(node: RopeNode, curr_pos: Int, seek_pos: Int, stack: List[PathElement]): Path
-       do
-               assert curr_pos >= 0
-               if node isa Leaf then
-                       self.leaf_cache = new LeafCache(node, curr_pos)
-                       return new Path(node, seek_pos - curr_pos, stack)
-               end
-               node = node.as(Concat)
-
-               if node.left != null then
-                       var next_pos = curr_pos + node.left.length
-                       stack.add(new PathElement(node))
-                       if next_pos > seek_pos then
-                               stack.last.left = true
-                               return get_node_from(node.left.as(not null), curr_pos, seek_pos, stack)
-                       end
-                       stack.last.right = true
-                       return get_node_from(node.right.as(not null), next_pos, seek_pos, stack)
-               else
-                       var vis = new PathElement(node)
-                       vis.right = true
-                       stack.add(vis)
-                       return get_node_from(node.right.as(not null), curr_pos, seek_pos, stack)
-               end
+       # Builds an empty `RopeBuffer`
+       init do
+               str = ""
+               ns = new NativeString(maxlen)
+               buf_size = maxlen
+               dumped = 0
        end
 
-       redef fun ==(o)
-       do
-               if not o isa Text then return false
-               if o.length != self.length then return false
-               var oit = o.chars.iterator
-               for i in self.chars.iterator do
-                       if i != oit.item then return false
-                       oit.next
-               end
-               return true
+       # Builds a new `RopeBuffer` with `str` in it.
+       init from(str: String) do
+               self.str = str
+               ns = new NativeString(maxlen)
+               buf_size = maxlen
+               length = str.length
+               dumped = 0
        end
-end
 
-# Rope that cannot be modified
-class RopeString
-       super Rope
-       super String
+       # Resets the informations of the `Buffer`
+       #
+       # This is called when doing in-place modifications
+       # on a previously to_s'd `RopeBuffer`
+       private fun reset do
+               var nns = new NativeString(buf_size)
+               var blen = rpos - dumped
+               ns.copy_to(nns, blen, dumped, 0)
+               dumped = 0
+               rpos = blen
+               written = false
+       end
 
-       redef fun to_s do return self
+       redef fun empty do return new RopeBuffer
 
-       redef fun empty do return once new RopeString.from("")
+       redef fun clear do
+               str = ""
+               length = 0
+               rpos = 0
+       end
 
-       redef var chars: SequenceRead[Char] = new RopeStringChars(self)
+       redef fun substring(from, count) do
+               var strlen = str.length
 
-       redef fun reversed
-       do
-               var ret = empty
-               for i in substrings do
-                       ret = i.as(String).reversed + ret
+               if from < 0 then
+                       count += from
+                       if count < 0 then count = 0
+                       from = 0
                end
-               return ret
-       end
 
-       redef fun to_upper
-       do
-               var ret = empty
-               for i in substrings do
-                       ret += i.as(String).to_upper
-               end
-               return ret
-       end
+               if count > length then count = length - from
 
-       redef fun to_lower
-       do
-               var ret = empty
-               for i in substrings do
-                       ret += i.as(String).to_lower
-               end
-               return ret
-       end
+               if count == 0 then return empty
 
-       redef fun +(o) do
-               if self.length == 0 then return o.to_s
-               if o.length == 0 then return self
-               var str = o.to_s
-               if str isa FlatString then
-                       return new RopeString.from_root(new Concat(root, new StringLeaf(str)))
-               else if str isa RopeString then
-                       return new RopeString.from_root(new Concat(root, str.root))
+               if from < strlen then
+                       var subpos = strlen - from
+                       if count <= subpos then
+                               return new RopeBuffer.from(str.substring(from, count))
+                       else
+                               var l = str.substring_from(from)
+                               var rem = count - subpos
+                               var nns = new NativeString(rem)
+                               ns.copy_to(nns, rem, dumped, 0)
+                               return new RopeBuffer.from(l + nns.to_s_with_length(rem))
+                       end
                else
-                       abort
-               end
-       end
-
-       redef fun *(n)
-       do
-               var ret = new RopeString.from("")
-               for i in [0..n[ do
-                       ret = (ret + self).as(RopeString)
+                       var nns = new NativeString(count)
+                       ns.copy_to(nns, count, dumped, 0)
+                       return new RopeBuffer.from(nns.to_s_with_length(count))
                end
-               return ret
        end
 
-       # Inserts a String `str` at position `pos`
-       redef fun insert_at(str, pos)
-       do
-               if str.length == 0 then return self
-               if self.length == 0 then return new RopeString.from(str)
-
-               assert pos >= 0 and pos <= length
-
-               var path = node_at(pos)
-
-               var last_concat: Concat
-
-               if path.offset == 0 then
-                       if str isa FlatString then
-                               last_concat = new Concat(new StringLeaf(str), path.leaf)
-                       else
-                               last_concat = new Concat(str.as(RopeString).root, path.leaf)
+       redef fun append(s) do
+               var slen = s.length
+               length += slen
+               var rp = rpos
+               if s isa Rope then
+                       if rp > 0 and dumped != rp then
+                               str += new FlatString.with_infos(ns, rp - dumped, dumped, rp - 1)
+                               dumped = rp
                        end
-               else if path.offset == path.leaf.length then
-                       if str isa FlatString then
-                               last_concat = new Concat(path.leaf, new StringLeaf(str))
-                       else
-                               last_concat = new Concat(path.leaf, str.as(RopeString).root)
+                       str = str + s
+                       return
+               end
+               if slen > maxlen then
+                       if rp > 0 and dumped != rp then
+                               str += new FlatString.with_infos(ns, rp - dumped, dumped, rp - 1)
+                               dumped = rp
                        end
+                       str = str + s
+                       return
+               end
+               var remsp = buf_size - rp
+               var sits: NativeString
+               var begin: Int
+               if s isa FlatString then
+                       begin = s.index_from
+                       sits = s.items
+               else if s isa FlatBuffer then
+                       begin = 0
+                       sits = s.items
                else
-                       var s = path.leaf.str
-                       var l_half = s.substring(0, s.length - path.offset)
-                       var r_half = s.substring_from(s.length - path.offset)
-                       var cct: Concat
-                       var ll = new StringLeaf(l_half.as(FlatString))
-                       if str isa FlatString then
-                               cct = new Concat(ll, new StringLeaf(str))
+                       if slen <= remsp then
+                               for i in s.chars do
+                                       ns[rpos] = i
+                                       rpos += 1
+                               end
                        else
-                               cct = new Concat(ll, str.as(RopeString).root)
+                               var spos = 0
+                               for i in [0..remsp[ do
+                                       ns[rpos] = s[spos]
+                                       rpos += 1
+                                       spos += 1
+                               end
+                               dump_buffer
+                               while spos < slen do
+                                       ns[rpos] = s[spos]
+                                       spos += 1
+                                       rpos += 1
+                               end
                        end
-                       last_concat = new Concat(cct, new StringLeaf(r_half.as(FlatString)))
+                       return
                end
-
-               for i in path.stack.reverse_iterator do
-                       if i.left then
-                               last_concat = new Concat(last_concat, i.node.right)
+               if slen <= remsp then
+                       sits.copy_to(ns, slen, begin, rp)
+                       if rp == buf_size then
+                               rpos = buf_size
+                               dump_buffer
+                               rpos = 0
                        else
-                               last_concat = new Concat(i.node.left, last_concat)
+                               rpos += slen
                        end
+               else
+                       sits.copy_to(ns, remsp, begin, rp)
+                       rpos = buf_size
+                       dump_buffer
+                       var nlen = slen - remsp
+                       sits.copy_to(ns, nlen, begin + remsp, 0)
+                       rpos = nlen
                end
-
-               return new RopeString.from_root(last_concat)
        end
 
-       # O(log(n))
-       #
-       #     var rope = new RopeString.from("abcd")
-       #     assert rope.substring(1, 2)         ==  "bc"
-       #     assert rope.substring(-1, 2)         ==  "a"
-       #     assert rope.substring(1, 0)         ==  ""
-       #     assert rope.substring(2, 5)         ==  "cd"
-       #
-       redef fun substring(pos, len)
-       do
-               if pos < 0 then
-                       len += pos
-                       pos = 0
+       redef fun add(c) do
+               var rp = rpos
+               length += 1
+               ns[rp] = c
+               rp += 1
+               if rp == buf_size then
+                       rpos = rp
+                       dump_buffer
+                       rp = 0
                end
+               rpos = rp
+       end
 
-               if pos + len > length then len = length - pos
-
-               if len <= 0 then return new RopeString.from("")
-
-               var path = node_at(pos)
+       # Converts the Buffer to a FlatString, appends it to
+       # the final String and re-allocates a new larger Buffer.
+       private fun dump_buffer do
+               written = false
+               var nstr = new FlatString.with_infos(ns, rpos - dumped, dumped, rpos - 1)
+               str += nstr
+               var bs = buf_size
+               bs = bs * 2
+               ns = new NativeString(bs)
+               buf_size = bs
+               dumped = 0
+       end
 
-               var lf = path.leaf
-               var offset = path.offset
+       redef fun output do
+               str.output
+               new FlatString.with_infos(ns, rpos - dumped, dumped, rpos - 1).output
+       end
 
-               if path.leaf.str.length - offset > len then lf = new StringLeaf(lf.str.substring(offset,len).as(FlatString)) else lf = new StringLeaf(lf.str.substring_from(offset).as(FlatString))
+       # Enlarge is useless here since the `Buffer`
+       # part is automatically dumped when necessary.
+       #
+       # Also, since the buffer can not be overused by a
+       # single string, there is no need for manual
+       # resizing.
+       #
+       # "You have no power here !"
+       redef fun enlarge(i) do end
 
-               var nod: RopeNode = lf
+       redef fun to_s do
+               written = true
+               var nnslen = rpos - dumped
+               if nnslen == 0 then return str
+               return str + new FlatString.with_infos(ns, rpos - dumped, dumped, rpos - 1)
+       end
 
-               for i in path.stack.reverse_iterator do
-                       if i.right then continue
-                       nod = new Concat(nod, i.node.right)
+       redef fun reverse do
+               str = str.reversed
+               var nns = new NativeString(buf_size)
+               var j = rpos
+               var mits = ns
+               for i in [0 .. rpos[ do
+                       nns[i] = mits[j]
+                       j -= 1
                end
+               ns = nns
+       end
 
-               var ret = new RopeString
-               ret.root = nod
-
-               path = ret.node_at(len-1)
-
-               offset = path.offset
-               nod = new StringLeaf(path.leaf.str.substring(0, offset+1).as(FlatString))
-
-               for i in path.stack.reverse_iterator do
-                       if i.left then continue
-                       nod = new Concat(i.node.left, nod)
+       redef fun upper do
+               if written then reset
+               str = str.to_upper
+               var mits = ns
+               for i in [0 .. rpos[ do
+                       mits[i] = mits[i].to_upper
                end
+       end
 
-               ret.root = nod
-
-               return ret
+       redef fun lower do
+               if written then reset
+               str = str.to_lower
+               var mits = ns
+               for i in [0 .. rpos[ do
+                       mits[i] = mits[i].to_lower
+               end
        end
 end
 
 redef class FlatString
 
-       redef fun insert_at(s, pos)
-       do
+       redef fun insert_at(s, pos) do
+               var l = substring(0, pos)
+               var r = substring_from(pos)
+               return l + s + r
+       end
 
-               if pos == 0 then
-                       var r = new RopeString.from(s)
-                       return r + self
-               end
-               if pos == length then
-                       var r = new RopeString.from(self)
-                       return r + s
+       redef fun +(o) do
+               var s = o.to_s
+               var slen = s.length
+               var mlen = length
+               if slen == 0 then return self
+               if mlen == 0 then return s
+               var nlen = slen + mlen
+               if s isa FlatString then
+                       if nlen > maxlen then return new Concat(self, s)
+                       var mits = items
+                       var sifrom = s.index_from
+                       var mifrom = index_from
+                       var sits = s.items
+                       var ns = new NativeString(nlen + 1)
+                       mits.copy_to(ns, mlen, mifrom, 0)
+                       sits.copy_to(ns, slen, sifrom, mlen)
+                       return ns.to_s_with_length(nlen)
+               else if s isa Concat then
+                       var sl = s.left
+                       var sllen = sl.length
+                       if sllen + mlen > maxlen then return new Concat(self, s)
+                       return new Concat(self + sl, s.right)
+               else
+                       abort
                end
-
-               var l = substring(0,pos)
-               var r = substring_from(pos)
-               var ret: String = new RopeString.from(l)
-               ret += s
-               return ret + r
        end
+end
 
+# A simple linked list for use with iterators
+private class RopeIterPiece
+       # The encapsulated node of the `Rope`
+       var node: String
+       # Was its left child (if any) visited ?
+       var ldone: Bool
+       # Was its right child (if any) visited ?
+       var rdone: Bool
+       # The previous node in the list.
+       var prev: nullable RopeIterPiece
 end
 
-private class RopeStringChars
-       super SequenceRead[Char]
+# A reverse iterator capable of working with `Rope` objects
+private class RopeReviter
+       super IndexedIterator[Char]
 
-       var tgt: Rope
+       # Current NativeString
+       var ns: String
+       # Current position in NativeString
+       var pns: Int
+       # Position in the Rope (0-indexed)
+       var pos: Int
+       # Iterator on the substrings, does the Postfix part of
+       # the Rope traversal.
+       var subs: IndexedIterator[String]
 
-       redef fun [](pos)
-       do
-               assert pos < tgt.length
-               if tgt.leaf_cache != null and pos >= tgt.leaf_cache.pos and (tgt.leaf_cache.pos + tgt.leaf_cache.leaf.length) > pos then return tgt.leaf_cache.leaf.str.chars[pos - tgt.leaf_cache.pos]
-               var path = tgt.node_at(pos)
-               return path.leaf.str.chars[path.offset]
+       init(root: RopeString) do
+               pos = root.length - 1
+               subs = new ReverseRopeSubstrings(root)
+               ns = subs.item
+               pns = ns.length - 1
        end
 
-       redef fun iterator do return iterator_from(0)
-
-       redef fun iterator_from(pos) do return new RopeCharIterator(tgt, pos)
+       init from(root: RopeString, pos: Int) do
+               self.pos = pos
+               subs = new ReverseRopeSubstrings.from(root, pos)
+               ns = subs.item
+               pns = pos - subs.index
+       end
 
-       redef fun reverse_iterator do return reverse_iterator_from(tgt.length-1)
+       redef fun index do return pos
 
-       redef fun reverse_iterator_from(pos) do return new ReverseRopeCharIterator(tgt, pos)
-end
+       redef fun is_ok do return pos >= 0
 
-# Used to iterate on a Rope
-private class IteratorElement
+       redef fun item do return ns[pns]
 
-       init(e: RopeNode)
-       do
-               if e isa Leaf then
-                       left = true
-                       right = true
-               end
-               node = e
+       redef fun next do
+               pns -= 1
+               pos -= 1
+               if pns >= 0 then return
+               if not subs.is_ok then return
+               subs.next
+               if not subs.is_ok then return
+               ns = subs.item
+               pns = ns.length - 1
        end
-
-       # The node being visited
-       var node: RopeNode
-       # If the node has a left child, was it visited ?
-       var left = false
-       # If the node has a right child, was it visited ?
-       var right = false
-       # Was the current node visited ?
-       var done = false
 end
 
-# Simple Postfix iterator on the nodes of a Rope
-private class Postfix
-       super IndexedIterator[RopeNode]
-
-       # Target Rope to iterate on
-       var target: Rope
+# Forward iterator on the chars of a `Rope`
+private class RopeIter
+       super IndexedIterator[Char]
 
-       # Current position in Rope
+       # Position in current `String`
+       var pns: Int
+       # Current `String` being iterated on
+       var str: String
+       # Substrings of the Rope
+       var subs: IndexedIterator[String]
+       # Maximum position to iterate on (e.g. Rope.length)
+       var max: Int
+       # Position (char) in the Rope (0-indexed)
        var pos: Int
 
-       # Visited nodes
-       var stack = new List[IteratorElement]
+       init(root: RopeString) do
+               subs = new RopeSubstrings(root)
+               pns = 0
+               str = subs.item
+               max = root.length - 1
+               pos = 0
+       end
 
-       init from(tgt: Rope, pos: Int)
-       do
-               self.target = tgt
+       init from(root: RopeString, pos: Int) do
+               subs = new RopeSubstrings.from(root, pos)
+               pns = pos - subs.index
                self.pos = pos
-               if pos < 0 or pos >= tgt.length then return
-               var path = tgt.node_at(pos)
-               self.pos -= path.offset
-               for i in path.stack do
-                       var item = new IteratorElement(i.node)
-                       item.left = true
-                       if i.right then item.right = true
-                       stack.push item
-               end
-               var item = new IteratorElement(path.leaf)
-               item.done = true
-               stack.push item
+               str = subs.item
+               max = root.length - 1
        end
 
-       redef fun item
-       do
-               assert is_ok
-               return stack.last.node
-       end
+       redef fun item do return str[pns]
 
-       redef fun is_ok do return not stack.is_empty
+       redef fun is_ok do return pos <= max
 
        redef fun index do return pos
 
        redef fun next do
-               if stack.is_empty then return
-               if pos > target.length-1 then
-                       stack.clear
-                       return
-               end
-               var lst = stack.last
-               if lst.done then
-                       if lst.node isa Leaf then
-                               pos += lst.node.length
-                       end
-                       stack.pop
-                       next
-                       return
-               end
-               if not lst.left then
-                       lst.left = true
-                       var nod = lst.node
-                       if nod isa Concat and nod.left != null then
-                               stack.push(new IteratorElement(nod.left.as(not null)))
-                               next
-                               return
-                       end
-               end
-               if not lst.right then
-                       lst.right = true
-                       var nod = lst.node
-                       if nod isa Concat and nod.right != null then
-                               stack.push(new IteratorElement(nod.right.as(not null)))
-                               next
-                               return
-                       end
-               end
-               lst.done = true
+               pns += 1
+               pos += 1
+               if pns < subs.item.length then return
+               if not subs.is_ok then return
+               subs.next
+               if not subs.is_ok then return
+               str = subs.item
+               pns = 0
        end
 end
 
-# Iterates on the leaves (substrings) of the Rope
-class LeavesIterator
-       super IndexedIterator[Leaf]
-
-       private var nodes: Postfix
+# Substrings of a Rope (i.e. Reverse postfix iterator on leaves)
+private class ReverseRopeSubstrings
+       super IndexedIterator[String]
+
+       # Visit Stack
+       var iter: RopeIterPiece is noinit
+       # Position in `Rope`
+       var pos: Int is noinit
+
+       # Current leaf
+       var str: String is noinit
+
+       init(root: RopeString) do
+               var r = new RopeIterPiece(root, false, true, null)
+               pos = root.length - 1
+               var lnod: String = root
+               loop
+                       if lnod isa Concat then
+                               lnod = lnod.right
+                               r = new RopeIterPiece(lnod, false, true, r)
+                       else
+                               str = lnod
+                               iter = r
+                               break
+                       end
+               end
+       end
 
-       init(tgt: Rope, pos: Int)
-       do
-               nodes = tgt.postfix(pos)
+       init from(root: RopeString, pos: Int) do
+               var r = new RopeIterPiece(root, false, true, null)
+               var rnod: String = root
+               var off = pos
+               loop
+                       if rnod isa Concat then
+                               if off >= rnod.left.length then
+                                       off -= rnod.left.length
+                                       rnod = rnod.right
+                                       r = new RopeIterPiece(rnod, false, true, r)
+                               else
+                                       r.ldone = true
+                                       rnod = rnod.left
+                                       r = new RopeIterPiece(rnod, false, true, r)
+                               end
+                       else
+                               str = rnod
+                               r.ldone = true
+                               iter = r
+                               self.pos = pos - off
+                               break
+                       end
+               end
        end
 
-       redef fun is_ok do return nodes.is_ok
+       redef fun item do return str
 
-       redef fun item
-       do
-               assert is_ok
-               return nodes.item.as(Leaf)
-       end
+       redef fun index do return pos
 
-       redef fun index do return nodes.index
+       redef fun is_ok do return pos >= 0
 
-       redef fun next
-       do
-               while nodes.is_ok do
-                       nodes.next
-                       if nodes.is_ok and nodes.item isa Leaf then break
+       redef fun next do
+               if pos < 0 then return
+               var curr: nullable RopeIterPiece = iter.prev
+               var currit = curr.node
+               while curr != null do
+                       currit = curr.node
+                       if not currit isa Concat then
+                               str = currit
+                               pos -= str.length
+                               iter = curr
+                               return
+                       end
+                       if not curr.rdone then
+                               curr.rdone = true
+                               curr = new RopeIterPiece(currit.right, false, false, curr)
+                               continue
+                       end
+                       if not curr.ldone then
+                               curr.ldone = true
+                               curr = new RopeIterPiece(currit.left, false, false, curr)
+                               continue
+                       end
+                       curr = curr.prev
                end
+               pos = -1
        end
 end
 
-# Uses the leaves and calculates a new substring on each iteration
-class SubstringsIterator
-       super IndexedIterator[Text]
-
-       private var nodes: IndexedIterator[Leaf]
-
-       # Current position in Rope
-       var pos: Int
+private class RopeBufSubstringIterator
+       super Iterator[String]
 
-       # Current substring, computed from the current Leaf and indexes
-       var substring: Text
+       # Iterator on the substrings of the building string
+       var iter: Iterator[String]
+       # Makes a String out of the buffered part of the Ropebuffer
+       var nsstr: String
+       # Did we attain the buffered part ?
+       var nsstr_done = false
 
-       init(tgt: Rope, pos: Int)
-       do
-               nodes = tgt.leaves(pos)
-               self.pos = pos
-               if pos < 0 or pos >= tgt.length then return
-               make_substring
-       end
-
-       # Compute the bounds of the current substring and makes the substring
-       private fun make_substring
-       do
-               substring = nodes.item.str
-               var min = 0
-               var length = substring.length
-               if nodes.index < pos then
-                       min = pos - nodes.index
-               end
-               substring = substring.substring(min, length)
+       init(str: RopeBuffer) do
+               iter = str.str.substrings
+               nsstr = new FlatString.with_infos(str.ns, str.rpos - str.dumped, str.dumped, str.rpos - 1)
+               if str.length == 0 then nsstr_done = true
        end
 
-       redef fun is_ok do return nodes.is_ok
+       redef fun is_ok do return iter.is_ok or not nsstr_done
 
-       redef fun item
-       do
+       redef fun item do
                assert is_ok
-               return substring
+               if iter.is_ok then return iter.item
+               return nsstr
        end
 
-       redef fun index do return pos
-
-       redef fun next
-       do
-               pos += substring.length
-               nodes.next
-               if nodes.is_ok then make_substring
+       redef fun next do
+               if iter.is_ok then
+                       iter.next
+                       return
+               end
+               nsstr_done = true
        end
-
 end
 
-class RopeCharIterator
-       super IndexedIterator[Char]
-
-       var substrings: IndexedIterator[Text]
-
-       var pos: Int
-
-       var max: Int
-
-       var substr_iter: IndexedIterator[Char]
+# Substrings of a Rope (i.e. Postfix iterator on leaves)
+private class RopeSubstrings
+       super IndexedIterator[String]
+
+       # Visit Stack
+       var iter: RopeIterPiece is noinit
+       # Position in `Rope`
+       var pos: Int is noinit
+       # Maximum position in `Rope` (i.e. length - 1)
+       var max: Int is noinit
+
+       # Current leaf
+       var str: String is noinit
+
+       init(root: RopeString) do
+               var r = new RopeIterPiece(root, true, false, null)
+               pos = 0
+               max = root.length - 1
+               var rnod: String = root
+               loop
+                       if rnod isa Concat then
+                               rnod = rnod.left
+                               r = new RopeIterPiece(rnod, true, false, r)
+                       else
+                               str = rnod
+                               r.rdone = true
+                               iter = r
+                               break
+                       end
+               end
+       end
 
-       init(tgt: Rope, from: Int)
-       do
-               substrings = tgt.substrings_from(from)
-               max = tgt.length - 1
-               if not substrings.is_ok then
-                       pos = tgt.length
-                       return
+       init from(root: RopeString, pos: Int) do
+               var r = new RopeIterPiece(root, true, false, null)
+               max = root.length - 1
+               var rnod: String = root
+               var off = pos
+               loop
+                       if rnod isa Concat then
+                               if off >= rnod.left.length then
+                                       r.rdone = true
+                                       off -= rnod.left.length
+                                       rnod = rnod.right
+                                       r = new RopeIterPiece(rnod, true, false, r)
+                               else
+                                       rnod = rnod.left
+                                       r = new RopeIterPiece(rnod, true, false, r)
+                               end
+                       else
+                               str = rnod
+                               r.rdone = true
+                               iter = r
+                               self.pos = pos - off
+                               break
+                       end
                end
-               pos = from
-               substr_iter = substrings.item.chars.iterator
        end
 
-       redef fun item do return substr_iter.item
+       redef fun item do return str
 
        redef fun is_ok do return pos <= max
 
        redef fun index do return pos
 
-       redef fun next
-       do
-               pos += 1
-               if substr_iter.is_ok then
-                       substr_iter.next
-               end
-               if not substr_iter.is_ok then
-                       substrings.next
-                       if substrings.is_ok then
-                               substr_iter = substrings.item.chars.iterator
+       redef fun next do
+               pos += str.length
+               if pos > max then return
+               var it = iter.prev
+               var rnod: String = it.node
+               loop
+                       if not rnod isa Concat then
+                               it.ldone = true
+                               it.rdone = true
+                               str = rnod
+                               iter = it.as(not null)
+                               break
+                       end
+                       if not it.ldone then
+                               rnod = rnod.left
+                               it.ldone = true
+                               it = new RopeIterPiece(rnod, false, false, it)
+                       else if not it.rdone then
+                               it.rdone = true
+                               rnod = rnod.right
+                               it = new RopeIterPiece(rnod, false, false, it)
+                       else
+                               it = it.prev
+                               rnod = it.node
+                               continue
                        end
                end
        end
 end
 
-private class ReversePostfix
-       super IndexedIterator[RopeNode]
+# Implementation of a `StringCharView` for `RopeString` objects
+private class RopeChars
+       super StringCharView
 
-       var target: Rope
+       var tgt: RopeString
 
-       var pos: Int
+       init(s: RopeString) do tgt = s
 
-       var min = 0
+       redef fun [](i) do
+               return tgt[i]
+       end
 
-       var stack = new List[IteratorElement]
+       redef fun iterator_from(i) do return new RopeIter.from(tgt, i)
 
-       init from(tgt: Rope, pos: Int)
-       do
-               self.pos = pos
-               target = tgt
-               if pos < 0 or pos >= tgt.length then return
-               var path = tgt.node_at(pos)
-               self.pos -= path.offset
-               for i in path.stack do
-                       var elemt = new IteratorElement(i.node)
-                       elemt.right = true
-                       if i.left then
-                               elemt.left = true
-                       end
-                       stack.push elemt
-               end
-               stack.push(new IteratorElement(path.leaf))
-               stack.last.done = true
-       end
+       redef fun reverse_iterator_from(i) do return new RopeReviter.from(tgt, i)
 
-       redef fun item do
-               assert is_ok
-               return stack.last.node
-       end
+end
 
-       redef fun is_ok do return not stack.is_empty
+class RopeBufferIter
+       super IndexedIterator[Char]
 
-       redef fun index do return pos
+       var sit: IndexedIterator[Char]
 
-       redef fun next
-       do
-               if stack.is_empty then return
-               if pos < min then
-                       stack.clear
-                       return
-               end
-               var lst = stack.last
-               if lst.done then
-                       stack.pop
-                       next
-                       return
-               end
-               if not lst.right then
-                       var nod = lst.node.as(Concat)
-                       var rgt = nod.right
-                       lst.right = true
-                       if rgt != null then
-                               stack.push(new IteratorElement(rgt))
-                               next
-                               return
-                       end
-               end
-               if not lst.left then
-                       var nod = lst.node.as(Concat)
-                       var lft = nod.left
-                       lst.left = true
-                       if lft != null then
-                               stack.push(new IteratorElement(lft))
-                               next
-                               return
-                       end
-               end
-               if lst.node isa Leaf then pos -= lst.node.length
-               lst.done = true
-       end
-end
+       var ns: NativeString
+
+       var pns: Int
 
-private class ReverseLeavesIterator
-       super IndexedIterator[Leaf]
+       var maxpos: Int
 
-       var nodes: ReversePostfix
+       redef var index: Int
+
+       init(t: RopeBuffer) do
+               ns = t.ns
+               maxpos = t.rpos
+               sit = t.str.chars.iterator
+               pns = t.dumped
+               index = 0
+       end
 
-       init(tgt: Rope, from: Int)
-       do
-               nodes = tgt.reverse_postfix(from)
+       init from(t: RopeBuffer, pos: Int) do
+               ns = t.ns
+               maxpos = t.length
+               sit = t.str.chars.iterator_from(pos)
+               pns = pos - t.str.length
+               index = pos
        end
 
-       redef fun is_ok do return nodes.is_ok
+       redef fun is_ok do return index < maxpos
 
        redef fun item do
-               assert is_ok
-               return nodes.item.as(Leaf)
+               if sit.is_ok then return sit.item
+               return ns[pns]
        end
 
        redef fun next do
-               while nodes.is_ok do
-                       nodes.next
-                       if nodes.is_ok then if nodes.item isa Leaf then break
+               index += 1
+               if sit.is_ok then
+                       sit.next
+               else
+                       pns += 1
                end
        end
-
-       redef fun index do return nodes.index
-
 end
 
-private class ReverseSubstringsIterator
-       super IndexedIterator[Text]
+class RopeBufferReviter
+       super IndexedIterator[Char]
 
-       var leaves: ReverseLeavesIterator
+       var sit: IndexedIterator[Char]
 
-       var pos: Int
+       var ns: NativeString
+
+       var pns: Int
 
-       var str: Text
+       redef var index: Int
 
-       init(tgt: Rope, from: Int)
-       do
-               leaves = tgt.reverse_leaves(from)
-               pos = from
-               if not leaves.is_ok then return
-               str = leaves.item.str
-               make_substring
+       init(tgt: RopeBuffer) do
+               sit = tgt.str.chars.reverse_iterator
+               pns = tgt.rpos - 1
+               index = tgt.length - 1
+               ns = tgt.ns
        end
 
-       fun make_substring
-       do
-               if pos >= (leaves.index + str.length - 1) then return
-               str = str.substring(0, (pos - leaves.index + 1))
+       init from(tgt: RopeBuffer, pos: Int) do
+               sit = tgt.str.chars.reverse_iterator_from(pos - tgt.rpos - tgt.dumped)
+               pns = pos - tgt.str.length
+               index = pos
+               ns = tgt.ns
        end
 
-       redef fun is_ok do return leaves.is_ok
+       redef fun is_ok do return index > 0
 
        redef fun item do
-               assert is_ok
-               return str
+               if pns >= 0 then return ns[pns]
+               return sit.item
        end
 
-       redef fun index do return pos
-
        redef fun next do
-               pos -= str.length
-               leaves.next
-               if not leaves.is_ok then return
-               str = leaves.item.str
-               make_substring
+               index -= 1
+               if pns >= 0 then
+                       pns -= 1
+               else
+                       sit.next
+               end
        end
 end
 
-private class ReverseRopeCharIterator
-       super IndexedIterator[Char]
+# View on the chars of a `RopeBuffer`
+class RopeBufferChars
+       super BufferCharView
 
-       var substrs: IndexedIterator[Text]
+       redef type SELFTYPE: RopeBuffer
 
-       var pos: Int
-
-       var subiter: IndexedIterator[Char]
+       redef fun [](i) do
+               if i < target.str.length then
+                       return target.str[i]
+               else
+                       return target.ns[i - target.str.length]
+               end
+       end
 
-       init(tgt: Rope, from: Int)
-       do
-               substrs = tgt.reverse_substrings_from(from)
-               if not substrs.is_ok then
-                       pos = -1
-                       return
+       redef fun []=(i,c) do
+               if i == target.length then target.add c
+               if i < target.str.length then
+                       var s = target.str
+                       var l = s.substring(0, i)
+                       var r = s.substring_from(i + 1)
+                       target.str = l + c.to_s + r
+               else
+                       target.ns[i - target.str.length] = c
                end
-               subiter = substrs.item.chars.reverse_iterator
-               pos = from
        end
 
-       redef fun is_ok do return pos >= 0
+       redef fun add(c) do target.add c
 
-       redef fun item do
-               assert is_ok
-               return subiter.item
-       end
+       redef fun push(c) do target.add c
 
-       redef fun index do return pos
+       redef fun iterator_from(i) do return new RopeBufferIter.from(target, i)
 
-       redef fun next do
-               pos -= 1
-               if subiter.is_ok then subiter.next
-               if not subiter.is_ok then
-                       if substrs.is_ok then substrs.next
-                       if substrs.is_ok then subiter = substrs.item.chars.reverse_iterator
-               end
-       end
+       redef fun reverse_iterator_from(i) do return new RopeBufferReviter.from(target, i)
 end
-
index 4550113..a487d98 100644 (file)
@@ -22,9 +22,9 @@ import string_search
 import file
 import exec
 import stream
-import ropes
 import collection
 import math
+import ropes
 import kernel
 import gc
 import bitset
index 6765305..84b167a 100644 (file)
@@ -135,29 +135,6 @@ redef class Text
        redef fun write_to(stream) do stream.write(self)
 end
 
-redef class RopeNode
-       super Streamable
-end
-
-redef class Leaf
-
-       redef fun write_to(s) do s.write(str)
-end
-
-redef class Concat
-
-       redef fun write_to(s)
-       do
-               if left != null then left.write_to(s)
-               if right != null then right.write_to(s)
-       end
-end
-
-redef class RopeString
-
-       redef fun write_to(s) do root.write_to(s)
-end
-
 # Input streams with a buffer
 abstract class BufferedIStream
        super IStream
index 9e7ef6e..28ad7b5 100644 (file)
@@ -494,6 +494,27 @@ abstract class Text
        #     assert "\n\"'\\\{\}".escape_to_nit      == "\\n\\\"\\'\\\\\\\{\\\}"
        fun escape_to_nit: String do return escape_more_to_c("\{\}")
 
+       # Escape to POSIX Shell (sh).
+       #
+       # Abort if the text contains a null byte.
+       #
+       #     assert "\n\"'\\\{\}0".escape_to_sh == "'\n\"'\\''\\\{\}0'"
+       fun escape_to_sh: String do
+               var b = new FlatBuffer
+               b.chars.add '\''
+               for i in [0..length[ do
+                       var c = chars[i]
+                       if c == '\'' then
+                               b.append("'\\''")
+                       else
+                               assert without_null_byte: c != '\0'
+                               b.add(c)
+                       end
+               end
+               b.chars.add '\''
+               return b.to_s
+       end
+
        # Return a string where Nit escape sequences are transformed.
        #
        #     var s = "\\n"
@@ -737,11 +758,6 @@ private abstract class StringCharView
 
        private var target: SELFTYPE
 
-       private init(tgt: SELFTYPE)
-       do
-               target = tgt
-       end
-
        redef fun is_empty do return target.is_empty
 
        redef fun length do return target.length
@@ -783,6 +799,8 @@ abstract class String
 
        fun insert_at(s: String, pos: Int): SELFTYPE is abstract
 
+       redef fun substrings: Iterator[String] is abstract
+
        # Returns a reversed version of self
        #
        #     assert "hello".reversed  == "olleh"
@@ -913,8 +931,6 @@ private class FlatSubstringsIter
 
        var tgt: nullable FlatText
 
-       init(tgt: FlatText) do self.tgt = tgt
-
        redef fun item do
                assert is_ok
                return tgt.as(not null)
@@ -2105,7 +2121,6 @@ extern class NativeString `{ char* `}
        do
                assert length >= 0
                var str = new FlatString.with_infos(self, length, 0, length - 1)
-               str.real_items = self
                return str
        end
 
@@ -2115,7 +2130,8 @@ extern class NativeString `{ char* `}
                var new_self = calloc_string(length + 1)
                copy_to(new_self, length, 0, 0)
                var str = new FlatString.with_infos(new_self, length, 0, length - 1)
-               str.real_items = self
+               new_self[length] = '\0'
+               str.real_items = new_self
                return str
        end
 end
index 5aeac25..9b1fb8a 100644 (file)
@@ -139,13 +139,10 @@ class BM_Pattern
                end
        end
 
-       # Compile a new motif
-       init(motif: String)
+       init
        do
-               _motif = motif
                _length = _motif.length
                _gs = new Array[Int].with_capacity(_length)
-               _bc_table = new ArrayMap[Char, Int]
                compute_gs
                compute_bc
        end
@@ -154,7 +151,7 @@ class BM_Pattern
        private var motif: String
 
        # length of the motif
-       private var length: Int
+       private var length: Int is noinit
 
        private fun bc(e: Char): Int
        do
@@ -166,10 +163,10 @@ class BM_Pattern
        end
 
        # good shifts
-       private var gs: Array[Int]
+       private var gs: Array[Int] is noinit
        
        # bad characters
-       private var bc_table: Map[Char, Int]
+       private var bc_table = new ArrayMap[Char, Int]
 
        private fun compute_bc
        do
@@ -255,15 +252,11 @@ class Match
        # The contents of the matching part
        redef fun to_s do return string.substring(from,length)
 
-       # Matches `len` characters of `s` from `f`.
-       init(s: String, f: Int, len: Int)
+       init
        do
-               assert positive_length: len >= 0
-               assert valid_from: f >= 0
-               assert valid_after: f + len <= s.length
-               string = s
-               from = f
-               length = len
+               assert positive_length: length >= 0
+               assert valid_from: from >= 0
+               assert valid_after: from + length <= string.length
        end
 end
 
@@ -334,6 +327,37 @@ redef class Text
        #     assert "I say hello to the world!".search_from("hello",7)       == null
        fun search_from(p: Pattern, from: Int): nullable Match do return p.search_in(self, from)
 
+       # Search the last occurence of the text `t`.
+       #
+       #     assert "bob".search_last("b").from == 2
+       #     assert "bob".search_last("bo").from == 0
+       #     assert "bob".search_last("ob").from == 1
+       #     assert "bobob".search_last("ob").from == 3
+       #     assert "bobbob".search_last("bb").from == 2
+       #     assert "bobbob".search_last("bob").from == 3
+       #     assert "bob".search_last("z") == null
+       #     assert "".search_last("b") == null
+       fun search_last(t: Text): nullable Match do
+               return search_last_up_to(t, length)
+       end
+
+       # Search the last occurence of the text `t` before `up_to`.
+       #
+       #     assert "bobbob".search_last_up_to("b", 3).from == 2
+       #     assert "bobbob".search_last_up_to("b", 6).from == 5
+       #     assert "bobbob".search_last_up_to("b", 0) == null
+       fun search_last_up_to(t: Text, up_to: Int): nullable Match do
+               var i = up_to - t.length
+
+               while i >= 0 do
+                       if substring(i, t.length) == t then
+                               return new Match(self.to_s, i, t.length)
+                       end
+                       i -= 1
+               end
+               return null
+       end
+
        # Search all occurrences of p into self.
        #
        #     var a = new Array[Int]
index 16c2502..c473a3c 100644 (file)
@@ -448,8 +448,8 @@ redef class FlatString
                        items.copy_to(new_str, bytelen, index_from, 0)
                        o.items.copy_to(new_str, o.bytelen, o.index_from, bytelen)
                        return new FlatString.full(new_str, 0, new_bytelen - 1, new_bytelen, newlen)
-               else if o isa RopeString then
-                       return new RopeString.from(self) + o
+               else if o isa Concat then
+                       return new Concat(self, o)
                else
                        # If it goes to this point, that means another String implementation was concerned, therefore you need to support the + operation for this variant
                        abort
@@ -519,7 +519,7 @@ redef class FlatBuffer
        redef var bytelen: Int
 
        redef init from(s) do
-               if s isa RopeString then
+               if s isa Concat then
                        with_capacity(50)
                        for i in s.substrings do self.append(i)
                end
@@ -618,7 +618,7 @@ redef class FlatBuffer
        end
 
        redef fun append(s) do
-               if s isa RopeString then
+               if s isa Concat then
                        for i in s.substrings do append i
                end
                var i = s.as(FlatString)
diff --git a/misc/jenkins/nitester-wrapper.sh b/misc/jenkins/nitester-wrapper.sh
new file mode 100755 (executable)
index 0000000..2f9e20f
--- /dev/null
@@ -0,0 +1,47 @@
+#!/bin/bash
+# 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.
+
+# This script is a wrapper for `nitester` which also manages a local repo
+#
+# The first argument _must_ be the hash of the commit at the head of the
+# branch to test. The other arguments are passed on to `nitester`.
+
+hash=$1
+shift
+
+set +x
+
+local_repo=nit/
+remote_repo=privat
+
+tools_dir=misc/jenkins/
+
+cd $local_repo
+git clean -fdxq .
+
+git fetch $remote_repo
+git checkout $hash
+
+# Make nitg and tools
+$tools_dir/unitrun.sh "run-make-0initial_make" make
+
+# Make nitester
+$tools_dir/unitrun.sh "run-make-nitester" make -C contrib/nitester/
+
+# Run tests
+cd tests
+mkdir -p out
+rm ~/jenkins_xml/*.xml
+mpirun -np 30 ../contrib/nitester/bin/nitester $@
index 54d875c..10dfd38 100755 (executable)
@@ -24,9 +24,18 @@ fi
 name=$1
 shift
 
+# Detect a working time command
+if env time --quiet -f%U true 2>/dev/null; then
+       TIME="env time --quiet -f%U -o '${name}.t.out'"
+elif env time -f%U true 2>/dev/null; then
+       TIME="env time -f%U -o '${name}.t.out'"
+else
+       TIME=
+fi
+
 # Magic here! This tee and save both stdout and stderr in distinct files without messing with them
 # Time  just get the user time
-/usr/bin/time -f%U --quiet -o "${name}.t.out" "$@" > >(tee "${name}.out") 2> >(tee "${name}.2.out" >&2)
+$TIME "$@" > >(tee "${name}.out") 2> >(tee "${name}.2.out" >&2)
 res=$?
 
 c=`echo "${name%-*}" | tr "-" "."`
diff --git a/share/man/.gitignore b/share/man/.gitignore
new file mode 100644 (file)
index 0000000..edbf170
--- /dev/null
@@ -0,0 +1,3 @@
+man1
+www
+pdf.out
index 3eeeb03..4aa0754 100644 (file)
@@ -18,4 +18,25 @@ OUT=$(patsubst %.md,man1/%.1,$(IN))
 all: $(OUT)
 
 man1/%.1: %.md
+       mkdir -p man1
        pandoc $< -t man -s -o $@
+
+# Rule to produce mdwn files for ikiwiki that will be used at http://nitlanguage.org/tools/
+web:
+       rm -r www 2>/dev/null || true
+       mkdir -p www
+       cp nit*.md www
+       rename '$$_ = "$${_}wn"' www/*.md
+       sed -i -e '1d;/SEE ALSO/,$$d' www/*.mdwn
+
+publish: web
+       rsync www/* asimov:wiki/nitlanguage/doc/tools/
+       ssh asimov make -C wiki/nitlanguage
+
+pdf:
+       mkdir -p pdf.out
+       for x in nit*.md; do echo $$x; pandoc -V header-includes='\usepackage{savetrees}' $$x -o pdf.out/$$x.pdf; done
+       pdfjoin pdf.out/*.pdf -o man.pdf
+
+clean:
+       rm -r www pdf.out || true
index a167029..71df3ee 100644 (file)
@@ -13,9 +13,9 @@ man -l man1/nitg.1
 ~~~
 
 For global access, one can set the `MANPATH` environment variable to this `man` directory (not the `man1` subdirectory).
-Do not forget to append a trailing column (`:`) to keep existing manpages accessible.
+Do not forget to append `$MANPATH` to keep existing manpages accessible.
 
 ~~~
-export MANPATH=/path/to/nit/share/man:
+export MANPATH=/path/to/nit/share/man:$MANPATH
 man nitg
 ~~~
diff --git a/share/man/man1/nitc.1 b/share/man/man1/nitc.1
new file mode 120000 (symlink)
index 0000000..e213084
--- /dev/null
@@ -0,0 +1 @@
+nitg.1
\ No newline at end of file
index 26b2adb..75d357c 100644 (file)
@@ -2,70 +2,88 @@
 
 # NAME
 
-Interprets and debugs Nit programs.
+nit - interprets and debugs Nit programs.
 
-# SYNOPSYS
+# SYNOPSIS
 
-nit [*options*]...
+nit [*options*] FILE [ARG]...
 
-# OPTIONS
+nit [*options*] -e COMMAND [ARG]...
+
+# DESCRIPTION
+
+`nit` is the current official interpreter.
+It takes the main module of a program as the first argument then the options and commands of the program.
+
+    $ nit examples/hello_world.nit
+    hello world
+
+The Nit interpreter is usable and valid as a *shebang* interpreted directive.
+It is however recommended to use with `/usr/bin/env` because the location of the executable is not standardized.
+
+    #!/usr/bin/env nit
+    print "hello world"
 
-`-W`, `--warn`
-:   Show more warnings
+The interpreter includes an interactive debugger, it supports basic commands used for debugging a program much like GDB or such.
+See the `DEBUGGER` section for details.
 
-`-w`, `--warning`
-:   Show/hide a specific warning
 
-`-q`, `--quiet`
-:   Do not show warnings
+The behavior of the interpreter may differs slightly from the compiler.
 
-`--stop-on-first-error`
-:   Stop on first error
+First, the interpreted is the reference implementation for the specification of the Nit language.
+That means if `nitg` and `nit` have a different behavior on a same program, it is likely that `nit` is right and `nitg` is wrong.
 
-`--no-color`
-:   Do not use color to display errors and warnings
+Second, the FFI is not yet implemented in the interpreter.
+Only a subset of the standard methods are implemented with some hard-coded behaviors.
+While it is enough to use most of the standard library, a lot of additional libraries may not be usable by the interpreter.
 
-`--log`
-:   Generate various log files
+Last, `nit` is the *Naive Interpretation Tool*, it means that it is slow and may take an average of 50.000% in overhead comparatively to `nitg`(it also means that `nitg` is fast).
+In practice, the slowness is not an issue for simple Nit scripts;
+it is not a big deal if `nit` takes  millisecond to execute programs even if `nitg` only need microseconds.
 
-`--log-dir`
-:   Directory where to generate log files
 
-`-h`, `-?`, `--help`
-:   Show Help (This screen)
+# OPTIONS
+
+Most options are the same than `nitg(1)`.
+Here, only the specific one are indicated.
+
+Note that, unlike in other Nit tools, the options *MUST* be indicated before the main module of a program.
+Whatever follows it is used as arguments of the interpreted program.
 
-`--version`
-:   Show version and exit
+    $ nit -e 'print args.first' -v
+    -v
 
-`--set-dummy-tool`
-:   Set toolname and version to DUMMY. Useful for testing
+## COMMAND
 
-`-v`, `--verbose`
-:   Verbose
+`-e`
+:   Specifies the program from command-line.
 
-`--bash-completion`
-:   Generate bash_completion file for this program
+    The `-e` option runs a program written on the command line.
+    Like with ruby, perl, bash and other script language.
 
-`--stub-man`
-:   Generate a stub manpage in pandoc markdown format
+        $ nit -e 'print 5+5'
+        10
 
-`--disable-phase`
-:   DEBUG: Disable a specific phase; use `list` to get the list.
+`-n`
+:   Repeatedly run the program for each line in file-name arguments.
 
-`-I`, `--path`
-:   Set include path for loaders (may be used more than once)
+    If no arguments are given, then `nit` iterates over the lines of the standard input (stdin).
 
-`--only-parse`
-:   Only proceed to parse step of loaders
+        $ echo "hello world" | nit -n -e 'print sys.line.capitalized'
+        Hello World
 
-`--only-metamodel`
-:   Stop after meta-model processing
+    If some arguments are given, then `nit` considers that each argument is a filepath then it iterates on their lines.
 
-`--ignore-visibility`
-:   Do not check, and produce errors, on visibility issues.
+## INTERPRETATION OPTIONS
 
 `--discover-call-trace`
-:   Trace calls of the first invocation of a method
+:   Trace calls of the first invocation of methods.
+
+    Each time a method is invoked for the first time, its information is printed on the standard output for error (`stderr`).
+
+    This option helps the user to have a simplified but humanly readable overview of the behavior of a particular program execution.
+
+## DEBUGGER OPTIONS
 
 `-d`
 :   Launches the target program with the debugger attached to it
@@ -82,17 +100,93 @@ nit [*options*]...
 `--port`
 :   Sets the debug port (Defaults to 22125) - Must be contained between 0 and 65535
 
+## OTHER OPTIONS
+
 `-o`
-:   compatibility (does noting)
+:   Does nothing. Used for compatibility.
 
-`-m`
-:   Additionals module to min-in
 
-`-e`
-:   Specifies the program from command-line
+# DEBUGGER
+
+To use use the debugger, launch your program using the nit interpreter `nit` with `-d` option.
+
+It is also possible to execute the program normally until an error is encountered using the `-c` option.
+
+A remote debugger is also available, it can be used with the client-side executable `nitdbg_client`.
+
+On the client side, the debugger works like the previous one, input some commands when debugging a program, except you have to launch the server before trying to debug.
+
+## DEBUGGER FEATURES
+
+When using a debugger, a must-have is the possibility to control execution of your program by stepping over, in and out of a line/snippet of code. The nit debugger allows you to do that.
+
+You can add/remove breakpoints on instructions, so that the execution will stop when the execution reaches the specified line of the specified file.
+
+When an error is encountered, the debugger gives you the chance of inputting commands before exiting.
+
+The debugger also gives the possibility of printing the values of the requested variables.
+
+The modification of variables at runtime is possible too, but only if the variables are of primitive types (until it becomes possible).
+
+Also, you probably won't want to type a long variable name every time you wish to print its value, the debugger has the possibility of setting aliases to replace the awfully long and cryptic name of that variable you try to access by a beautiful alias.
+
+If you want to trace the modifications or uses of a variable of your choice, the trace command will be perfect for you as it will print or break when encountering the variable of your choice.
+
+## DEBUGGER COMMANDS
+
+`n`
+:   Proceeds to the next instruction (step-over)
+
+`s`
+:   Steps in an instruction
+
+`finish`
+:   Steps out of an instruction
+
+`c`
+:   Continues the execution until a breakpoint is encountered or until an error/end of program
+
+`b/break line_number`
+:   Adds a breakpoint on line *line_number* for the current file
+
+`b/break file line_number`
+:   Adds a breakpoint on line *line_number* for the file *file* (Don't forget to add the .nit extension to the command)
+
+`d/delete line_number`
+:   Removes a breakpoint on line *line_number* for the current file
+
+`d/delete file line_number`
+:   Removes a breakpoint on line *line_number* for the file *file*
+
+`kill`
+:   Kills the current program (produces a stack trace)
+
+`variable = value`
+:   Sets the value of *variable* to *value* (Only supports primitive types for now : Bool, Char, Int, Float)
+
+`p/print variable_name`
+:   Prints the value of the variable *variable_name*
+
+`p/print stack`
+:   Prints a stack trace starting with the current frame
+
+`p/print variable_name[index]`
+:   Prints the value of the variable contained at the index *index* of variable *variable_name* (*variable_name* must be a subtype of SequenceRead)
+
+`p/print variable_name[index_from..index_to]`
+:   Prints the values of all the variables contained from index *index_from* up to *index_to* in the variable *variable_name*
+
+All the print commands also work on any dimension SequenceRead collection.
+
+`variable_name as alias`
+:   Sets an alias *alias* for the variable *variable_name*
+
+`trace variable_name [break/print]`
+:   Traces the uses of the variable you chose to trace by printing the statement it appears in or by breaking on each use. (The [break/print] part is not mandatory, by default, the print option will be used)
+
+`untrace variable_name`
+:   Removes the trace on the variable you chose to trace earlier in the program
 
-`-n`
-:   Repeatedly run the program for each line in file-name arguments
 
 # SEE ALSO
 
diff --git a/share/man/nitdbg_client.md b/share/man/nitdbg_client.md
new file mode 100644 (file)
index 0000000..52e2e32
--- /dev/null
@@ -0,0 +1,29 @@
+% NITDBG_CLIENT(1)
+
+# NAME
+
+nitdbg_client - network client for remote debugging.
+
+# SYNOPSIS
+
+nitdbg_client [*options*]...
+
+# DESCRIPTION
+
+`nitdbg_client` connects to a `nit` debugger server and controls it.
+
+See the interpreter command `nit(1)` for details about remote debugging.
+
+# OPTIONS
+
+`--host`
+:   Sets the host to debug from, use IPV4 only. (Defaults to 127.0.0.1).
+
+`--port`
+:   Sets the debug port (Defaults to 22125).
+
+    Must be contained between 0 and 65535
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
index d39c076..342a284 100644 (file)
@@ -2,91 +2,82 @@
 
 # NAME
 
-Generates HTML pages of API documentation from Nit source files.
+nitdoc - generates HTML pages of API documentation from Nit source files.
 
-# SYNOPSYS
+# SYNOPSIS
 
-nitdoc [*options*]...
+nitdoc [*options*]... FILE...
 
-# OPTIONS
+# DESCRIPTION
 
-`-W`, `--warn`
-:   Show more warnings
+`nitdoc` takes one or more modules and generate HTML pages of API documentation for these modules and their imported modules.
 
-`-w`, `--warning`
-:   Show/hide a specific warning
+The documentation is extracted from the comments found above the definition of modules, classes, and properties.
 
-`-q`, `--quiet`
-:   Do not show warnings
+Internally, `nitdoc` relies on the presence of the `dot` command from the [graphviz] project.
+If the dot program is not present or not found, no image of hierarchies are generated.
+See option `--no-dot`.
 
-`--stop-on-first-error`
-:   Stop on first error
+The documentation of the Nit [standard library] is generated with this tool.
 
-`--no-color`
-:   Do not use color to display errors and warnings
+  [graphviz]: http://www.graphviz.org
+  [standard library]: http://nitlanguage.org/doc/stdlib
 
-`--log`
-:   Generate various log files
+# DOCUMENTATION FORMAT
 
-`--log-dir`
-:   Directory where to generate log files
+The format of the documentation is a dialect of [markdown] that allows GitHub fences (`~~~`).
 
-`-h`, `-?`, `--help`
-:   Show Help (This screen)
+Code blocks are interpreted as snippets of Nit programs and intended to be used as examples of code.
+When these code snippets are valid, executable and contain at least and `assert` clause, they could be automatically executed and verified.
+See niunit(1) for details.
 
-`--version`
-:   Show version and exit
+  [markdown]: http://daringfireball.net/projects/markdown
 
-`--set-dummy-tool`
-:   Set toolname and version to DUMMY. Useful for testing
+# OPTIONS
 
-`-v`, `--verbose`
-:   Verbose
+`-d`, `--dir`
+:   output directory.
 
-`--bash-completion`
-:   Generate bash_completion file for this program
+    Where the HTML files are generated.
 
-`--stub-man`
-:   Generate a stub manpage in pandoc markdown format
+    By default, the directory is named `doc`.
 
-`--disable-phase`
-:   DEBUG: Disable a specific phase; use `list` to get the list.
+`--source`
+:   Format to link source code.
 
-`-I`, `--path`
-:   Set include path for loaders (may be used more than once)
+    The format string is used to generated links to some parts of the source-code.
+    Use `%f` for filename, `%l` for first line, and `%L` for last line.
 
-`--only-parse`
-:   Only proceed to parse step of loaders
+    For instance, the [standard library] use the following value to link to files in GitHub:
 
-`--only-metamodel`
-:   Stop after meta-model processing
+        "https://github.com/privat/nit/blob/$(git rev-parse HEAD)/%f#L%l-%L"
 
-`--ignore-visibility`
-:   Do not check, and produce errors, on visibility issues.
+    Here, the `git rev-parse HEAD` is used to link to the current snapshot revision of the file.
 
-`-d`, `--dir`
-:   output directory
+`--no-dot`
+:   do not generate graphs with graphviz.
 
-`--source`
-:   link for source (%f for filename, %l for first line, %L for last line)
+`--private`
+:   also generate private API.
+
+## CUSTOMIZATION
 
 `--sharedir`
-:   directory containing nitdoc assets
+:   directory containing nitdoc assets.
 
-`--shareurl`
-:   use shareurl instead of copy shared files
+    By default `$NIT_DIR/share/nitdoc/` is used.
 
-`--no-dot`
-:   do not generate graphes with graphviz
+`--shareurl`
+:   use shareurl instead of copy shared files.
 
-`--private`
-:   also generate private API
+    By default, assets from the sharedir a copied into the output directory and refered with a relative path in the generated files.
+    Whith this option, the assets are not copied and the given URL of path is used in the generated files to locate assets.
 
 `--custom-title`
-:   custom title for homepage
+:   custom title for homepage.
 
 `--custom-footer-text`
-:   custom footer text
+:   custom footer text.
 
 `--custom-overview-text`
 :   custom intro text for homepage
@@ -94,6 +85,8 @@ nitdoc [*options*]...
 `--custom-brand`
 :   custom link to external site
 
+## SERVICES
+
 `--github-upstream`
 :   Git branch where edited commits will be pulled into (ex: user:repo:branch)
 
@@ -104,7 +97,7 @@ nitdoc [*options*]...
 :   Git working directory used to resolve path name (ex: /home/me/myproject/)
 
 `--piwik-tracker`
-:   Piwik tracker URL (ex: nitlanguage.org/piwik/)
+:   Piwik tracker URL (ex: `"nitlanguage.org/piwik/"`)
 
 `--piwik-site-id`
 :   Piwik site ID
index 1c45f1d..f35be1c 100644 (file)
 
 # NAME
 
-Compiles Nit programs.
+nitg - compiles Nit programs.
 
-# SYNOPSYS
 
-nitg [*options*]...
+# SYNOPSIS
+
+nitg [*options*] FILE...
+
+
+# DESCRIPTION
+
+nitg is the current official Nit compiler.
+It takes the main module of a Nit program as argument and produces an executable file.
+
+By default, the generated executables are produced in the current directory.
+(see `--dir` for details.)
+
+Internally, nitg rely on the presence of a C compiler. Usually gcc (but nitg was successfully tested with clang).
+A compilation directory is therefore created and (re-)used.
+By default, the compilation directory is named `.nit_compile`.
+(see `--compile-dir` for details.)
+
+Currently, because Nit is still in heavy development, the compilation directory is not cleaned after the compilation.
+
+By default, the compilation process tries to have a good trade-off between the compilation time and the performance of produced executables.
+To produce more optimized executables, the current best option is `--semi-global`.
+
+To improve the compilation time and simplify the compilation of multiple programs, more than one file can be given.
+Each one will be compiled into a distinct executable.
+
+    $ nitg prog1.nit prog2.nit
+
+To combine files into a single program, use the `-m` option.
+
+    $ nitg prog1.nit -m other_module.nit
+
+nitg can produces executables for various platforms when specific modules are used.
+Currently, android, pnacl and emscripten are supported.
+See the documentation of these specific modules for details.
+
 
 # OPTIONS
 
+## MESSAGES
+
 `-W`, `--warn`
-:   Show more warnings
+:   Show additional warnings (advices).
+
+    By default, only important warnings are displayed.
+    May be overridden by `-w`.
+
+    Important warnings are displayed by default. A warning is considered important when:
+
+     * There is a simple correction.
+     * There is no reason to let the code this way.
+     * There is always a real issue (no false positive).
+
+    Other warnings, called advices, are not displayed by default to avoid filling the terminal with
+    unwanted information.
+    A warning is considered an advice when:
+
+     * The correction could be complex. e.g. require a refactorisation or an API change.
+     * The correction cannot be done. e.g. Code that use a deprecated API for some compatibility reason.
+     * There is not a real issue (false positive). Note that this should be unlikely.
+     * Transitional: While a real important warning, it fires a lot in current code, so a transition is needed
+       in order to let people fix them before promoting the advice to an important warning.
 
 `-w`, `--warning`
-:   Show/hide a specific warning
+:   Show/hide a specific warning.
+
+    Each type of warning can be individually displayed or hidden.
+    The `-w` option takes the name of a warning (displayed at the end of the warning message, between parentheses) to activate it;
+    and "no-{name}" to disable it.
+    It has precedence over -q and -W.
+    Multiple `-w` can be given.
+
+    To show only `missing-doc` warnings in standard"
+
+        $ nitg -q -w missing-doc standard
+
+    To show all warnings and advices, except `missing-doc`:
+
+        $ nitg -W -w no-missing-doc standard
+
+    To show important warnings except `useless-type-test`, but not advice except `missing-doc`:
+
+        $ nitg -w missing-doc -w no-useless-type-test standard
 
 `-q`, `--quiet`
-:   Do not show warnings
+:   Do not show warnings.
+    May be overridden by `-w`
 
 `--stop-on-first-error`
-:   Stop on first error
+:   Just display the first encountered error then stop.
+
+    By default, nitg tries to detect and display more than one error before aborting the compilation.
 
 `--no-color`
-:   Do not use color to display errors and warnings
+:   Do not use color to display errors and warnings.
+
+    Also, do not echo the line.
+    This options is mainly used by scripts and tools that need parsable error messages.
+
+`-v`, `--verbose`
+:   Additional messages from the tool.
+    Multiple `-v` can be given to improve the verbosity.
+
+    With one `-v`, there is constant number of lines.
+    With two `-v`, the number of lines is proportional to the number of modules.
+    With three `-v`, the number of lines is proportional to the number of definition of classes.
+    With four `-v`, the number of lines is proportional to the number of definition of properties.
 
 `--log`
-:   Generate various log files
+:   Generate various log files.
+    Currently unused.
 
 `--log-dir`
-:   Directory where to generate log files
+:   Directory where to generate log files.
+    Currently unused.
+
 
 `-h`, `-?`, `--help`
-:   Show Help (This screen)
+:   Show Help (the list of options).
 
 `--version`
-:   Show version and exit
+:   Show version and exit.
 
-`--set-dummy-tool`
-:   Set toolname and version to DUMMY. Useful for testing
 
-`-v`, `--verbose`
-:   Verbose
+## PATHS
 
-`--bash-completion`
-:   Generate bash_completion file for this program
+`-I`, `--path`
+:   Add an additional include path.
 
-`--stub-man`
-:   Generate a stub manpage in pandoc markdown format
+    This option is used to indicate an additional path of a directory containing Nit libraries.
 
-`--disable-phase`
-:   DEBUG: Disable a specific phase; use `list` to get the list.
+    The path added with `-I` are searched before those added by the environment variable `NIT_PATH`.
 
-`-I`, `--path`
-:   Set include path for loaders (may be used more than once)
+    May be used more than once.
 
-`--only-parse`
-:   Only proceed to parse step of loaders
+`-o`, `--output`
+:   Output executable name.
 
-`--only-metamodel`
-:   Stop after meta-model processing
+    Indicates the path and name of the produced executable.
 
-`--ignore-visibility`
-:   Do not check, and produce errors, on visibility issues.
+    Note: it is better to use `--dir` if only the directory is important.
+    This way, the platform extension will be correctly set.
 
-`-o`, `--output`
-:   Output file
+    `-o` is not usable if multiple programs are compiled at once.
 
 `--dir`
-:   Output directory
+:   Output directory.
 
-`--no-cc`
-:   Do not invoke C compiler
+    Produce the executables in the given directory instead of the current directory.
 
-`--no-main`
-:   Do not generate main entry point
+`--nit-dir`
+:   Base directory of the Nit installation.
 
-`--make-flags`
-:   Additional options to make
+    Has precedence over the environment variable `NIT_DIR`.
+
+## COMPILATION
 
 `--compile-dir`
-:   Directory used to generate temporary files
+:   Directory used to generate temporary files.
 
-`--hardening`
-:   Generate contracts in the C code against bugs in the compiler
+    By default, it is named `.nit_compile`.
 
-`--no-shortcut-range`
-:   Always insantiate a range and its iterator on 'for' loops
+`--no-cc`
+:   Do not invoke the C compiler.
 
-`--no-check-covariance`
-:   Disable type tests of covariant parameters (dangerous)
+    Files in the compilation directory are generated but the C compiler is not invoked.
 
-`--no-check-attr-isset`
-:   Disable isset tests before each attribute access (dangerous)
+    This option is mainly used to produce C files distributable then compilable on system that do not have a Nit compiler (e.g. embedded system).
+    In this case, it is suggested to also use the options `--dir`, `--compile-dir` and `--semi-global`.
 
-`--no-check-assert`
-:   Disable the evaluation of explicit 'assert' and 'as' (dangerous)
+        $ nitg examples/hello_world.nit --no-cc --dir hello --compile-dir hello --semi-global
 
-`--no-check-autocast`
-:   Disable implicit casts on unsafe expression usage (dangerous)
+    Will produce a `hello` directory that contains the required C files to finish the compilation.
+    Only the C files required for the program are generated.
+    The final binary will be generated in the same directory.
 
-`--no-check-null`
-:   Disable tests of null receiver (dangerous)
+`-m`
+:   Additional module to mix-in.
 
-`--no-check-all`
-:   Disable all tests (dangerous)
+    Additional modules are imported and refine the main module of the program.
+    This has basically the same effect than implementing a specific module that imports the main module of the program then each one of the mix-in modules.
+    May be used more than once.
 
-`--typing-test-metrics`
-:   Enable static and dynamic count of all type tests
+    This is option is used to weave additional behaviors to existing programs.
+    Modules designated to bring features to programs by refining basic or specialized services, without any intervention of the main program, are good candidates to be used with the `-m` option.
+    E.g. `hash_debug`.
 
-`--invocation-metrics`
-:   Enable static and dynamic count of all method invocations
+    An other usage of the `-m` option is to compile program to a specific platform. E.g. `emscripten`  or `android`.
 
-`--isset-checks-metrics`
-:   Enable static and dynamic count of isset checks before attributes access
+    A last usage is to develop programs as product lines with a main basic module (vanilla) and specific distinct features as flavor modules, then to combine them at compile-time.
 
-`--stacktrace`
-:   Control the generation of stack traces
+        $ nitg prog_vanilla.nit -m feature_chocolate.nit -m feature_cherry.nit
 
-`--no-gcc-directive`
-:   Disable a advanced gcc directives for optimization
+`-D`, `--define`
+:   Define a specific property.
+
+    The `-D` option allows to refine a top-level method at compile-time.
+    This has basically the same effect than implementing a specific module that imports the main module of the program and refines the designated methods.
+
+    The designated method must be top-level function with no parameters that returns a Bool, an Int or a String.
+
+    The argument of the `-D` option is "{name}={value}".
+    For Bool, the argument can also be just "{name}", in this case, the value is considered to be `true`.
+
+        $ nitg foo.nit -D prefix=/opt/foo -D port=8080 -D with_ssl
 
 `--release`
-:   Compile in release mode and finalize application
+:   Compile in release mode and finalize application.
 
-`--global`
-:   Use global compilation
+    Currently, this only affect the android platform.
+
+## COMPILATION MODES
+
+`nitg` includes distinct compilation modes.
 
 `--separate`
-:   Use separate compilation
+:   Use separate compilation (default mode).
 
-`--no-inline-intern`
-:   Do not inline call to intern methods
+    In separate compilation, modules are compiled independently of their programs.
+    This makes the recompilation of programs faster since only the modified files need to be recompiled.
 
-`--no-union-attribute`
-:   Put primitive attibutes in a box instead of an union
+`--global`
+:   Use global compilation.
 
-`--no-shortcut-equal`
-:   Always call == in a polymorphic way
+    The produced executables may become huge and the compilation time is prohibitive.
+    But sometime, they are faster.
+
+    In practice, `--semi-global` produces nearly as fast but smaller executables.
+
+`--erasure`
+:   Erase generic types.
+
+    Like `--separate` but use an erasure dynamic typing policy for generics and virtual types.
+    Usually you do not need this, even if you understand the previous sentence.
+
+
+## SEMI-GLOBAL OPTIMIZATIONS
+
+In `--separate` and in `--erasure` modes, some optimization can be gained by relaxing the constraint about
+the independence on programs.
+
+Therefore, with these options, the produced executables may be faster and smaller but the recompilation time
+will increase.
+
+`--semi-global`
+:   Enable all semi-global optimizations.
+
+`--rta`
+:   Activate RTA (Rapid Type Analysis).
+
+    This option only make sense in `--erasure` to enable some semi-global optimizations.
+
+    RTA is implicitly enabled in `--separate` and `--global`.
 
 `--inline-coloring-numbers`
-:   Inline colors and ids (semi-global)
+:   Inline colors and ids (semi-global).
 
 `--inline-some-methods`
-:   Allow the separate compiler to inline some methods (semi-global)
+:   Allow the separate compiler to inline some methods (semi-global).
+    Need `--rta`.
 
 `--direct-call-monomorph`
-:   Allow the separate compiler to direct call monomorph sites (semi-global)
+:   Allow the separate compiler to direct call monomorphic sites (semi-global).
+    Need `--rta`.
 
 `--skip-dead-methods`
-:   Do not compile dead methods (semi-global)
+:   Do not compile dead methods (semi-global).
+    Need `--rta`.
 
-`--semi-global`
-:   Enable all semi-global optimizations
+
+## DANGEROUS OPTIMIZATIONS
+
+The following optimizations disable runtime checks.
+It means that correct (non-buggy) programs may be slightly faster.
+It also means that incorrect (buggy) programs may have unspecified behaviors
+(e.g. formatting your hard drive or killing your cat).
+
+In fact, these options are mainly used to bench the compilation results.
+
+`--no-check-all`
+:   Disable all tests (dangerous).
+
+`--no-check-covariance`
+:   Disable type tests of covariant parameters (dangerous).
+
+`--no-check-attr-isset`
+:   Disable isset tests before each attribute access (dangerous).
+
+`--no-check-assert`
+:   Disable the evaluation of explicit `assert` and `as` (dangerous).
+
+`--no-check-autocast`
+:   Disable implicit casts on unsafe expression usage (dangerous).
+
+`--no-check-null`
+:   Disable tests of null receiver (dangerous).
+
+`--no-check-erasure-cast`
+:   Disable implicit casts on unsafe return with erasure-typing policy (dangerous).
+
+
+## UNOPTIMIZATIONS
+
+These options are used to debug or to bench the compilation results.
+Usually you do not need them since they make the generated code slower.
+
+`--hardening`
+:   Generate contracts in the C code against bugs in the compiler.
+
+`--no-shortcut-range`
+:   Always instantiate a range and its iterator on 'for' loops.
+
+`--no-union-attribute`
+:   Put primitive attributes in a box instead of an union.
+
+`--no-shortcut-equal`
+:   Always call == in a polymorphic way.
+
+`--no-inline-intern`
+:   Do not inline call to intern methods.
 
 `--colo-dead-methods`
-:   Force colorization of dead methods
+:   Force colorization of dead methods.
+
+`--no-gcc-directive`
+:   Disable advanced gcc directives for optimization.
+
+
+## INTERNAL OPTIONS
+
+These options can be used to control the fine behavior of the tool.
+They are useless for a normal user.
+
+`--disable-phase`
+:   Disable a specific phase; use `list` to get the list.
+
+`--only-parse`
+:   Only proceed to parse files.
+
+`--only-metamodel`
+:   Stop after meta-model processing.
+
+`--ignore-visibility`
+:   Do not check, and produce errors, on visibility issues.
+
+`--no-main`
+:   Do not generate main entry point.
+
+`--stacktrace`
+:   Control the generation of stack traces.
+
+`--max-c-lines`
+:   Maximum number of lines in generated C files. Use 0 for unlimited.
+
+`--group-c-files`
+:   Group all generated code in the same series of files.
+
+`--make-flags`
+:   Additional options to the `make` command.
+
+          $ nitg foo.nit --make-flags 'CC=clang' --make-flags 'CFLAGS="-O0 -g"'
+
+`--typing-test-metrics`
+:   Enable static and dynamic count of all type tests.
+
+`--invocation-metrics`
+:   Enable static and dynamic count of all method invocations.
+
+`--isset-checks-metrics`
+:   Enable static and dynamic count of isset checks before attributes access.
 
 `--tables-metrics`
-:   Enable static size measuring of tables used for vft, typing and resolution
+:   Enable static size measuring of tables used for vft, typing and resolution.
 
-`--erasure`
-:   Erase generic types
+`--set-dummy-tool`
+:   Set toolname and version to DUMMY. Useful for testing.
 
-`--no-check-erasure-cast`
-:   Disable implicit casts on unsafe return with erasure-typing policy (dangerous)
+`--bash-completion`
+:   Generate bash_completion file for this program.
 
-`--rta`
-:   Activate RTA (implicit with --global and --separate)
+`--stub-man`
+:   Generate a stub manpage in pandoc markdown format.
 
-`-m`
-:   Additionals module to min-in
+
+# ENVIRONMENT VARIABLES
+
+`NIT_DIR`
+:   Base directory of the Nit installation.
+
+    When the `NIT_DIR` environment variable is set then it specifies the path of the Nit install directory.
+
+    This directory is used to locate binaries, shared files and the common libraries.
+
+    When unset, the directory is guessed according to some heuristic.
+
+    The `--nit-dir` option also set the base directory of the Nit installation but has precedence.
+
+`NIT_PATH`
+:   Additional include paths.
+
+    The `NIT_PATH` environment variable contains paths of directories containing Nit libraries.
+    Each path is separated with a column (`:`).
+
+    The `-I` option also add additional paths.
+
+`NIT_GC_OPTION`
+:   Runtime control of the garbage collector.
+
+    The behavior of the GC of the executables produced by nitg can be tuned with this environment variable.
+
+    The environment variable is used when programs are executed, not when they are compiled.
+    Thus, you do not need to recompile programs in order to tweak their GC options.
+
+    Available values are:
+
+    * boehm: use the Boehm-Demers-Weiser's conservative garbage collector (default).
+    * malloc: disable the GC and just use `malloc` without doing any `free`.
+    * large: disable the GC and just allocate a large memory area to use for all instantiation.
+    * help: show the list of available options.
 
 # SEE ALSO
 
index 54b2896..517527f 100644 (file)
@@ -2,82 +2,52 @@
 
 # NAME
 
-Generates HTML of highlited code from Nit source files.
+nitlight - generates HTML of highlighted code from Nit source files.
 
-# SYNOPSYS
+# SYNOPSIS
 
-nitlight [*options*]...
+nitlight [*options*] FILE...
 
-# OPTIONS
-
-`-W`, `--warn`
-:   Show more warnings
-
-`-w`, `--warning`
-:   Show/hide a specific warning
-
-`-q`, `--quiet`
-:   Do not show warnings
-
-`--stop-on-first-error`
-:   Stop on first error
-
-`--no-color`
-:   Do not use color to display errors and warnings
+# DESCRIPTION
 
-`--log`
-:   Generate various log files
+Unlike generic lexical or syntactic highlighter, nitlight use semantic information on programs to improve the rendered result.
 
-`--log-dir`
-:   Directory where to generate log files
-
-`-h`, `-?`, `--help`
-:   Show Help (This screen)
-
-`--version`
-:   Show version and exit
-
-`--set-dummy-tool`
-:   Set toolname and version to DUMMY. Useful for testing
+# OPTIONS
 
-`-v`, `--verbose`
-:   Verbose
+Common options of the Nit tools are understood.
+Here, only the specific one are indicated.
 
-`--bash-completion`
-:   Generate bash_completion file for this program
+`-f`, `--fragment`
+:   Omit document header and footer.
 
-`--stub-man`
-:   Generate a stub manpage in pandoc markdown format
+    By default, a complete autonomous HTML document is generated.
+    If `-f` is given, only the inside of the body part is generated such that it could be integrated
+    into a HTML document.
 
-`--disable-phase`
-:   DEBUG: Disable a specific phase; use `list` to get the list.
+`--first-line`
+:   Start the source file at this line (default: 1).
 
-`-I`, `--path`
-:   Set include path for loaders (may be used more than once)
+    The generated HTML will only contains lines bellow the specified one.
 
-`--only-parse`
-:   Only proceed to parse step of loaders
+`--last-line`
+:   End the source file at this line (default: to the end)
 
-`--only-metamodel`
-:   Stop after meta-model processing
+    The generated HTML will only contains lines ebove the specified one.
 
-`--ignore-visibility`
-:   Do not check, and produce errors, on visibility issues.
+`-d`, `--dir`
+:   Output html files in a specific directory (required if more than one module).
 
-`-f`, `--fragment`
-:   Omit document header and footer
+    By default the generated HTML is outputted on the screen.
+    If this option is used, then HTML files are generated in the specified directory.
 
-`--first-line`
-:   Start the source file at this line (default: 1)
+    A basic `index.heml` and a `style.css` file are also generated in the directory.
 
-`--last-line`
-:   End the source file at this line (default: to the end)
+`--full`
+:   Process also imported modules.
 
-`-d`, `--dir`
-:   Output html files in a specific directory (required if more than one module)
+    By default, only the modules indicated on the command line are highlighted.
 
-`--full`
-:   Process also imported modules
+    With the `--full` option, all imported modules (even those in standard) are also precessed.
 
 # SEE ALSO
 
index 705a099..2d1f0a7 100644 (file)
@@ -2,91 +2,78 @@
 
 # NAME
 
-Lists the projects and/or paths of Nit sources files.
+nitls - lists the projects, groups and paths of Nit sources files.
 
-# SYNOPSYS
+# SYNOPSIS
 
-nitls [*options*]...
+nitls [*options*] FILE...
 
-# OPTIONS
+# DESCRIPTION
 
-`-W`, `--warn`
-:   Show more warnings
+`nitls` is used to list Nit files in directories and extract the module-group-project relation.
 
-`-w`, `--warning`
-:   Show/hide a specific warning
+It is basically a `ls` or a simple `find` specialized on `.nit` source files.
 
-`-q`, `--quiet`
-:   Do not show warnings
+# EXAMPLES
 
-`--stop-on-first-error`
-:   Stop on first error
+Show the tree of modules from the current directory and subdirectories.
 
-`--no-color`
-:   Do not use color to display errors and warnings
+    $ nitls -t -r .
 
-`--log`
-:   Generate various log files
+Show the list of projects imported by the modules of the current directory.
 
-`--log-dir`
-:   Directory where to generate log files
+    $ nitls -d -P *.nit
 
-`-h`, `-?`, `--help`
-:   Show Help (This screen)
+# OPTIONS
 
-`--version`
-:   Show version and exit
+## COLLECT
 
-`--set-dummy-tool`
-:   Set toolname and version to DUMMY. Useful for testing
+`-r`, `--recursive`
+:   Process directories recursively.
 
-`-v`, `--verbose`
-:   Verbose
+    All `.nit` files found in the specified directory and subdirectories are considered.
 
-`--bash-completion`
-:   Generate bash_completion file for this program
+`-d`, `--depends`
+:   List dependencies of given modules
 
-`--stub-man`
-:   Generate a stub manpage in pandoc markdown format
+    All imported modules are also considered.
 
-`--disable-phase`
-:   DEBUG: Disable a specific phase; use `list` to get the list.
+`-k`, `--keep`
+:   Ignore errors and files that are not a Nit source file.
 
-`-I`, `--path`
-:   Set include path for loaders (may be used more than once)
+    When a file that is not a valit Nit module is encoutered, it is ignored and the rest of the file are
+    processed.
 
-`--only-parse`
-:   Only proceed to parse step of loaders
+    Without this option, a error message is displayed and nitls terminates on such a case.
 
-`--only-metamodel`
-:   Stop after meta-model processing
+## PRESENTATION MODE
 
-`--ignore-visibility`
-:   Do not check, and produce errors, on visibility issues.
+Three presentation modes are available.
 
-`-k`, `--keep`
-:   Ignore errors and files that are not a Nit source file
+`-P`, `--project`
+:   List projects in a flat list (default).
 
-`-r`, `--recursive`
-:   Process directories recussively
+    Only project are displayed (and not the individual files).
 
 `-t`, `--tree`
-:   List source files in their groups and projects
+:   List source files in their groups and projects.
+
+    Each `.nit` file is presented in a tree of projects and groups.
 
 `-s`, `--source`
-:   List source files
+:   List source files in a flat list.
 
-`-P`, `--project`
-:   List projects paths (default)
+    Each `.nit` file is presented indivitually.
 
-`-d`, `--depends`
-:   List dependencies of given modules
+## PRESENTATION OPTIONS
 
 `-p`, `--path`
-:   List only path (instead of name + path)
+:   List only path (instead of name + path).
 
 `-M`
-:   List dependencies suitable for a rule in a Makefile. Alias for -d, -p and -s
+:   List dependencies suitable for a rule in a Makefile.
+
+    Alias for `-d`, `-p` and `-s`.
 
 # SEE ALSO
 
index 5aeb779..9b01489 100644 (file)
@@ -2,67 +2,15 @@
 
 # NAME
 
-Computes various metrics on Nit programs.
+nitmetrics -- computes various metrics on Nit programs.
 
-# SYNOPSYS
+# SYNOPSIS
 
-nitmetrics [*options*]...
+nitmetrics [*options*]... FILE...
 
 # OPTIONS
 
-`-W`, `--warn`
-:   Show more warnings
-
-`-w`, `--warning`
-:   Show/hide a specific warning
-
-`-q`, `--quiet`
-:   Do not show warnings
-
-`--stop-on-first-error`
-:   Stop on first error
-
-`--no-color`
-:   Do not use color to display errors and warnings
-
-`--log`
-:   Generate various log files
-
-`--log-dir`
-:   Directory where to generate log files
-
-`-h`, `-?`, `--help`
-:   Show Help (This screen)
-
-`--version`
-:   Show version and exit
-
-`--set-dummy-tool`
-:   Set toolname and version to DUMMY. Useful for testing
-
-`-v`, `--verbose`
-:   Verbose
-
-`--bash-completion`
-:   Generate bash_completion file for this program
-
-`--stub-man`
-:   Generate a stub manpage in pandoc markdown format
-
-`--disable-phase`
-:   DEBUG: Disable a specific phase; use `list` to get the list.
-
-`-I`, `--path`
-:   Set include path for loaders (may be used more than once)
-
-`--only-parse`
-:   Only proceed to parse step of loaders
-
-`--only-metamodel`
-:   Stop after meta-model processing
-
-`--ignore-visibility`
-:   Do not check, and produce errors, on visibility issues.
+## METRICS
 
 `--all`
 :   Compute all metrics
@@ -100,20 +48,22 @@ nitmetrics [*options*]...
 `--rta`
 :   Compute RTA metrics
 
-`--csv`
-:   Export metrics in CSV format
-
 `--generate_hyperdoc`
 :   Generate Hyperdoc
 
 `--poset`
 :   Complete metrics on posets
 
+## OUTPUT
+
+`--csv`
+:   Also export metrics in CSV format.
+
 `-d`, `--dir`
-:   Directory where some statistics files are generated
+:   Directory where some statistics files are generated.
 
 `--no-colors`
-:   Disable colors in console outputs
+:   Disable colors in console outputs.
 
 # SEE ALSO
 
index f852d27..001a6ce 100644 (file)
@@ -2,67 +2,21 @@
 
 # NAME
 
-Collect potential style and code issues.
+nitpick - collect potential style and code issues.
 
-# SYNOPSYS
+# SYNOPSIS
 
-nitpick [*options*]...
+nitpick [*options*] FILE...
 
-# OPTIONS
-
-`-W`, `--warn`
-:   Show more warnings
-
-`-w`, `--warning`
-:   Show/hide a specific warning
-
-`-q`, `--quiet`
-:   Do not show warnings
-
-`--stop-on-first-error`
-:   Stop on first error
-
-`--no-color`
-:   Do not use color to display errors and warnings
-
-`--log`
-:   Generate various log files
-
-`--log-dir`
-:   Directory where to generate log files
+# DESCRIPTION
 
-`-h`, `-?`, `--help`
-:   Show Help (This screen)
+`nitpick` is a fast code checker.
 
-`--version`
-:   Show version and exit
+It is currently used with the vim syntactic plugin.
 
-`--set-dummy-tool`
-:   Set toolname and version to DUMMY. Useful for testing
-
-`-v`, `--verbose`
-:   Verbose
-
-`--bash-completion`
-:   Generate bash_completion file for this program
-
-`--stub-man`
-:   Generate a stub manpage in pandoc markdown format
-
-`--disable-phase`
-:   DEBUG: Disable a specific phase; use `list` to get the list.
-
-`-I`, `--path`
-:   Set include path for loaders (may be used more than once)
-
-`--only-parse`
-:   Only proceed to parse step of loaders
-
-`--only-metamodel`
-:   Stop after meta-model processing
+# OPTIONS
 
-`--ignore-visibility`
-:   Do not check, and produce errors, on visibility issues.
+Only common options of the Nit tools are understood.
 
 # SEE ALSO
 
index 3238ced..5fac6a4 100644 (file)
@@ -2,68 +2,14 @@
 
 # NAME
 
-Pretty print Nit code from Nit source files.
+nitpretty - pretty print Nit code from Nit source files.
 
-# SYNOPSYS
+# SYNOPSIS
 
-nitpretty [*options*]...
+nitpretty [*options*]... FILE
 
 # OPTIONS
 
-`-W`, `--warn`
-:   Show more warnings
-
-`-w`, `--warning`
-:   Show/hide a specific warning
-
-`-q`, `--quiet`
-:   Do not show warnings
-
-`--stop-on-first-error`
-:   Stop on first error
-
-`--no-color`
-:   Do not use color to display errors and warnings
-
-`--log`
-:   Generate various log files
-
-`--log-dir`
-:   Directory where to generate log files
-
-`-h`, `-?`, `--help`
-:   Show Help (This screen)
-
-`--version`
-:   Show version and exit
-
-`--set-dummy-tool`
-:   Set toolname and version to DUMMY. Useful for testing
-
-`-v`, `--verbose`
-:   Verbose
-
-`--bash-completion`
-:   Generate bash_completion file for this program
-
-`--stub-man`
-:   Generate a stub manpage in pandoc markdown format
-
-`--disable-phase`
-:   DEBUG: Disable a specific phase; use `list` to get the list.
-
-`-I`, `--path`
-:   Set include path for loaders (may be used more than once)
-
-`--only-parse`
-:   Only proceed to parse step of loaders
-
-`--only-metamodel`
-:   Stop after meta-model processing
-
-`--ignore-visibility`
-:   Do not check, and produce errors, on visibility issues.
-
 `--dir`
 :   Working directory (default is '.nitpretty')
 
index 056b692..15ad1d3 100644 (file)
@@ -2,11 +2,11 @@
 
 # NAME
 
-Generates a serialization support module
+nitserial - generates a serialization support module
 
-# SYNOPSYS
+# SYNOPSIS
 
-nitserial [*options*]...
+nitserial [*options*]... FILE
 
 # OPTIONS
 
@@ -16,60 +16,6 @@ nitserial [*options*]...
 `--dir`
 :   Output directory
 
-`-W`, `--warn`
-:   Show more warnings
-
-`-w`, `--warning`
-:   Show/hide a specific warning
-
-`-q`, `--quiet`
-:   Do not show warnings
-
-`--stop-on-first-error`
-:   Stop on first error
-
-`--no-color`
-:   Do not use color to display errors and warnings
-
-`--log`
-:   Generate various log files
-
-`--log-dir`
-:   Directory where to generate log files
-
-`-h`, `-?`, `--help`
-:   Show Help (This screen)
-
-`--version`
-:   Show version and exit
-
-`--set-dummy-tool`
-:   Set toolname and version to DUMMY. Useful for testing
-
-`-v`, `--verbose`
-:   Verbose
-
-`--bash-completion`
-:   Generate bash_completion file for this program
-
-`--stub-man`
-:   Generate a stub manpage in pandoc markdown format
-
-`--disable-phase`
-:   DEBUG: Disable a specific phase; use `list` to get the list.
-
-`-I`, `--path`
-:   Set include path for loaders (may be used more than once)
-
-`--only-parse`
-:   Only proceed to parse step of loaders
-
-`--only-metamodel`
-:   Stop after meta-model processing
-
-`--ignore-visibility`
-:   Do not check, and produce errors, on visibility issues.
-
 # SEE ALSO
 
 The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
index 24d2e1e..4737fa9 100644 (file)
 
 # NAME
 
-Executes the unit tests from Nit source files.
+nitunit - executes the unit tests from Nit source files.
 
-# SYNOPSYS
+# SYNOPSIS
 
-nitunit [*options*]...
+nitunit [*options*] FILE...
 
-# OPTIONS
+# DESCRIPTION
+
+Unit testing in Nit can be achieved in two ways:
+
+* using `DocUnits` in code comments
+* using `TestSuites` with test unit files
+
+`DocUnits` are executable pieces of code found in the documentation of modules,
+classes and properties.
+They are used for documentation purpose, they should be kept simple and illustrative.
+More advanced unit testing can be done using TestSuites.
+
+`TestSuites` are test files coupled to a tested module.
+They contain a list of test methods called TestCase.
+
+## Working with `DocUnits`
+
+With DocUnits, executable code can be placed in comments of modules, classes and properties.
+The execution can be verified using `assert`
+
+Example with a class:
+
+    module foo
+    #    var foo = new Foo
+    #    assert foo.bar == 10
+    class Foo
+        var bar = 10
+    end
 
-`-W`, `--warn`
-:   Show more warnings
+Everything used in the test must be declared.
+To test a method you have to instantiate its class:
 
-`-w`, `--warning`
-:   Show/hide a specific warning
+    module foo
+    #    var foo = new Foo
+    #    assert foo.bar == 10
+    class Foo
+        #    var foo = new Foo
+        #    assert foo.baz(1, 2) == 3
+        fun baz(a, b: Int) do return a + b
+    end
 
-`-q`, `--quiet`
-:   Do not show warnings
+The `nitunit` command is used to test Nit files:
 
-`--stop-on-first-error`
-:   Stop on first error
+    $ nitunit foo.nit
 
-`--no-color`
-:   Do not use color to display errors and warnings
+## Working with `TestSuites`
 
-`--log`
-:   Generate various log files
+TestSuites are Nit files that define a set of TestCases for a particular module.
 
-`--log-dir`
-:   Directory where to generate log files
+The test suite must be called `test_` followed by the name of the module to test.
+So for the module `foo.nit` the test suite will be called `test_foo.nit`.
 
-`-h`, `-?`, `--help`
-:   Show Help (This screen)
+The structure of a test suite is the following:
 
-`--version`
-:   Show version and exit
+    # test suite for module `foo`
+    module test_foo
+    import foo # can be intrude to test private things
+    class TestFoo
+        # test case for `foo::Foo::baz`
+        fun test_baz do
+            var subject = new Foo
+            assert subject.baz(1, 2) == 3
+        end
+    end
 
-`--set-dummy-tool`
-:   Set toolname and version to DUMMY. Useful for testing
+Test suite can be executed using the same `nitunit` command:
 
-`-v`, `--verbose`
-:   Verbose
+    $ nitunit foo.nit
 
-`--bash-completion`
-:   Generate bash_completion file for this program
+`nitunit` will execute a test for each method named `test_*` in a class named `Test*`
+so multiple tests can be executed for a single method:
 
-`--stub-man`
-:   Generate a stub manpage in pandoc markdown format
+    class TestFoo
+        fun test_baz_1 do
+            var subject = new Foo
+            assert subject.baz(1, 2) == 3
+        end
+        fun test_baz_2 do
+            var subject = new Foo
+            assert subject.baz(1, -2) == -1
+        end
+    end
 
-`--disable-phase`
-:   DEBUG: Disable a specific phase; use `list` to get the list.
+`TestSuites` also provide methods to configure the test run:
 
-`-I`, `--path`
-:   Set include path for loaders (may be used more than once)
+`before_test` and `after_test`: methods called before/after each test case.
+They can be used to factorize repetitive tasks:
 
-`--only-parse`
-:   Only proceed to parse step of loaders
+    class TestFoo
+        var subject: Foo
+        # Mandatory empty init
+        init do end
+        # Method executed before each test
+        fun before_test do
+            subject = new Foo
+        end
+        fun test_baz_1 do
+            assert subject.baz(1, 2) == 3
+        end
+        fun test_baz_2 do
+            assert subject.baz(1, -2) == -1
+        end
+    end
+
+When using custom test attributes, an empty `init` must be declared to allow automatic test running.
+
+`before_module` and `after_module`: methods called before/after each test suite.
+They have to be declared at top level:
+
+    module test_bdd_connector
+    import bdd_connector
+    # Testing the bdd_connector
+    class TestConnector
+        # test cases using a server
+    end
+    # Method executed before testing the module
+    fun before_module do
+        # start server before all test cases
+    end
+    # Method executed after testing the module
+    fun after_module do
+        # stop server after all test cases
+    end
+
+## Generating test suites
+
+ Write test suites for big modules can be a repetitive and boring task...
+ To make it easier, `nitunit` can generate test skeletons for Nit modules:
+
+    $ nitunit --gen-suite foo.nit
+
+ This will generate the test suite `test_foo` containing test case stubs for all public
+ methods found in `foo.nit`.
 
-`--only-metamodel`
-:   Stop after meta-model processing
 
-`--ignore-visibility`
-:   Do not check, and produce errors, on visibility issues.
+# OPTIONS
 
 `--full`
-:   Process also imported modules
+:   Process also imported modules.
+
+    By default, only the modules indicated on the command line are tested.
+
+    With the `--full` option, all imported modules (even those in standard) are also precessed.
 
 `-o`, `--output`
 :   Output name (default is 'nitunit.xml')
 
+    `nitunit` produces a XML file comatible with JUnit.
+
 `--dir`
 :   Working directory (default is '.nitunit')
 
+    In order to execute the tests, nit files are generated then compiled and executed in the giver working directory.
+
 `--no-act`
-:   Does not compile and run tests
+:   Does not compile and run tests.
 
 `-p`, `--pattern`
-:   Only run test case with name that match pattern. Examples: 'TestFoo', 'TestFoo*', 'TestFoo::test_foo', 'TestFoo::test_foo*', 'test_foo', 'test_foo*'
+:   Only run test case with name that match pattern. Examples: `TestFoo`, `TestFoo*`, `TestFoo::test_foo`, `TestFoo::test_foo*`, `test_foo`, `test_foo*`
 
 `-t`, `--target-file`
 :   Specify test suite location.
 
+## SUITE GENERATION
+
 `--gen-suite`
 :   Generate test suite skeleton for a module
 
 `-f`, `--force`
-:   Force test generation even if file exists
+:   Force test generation even if file exists.
+
+    Any existing test suite will be overwritten.
 
 `--private`
-:   Also generate test case for private methods
+:   Also generate test case for private methods.
 
 `--only-show`
-:   Only display skeleton, do not write file
+:   Only display the skeleton, do not write any file.
 
 # SEE ALSO
 
index 73cee66..c655110 100644 (file)
@@ -2,67 +2,44 @@
 
 # NAME
 
-Displays specific pieces of API information from Nit source files.
+nitx - displays specific pieces of API information from Nit source files.
 
-# SYNOPSYS
+# SYNOPSIS
 
-nitx [*options*]...
+nitx [*options*] FILE [COMMAND]
 
-# OPTIONS
-
-`-W`, `--warn`
-:   Show more warnings
-
-`-w`, `--warning`
-:   Show/hide a specific warning
-
-`-q`, `--quiet`
-:   Do not show warnings
+# DESCRIPTION
 
-`--stop-on-first-error`
-:   Stop on first error
+`nitx` in an interactive tool that display information about programs and libraries.
 
-`--no-color`
-:   Do not use color to display errors and warnings
+A command that query some information can be given as and argument.
+This will immediately displays the information then terminates the programs.
 
-`--log`
-:   Generate various log files
+If no command are given, the program starts an interactive session where commands are entered until `:q` is given.
 
-`--log-dir`
-:   Directory where to generate log files
+# COMMANDS
 
-`-h`, `-?`, `--help`
-:   Show Help (This screen)
+`name`
+:   lookup module, class and property with the corresponding 'name'.
 
-`--version`
-:   Show version and exit
+`param: Type`
+:   lookup methods using the corresponding 'Type' as parameter.
 
-`--set-dummy-tool`
-:   Set toolname and version to DUMMY. Useful for testing
+`return: Type`
+:   lookup methods returning the corresponding 'Type'.
 
-`-v`, `--verbose`
-:   Verbose
+`new: Type`
+:   lookup methods creating new instances of 'Type'.
 
-`--bash-completion`
-:   Generate bash_completion file for this program
+`:h`
+:   display an help message about the commands.
 
-`--stub-man`
-:   Generate a stub manpage in pandoc markdown format
+`:q`
+:   exit the tool.
 
-`--disable-phase`
-:   DEBUG: Disable a specific phase; use `list` to get the list.
-
-`-I`, `--path`
-:   Set include path for loaders (may be used more than once)
-
-`--only-parse`
-:   Only proceed to parse step of loaders
-
-`--only-metamodel`
-:   Stop after meta-model processing
+# OPTIONS
 
-`--ignore-visibility`
-:   Do not check, and produce errors, on visibility issues.
+Only common options of the Nit tools are understood.
 
 # SEE ALSO
 
index 07934dd..b835f2a 100644 (file)
@@ -49,9 +49,9 @@ class CCompilationUnit
 
        fun add_local_function( efc : CFunction )
        do
-               body_decl.add( "{efc.signature};\n" )
-               body_impl.add( "\n" )
-               body_impl.add( efc.to_writer )
+               body_decl.add "static {efc.signature};\n"
+               body_impl.add "\n"
+               body_impl.add efc.to_writer
        end
 
        fun add_exported_function( efc : CFunction )
@@ -115,20 +115,17 @@ class ExternFile
        fun compiles_to_o_file: Bool do return false
 
        fun add_to_jar: Bool do return false
+
+       # Additional libraries needed for the compilation
+       # Will be used with pkg-config
+       var pkgconfigs = new Array[String]
 end
 
 # An extern C file to compile
 class ExternCFile
        super ExternFile
 
-       init (filename, cflags: String)
-       do
-               super filename
-
-               self.cflags = cflags
-       end
-
-       # Additionnal specific CC compiler -c flags
+       # Additional specific CC compiler -c flags
        var cflags: String
 
        redef fun hash do return filename.hash
@@ -143,7 +140,11 @@ class ExternCFile
        redef fun makefile_rule_content do
                var ff = filename.basename("")
                var o = makefile_rule_name
-               return "$(CC) $(CFLAGS) {self.cflags} -c -o {o} {ff}"
+               var pkg = ""
+               if not pkgconfigs.is_empty then
+                       pkg = "`pkg-config --cflags {pkgconfigs.join(" ")}`"
+               end
+               return "$(CC) $(CFLAGS) {self.cflags} {pkg} -c -o {o} {ff}"
        end
 
        redef fun compiles_to_o_file do return true
index e3c2fdf..16c0e4b 100644 (file)
@@ -34,8 +34,6 @@ redef class ToolContext
        var opt_no_cc = new OptionBool("Do not invoke C compiler", "--no-cc")
        # --no-main
        var opt_no_main = new OptionBool("Do not generate main entry point", "--no-main")
-       # --cc-paths
-       var opt_cc_path = new OptionArray("Set include path for C header files (may be used more than once)", "--cc-path")
        # --make-flags
        var opt_make_flags = new OptionString("Additional options to make", "--make-flags")
        # --max-c-lines
@@ -81,6 +79,8 @@ redef class ToolContext
                self.option_context.add_option(self.opt_no_gcc_directive)
                self.option_context.add_option(self.opt_release)
                self.option_context.add_option(self.opt_max_c_lines, self.opt_group_c_files)
+
+               opt_no_main.hidden = true
        end
 
        redef fun process_options(args)
@@ -151,43 +151,9 @@ end
 
 class MakefileToolchain
        super Toolchain
-       # The list of directories to search for included C headers (-I for C compilers)
-       # The list is initially set with :
-       #   * the toolcontext --cc-path option
-       #   * the NIT_CC_PATH environment variable
-       #   * `toolcontext.nit_dir`
-       # Path can be added (or removed) by the client
-       var cc_paths = new Array[String]
-
-       # The clib directory of Nit
-       # Used to found some common runtime
-       var clib: String is noinit
-
-       protected fun gather_cc_paths
-       do
-               # Look for the the Nit clib path
-               var path_env = toolcontext.nit_dir
-               if path_env != null then
-                       var libname = "{path_env}/clib"
-                       if not libname.file_exists then
-                               toolcontext.fatal_error(null, "Cannot determine the nit clib path. define envvar NIT_DIR.")
-                       end
-                       clib = libname
-               end
-
-               # Add user defined cc_paths
-               cc_paths.append(toolcontext.opt_cc_path.value)
-
-               path_env = "NIT_CC_PATH".environ
-               if not path_env.is_empty then
-                       cc_paths.append(path_env.split_with(':'))
-               end
-       end
 
        redef fun write_and_make(compiler)
        do
-               gather_cc_paths
-
                var compile_dir = compile_dir
 
                # Generate the .h and .c files
@@ -225,12 +191,14 @@ class MakefileToolchain
        do
                var platform = compiler.mainmodule.target_platform
                if self.toolcontext.opt_stacktrace.value == "nitstack" and (platform == null or platform.supports_libunwind) then compiler.build_c_to_nit_bindings
-               var cc_opt_with_libgc = "-DWITH_LIBGC `pkg-config --cflags bdw-gc`"
+               var cc_opt_with_libgc = "-DWITH_LIBGC"
                if platform != null and not platform.supports_libgc then cc_opt_with_libgc = ""
 
                # Add gc_choser.h to aditionnal bodies
                var gc_chooser = new ExternCFile("gc_chooser.c", cc_opt_with_libgc)
+               if cc_opt_with_libgc != "" then gc_chooser.pkgconfigs.add "bdw-gc"
                compiler.extern_bodies.add(gc_chooser)
+               var clib = toolcontext.nit_dir / "clib"
                compiler.files_to_copy.add "{clib}/gc_chooser.c"
                compiler.files_to_copy.add "{clib}/gc_chooser.h"
 
@@ -316,7 +284,7 @@ class MakefileToolchain
                self.toolcontext.info("Total C source files to compile: {cfiles.length}", 2)
        end
 
-       fun makefile_name(mainmodule: MModule): String do return "{mainmodule.name}.mk"
+       fun makefile_name(mainmodule: MModule): String do return "{mainmodule.c_name}.mk"
 
        fun default_outname(mainmodule: MModule): String
        do
@@ -352,18 +320,13 @@ class MakefileToolchain
                var makepath = "{compile_dir}/{makename}"
                var makefile = new OFStream.open(makepath)
 
-               var cc_includes = ""
-               for p in cc_paths do
-                       cc_includes += " -I \"" + p + "\""
-               end
-
                var linker_options = new HashSet[String]
                for m in mainmodule.in_importation.greaters do
                        var libs = m.collect_linker_libs
                        if libs != null then linker_options.add_all(libs)
                end
 
-               makefile.write("CC = ccache cc\nCXX = ccache c++\nCFLAGS = -g -O2 -Wno-unused-value -Wno-switch\nCINCL = {cc_includes}\nLDFLAGS ?= \nLDLIBS  ?= -lm `pkg-config --libs bdw-gc` {linker_options.join(" ")}\n\n")
+               makefile.write("CC = ccache cc\nCXX = ccache c++\nCFLAGS = -g -O2 -Wno-unused-value -Wno-switch\nCINCL =\nLDFLAGS ?= \nLDLIBS  ?= -lm {linker_options.join(" ")}\n\n")
 
                var ost = toolcontext.opt_stacktrace.value
                if (ost == "libunwind" or ost == "nitstack") and (platform == null or platform.supports_libunwind) then makefile.write("NEED_LIBUNWIND := YesPlease\n")
@@ -399,6 +362,28 @@ class MakefileToolchain
 
                var java_files = new Array[ExternFile]
 
+               var pkgconfigs = new Array[String]
+               for f in compiler.extern_bodies do
+                       pkgconfigs.add_all f.pkgconfigs
+               end
+               # Protect pkg-config
+               if not pkgconfigs.is_empty then
+                       makefile.write """
+# does pkg-config exists?
+ifneq ($(shell which pkg-config >/dev/null; echo $$?), 0)
+$(error "Command `pkg-config` not found. Please install it")
+endif
+"""
+                       for p in pkgconfigs do
+                               makefile.write """
+# Check for library {{{p}}}
+ifneq ($(shell pkg-config --exists '{{{p}}}'; echo $$?), 0)
+$(error "pkg-config: package {{{p}}} is not found.")
+endif
+"""
+                       end
+               end
+
                # Compile each required extern body into a specific .o
                for f in compiler.extern_bodies do
                        var o = f.makefile_rule_name
@@ -424,7 +409,11 @@ class MakefileToolchain
                end
 
                # Link edition
-               makefile.write("{outpath}: {dep_rules.join(" ")}\n\t$(CC) $(LDFLAGS) -o {outpath} {ofiles.join(" ")} $(LDLIBS)\n\n")
+               var pkg = ""
+               if not pkgconfigs.is_empty then
+                       pkg = "`pkg-config --libs {pkgconfigs.join(" ")}`"
+               end
+               makefile.write("{outpath}: {dep_rules.join(" ")}\n\t$(CC) $(LDFLAGS) -o {outpath} {ofiles.join(" ")} $(LDLIBS) {pkg}\n\n")
                # Clean
                makefile.write("clean:\n\trm {ofiles.join(" ")} 2>/dev/null\n\n")
                makefile.close
@@ -465,7 +454,7 @@ abstract class AbstractCompiler
        var mainmodule: MModule is writable
 
        # The real main module of the program
-       var realmainmodule: MModule
+       var realmainmodule: MModule is noinit
 
        # The modelbuilder used to know the model and the AST
        var modelbuilder: ModelBuilder is protected writable
@@ -473,11 +462,9 @@ abstract class AbstractCompiler
        # Is hardening asked? (see --hardening)
        fun hardening: Bool do return self.modelbuilder.toolcontext.opt_hardening.value
 
-       init(mainmodule: MModule, modelbuilder: ModelBuilder)
+       init
        do
-               self.mainmodule = mainmodule
                self.realmainmodule = mainmodule
-               self.modelbuilder = modelbuilder
        end
 
        # Force the creation of a new file
@@ -486,7 +473,7 @@ abstract class AbstractCompiler
        do
                if modelbuilder.toolcontext.opt_group_c_files.value then
                        if self.files.is_empty then
-                               var f = new CodeFile(mainmodule.name)
+                               var f = new CodeFile(mainmodule.c_name)
                                self.files.add(f)
                        end
                        return self.files.first
@@ -504,7 +491,7 @@ abstract class AbstractCompiler
        fun new_visitor: VISITOR is abstract
 
        # Where global declaration are stored (the main .h)
-       var header: CodeWriter is writable
+       var header: CodeWriter is writable, noinit
 
        # Provide a declaration that can be requested (before or latter) by a visitor
        fun provide_declaration(key: String, s: String)
@@ -1026,9 +1013,8 @@ class CodeWriter
        # (used for local or global declaration)
        fun add_decl(s: String) do self.decl_lines.add(s)
 
-       init(file: CodeFile)
+       init
        do
-               self.file = file
                file.writers.add(self)
        end
 end
@@ -1045,7 +1031,7 @@ abstract class AbstractCompilerVisitor
        var current_node: nullable ANode = null is writable
 
        # The current `Frame`
-       var frame: nullable Frame is writable
+       var frame: nullable Frame = null is writable
 
        # Alias for self.compiler.mainmodule.object_type
        fun object_type: MClassType do return self.compiler.mainmodule.object_type
@@ -1053,11 +1039,10 @@ abstract class AbstractCompilerVisitor
        # Alias for self.compiler.mainmodule.bool_type
        fun bool_type: MClassType do return self.compiler.mainmodule.bool_type
 
-       var writer: CodeWriter
+       var writer: CodeWriter is noinit
 
-       init(compiler: COMPILER)
+       init
        do
-               self.compiler = compiler
                self.writer = new CodeWriter(compiler.files.last)
        end
 
@@ -1641,11 +1626,8 @@ class RuntimeVariable
        # false (usual value) means that the variable is a mcasttype or a subtype.
        var is_exact: Bool = false is writable
 
-       init(name: String, mtype: MType, mcasttype: MType)
+       init
        do
-               self.name = name
-               self.mtype = mtype
-               self.mcasttype = mcasttype
                assert not mtype.need_anchor
                assert not mcasttype.need_anchor
        end
@@ -1715,7 +1697,7 @@ redef class MClassType
        do
                var res = self.c_name_cache
                if res != null then return res
-               res = "{mclass.intro_mmodule.name.to_cmangle}__{mclass.name.to_cmangle}"
+               res = "{mclass.intro_mmodule.c_name}__{mclass.name.to_cmangle}"
                self.c_name_cache = res
                return res
        end
@@ -1821,7 +1803,7 @@ redef class MClass
        fun c_name: String do
                var res = self.c_name_cache
                if res != null then return res
-               res = "{intro_mmodule.name.to_cmangle}__{name.to_cmangle}"
+               res = "{intro_mmodule.c_name}__{name.to_cmangle}"
                self.c_name_cache = res
                return res
        end
@@ -1849,7 +1831,7 @@ redef class MPropDef
        do
                var res = self.c_name_cache
                if res != null then return res
-               res = "{self.mclassdef.mmodule.name.to_cmangle}__{self.mclassdef.mclass.name.to_cmangle}__{self.mproperty.name.to_cmangle}"
+               res = "{self.mclassdef.mmodule.c_name}__{self.mclassdef.mclass.name.to_cmangle}__{self.mproperty.name.to_cmangle}"
                self.c_name_cache = res
                return res
        end
@@ -3033,6 +3015,19 @@ redef class Array[E]
 end
 
 redef class MModule
+       # Return the name of the global C identifier associated to `self`.
+       # This name is used to prefix files and other C identifiers associated with `self`.
+       var c_name: String is lazy do
+               var g = mgroup
+               var res
+               if g != null and g.mproject.name != name then
+                       res = g.mproject.name.to_cmangle + "__" + name.to_cmangle
+               else
+                       res = name.to_cmangle
+               end
+               return res
+       end
+
        # All `MProperty` associated to all `MClassDef` of `mclass`
        fun properties(mclass: MClass): Set[MProperty] do
                if not self.properties_cache.has_key(mclass) then
index 6fec966..55468fd 100644 (file)
@@ -205,8 +205,8 @@ $(call import-module,android/native_app_glue)
                # libpng is not available on Android NDK
                # FIXME make obtionnal when we have alternatives to mnit
                var nit_dir = toolcontext.nit_dir
-               var share_dir =  "{nit_dir or else ""}/share/"
-               if nit_dir == null or not share_dir.file_exists then
+               var share_dir =  nit_dir/"share/"
+               if not share_dir.file_exists then
                        print "Android project error: Nit share directory not found, please use the environment variable NIT_DIR"
                        exit 1
                end
index e447080..bf8dc30 100644 (file)
@@ -47,8 +47,7 @@ class POSetConflictGraph[E: Object]
 
        var poset: POSet[E]
 
-       init(poset: POSet[E]) do
-               self.poset = poset
+       init do
                extract_core
                extract_border
                extract_crown
@@ -331,11 +330,6 @@ class POSetBucketsColorer[H: Object, E: Object]
        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
index e9c740a..b6cb920 100644 (file)
@@ -53,7 +53,9 @@ extern void nitni_global_ref_decr(void*);
                nitni_ccu.write_as_nitni(self, v.compiler.modelbuilder.compile_dir)
 
                for file in nitni_ccu.files do
-                       v.compiler.extern_bodies.add(new ExternCFile(file, c_compiler_options))
+                       var f = new ExternCFile(file, c_compiler_options)
+                       f.pkgconfigs.add_all pkgconfigs
+                       v.compiler.extern_bodies.add(f)
                end
 
                # reset FFI things so the next compilation job, if any, starts with a clean context
@@ -118,21 +120,21 @@ redef class AMethPropdef
                                mtype.compile_extern_type(v, ccu)
 
                                # has callbacks already been compiled? (this may very well happen with global compilation)
-                               if mmodule.check_callback_compilation(mtype) then mtype.compile_extern_helper_functions(v, ccu)
+                               mtype.compile_extern_helper_functions(v, ccu, mmodule.check_callback_compilation(mtype))
                        end
                end
 
                # compile callbacks
-               for cb in foreign_callbacks.callbacks do if mainmodule.check_callback_compilation(cb) then
-                       cb.compile_extern_callback(v, ccu)
+               for cb in foreign_callbacks.callbacks do
+                       cb.compile_extern_callback(v, ccu, mainmodule.check_callback_compilation(cb))
                end
 
-               for cb in foreign_callbacks.supers do if mainmodule.check_callback_compilation(cb) then
-                       cb.compile_extern_callback(v, ccu)
+               for cb in foreign_callbacks.supers do
+                       cb.compile_extern_callback(v, ccu, mainmodule.check_callback_compilation(cb))
                end
 
-               for cb in foreign_callbacks.casts do if mainmodule.check_callback_compilation(cb) then
-                       cb.compile_extern_callbacks(v, ccu)
+               for cb in foreign_callbacks.casts do
+                       cb.compile_extern_callbacks(v, ccu, mainmodule.check_callback_compilation(cb))
                end
 
                # manage nitni callback set
@@ -310,7 +312,7 @@ redef class MType
                ccu.header_c_types.add("#endif\n")
        end
 
-       private fun compile_extern_helper_functions(v: AbstractCompilerVisitor, ccu: CCompilationUnit)
+       private fun compile_extern_helper_functions(v: AbstractCompilerVisitor, ccu: CCompilationUnit, compile_implementation_too: Bool)
        do
                # actually, we do not need to do anything when using the bohem garbage collector
                var call_context = from_c_call_context
@@ -328,7 +330,7 @@ redef class MType
 end
 
 redef class MNullableType
-       redef fun compile_extern_helper_functions(v, ccu)
+       redef fun compile_extern_helper_functions(v, ccu, compile_implementation_too)
        do
                super
 
@@ -342,6 +344,8 @@ redef class MNullableType
                # In nitni files, #define friendly as extern
                ccu.header_decl.add("#define {base_cname} {full_cname}\n")
 
+               if not compile_implementation_too then return
+
                # FIXME: This is ugly an broke the separate compilation principle
                # The real function MUST be compiled only once, #define pragma only protect the compiler, not the loader
                # However, I am not sure of the right approach here (eg. week refs are ugly)
@@ -362,7 +366,7 @@ redef class MNullableType
 end
 
 redef class MExplicitCall
-       private fun compile_extern_callback(v: AbstractCompilerVisitor, ccu: CCompilationUnit)
+       private fun compile_extern_callback(v: AbstractCompilerVisitor, ccu: CCompilationUnit, compile_implementation_too: Bool)
        do
                var mproperty = mproperty
                assert mproperty isa MMethod
@@ -371,6 +375,8 @@ redef class MExplicitCall
                var full_friendly_csignature = mproperty.build_csignature(recv_mtype, v.compiler.mainmodule, null, long_signature, internal_call_context)
                ccu.header_decl.add("extern {full_friendly_csignature};\n")
 
+               if not compile_implementation_too then return
+
                # Internally, implement internal function
                var nitni_visitor = v.compiler.new_visitor
                nitni_visitor.frame = v.frame
@@ -422,7 +428,7 @@ redef class MExplicitCall
 end
 
 redef class MExplicitSuper
-       private fun compile_extern_callback(v: AbstractCompilerVisitor, ccu: CCompilationUnit)
+       private fun compile_extern_callback(v: AbstractCompilerVisitor, ccu: CCompilationUnit, compile_implementation_too: Bool)
        do
                var mproperty = from.mproperty
                assert mproperty isa MMethod
@@ -437,6 +443,8 @@ redef class MExplicitSuper
                var internal_cname = mproperty.build_cname(mclass_type, v.compiler.mainmodule, "___super", long_signature)
                ccu.header_decl.add("#define {friendly_cname} {internal_cname}\n")
 
+               if not compile_implementation_too then return
+
                # Internally, implement internal function
                var nitni_visitor = v.compiler.new_visitor
                nitni_visitor.frame = v.frame
@@ -475,7 +483,7 @@ redef class MExplicitSuper
 end
 
 redef class MExplicitCast
-       private fun compile_extern_callbacks(v: AbstractCompilerVisitor, ccu: CCompilationUnit)
+       private fun compile_extern_callbacks(v: AbstractCompilerVisitor, ccu: CCompilationUnit, compile_implementation_too: Bool)
        do
                var from = from
                var to = to
@@ -491,22 +499,23 @@ redef class MExplicitCast
                # In nitni files, #define friendly as extern
                ccu.header_decl.add("#define {check_cname} {v.compiler.mainmodule.name}___{check_cname}\n")
 
-               # Internally, implement internal function
-               var nitni_visitor = v.compiler.new_visitor
-               nitni_visitor.frame = v.frame
+               if compile_implementation_too then
+                       # Internally, implement internal function
+                       var nitni_visitor = v.compiler.new_visitor
+                       nitni_visitor.frame = v.frame
 
-               var full_internal_csignature = "int {v.compiler.mainmodule.name }___{from.mangled_cname}_is_a_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
+                       var full_internal_csignature = "int {v.compiler.mainmodule.name }___{from.mangled_cname}_is_a_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
 
-               nitni_visitor.add_decl("/* nitni check for {from} to {to} */")
-               nitni_visitor.add_decl("{full_internal_csignature} \{")
+                       nitni_visitor.add_decl("/* nitni check for {from} to {to} */")
+                       nitni_visitor.add_decl("{full_internal_csignature} \{")
 
-               #var from_var = new RuntimeVariable("from->value", from, from)
-               var from_var = nitni_visitor.var_from_c("from", from)
-               from_var = nitni_visitor.box_extern(from_var, from)
-               var recv_var = nitni_visitor.type_test(from_var, to, "FFI isa")
-               nitni_visitor.add("return {recv_var};")
+                       var from_var = nitni_visitor.var_from_c("from", from)
+                       from_var = nitni_visitor.box_extern(from_var, from)
+                       var recv_var = nitni_visitor.type_test(from_var, to, "FFI isa")
+                       nitni_visitor.add("return {recv_var};")
 
-               nitni_visitor.add("\}")
+                       nitni_visitor.add("\}")
+               end
 
                # special checks
                if from == to.as_nullable then
@@ -525,30 +534,32 @@ redef class MExplicitCast
                # In nitni files, #define friendly as extern
                ccu.header_decl.add("#define {cast_cname} {v.compiler.mainmodule.name}___{cast_cname}\n")
 
-               # Internally, implement internal function
-               nitni_visitor = v.compiler.new_visitor
-               nitni_visitor.frame = v.frame
+               if compile_implementation_too then
+                       # Internally, implement internal function
+                       var nitni_visitor = v.compiler.new_visitor
+                       nitni_visitor.frame = v.frame
 
-               full_internal_csignature = "{to.cname_blind} {v.compiler.mainmodule.name }___{from.mangled_cname}_as_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
-               nitni_visitor.add_decl("/* nitni cast for {from} to {to} */")
-               nitni_visitor.add_decl("{full_internal_csignature} \{")
+                       var full_internal_csignature = "{to.cname_blind} {v.compiler.mainmodule.name }___{from.mangled_cname}_as_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
+                       nitni_visitor.add_decl("/* nitni cast for {from} to {to} */")
+                       nitni_visitor.add_decl("{full_internal_csignature} \{")
 
-               from_var = nitni_visitor.var_from_c("from", from)
-               from_var = nitni_visitor.box_extern(from_var, from)
+                       var from_var = nitni_visitor.var_from_c("from", from)
+                       from_var = nitni_visitor.box_extern(from_var, from)
 
-               ## test type
-               var check = nitni_visitor.type_test(from_var, to, "FFI cast")
-               nitni_visitor.add("if (!{check}) \{")
-               nitni_visitor.add_abort("FFI cast failed")
-               nitni_visitor.add("\}")
+                       ## test type
+                       var check = nitni_visitor.type_test(from_var, to, "FFI cast")
+                       nitni_visitor.add("if (!{check}) \{")
+                       nitni_visitor.add_abort("FFI cast failed")
+                       nitni_visitor.add("\}")
 
-               ## internal cast
-               recv_var = nitni_visitor.autobox(from_var, to)
-               recv_var = nitni_visitor.unbox_extern(recv_var, to)
+                       ## internal cast
+                       var recv_var = nitni_visitor.autobox(from_var, to)
+                       recv_var = nitni_visitor.unbox_extern(recv_var, to)
 
-               nitni_visitor.ret_to_c(recv_var, to)
+                       nitni_visitor.ret_to_c(recv_var, to)
 
-               nitni_visitor.add("\}")
+                       nitni_visitor.add("\}")
+               end
 
                # special casts
                if from.as_nullable == to then
index c594451..113b549 100644 (file)
@@ -114,12 +114,10 @@ class GlobalCompiler
        # The result of the RTA (used to know live types and methods)
        var runtime_type_analysis: RapidTypeAnalysis
 
-       init(mainmodule: MModule, modelbuilder: ModelBuilder, runtime_type_analysis: RapidTypeAnalysis)
+       init
        do
-               super(mainmodule, modelbuilder)
                var file = new_file("{mainmodule.name}.nitgg")
                self.header = new CodeWriter(file)
-               self.runtime_type_analysis = runtime_type_analysis
                self.live_primitive_types = new Array[MClassType]
                for t in runtime_type_analysis.live_types do
                        if t.ctype != "val*" or t.mclass.name == "Pointer" then
@@ -163,7 +161,7 @@ class GlobalCompiler
 
        # Subset of runtime_type_analysis.live_types that contains only primitive types
        # Used to implement the equal test
-       var live_primitive_types: Array[MClassType]
+       var live_primitive_types: Array[MClassType] is noinit
 
        # Add a new todo task
        fun todo(m: AbstractRuntimeFunction)
@@ -916,12 +914,6 @@ private class CustomizedRuntimeFunction
        # (usually is a live type but no strong guarantee)
        var recv: MClassType
 
-       init(mmethoddef: MMethodDef, recv: MClassType)
-       do
-               super(mmethoddef)
-               self.recv = recv
-       end
-
        redef fun build_c_name
        do
                var res = self.c_name_cache
index 216ccd5..491ebfe 100644 (file)
@@ -92,9 +92,11 @@ redef class ModelBuilder
                var compiler = new SeparateCompiler(mainmodule, self, runtime_type_analysis)
                compiler.compile_header
 
+               var c_name = mainmodule.c_name
+
                # compile class structures
                self.toolcontext.info("Property coloring", 2)
-               compiler.new_file("{mainmodule.name}.classes")
+               compiler.new_file("{c_name}.classes")
                compiler.do_property_coloring
                for m in mainmodule.in_importation.greaters do
                        for mclass in m.intro_mclasses do
@@ -104,21 +106,21 @@ redef class ModelBuilder
                end
 
                # The main function of the C
-               compiler.new_file("{mainmodule.name}.main")
+               compiler.new_file("{c_name}.main")
                compiler.compile_nitni_global_ref_functions
                compiler.compile_main_function
                compiler.compile_finalizer_function
 
                # compile methods
                for m in mainmodule.in_importation.greaters do
-                       self.toolcontext.info("Generate C for module {m}", 2)
-                       compiler.new_file("{m.name}.sep")
+                       self.toolcontext.info("Generate C for module {m.full_name}", 2)
+                       compiler.new_file("{m.c_name}.sep")
                        compiler.compile_module_to_c(m)
                end
 
                # compile live & cast type structures
                self.toolcontext.info("Type coloring", 2)
-               compiler.new_file("{mainmodule.name}.types")
+               compiler.new_file("{c_name}.types")
                var mtypes = compiler.do_type_coloring
                for t in mtypes do
                        compiler.compile_type_to_c(t)
@@ -156,17 +158,15 @@ 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_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]
+       private var type_ids: Map[MType, Int] is noinit
+       private var type_colors: Map[MType, Int] is noinit
+       private var opentype_colors: Map[MType, Int] is noinit
+       protected var method_colors: Map[PropertyLayoutElement, Int] is noinit
+       protected var attr_colors: Map[MAttribute, Int] is noinit
 
-       init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: nullable RapidTypeAnalysis) do
-               super(mainmodule, mmbuilder)
+       init do
                var file = new_file("nit.common")
                self.header = new CodeWriter(file)
-               self.runtime_type_analysis = runtime_type_analysis
                self.compile_box_kinds
        end
 
index 55844f6..233bf54 100644 (file)
@@ -67,9 +67,11 @@ redef class ModelBuilder
                var compiler = new SeparateErasureCompiler(mainmodule, self, runtime_type_analysis)
                compiler.compile_header
 
+               var c_name = mainmodule.c_name
+
                # compile class structures
                self.toolcontext.info("Property coloring", 2)
-               compiler.new_file("{mainmodule.name}.tables")
+               compiler.new_file("{c_name}.tables")
                compiler.do_property_coloring
                for m in mainmodule.in_importation.greaters do
                        for mclass in m.intro_mclasses do
@@ -79,14 +81,14 @@ redef class ModelBuilder
                compiler.compile_color_consts(compiler.vt_colors)
 
                # The main function of the C
-               compiler.new_file("{mainmodule.name}.main")
+               compiler.new_file("{c_name}.main")
                compiler.compile_nitni_global_ref_functions
                compiler.compile_main_function
 
                # compile methods
                for m in mainmodule.in_importation.greaters do
-                       self.toolcontext.info("Generate C for module {m}", 2)
-                       compiler.new_file("{m.name}.sep")
+                       self.toolcontext.info("Generate C for module {m.full_name}", 2)
+                       compiler.new_file("{m.c_name}.sep")
                        compiler.compile_module_to_c(m)
                end
 
@@ -101,12 +103,11 @@ end
 class SeparateErasureCompiler
        super SeparateCompiler
 
-       private var class_ids: Map[MClass, Int]
-       private var class_colors: Map[MClass, Int]
-       protected var vt_colors: Map[MVirtualTypeProp, Int]
+       private var class_ids: Map[MClass, Int] is noinit
+       private var class_colors: Map[MClass, Int] is noinit
+       protected var vt_colors: Map[MVirtualTypeProp, Int] is noinit
 
-       init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: nullable RapidTypeAnalysis) do
-               super
+       init do
 
                # Class coloring
                var poset = mainmodule.flatten_mclass_hierarchy
@@ -438,8 +439,8 @@ class SeparateErasureCompiler
 
        # Stats
 
-       private var class_tables: Map[MClass, Array[nullable MClass]]
-       private var vt_tables: Map[MClass, Array[nullable MPropDef]]
+       private var class_tables: Map[MClass, Array[nullable MClass]] is noinit
+       private var vt_tables: Map[MClass, Array[nullable MPropDef]] is noinit
 
        redef fun display_sizes
        do
index 41386d2..4141f75 100644 (file)
@@ -19,6 +19,11 @@ import model_utils
 import markdown
 import doc_templates
 import ordered_tree
+import model_ext
+
+
+################################################################################
+# Additions to Nit entities.
 
 redef class MDoc
        # Comment synopsys HTML escaped
@@ -714,3 +719,22 @@ redef class ConcernsTree
                li.append lst
        end
 end
+
+
+################################################################################
+# Additions to `model_ext`.
+
+redef class MRawType
+       redef fun tpl_signature do
+               var tpl = new Template
+
+               for part in parts do
+                       if part.target != null then
+                               tpl.add part.target.as(not null).tpl_link
+                       else
+                               tpl.add part.text.html_escape
+                       end
+               end
+               return tpl
+       end
+end
index 73ae262..5d71b02 100644 (file)
@@ -86,15 +86,9 @@ end
 
 # The Nitdoc class explores the model and generate pages for each mentities found
 class Nitdoc
+       var ctx: ToolContext
        var model: Model
        var mainmodule: MModule
-       var ctx: ToolContext
-
-       init(ctx: ToolContext, model: Model, mainmodule: MModule) do
-               self.ctx = ctx
-               self.model = model
-               self.mainmodule = mainmodule
-       end
 
        fun generate do
                init_output_dir
@@ -115,11 +109,7 @@ class Nitdoc
                var sharedir = ctx.opt_sharedir.value
                if sharedir == null then
                        var dir = ctx.nit_dir
-                       if dir == null then
-                               print "Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
-                               abort
-                       end
-                       sharedir = "{dir}/share/nitdoc"
+                       sharedir = dir/"share/nitdoc"
                        if not sharedir.file_exists then
                                print "Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
                                abort
@@ -127,9 +117,9 @@ class Nitdoc
                end
                # copy shared files
                if ctx.opt_shareurl.value == null then
-                       sys.system("cp -r {sharedir.to_s}/* {output_dir.to_s}/")
+                       sys.system("cp -r -- {sharedir.to_s.escape_to_sh}/* {output_dir.to_s.escape_to_sh}/")
                else
-                       sys.system("cp -r {sharedir.to_s}/resources/ {output_dir.to_s}/resources/")
+                       sys.system("cp -r -- {sharedir.to_s.escape_to_sh}/resources/ {output_dir.to_s.escape_to_sh}/resources/")
                end
 
        end
@@ -196,7 +186,10 @@ class QuickSearch
        private var mclasses = new HashSet[MClass]
        private var mpropdefs = new HashMap[String, Set[MPropDef]]
 
-       init(ctx: ToolContext, model: Model) do
+       var ctx: ToolContext
+       var model: Model
+
+       init do
                for mmodule in model.mmodules do
                        if mmodule.is_fictive then continue
                        mmodules.add mmodule
@@ -253,12 +246,6 @@ abstract class NitdocPage
        private var mainmodule: MModule
        private var name_sorter = new MEntityNameSorter
 
-       init(ctx: ToolContext, model: Model, mainmodule: MModule) do
-               self.ctx = ctx
-               self.model = model
-               self.mainmodule = mainmodule
-       end
-
        # Render the page as a html template
        fun render: Template do
                var shareurl = "."
@@ -324,14 +311,16 @@ abstract class NitdocPage
 
        # Clickable graphviz image using dot format
        # return null if no graph for this page
-       fun tpl_graph(dot: FlatBuffer, name: String, title: nullable String): nullable TplArticle do
+       fun tpl_graph(dot: Buffer, name: String, title: nullable String): nullable TplArticle do
                if ctx.opt_nodot.value then return null
                var output_dir = ctx.output_dir
-               var file = new OFStream.open("{output_dir}/{name}.dot")
+               var path = output_dir / name
+               var path_sh = path.escape_to_sh
+               var file = new OFStream.open("{path}.dot")
                file.write(dot)
                file.close
-               sys.system("\{ test -f {output_dir}/{name}.png && test -f {output_dir}/{name}.s.dot && diff {output_dir}/{name}.dot {output_dir}/{name}.s.dot >/dev/null 2>&1 ; \} || \{ cp {output_dir}/{name}.dot {output_dir}/{name}.s.dot && dot -Tpng -o{output_dir}/{name}.png -Tcmapx -o{output_dir}/{name}.map {output_dir}/{name}.s.dot ; \}")
-               var fmap = new IFStream.open("{output_dir}/{name}.map")
+               sys.system("\{ test -f {path_sh}.png && test -f {path_sh}.s.dot && diff -- {path_sh}.dot {path_sh}.s.dot >/dev/null 2>&1 ; \} || \{ cp -- {path_sh}.dot {path_sh}.s.dot && dot -Tpng -o{path_sh}.png -Tcmapx -o{path_sh}.map {path_sh}.s.dot ; \}")
+               var fmap = new IFStream.open("{path}.map")
                var map = fmap.read_all
                fmap.close
 
@@ -339,11 +328,12 @@ abstract class NitdocPage
                var alt = ""
                if title != null then
                        article.title = title
-                       alt = "alt='{title}'"
+                       alt = "alt='{title.html_escape}'"
                end
                article.css_classes.add "text-center"
                var content = new Template
-               content.add "<img src='{name}.png' usemap='#{name}' style='margin:auto' {alt}/>"
+               var name_html = name.html_escape
+               content.add "<img src='{name_html}.png' usemap='#{name_html}' style='margin:auto' {alt}/>"
                content.add map
                article.content = content
                return article
@@ -673,13 +663,11 @@ class NitdocGroup
 
        private var mgroup: MGroup
 
-       private var concerns: ConcernsTree
-       private var intros: Set[MClass]
-       private var redefs: Set[MClass]
+       private var concerns: ConcernsTree is noinit
+       private var intros: Set[MClass] is noinit
+       private var redefs: Set[MClass] is noinit
 
-       init(ctx: ToolContext, model: Model, mainmodule: MModule, mgroup: MGroup) do
-               super
-               self.mgroup = mgroup
+       init do
                self.concerns = model.concerns_tree(mgroup.collect_mmodules)
                self.concerns.sort_with(new MConcernRankSorter)
                self.intros = mgroup.in_nesting_intro_mclasses(ctx.min_visibility)
@@ -800,14 +788,12 @@ class NitdocModule
        super NitdocPage
 
        private var mmodule: MModule
-       private var concerns: ConcernsTree
-       private var mclasses2mdefs: Map[MClass, Set[MClassDef]]
-       private var mmodules2mclasses: Map[MModule, Set[MClass]]
+       private var concerns: ConcernsTree is noinit
+       private var mclasses2mdefs: Map[MClass, Set[MClassDef]] is noinit
+       private var mmodules2mclasses: Map[MModule, Set[MClass]] is noinit
 
 
-       init(ctx: ToolContext, model: Model, mainmodule: MModule, mmodule: MModule) do
-               super
-               self.mmodule = mmodule
+       init do
                var mclassdefs = new HashSet[MClassDef]
                mclassdefs.add_all mmodule.intro_mclassdefs(ctx.min_visibility)
                mclassdefs.add_all mmodule.redef_mclassdefs(ctx.min_visibility)
@@ -1009,17 +995,17 @@ class NitdocModule
                        end
                end
                # build graph
-               var op = new FlatBuffer
-               var name = "dep_{mmodule.name}"
-               op.append("digraph {name} \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
+               var op = new RopeBuffer
+               var name = "dep_module_{mmodule.nitdoc_id}"
+               op.append("digraph \"{name.escape_to_dot}\" \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
                for mmodule in poset do
                        if mmodule == self.mmodule then
-                               op.append("\"{mmodule.name}\"[shape=box,margin=0.03];\n")
+                               op.append("\"{mmodule.name.escape_to_dot}\"[shape=box,margin=0.03];\n")
                        else
-                               op.append("\"{mmodule.name}\"[URL=\"{mmodule.nitdoc_url}\"];\n")
+                               op.append("\"{mmodule.name.escape_to_dot}\"[URL=\"{mmodule.nitdoc_url.escape_to_dot}\"];\n")
                        end
                        for omodule in poset[mmodule].direct_greaters do
-                               op.append("\"{mmodule.name}\"->\"{omodule.name}\";\n")
+                               op.append("\"{mmodule.name.escape_to_dot}\"->\"{omodule.name.escape_to_dot}\";\n")
                        end
                end
                op.append("\}\n")
@@ -1043,13 +1029,11 @@ class NitdocClass
        super NitdocPage
 
        private var mclass: MClass
-       private var concerns: ConcernsTree
-       private var mprops2mdefs: Map[MProperty, Set[MPropDef]]
-       private var mmodules2mprops: Map[MModule, Set[MProperty]]
+       private var concerns: ConcernsTree is noinit
+       private var mprops2mdefs: Map[MProperty, Set[MPropDef]] is noinit
+       private var mmodules2mprops: Map[MModule, Set[MProperty]] is noinit
 
-       init(ctx: ToolContext, model: Model, mainmodule: MModule, mclass: MClass) do
-               super
-               self.mclass = mclass
+       init do
                var mpropdefs = new HashSet[MPropDef]
                mpropdefs.add_all mclass.intro_mpropdefs(ctx.min_visibility)
                mpropdefs.add_all mclass.redef_mpropdefs(ctx.min_visibility)
@@ -1392,9 +1376,9 @@ class NitdocClass
                        end
                end
 
-               var op = new FlatBuffer
-               var name = "dep_{mclass.name}"
-               op.append("digraph {name} \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
+               var op = new RopeBuffer
+               var name = "dep_class_{mclass.nitdoc_id}"
+               op.append("digraph \"{name.escape_to_dot}\" \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
                var classes = poset.to_a
                var todo = new Array[MClass]
                var done = new HashSet[MClass]
@@ -1405,18 +1389,18 @@ class NitdocClass
                        if done.has(c) then continue
                        done.add c
                        if c == mclass then
-                               op.append("\"{c.name}\"[shape=box,margin=0.03];\n")
+                               op.append("\"{c.name.escape_to_dot}\"[shape=box,margin=0.03];\n")
                        else
-                               op.append("\"{c.name}\"[URL=\"{c.nitdoc_url}\"];\n")
+                               op.append("\"{c.name.escape_to_dot}\"[URL=\"{c.nitdoc_url.escape_to_dot}\"];\n")
                        end
                        var smallers = poset[c].direct_smallers
                        if smallers.length < 10 then
                                for c2 in smallers do
-                                       op.append("\"{c2.name}\"->\"{c.name}\";\n")
+                                       op.append("\"{c2.name.escape_to_dot}\"->\"{c.name.escape_to_dot}\";\n")
                                end
                                todo.add_all smallers
                        else
-                               op.append("\"...\"->\"{c.name}\";\n")
+                               op.append("\"...\"->\"{c.name.escape_to_dot}\";\n")
                        end
                end
                op.append("\}\n")
@@ -1429,11 +1413,10 @@ class NitdocProperty
        super NitdocPage
 
        private var mproperty: MProperty
-       private var concerns: ConcernsTree
-       private var mmodules2mdefs: Map[MModule, Set[MPropDef]]
+       private var concerns: ConcernsTree is noinit
+       private var mmodules2mdefs: Map[MModule, Set[MPropDef]] is noinit
 
-       init(ctx: ToolContext, model: Model, mainmodule: MModule, mproperty: MProperty) do
-               super
+       init do
                self.mproperty = mproperty
                self.mmodules2mdefs = sort_by_mmodule(collect_mpropdefs)
                self.concerns = model.concerns_tree(mmodules2mdefs.keys)
index 516b17e..0e8f00b 100644 (file)
@@ -49,8 +49,6 @@ class TplPage
        # JS scripts to append at the end of the body
        var scripts = new Array[TplScript]
 
-       init do end
-
        # Add a section to this page
        fun add_section(section: TplSection) do
                sections.add section
@@ -162,10 +160,6 @@ class TplTopMenu
        # Used to select the active link.
        private var current_url: String
 
-       init(current_url: String) do
-               self.current_url = current_url
-       end
-
        # Add a new link to the menu.
        fun add_link(content: TplLink) do
                var is_active = content.href == current_url
@@ -272,18 +266,17 @@ class TplSideBox
        # Box HTML id
        # equals to `title.to_cmangle` by default
        # Used for collapsing
-       var id: String
+       var id: String is noinit
 
        # Content to display in the box
        # box will not be rendered if the content is null
-       var content: nullable Streamable is writable
+       var content: nullable Streamable = null is writable
 
        # Is the box opened by default
        # otherwise, the user will have to clic on the title to display the content
        var is_open = false is writable
 
-       init(title: String) do
-               self.title = title
+       init do
                self.id = title.to_cmangle
        end
 
@@ -358,8 +351,6 @@ class TplSummaryEntry
        # Will be displayed as a tree
        var children = new Array[TplSummaryElt]
 
-       init(text: Streamable) do self.text = text
-
        redef fun add_child(child) do children.add child
 
        redef fun rendering do
@@ -385,14 +376,14 @@ class TplSectionElt
        # Title to display if any
        # if both `title` and `summary_title` are null then
        # the section will not appear in the summary
-       var title: nullable Streamable is writable
+       var title: nullable Streamable = null is writable
 
        # Subtitle to display if any
-       var subtitle: nullable Streamable is writable
+       var subtitle: nullable Streamable = null is writable
 
        # Title that appear in the summary
        # if null use `title` instead
-       var summary_title: nullable String is writable
+       var summary_title: nullable String = null is writable
 
        # CSS classes to apply on the section element
        var css_classes = new Array[String]
@@ -401,9 +392,7 @@ class TplSectionElt
        var title_classes = new Array[String]
 
        # Parent article/section if any
-       var parent: nullable TplSectionElt
-
-       init(id: String) do self.id = id
+       var parent: nullable TplSectionElt = null
 
        init with_title(id: String, title: Streamable) do
                init(id)
@@ -660,12 +649,7 @@ class TplLink
        var text: Streamable is writable
 
        # Optional title
-       var title: nullable String is writable
-
-       init(href, text: String) do
-               self.href = href
-               self.text = text
-       end
+       var title: nullable String = null is writable
 
        init with_title(href, text, title: String) do
                init(href, text)
@@ -780,7 +764,7 @@ class TplTabPanel
        # The panel id.
        #
        # Used to show/hide panel.
-       var id: String
+       var id: String is noinit
 
        # The panel name.
        #
@@ -856,11 +840,6 @@ class TagAttribute
        var name: String
        var value: nullable String
 
-       init(name: String, value: nullable String) do
-               self.name = name
-               self.value = value
-       end
-
        redef fun rendering do
                var value = self.value
                if value == null then
@@ -902,12 +881,6 @@ class TplPiwikScript
        var tracker_url: String
        var site_id: String
 
-       init(tracker_url, site_id: String) do
-               super
-               self.tracker_url = tracker_url
-               self.site_id = site_id
-       end
-
        redef fun render_content do
                add "<!-- Piwik -->"
                add "var _paq = _paq || [];"
diff --git a/src/doc/model_ext.nit b/src/doc/model_ext.nit
new file mode 100644 (file)
index 0000000..fe74325
--- /dev/null
@@ -0,0 +1,98 @@
+# 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.
+
+# Extensions to the Nit model for foreign languages.
+module doc::model_ext
+
+intrude import model
+intrude import model::model_base
+
+# A type described by a text annoted with links.
+#
+# For use with Nitdoc only.
+class MRawType
+       super MType
+
+       redef var model: Model
+
+       # The parts that contitute the description of the type.
+       var parts: Sequence[MTypePart] = new Array[MTypePart]
+
+       redef fun as_nullable do
+               not_available
+               return self
+       end
+       redef fun need_anchor do
+               not_available
+               return false
+       end
+       redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do
+               not_available
+               return self
+       end
+       redef fun can_resolve_for(mtype, anchor, mmodule) do
+               not_available
+               return true
+       end
+       redef fun collect_mclassdefs(mmodule) do
+               not_available
+               return new HashSet[MClassDef]
+       end
+       redef fun collect_mclasses(mmodule) do
+               not_available
+               return new HashSet[MClass]
+       end
+       redef fun collect_mtypes(mmodule) do
+               not_available
+               return new HashSet[MClassType]
+       end
+
+       redef fun to_s do return parts.to_s
+
+       private fun not_available do
+               assert false else
+                       sys.stderr.write "A `MRawType` is for documentation-purpose only so the requested operation is not available.\n"
+               end
+       end
+end
+
+# A part of a `RawType`.
+class MTypePart
+       super MEntity
+
+       redef var model: Model
+
+       # The textual content.
+       var text: String
+
+       # If the part links to another entity, the targeted entity.
+       var target: nullable MEntity
+
+       redef fun name do return text
+       redef fun to_s do return text
+
+       # Return a version of `self` that links to the specified entity.
+       fun link_to(target: nullable MEntity): MTypePart do
+               return new MTypePart(model, text, target)
+       end
+end
+
+# The “package” visiblity.
+#
+# Any visibility roughly equivalent to the default visibility of Java, that is
+# private for a collection of modules.
+fun package_visibility: MVisibility do return once new MVisibility("package", 2)
+
+# A class kind with no equivalent semantic in Nit.
+fun raw_kind(s: String): MClassKind do return new MClassKind(s, false)
index 92697f5..6fba61a 100644 (file)
@@ -74,17 +74,16 @@ end
 redef class MModule
        var c_compiler_options = "" is writable
        var c_linker_options = "" is writable
+
+       # Additional libraries needed for the compilation
+       # Will be used with pkg-config
+       var pkgconfigs = new Array[String]
 end
 
 class ForeignCType
        super ForeignType
 
        redef var ctype: String
-
-       init(ctype: String)
-       do
-               self.ctype = ctype
-       end
 end
 
 redef class NitniCallback
@@ -114,7 +113,7 @@ end
 class ToCCallContext
        super CallContext
 
-       private init do end
+       # TODO: private init because singleton instance (see `to_c_call_context`)
 
        redef fun name_mtype(mtype)
        do
@@ -127,7 +126,7 @@ end
 class FromCCallContext
        super CallContext
 
-       private init do end
+       # TODO: private init because singleton instance (see `from_c_call_context`)
 
        redef fun name_mtype(mtype) do return mtype.cname
 end
index 1d82c0d..af4e938 100644 (file)
@@ -166,7 +166,6 @@ class DirectCCompilerOption
        super CCompilerOption
 
        var option: String
-       init (opt: String) do option = opt
 end
 
 class ExecCCompilerOption
@@ -174,10 +173,4 @@ class ExecCCompilerOption
 
        var command: Array[String]
        var exec_node: ACallExpr
-
-       init (command: Array[String], exec_node: ACallExpr)
-       do
-               self.command = command
-               self.exec_node = exec_node
-       end
 end
index f75c100..8ca389a 100644 (file)
@@ -103,7 +103,7 @@ class CPPLanguage
                end
                fc.exprs.add(mproperty.build_ccall(mclass_type, mmodule, "___cpp_impl", long_signature, cpp_call_context, "_for_cpp"))
                fc.exprs.add("\n")
-               mmodule.cpp_file.add_local_function(fc)
+               mmodule.cpp_file.add_exported_function(fc)
 
                # Custom C++, the body of the Nit C++ method is copied to its own C++ function
                var cpp_signature = mproperty.build_csignature(mclass_type, mmodule, "___cpp_impl", long_signature, cpp_call_context)
@@ -178,11 +178,6 @@ class ExternCppFile
        super ExternFile
 
        var mmodule: MModule
-       init(path: String, mmodule: MModule)
-       do
-               super
-               self.mmodule = mmodule
-       end
 
        redef fun makefile_rule_name do return "{filename.basename("")}.o"
        redef fun makefile_rule_content do return "$(CXX) $(CFLAGS) {mmodule.cpp_compiler_options} -c {filename.basename("")} -o {filename.basename("")}.o"
@@ -193,11 +188,6 @@ class ForeignCppType
        super ForeignType
 
        var cpp_type: String
-
-       init (cpp_type: String)
-       do
-               self.cpp_type = cpp_type
-       end
 end
 
 redef class NitniCallback
index a418616..a2dda26 100644 (file)
@@ -60,7 +60,11 @@ redef class MModule
                end
 
                ffi_ccu.write_as_impl(self, compdir)
-               for filename in ffi_ccu.files do ffi_files.add(new ExternCFile(filename, c_compiler_options))
+               for filename in ffi_ccu.files do
+                       var f = new ExternCFile(filename, c_compiler_options)
+                       f.pkgconfigs.add_all pkgconfigs
+                       ffi_files.add(f)
+               end
        end
 
        # Avoid the compile a ffi propdef more than once
index 3b53826..e470276 100644 (file)
@@ -99,7 +99,9 @@ end
 # Visitor for a specific languages. Works kinda like a `Phase` and is executed
 # by a `Phase`.
 class FFILanguage
-       init(ffi_language_assignation_phase: FFILanguageAssignationPhase)
+       var ffi_language_assignation_phase: FFILanguageAssignationPhase
+
+       init
        do
                ffi_language_assignation_phase.languages.add(self)
        end
index 49a880b..fa3cc84 100644 (file)
@@ -155,6 +155,8 @@ class JavaLanguage
                {{{block.code}}}
        }
 """
+
+               mmodule.callbacks_used_from_java.join m.foreign_callbacks
        end
 
        redef fun compile_extern_class(block, m, ccu, mmodule) do end
@@ -170,7 +172,7 @@ class JavaLanguage
                mmodule.insert_compiler_options
 
                # Enable linking C callbacks to java native methods
-               mmodule.ensure_linking_callback_methods(ffi_ccu.as(not null), mmodule.ffi_callbacks[self])
+               mmodule.ensure_linking_callback_methods(ffi_ccu.as(not null))
 
                # Java implementation code
                var java_file = mmodule.java_file
@@ -189,6 +191,7 @@ class JavaLanguage
 end
 
 redef class MModule
+       private var callbacks_used_from_java = new ForeignCallbackSet
 
        # Pure java class source file
        private var java_file: nullable JavaClassTemplate = null
@@ -203,8 +206,9 @@ redef class MModule
        end
 
        # Compile C code to call JNI and link C callbacks implementations to Java extern methods
-       private fun ensure_linking_callback_methods(ccu: CCompilationUnit, callbacks: Set[NitniCallback])
+       private fun ensure_linking_callback_methods(ccu: CCompilationUnit)
        do
+               var callbacks = callbacks_used_from_java.callbacks
                if callbacks.is_empty then
                        ccu.body_decl.add "static int nit_ffi_with_java_registered_natives = 1;\n"
                        return
@@ -217,7 +221,7 @@ redef class MModule
                        jni_methods.add_all(cb.jni_methods_declaration(self))
                end
 
-               var cf = new CFunction("static void nit_ffi_with_java_register_natives(JNIEnv* env, jclass jclazz)")
+               var cf = new CFunction("void nit_ffi_with_java_register_natives(JNIEnv* env, jclass jclazz)")
                cf.exprs.add """
        nit_ffi_with_java_registered_natives = 1;
 
@@ -330,7 +334,6 @@ class JavaClassTemplate
        super Template
 
        var java_class_name: String
-       init(name: String) do self.java_class_name = name
 
        var header = new Template
        var class_content = new Template
@@ -394,7 +397,6 @@ class ForeignJavaType
        super ForeignType
 
        var java_type: String
-       init (java_type: String) do self.java_type = java_type
 end
 
 redef class NitniCallback
@@ -413,6 +415,8 @@ end
 redef class MExplicitCall
        redef fun compile_callback_to_java(mmodule, mainmodule, ccu)
        do
+               if not mmodule.callbacks_used_from_java.callbacks.has(self) then return
+
                var mproperty = mproperty
                assert mproperty isa MMethod
 
index 335d8d1..dca4fab 100644 (file)
@@ -87,15 +87,7 @@ class PkgconfigPhase
                                return
                        end
 
-                       # compiler
-                       var proc = new IProcess("pkg-config", "--cflags", pkg)
-                       var compiler_opts = proc.read_all
-                       mmodule.c_compiler_options = "{mmodule.c_compiler_options} {compiler_opts.replace("\n", " ")}"
-
-                       # linker
-                       proc = new IProcess("pkg-config", "--libs", pkg)
-                       var linker_opts = proc.read_all
-                       mmodule.c_linker_options = "{mmodule.c_linker_options} {linker_opts.replace("\n", " ")}"
+                       mmodule.pkgconfigs.add pkg
                end
 
        end
index 9737245..4af7e46 100644 (file)
@@ -31,7 +31,7 @@ end
 private class CachedPhase
        super Phase
 
-       init(toolcontext, depends)
+       init
        do
                # FIXME The phase has to be executed just after `modelize_property_phase`
                # But there is no simple way to express this
index 5833009..4a8cfb4 100644 (file)
@@ -55,12 +55,6 @@ private class DivByZeroVisitor
        # The mmodule is the current module
        var mmodule: MModule
 
-       init(toolcontext: ToolContext, mmodule: MModule)
-       do
-               self.toolcontext = toolcontext
-               self.mmodule = mmodule
-       end
-
        redef fun visit(node)
        do
                # Recursively visit all sub-nodes
index 7f0427d..28b9127 100644 (file)
@@ -190,13 +190,6 @@ private class PreciseTypeVisitor
        var mclassdef: MClassDef
        var toolcontext: ToolContext
 
-       init(npropdef: AMethPropdef, mclassdef: MClassDef, toolcontext: ToolContext)
-       do
-               self.npropdef = npropdef
-               self.mclassdef = mclassdef
-               self.toolcontext = toolcontext
-       end
-
        redef fun visit(n) do n.accept_precise_type_visitor(self)
 end
 
index 9e3775d..c897ed9 100644 (file)
@@ -58,11 +58,6 @@ private class SimpleMiscVisitor
        do
                toolcontext.warning(node.hot_location, tag, msg)
        end
-
-       init(toolcontext: ToolContext)
-       do
-               self.toolcontext = toolcontext
-       end
 end
 
 
index 8723ed7..fc9ca2a 100644 (file)
@@ -65,7 +65,7 @@ end
 
 redef class ScopeVisitor
 
-       redef init(toolcontext)
+       redef init
        do
                super
                if toolcontext.dbg != null then
@@ -1442,16 +1442,11 @@ end
 private class TraceObject
 
        # Map of the local names bound to a frame
-       var trace_map: HashMap[Frame, String]
+       var trace_map = new HashMap[Frame, String]
+
        # Decides if breaking or printing statement when the variable is encountered
        var break_on_encounter: Bool
 
-       init(break_on_encounter: Bool)
-       do
-               trace_map = new HashMap[Frame, String]
-               self.break_on_encounter = break_on_encounter
-       end
-
        # Adds the local alias for a variable and the frame bound to it
        fun add_frame_variable(frame: Frame, variable_name: String)
        do
index e358b12..86bba5f 100644 (file)
@@ -67,15 +67,14 @@ class NaiveInterpreter
        var arguments: Array[String]
 
        # The main Sys instance
-       var mainobj: nullable Instance
+       var mainobj: nullable Instance is noinit
 
-       init(modelbuilder: ModelBuilder, mainmodule: MModule, arguments: Array[String])
+       init
        do
-               self.modelbuilder = modelbuilder
-               self.mainmodule = mainmodule
-               self.arguments = arguments
                self.true_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, true)
+               init_instance_primitive(self.true_instance)
                self.false_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, false)
+               init_instance_primitive(self.false_instance)
                self.null_instance = new MutableInstance(mainmodule.model.null_type)
        end
 
@@ -192,40 +191,47 @@ class NaiveInterpreter
        # Return the integer instance associated with `val`.
        fun int_instance(val: Int): Instance
        do
-               var ic = self.mainmodule.get_primitive_class("Int")
-               return new PrimitiveInstance[Int](ic.mclass_type, val)
+               var ic = get_primitive_class("Int")
+               var instance = new PrimitiveInstance[Int](ic.mclass_type, val)
+               init_instance_primitive(instance)
+               return instance
        end
 
        # Return the char instance associated with `val`.
        fun char_instance(val: Char): Instance
        do
-               var ic = self.mainmodule.get_primitive_class("Char")
-               return new PrimitiveInstance[Char](ic.mclass_type, val)
+               var ic = get_primitive_class("Char")
+               var instance = new PrimitiveInstance[Char](ic.mclass_type, val)
+               init_instance_primitive(instance)
+               return instance
        end
 
        # Return the float instance associated with `val`.
        fun float_instance(val: Float): Instance
        do
-               var ic = self.mainmodule.get_primitive_class("Float")
-               return new PrimitiveInstance[Float](ic.mclass_type, val)
+               var ic = get_primitive_class("Float")
+               var instance = new PrimitiveInstance[Float](ic.mclass_type, val)
+               init_instance_primitive(instance)
+               return instance
        end
 
        # The unique instance of the `true` value.
-       var true_instance: Instance
+       var true_instance: Instance is noinit
 
        # The unique instance of the `false` value.
-       var false_instance: Instance
+       var false_instance: Instance is noinit
 
        # The unique instance of the `null` value.
-       var null_instance: Instance
+       var null_instance: Instance is noinit
 
        # Return a new array made of `values`.
        # The dynamic type of the result is Array[elttype].
        fun array_instance(values: Array[Instance], elttype: MType): Instance
        do
                assert not elttype.need_anchor
-               var nat = new PrimitiveInstance[Array[Instance]](self.mainmodule.get_primitive_class("NativeArray").get_mtype([elttype]), values)
-               var mtype = self.mainmodule.get_primitive_class("Array").get_mtype([elttype])
+               var nat = new PrimitiveInstance[Array[Instance]](get_primitive_class("NativeArray").get_mtype([elttype]), values)
+               init_instance_primitive(nat)
+               var mtype = get_primitive_class("Array").get_mtype([elttype])
                var res = new MutableInstance(mtype)
                self.init_instance(res)
                self.send(self.force_get_primitive_method("with_native", mtype), [res, nat, self.int_instance(values.length)])
@@ -250,8 +256,10 @@ class NaiveInterpreter
        do
                var val = new FlatBuffer.from(txt)
                val.add('\0')
-               var ic = self.mainmodule.get_primitive_class("NativeString")
-               return new PrimitiveInstance[Buffer](ic.mclass_type, val)
+               var ic = get_primitive_class("NativeString")
+               var instance = new PrimitiveInstance[Buffer](ic.mclass_type, val)
+               init_instance_primitive(instance)
+               return instance
        end
 
        # Return a new String instance for `txt`
@@ -532,6 +540,16 @@ class NaiveInterpreter
                end
        end
 
+       # A hook to initialize a `PrimitiveInstance`
+       fun init_instance_primitive(recv: Instance) do end
+
+       # Return the primitive `MClass` corresponding to the `name` given in parameter
+       # `name` : name of the primitive class
+       fun get_primitive_class(name: String): MClass
+       do
+               return mainmodule.get_primitive_class(name)
+       end
+
        # This function determine the correct type according the reciever of the current definition (self).
        fun unanchor_type(mtype: MType): MType
        do
@@ -589,12 +607,6 @@ class PrimitiveInstance[E: Object]
        # The real value encapsulated
        redef var val: E
 
-       init(mtype: MType, val: E)
-       do
-               super(mtype)
-               self.val = val
-       end
-
        redef fun is_true
        do
                if val == true then return true
@@ -954,7 +966,9 @@ redef class AMethPropdef
                else if cname == "NativeArray" then
                        if pname == "new" then
                                var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
-                               return new PrimitiveInstance[Array[Instance]](args[0].mtype, val)
+                               var instance = new PrimitiveInstance[Array[Instance]](args[0].mtype, val)
+                               v.init_instance_primitive(instance)
+                               return instance
                        end
                        var recvval = args.first.val.as(Array[Instance])
                        if pname == "[]" then
@@ -973,17 +987,27 @@ redef class AMethPropdef
                        end
                else if cname == "NativeFile" then
                        if pname == "native_stdout" then
-                               return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, sys.stdout)
+                               var instance = new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, sys.stdout)
+                               v.init_instance_primitive(instance)
+                               return instance
                        else if pname == "native_stdin" then
-                               return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, sys.stdin)
+                               var instance = new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, sys.stdin)
+                               v.init_instance_primitive(instance)
+                               return instance
                        else if pname == "native_stderr" then
-                               return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, sys.stderr)
+                               var instance = new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, sys.stderr)
+                               v.init_instance_primitive(instance)
+                               return instance
                        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))
+                               var instance = new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, new IFStream.open(a1.to_s))
+                               v.init_instance_primitive(instance)
+                               return instance
                        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))
+                               var instance = new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, new OFStream.open(a1.to_s))
+                               v.init_instance_primitive(instance)
+                               return instance
                        end
                        var recvval = args.first.val
                        if pname == "io_write" then
@@ -1004,10 +1028,12 @@ redef class AMethPropdef
                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 = recvtype.supertype_to(v.mainmodule, recvtype, v.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)
+                       var instance = new PrimitiveInstance[Array[Instance]](v.get_primitive_class("NativeArray").get_mtype([mtype]), val)
+                       v.init_instance_primitive(instance)
+                       return instance
                else if pname == "native_argc" then
                        return v.int_instance(v.arguments.length)
                else if pname == "native_argv" then
@@ -1491,7 +1517,7 @@ redef class ASuperstringExpr
                        if i == null then return null
                        array.add(i)
                end
-               var i = v.array_instance(array, v.mainmodule.get_primitive_class("Object").mclass_type)
+               var i = v.array_instance(array, v.get_primitive_class("Object").mclass_type)
                var res = v.send(v.force_get_primitive_method("to_s", i.mtype), [i])
                assert res != null
                return res
index ef4851b..e39409f 100644 (file)
@@ -44,11 +44,6 @@ private class LiteralVisitor
 
        var toolcontext: ToolContext
 
-       init(toolcontext: ToolContext)
-       do
-               self.toolcontext = toolcontext
-       end
-
        redef fun visit(n)
        do
                n.accept_literal(self)
index c092b28..993ce7d 100644 (file)
@@ -23,12 +23,13 @@ class SourceFile
        var filename: String
 
        # The content of the source
-       var string: String
+       var string: String is noinit
 
-       # Create a new sourcefile using a filename and a stream
-       init(filename: String, stream: IStream)
+       # The original stream used to initialize `string`
+       var stream: IStream
+
+       init
        do
-               self.filename = filename
                string = stream.read_all
                line_starts[0] = 0
        end
@@ -56,14 +57,6 @@ class Location
        var column_start: Int
        var column_end: Int
 
-       init(f: nullable SourceFile, line_s: Int, line_e: Int, column_s: Int, column_e: Int) do
-               file = f
-               line_start = line_s
-               line_end = line_e
-               column_start = column_s
-               column_end = column_e
-       end
-
        # The index in the start character in the source
        fun pstart: Int do return file.line_starts[line_start-1] + column_start-1
 
@@ -83,7 +76,7 @@ class Location
                return res
        end
 
-       private var text_cache: nullable String
+       private var text_cache: nullable String = null
 
        init with_file(f: SourceFile) do init(f,0,0,0,0)
 
index e902b05..3522245 100644 (file)
@@ -53,12 +53,12 @@ do
                dot.mprojects.add(g.mproject)
        end
        var projectpath = toolcontext.output_dir.join_path("project_hierarchy.dot")
-       print "generating {projectpath}"
+       print "generating project_hierarchy.dot"
        dot.write_to_file(projectpath)
 
        var modulepath = toolcontext.output_dir.join_path("module_hierarchy.dot")
        dot.mprojects.add_all(model.mprojects)
-       print "generating {modulepath}"
+       print "generating module_hierarchy.dot"
        dot.write_to_file(modulepath)
 end
 
index 923923a..f2c11a6 100644 (file)
@@ -88,10 +88,10 @@ class MModule
        # The view of the module in the `model.mmodule_nesting_hierarchy`
        #
        # TODO REMOVE, rely on mgroup instead
-       var in_nesting: POSetElement[MModule]
+       var in_nesting: POSetElement[MModule] is noinit
 
        # The view of the module in the `model.mmodule_importation_hierarchy`
-       var in_importation: POSetElement[MModule]
+       var in_importation: POSetElement[MModule] is noinit
 
        # The canonical name of the module
        # Example: `"project::name"`
@@ -106,15 +106,11 @@ class MModule
        end
 
        # Create a new empty module and register it to a model
-       init(model: Model, mgroup: nullable MGroup, name: String, location: Location)
+       init
        do
-               self.model = model
-               self.name = name
-               self.location = location
                model.mmodules_by_name.add_one(name, self)
                model.mmodules.add(self)
                self.in_nesting = model.mmodule_nesting_hierarchy.add_node(self)
-               self.mgroup = mgroup
                if mgroup != null then
                        mgroup.mmodules.add(self)
                        if mgroup.name == name then
index d776cec..f5582d8 100644 (file)
@@ -362,35 +362,20 @@ class MClass
 
        # The number of generic formal parameters
        # 0 if the class is not generic
-       var arity: Int
+       var arity: Int is noinit
 
        # Each generic formal parameters in order.
        # is empty if the class is not generic
        var mparameters = new Array[MParameterType]
 
-       # The kind of the class (interface, abstract class, etc.)
-       # In Nit, the kind of a class cannot evolve in refinements
-       var kind: MClassKind
-
-       # The visibility of the class
-       # In Nit, the visibility of a class cannot evolve in refinements
-       var visibility: MVisibility
-
-       init(intro_mmodule: MModule, name: String, parameter_names: nullable Array[String], kind: MClassKind, visibility: MVisibility)
+       protected fun setup_parameter_names(parameter_names: nullable Array[String]) is
+               autoinit
        do
-               self.intro_mmodule = intro_mmodule
-               self.name = name
                if parameter_names == null then
                        self.arity = 0
                else
                        self.arity = parameter_names.length
                end
-               self.kind = kind
-               self.visibility = visibility
-               intro_mmodule.intro_mclasses.add(self)
-               var model = intro_mmodule.model
-               model.mclasses_by_name.add_one(name, self)
-               model.mclasses.add(self)
 
                # Create the formal parameter types
                if arity > 0 then
@@ -409,6 +394,22 @@ class MClass
                end
        end
 
+       # The kind of the class (interface, abstract class, etc.)
+       # In Nit, the kind of a class cannot evolve in refinements
+       var kind: MClassKind
+
+       # The visibility of the class
+       # In Nit, the visibility of a class cannot evolve in refinements
+       var visibility: MVisibility
+
+       init
+       do
+               intro_mmodule.intro_mclasses.add(self)
+               var model = intro_mmodule.model
+               model.mclasses_by_name.add_one(name, self)
+               model.mclasses.add(self)
+       end
+
        redef fun model do return intro_mmodule.model
 
        # All class definitions (introduction and refinements)
@@ -421,7 +422,7 @@ class MClass
        #
        # Warning: such a definition may not exist in the early life of the object.
        # In this case, the method will abort.
-       var intro: MClassDef
+       var intro: MClassDef is noinit
 
        # Return the class `self` in the class hierarchy of the module `mmodule`.
        #
@@ -447,7 +448,7 @@ class MClass
        # To get other types based on a generic class, see `get_mtype`.
        #
        # ENSURE: `mclass_type.mclass == self`
-       var mclass_type: MClassType
+       var mclass_type: MClassType is noinit
 
        # Return a generic type based on the class
        # Is the class is not generic, then the result is `mclass_type`
@@ -490,7 +491,7 @@ class MClassDef
        var mmodule: MModule
 
        # The associated `MClass`
-       var mclass: MClass
+       var mclass: MClass is noinit
 
        # The bounded type associated to the mclassdef
        #
@@ -509,14 +510,11 @@ class MClassDef
 
        # Internal name combining the module and the class
        # Example: "mymodule#MyClass"
-       redef var to_s: String
+       redef var to_s: String is noinit
 
-       init(mmodule: MModule, bound_mtype: MClassType, location: Location)
+       init
        do
-               self.bound_mtype = bound_mtype
-               self.mmodule = mmodule
                self.mclass = bound_mtype.mclass
-               self.location = location
                mmodule.mclassdefs.add(self)
                mclass.mclassdefs.add(self)
                if mclass.intro_mmodule == mmodule then
@@ -988,10 +986,7 @@ class MClassType
 
        redef fun model do return self.mclass.intro_mmodule.model
 
-       private init(mclass: MClass)
-       do
-               self.mclass = mclass
-       end
+       # TODO: private init because strongly bounded to its mclass. see `mclass.mclass_type`
 
        # The formal arguments of the type
        # ENSURE: `result.length == self.mclass.arity`
@@ -1081,11 +1076,13 @@ end
 class MGenericType
        super MClassType
 
-       private init(mclass: MClass, arguments: Array[MType])
+       redef var arguments
+
+       # TODO: private init because strongly bounded to its mclass. see `mclass.get_mtype`
+
+       init
        do
-               super(mclass)
                assert self.mclass.arity == arguments.length
-               self.arguments = arguments
 
                self.need_anchor = false
                for t in arguments do
@@ -1100,9 +1097,9 @@ class MGenericType
 
        # Recursively print the type of the arguments within brackets.
        # Example: `"Map[String, List[Int]]"`
-       redef var to_s: String
+       redef var to_s: String is noinit
 
-       redef var need_anchor: Bool
+       redef var need_anchor: Bool is noinit
 
        redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
        do
@@ -1243,11 +1240,6 @@ class MVirtualType
        end
 
        redef fun to_s do return self.mproperty.to_s
-
-       init(mproperty: MProperty)
-       do
-               self.mproperty = mproperty
-       end
 end
 
 # The type associated to a formal parameter generic type of a class
@@ -1372,13 +1364,6 @@ class MParameterType
                end
                return mtype.collect_mclassdefs(mmodule).has(mclass.intro)
        end
-
-       init(mclass: MClass, rank: Int, name: String)
-       do
-               self.mclass = mclass
-               self.rank = rank
-               self.name = name
-       end
 end
 
 # A type prefixed with "nullable"
@@ -1390,13 +1375,12 @@ class MNullableType
 
        redef fun model do return self.mtype.model
 
-       init(mtype: MType)
+       init
        do
-               self.mtype = mtype
                self.to_s = "nullable {mtype}"
        end
 
-       redef var to_s: String
+       redef var to_s: String is noinit
 
        redef fun need_anchor do return mtype.need_anchor
        redef fun as_nullable do return self
@@ -1441,10 +1425,6 @@ end
 class MNullType
        super MType
        redef var model: Model
-       protected init(model: Model)
-       do
-               self.model = model
-       end
        redef fun to_s do return "null"
        redef fun as_nullable do return self
        redef fun need_anchor do return false
@@ -1492,7 +1472,7 @@ class MSignature
        end
 
        # REQUIRE: 1 <= mparameters.count p -> p.is_vararg
-       init(mparameters: Array[MParameter], return_mtype: nullable MType)
+       init
        do
                var vararg_rank = -1
                for i in [0..mparameters.length[ do
@@ -1502,15 +1482,13 @@ class MSignature
                                vararg_rank = i
                        end
                end
-               self.mparameters = mparameters
-               self.return_mtype = return_mtype
                self.vararg_rank = vararg_rank
        end
 
        # The rank of the ellipsis (`...`) for vararg (starting from 0).
        # value is -1 if there is no vararg.
        # Example: for "(a: Int, b: Bool..., c: Char)" #-> vararg_rank=1
-       var vararg_rank: Int
+       var vararg_rank: Int is noinit
 
        # The number or parameters
        fun arity: Int do return mparameters.length
@@ -1568,12 +1546,6 @@ class MParameter
        # Is the parameter a vararg?
        var is_vararg: Bool
 
-       init(name: String, mtype: MType, is_vararg: Bool) do
-               self.name = name
-               self.mtype = mtype
-               self.is_vararg = is_vararg
-       end
-
        redef fun to_s
        do
                if is_vararg then
@@ -1630,11 +1602,8 @@ abstract class MProperty
        # The visibility of the property
        var visibility: MVisibility
 
-       init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
+       init
        do
-               self.intro_mclassdef = intro_mclassdef
-               self.name = name
-               self.visibility = visibility
                intro_mclassdef.intro_mproperties.add(self)
                var model = intro_mclassdef.mmodule.model
                model.mproperties_by_name.add_one(name, self)
@@ -1650,7 +1619,7 @@ abstract class MProperty
        #
        # Warning: such a definition may not exist in the early life of the object.
        # In this case, the method will abort.
-       var intro: MPROPDEF
+       var intro: MPROPDEF is noinit
 
        redef fun model do return intro.model
 
@@ -1819,11 +1788,6 @@ class MMethod
 
        redef type MPROPDEF: MMethodDef
 
-       init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
-       do
-               super
-       end
-
        # Is the property defined at the top_level of the module?
        # Currently such a property are stored in `Object`
        var is_toplevel: Bool = false is writable
@@ -1854,10 +1818,6 @@ class MAttribute
 
        redef type MPROPDEF: MAttributeDef
 
-       init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
-       do
-               super
-       end
 end
 
 # A global virtual type
@@ -1866,11 +1826,6 @@ class MVirtualTypeProp
 
        redef type MPROPDEF: MVirtualTypeDef
 
-       init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
-       do
-               super
-       end
-
        # The formal type associated to the virtual type property
        var mvirtualtype = new MVirtualType(self)
 end
@@ -1889,20 +1844,17 @@ abstract class MPropDef
        # Self class
        type MPROPDEF: MPropDef
 
-       # The origin of the definition
-       var location: Location
-
        # The class definition where the property definition is
        var mclassdef: MClassDef
 
        # The associated global property
        var mproperty: MPROPERTY
 
-       init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
+       # The origin of the definition
+       var location: Location
+
+       init
        do
-               self.mclassdef = mclassdef
-               self.mproperty = mproperty
-               self.location = location
                mclassdef.mpropdefs.add(self)
                mproperty.mpropdefs.add(self)
                if mproperty.intro_mclassdef == mclassdef then
@@ -1919,7 +1871,7 @@ abstract class MPropDef
 
        # Internal name combining the module, the class and the property
        # Example: "mymodule#MyClass#mymethod"
-       redef var to_s: String
+       redef var to_s: String is noinit
 
        # Is self the definition that introduce the property?
        fun is_intro: Bool do return mproperty.intro == self
@@ -1950,11 +1902,6 @@ class MMethodDef
        redef type MPROPERTY: MMethod
        redef type MPROPDEF: MMethodDef
 
-       init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
-       do
-               super
-       end
-
        # The signature attached to the property definition
        var msignature: nullable MSignature = null is writable
 
@@ -1998,11 +1945,6 @@ class MAttributeDef
        redef type MPROPERTY: MAttribute
        redef type MPROPDEF: MAttributeDef
 
-       init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
-       do
-               super
-       end
-
        # The static type of the attribute
        var static_mtype: nullable MType = null is writable
 end
@@ -2014,11 +1956,6 @@ class MVirtualTypeDef
        redef type MPROPERTY: MVirtualTypeProp
        redef type MPROPDEF: MVirtualTypeDef
 
-       init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
-       do
-               super
-       end
-
        # The bound of the virtual type
        var bound: nullable MType = null is writable
 
@@ -2041,11 +1978,8 @@ class MClassKind
 
        # Is a constructor required?
        var need_init: Bool
-       private init(s: String, need_init: Bool)
-       do
-               self.to_s = s
-               self.need_init = need_init
-       end
+
+       # TODO: private init because enumeration.
 
        # Can a class of kind `self` specializes a class of kine `other`?
        fun can_specialize(other: MClassKind): Bool
index ae5553d..4ee1eb6 100644 (file)
@@ -58,11 +58,7 @@ class MVisibility
 
        private var level: Int
 
-       private init(s: String, level: Int)
-       do
-               self.to_s = s
-               self.level = level
-       end
+       # TODO: private init because enumeration.
 
        # Is self give less visibility than other
        # none < private < protected < public < intrude
index 03ca3eb..bdb8373 100644 (file)
@@ -26,8 +26,6 @@ class MProjectTree
        # The model where to look for information
        var model: Model
 
-       init(model: Model) do self.model = model
-
        redef fun display(a) do
                if a isa MGroup then
                        if a.parent == null then return "{a.mproject.name} ({a.filepath.to_s})"
index 49ce780..c23e5cb 100644 (file)
@@ -37,10 +37,8 @@ class MProject
 
        redef fun to_s do return name
 
-       init(name: String, model: Model)
+       init
        do
-               self.name = name
-               self.model = model
                model.mprojects.add(self)
                model.mproject_by_name.add_one(name, self)
        end
@@ -75,21 +73,19 @@ class MGroup
        # The group is the group tree on the project (`mproject.mgroups`)
        # nested groups (children) are smaller
        # nesting group (see `parent`) is bigger
-       var in_nesting: POSetElement[MGroup]
+       var in_nesting: POSetElement[MGroup] is noinit
 
        # Is `self` the root of its project?
        fun is_root: Bool do return mproject.root == self
 
        # The filepath (usually a directory) of the group, if any
-       var filepath: nullable String is writable
+       var filepath: nullable String = null is writable
 
-       init (name: String, mproject: MProject, parent: nullable MGroup)
+       init
        do
-               self.name = name
-               self.mproject = mproject
-               self.parent = parent
                var tree = mproject.mgroups
                self.in_nesting = tree.add_node(self)
+               var parent = self.parent
                if parent != null then
                        tree.add_edge(self, parent)
                end
index cc613f3..83f5e0e 100644 (file)
@@ -125,10 +125,8 @@ class ModelBuilder
 
        # Instantiate a modelbuilder for a model and a toolcontext
        # Important, the options of the toolcontext must be correctly set (parse_option already called)
-       init(model: Model, toolcontext: ToolContext)
+       init
        do
-               self.model = model
-               self.toolcontext = toolcontext
                assert toolcontext.modelbuilder_real == null
                toolcontext.modelbuilder_real = self
 
@@ -141,10 +139,8 @@ class ModelBuilder
                end
 
                var nit_dir = toolcontext.nit_dir
-               if nit_dir != null then
-                       var libname = "{nit_dir}/lib"
-                       if libname.file_exists then paths.add(libname)
-               end
+               var libname = "{nit_dir}/lib"
+               if libname.file_exists then paths.add(libname)
        end
 
        # Load a bunch of modules.
index a5b3228..cb56d38 100644 (file)
@@ -490,16 +490,12 @@ redef class AMethPropdef
 
 
        # Can self be used as a root init?
-       private fun look_like_a_root_init(modelbuilder: ModelBuilder): Bool
+       private fun look_like_a_root_init(modelbuilder: ModelBuilder, mclassdef: MClassDef): Bool
        do
                # Need the `init` keyword
                if n_kwinit == null then return false
                # Need to by anonymous
                if self.n_methid != null then return false
-               # No parameters
-               if self.n_signature.n_params.length > 0 then return false
-               # Cannot be private or something
-               if not self.n_visibility isa APublicVisibility then return false
                # No annotation on itself
                if get_single_annotation("old_style_init", modelbuilder) != null then return false
                # Nor on its module
@@ -509,6 +505,16 @@ redef class AMethPropdef
                        var old = amoddecl.get_single_annotation("old_style_init", modelbuilder)
                        if old != null then return false
                end
+               # No parameters
+               if self.n_signature.n_params.length > 0 then
+                       modelbuilder.advice(self, "old-init", "Warning: init with signature in {mclassdef}")
+                       return false
+               end
+               # Cannot be private or something
+               if not self.n_visibility isa APublicVisibility then
+                       modelbuilder.advice(self, "old-init", "Warning: non-public init in {mclassdef}")
+                       return false
+               end
 
                return true
        end
@@ -547,9 +553,10 @@ redef class AMethPropdef
                        end
                end
 
+               var look_like_a_root_init = look_like_a_root_init(modelbuilder, mclassdef)
                var mprop: nullable MMethod = null
                if not is_init or n_kwredef != null then mprop = modelbuilder.try_get_mproperty_by_name(name_node, mclassdef, name).as(nullable MMethod)
-               if mprop == null and look_like_a_root_init(modelbuilder) then
+               if mprop == null and look_like_a_root_init then
                        mprop = modelbuilder.the_root_init_mmethod
                        var nb = n_block
                        if nb isa ABlockExpr and nb.n_expr.is_empty and n_doc == null then
@@ -559,7 +566,7 @@ redef class AMethPropdef
                if mprop == null then
                        var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility)
                        mprop = new MMethod(mclassdef, name, mvisibility)
-                       if look_like_a_root_init(modelbuilder) and modelbuilder.the_root_init_mmethod == null then
+                       if look_like_a_root_init and modelbuilder.the_root_init_mmethod == null then
                                modelbuilder.the_root_init_mmethod = mprop
                                mprop.is_root_init = true
                        end
@@ -580,9 +587,9 @@ redef class AMethPropdef
                self.mpropdef = mpropdef
                modelbuilder.mpropdef2npropdef[mpropdef] = self
                if mpropdef.is_intro then
-                       modelbuilder.toolcontext.info("{mpropdef} introduces new method {mprop.full_name}", 3)
+                       modelbuilder.toolcontext.info("{mpropdef} introduces new method {mprop.full_name}", 4)
                else
-                       modelbuilder.toolcontext.info("{mpropdef} redefines method {mprop.full_name}", 3)
+                       modelbuilder.toolcontext.info("{mpropdef} redefines method {mprop.full_name}", 4)
                end
        end
 
index df2792c..a566f31 100644 (file)
 # `MType`
 #
 # * labels: `MType`, `model_name` and `MEntity`. Must also have `MClassType`,
-# `MNullableType`, `MVirtualType` or `MSignature`, depending on the class of
-# the represented entity.
+# `MNullableType`, `MVirtualType`, `MRawType` or `MSignature`, depending on the
+# class of the represented entity.
 #
 # Additional label and relationships for `MClassType`:
 #
 #
 # * `(:MNullableType)-[:TYPE]->(:MType)`: base type of the nullable type.
 #
+# Additional attribute and relationship for `MRawType`:
+#
+# * `text`: JSON array of the parts’ text.
+# * `(:MRawType)-[:LINK]->(:MTypePart)`: the parts that link to another entity.
+#
 # Additional attribute and relationships for `MSignature`:
 #
 # * `parameter_names`: JSON array representing the list of the parameter names.
 #
 # MParameters are also ranked by their position in the corresponding signature.
 # Rank 0 for the first parameter, 1 for the next one and etc.
+#
+# `MTypePart`
+#
+# * labels: `MTypePart`, `model_name` and `MEntity`.
+# * `rank`: position in the `MRawType`.
+# * `(:MTypePart)-[:TARGET]->(:MEntity)`: the target of the link.
 module neo
 
-import model
+import doc::model_ext
 import neo4j
 import toolcontext
 
@@ -213,27 +224,27 @@ class NeoModel
 
        # Fill `model` using base pointed by `client`.
        fun load(model: Model): Model do
-               toolcontext.info("Locate all mentities...", 1)
-               var nodes = client.nodes_with_label(model_name)
-
-               toolcontext.info("Preload nodes...", 1)
-               pull_all_nodes(nodes)
-               toolcontext.info("Preload edges...", 1)
-               pull_all_edges(nodes)
+               var nodes: Array[NeoNode]
 
-               toolcontext.info("Build model...", 1)
+               toolcontext.info("Loading project node...", 1)
                nodes = client.nodes_with_labels([model_name, "MProject"])
                for node in nodes do to_mproject(model, node)
+               toolcontext.info("Loading groups...", 1)
                nodes = client.nodes_with_labels([model_name, "MGroup"])
                for node in nodes do to_mgroup(model, node)
+               toolcontext.info("Loading modules...", 1)
                nodes = client.nodes_with_labels([model_name, "MModule"])
                for node in nodes do to_mmodule(model, node)
+               toolcontext.info("Loading classes...", 1)
                nodes = client.nodes_with_labels([model_name, "MClass"])
                for node in nodes do to_mclass(model, node)
+               toolcontext.info("Loading class definitions...", 1)
                nodes = client.nodes_with_labels([model_name, "MClassDef"])
                for node in nodes do to_mclassdef(model, node)
+               toolcontext.info("Loading properties...", 1)
                nodes = client.nodes_with_labels([model_name, "MProperty"])
                for node in nodes do to_mproperty(model, node)
+               toolcontext.info("Loading property definitions...", 1)
                nodes = client.nodes_with_labels([model_name, "MPropDef"])
                for node in nodes do to_mpropdef(model, node)
                return model
@@ -270,52 +281,6 @@ class NeoModel
                do_batch(batch)
        end
 
-       # Load content for all `nodes` from base.
-       #
-       # Content corresponds to properties and labels that are loaded in batch mode.
-       private fun pull_all_nodes(nodes: Collection[NeoNode]) do
-               var batch = new NeoBatch(client)
-               var len = nodes.length
-               var sum = 0
-               var i = 1
-               for node in nodes do
-                       batch.load_node(node)
-                       if i == batch_max_size then
-                               do_batch(batch)
-                               sum += batch_max_size
-                               toolcontext.info(" {sum * 100 / len}% done", 1)
-                               batch = new NeoBatch(client)
-                               i = 1
-                       else
-                               i += 1
-                       end
-               end
-               do_batch(batch)
-       end
-
-       # Load all edges from base linked to `nodes`.
-       #
-       # Edges are loaded in batch mode.
-       private fun pull_all_edges(nodes: Collection[NeoNode]) do
-               var batch = new NeoBatch(client)
-               var len = nodes.length
-               var sum = 0
-               var i = 1
-               for node in nodes do
-                       batch.load_node_edges(node)
-                       if i == batch_max_size then
-                               do_batch(batch)
-                               sum += batch_max_size
-                               toolcontext.info(" {sum * 100 / len}% done", 1)
-                               batch = new NeoBatch(client)
-                               i = 1
-                       else
-                               i += 1
-                       end
-               end
-               do_batch(batch)
-       end
-
        # How many operation can be executed in one batch?
        private var batch_max_size = 1000
 
@@ -349,7 +314,9 @@ class NeoModel
        end
 
        # Mentities associated to nodes.
-       private var mentities = new HashMap[NeoNode, MEntity]
+       #
+       # The key is the node’s id.
+       private var mentities = new HashMap[Int, MEntity]
 
        # Nodes associated with MEntities.
        private var nodes = new HashMap[MEntity, NeoNode]
@@ -370,6 +337,20 @@ class NeoModel
                abort
        end
 
+       # Get the `MEntity` associated with `node`.
+       fun to_mentity(model: Model, node: NeoNode): MEntity do
+               if node.labels.has("MProject") then return to_mproject(model, node)
+               if node.labels.has("MGroup") then return to_mgroup(model, node)
+               if node.labels.has("MModule") then return to_mmodule(model, node)
+               if node.labels.has("MClass") then return to_mclass(model, node)
+               if node.labels.has("MClassDef") then return to_mclassdef(model, node)
+               if node.labels.has("MProperty") then return to_mproperty(model, node)
+               if node.labels.has("MPropDef") then return to_mpropdef(model, node)
+               if node.labels.has("MType") then return to_mtype(model, node)
+               if node.labels.has("MParameter") then return to_mparameter(model, node)
+               abort
+       end
+
        # Make a new `NeoNode` based on `mentity`.
        private fun make_node(mentity: MEntity): NeoNode do
                var node = new NeoNode
@@ -396,10 +377,12 @@ class NeoModel
        #
        # REQUIRE `node.labels.has("MProject")`
        private fun to_mproject(model: Model, node: NeoNode): MProject do
-               if mentities.has_key(node) then return mentities[node].as(MProject)
+               var m = mentities.get_or_null(node.id.as(Int))
+               if m isa MProject then return m
+
                assert node.labels.has("MProject")
                var mproject = new MProject(node["name"].to_s, model)
-               mentities[node] = mproject
+               mentities[node.id.as(Int)] = mproject
                set_doc(node, mproject)
                mproject.root = to_mgroup(model, node.out_nodes("ROOT").first)
                return mproject
@@ -428,7 +411,9 @@ class NeoModel
        #
        # REQUIRE `node.labels.has("MGroup")`
        private fun to_mgroup(model: Model, node: NeoNode): MGroup do
-               if mentities.has_key(node) then return mentities[node].as(MGroup)
+               var m = mentities.get_or_null(node.id.as(Int))
+               if m isa MGroup then return m
+
                assert node.labels.has("MGroup")
                var mproject = to_mproject(model, node.out_nodes("PROJECT").first)
                var parent: nullable MGroup = null
@@ -437,7 +422,7 @@ class NeoModel
                        parent = to_mgroup(model, out.first)
                end
                var mgroup = new MGroup(node["name"].to_s, mproject, parent)
-               mentities[node] = mgroup
+               mentities[node.id.as(Int)] = mgroup
                set_doc(node, mgroup)
                return mgroup
        end
@@ -464,7 +449,9 @@ class NeoModel
        #
        # REQUIRE `node.labels.has("MModule")`
        private fun to_mmodule(model: Model, node: NeoNode): MModule do
-               if mentities.has_key(node) then return mentities[node].as(MModule)
+               var m = mentities.get_or_null(node.id.as(Int))
+               if m isa MModule then return m
+
                assert node.labels.has("MModule")
                var ins = node.in_nodes("DECLARES")
                var mgroup: nullable MGroup = null
@@ -474,7 +461,7 @@ class NeoModel
                var name = node["name"].to_s
                var location = to_location(node["location"].to_s)
                var mmodule = new MModule(model, mgroup, name, location)
-               mentities[node] = mmodule
+               mentities[node.id.as(Int)] = mmodule
                set_doc(node, mmodule)
                var imported_mmodules = new Array[MModule]
                for smod in node.out_nodes("IMPORTS") do
@@ -504,7 +491,9 @@ class NeoModel
        #
        # REQUIRE `node.labels.has("MClass")`
        private fun to_mclass(model: Model, node: NeoNode): MClass do
-               if mentities.has_key(node) then return mentities[node].as(MClass)
+               var m = mentities.get_or_null(node.id.as(Int))
+               if m isa MClass then return m
+
                assert node.labels.has("MClass")
                var mmodule = to_mmodule(model, node.in_nodes("INTRODUCES").first)
                var name = node["name"].to_s
@@ -517,7 +506,7 @@ class NeoModel
                        end
                end
                var mclass = new MClass(mmodule, name, parameter_names, kind, visibility)
-               mentities[node] = mclass
+               mentities[node.id.as(Int)] = mclass
                set_doc(node, mclass)
                return mclass
        end
@@ -545,13 +534,15 @@ class NeoModel
        #
        # REQUIRE `node.labels.has("MClassDef")`
        private fun to_mclassdef(model: Model, node: NeoNode): MClassDef do
-               if mentities.has_key(node) then return mentities[node].as(MClassDef)
+               var m = mentities.get_or_null(node.id.as(Int))
+               if m isa MClassDef then return m
+
                assert node.labels.has("MClassDef")
                var mmodule = to_mmodule(model, node.in_nodes("DEFINES").first)
                var mtype = to_mtype(model, node.out_nodes("BOUNDTYPE").first).as(MClassType)
                var location = to_location(node["location"].to_s)
                var mclassdef = new MClassDef(mmodule, mtype, location)
-               mentities[node] = mclassdef
+               mentities[node.id.as(Int)] = mclassdef
                set_doc(node, mclassdef)
                var supertypes = new Array[MClassType]
                for sup in node.out_nodes("INHERITS") do
@@ -584,7 +575,9 @@ class NeoModel
        #
        # REQUIRE `node.labels.has("MProperty")`
        private fun to_mproperty(model: Model, node: NeoNode): MProperty do
-               if mentities.has_key(node) then return mentities[node].as(MProperty)
+               var m = mentities.get_or_null(node.id.as(Int))
+               if m isa MProperty then return m
+
                assert node.labels.has("MProperty")
                var intro_mclassdef = to_mclassdef(model, node.out_nodes("INTRO_CLASSDEF").first)
                var name = node["name"].to_s
@@ -602,7 +595,7 @@ class NeoModel
                        print "not yet implemented to_mproperty for {node.labels.join(",")}"
                        abort
                end
-               mentities[node] = mprop
+               mentities[node.id.as(Int)] = mprop
                set_doc(node, mprop)
                return mprop
        end
@@ -642,7 +635,9 @@ class NeoModel
        #
        # REQUIRE `node.labels.has("MPropDef")`
        private fun to_mpropdef(model: Model, node: NeoNode): MPropDef do
-               if mentities.has_key(node) then return mentities[node].as(MPropDef)
+               var m = mentities.get_or_null(node.id.as(Int))
+               if m isa MPropDef then return m
+
                assert node.labels.has("MPropDef")
                var mclassdef = to_mclassdef(model, node.in_nodes("DECLARES").first)
                var mproperty = to_mproperty(model, node.out_nodes("DEFINES").first)
@@ -653,16 +648,16 @@ class NeoModel
                        mpropdef.is_abstract = node["is_abstract"].as(Bool)
                        mpropdef.is_intern = node["is_intern"].as(Bool)
                        mpropdef.is_extern = node["is_extern"].as(Bool)
-                       mentities[node] = mpropdef
+                       mentities[node.id.as(Int)] = mpropdef
                        mpropdef.msignature = to_mtype(model, node.out_nodes("SIGNATURE").first).as(MSignature)
                else if node.labels.has("MAttributeDef") then
                        mpropdef = new MAttributeDef(mclassdef, mproperty.as(MAttribute), location)
-                       mentities[node] = mpropdef
+                       mentities[node.id.as(Int)] = mpropdef
                        var static_mtype = node.out_nodes("TYPE")
                        if not static_mtype.is_empty then mpropdef.static_mtype = to_mtype(model, static_mtype.first)
                else if node.labels.has("MVirtualTypeDef") then
                        mpropdef = new MVirtualTypeDef(mclassdef, mproperty.as(MVirtualTypeProp), location)
-                       mentities[node] = mpropdef
+                       mentities[node.id.as(Int)] = mpropdef
                        var bound = node.out_nodes("BOUND")
                        if not bound.is_empty then mpropdef.bound = to_mtype(model, bound.first)
                end
@@ -703,15 +698,41 @@ class NeoModel
                        var rank = 0
                        for mparameter in mtype.mparameters do
                                names.add mparameter.name
-                               var pnode = to_node(mparameter)
+                               var pnode = mparameter_node(mparameter)
                                pnode["rank"] = rank
                                node.out_edges.add(new NeoEdge(node, "PARAMETER", pnode))
+                               rank += 1
                        end
                        if not names.is_empty then node["parameter_names"] = names
                        var return_mtype = mtype.return_mtype
                        if return_mtype != null then
                                node.out_edges.add(new NeoEdge(node, "RETURNTYPE", to_node(return_mtype)))
                        end
+               else if mtype isa MRawType then
+                       node.labels.add "MRawType"
+                       var text = new JsonArray
+                       var rank = 0
+                       for part in mtype.parts do
+                               text.add part.text
+                               if part.target != null then
+                                       var pnode = mtypepart_node(part)
+                                       pnode["rank"] = rank
+                                       node.out_edges.add(new NeoEdge(node, "LINK", pnode))
+                               end
+                               rank += 1
+                       end
+                       if not text.is_empty then node["text"] = text
+               end
+               return node
+       end
+
+       # Build a `NeoNode` representing `mtypepart`.
+       private fun mtypepart_node(mtypepart: MTypePart): NeoNode do
+               var node = make_node(mtypepart)
+               node.labels.add "MTypePart"
+               if mtypepart.target != null then
+                       var target_node = to_node(mtypepart.target.as(not null))
+                       node.out_edges.add(new NeoEdge(node, "TARGET", target_node))
                end
                return node
        end
@@ -720,7 +741,9 @@ class NeoModel
        #
        # REQUIRE `node.labels.has("MType")`
        private fun to_mtype(model: Model, node: NeoNode): MType do
-               if mentities.has_key(node) then return mentities[node].as(MType)
+               var m = mentities.get_or_null(node.id.as(Int))
+               if m isa MType then return m
+
                assert node.labels.has("MType")
                if node.labels.has("MClassType") then
                        var mclass = to_mclass(model, node.out_nodes("CLASS").first)
@@ -729,24 +752,24 @@ class NeoModel
                                args.add to_mtype(model, narg)
                        end
                        var mtype = mclass.get_mtype(args)
-                       mentities[node] = mtype
+                       mentities[node.id.as(Int)] = mtype
                        return mtype
                else if node.labels.has("MParameterType") then
                        var mclass = to_mclass(model, node.out_nodes("CLASS").first)
                        var rank = node["rank"].to_s.to_i
                        var mtype = mclass.mparameters[rank]
-                       mentities[node] = mtype
+                       mentities[node.id.as(Int)] = mtype
                        return  mtype
                else if node.labels.has("MNullableType") then
                        var intype = to_mtype(model, node.out_nodes("TYPE").first)
                        var mtype = intype.as_nullable
-                       mentities[node] = mtype
+                       mentities[node.id.as(Int)] = mtype
                        return mtype
                else if node.labels.has("MVirtualType") then
                        var mproperty = to_mproperty(model, node.out_nodes("PROPERTY").first)
                        assert mproperty isa MVirtualTypeProp
                        var mtype = mproperty.mvirtualtype
-                       mentities[node] = mtype
+                       mentities[node.id.as(Int)] = mtype
                        return mtype
                else if node.labels.has("MSignature") then
                        # Get all param nodes
@@ -770,7 +793,26 @@ class NeoModel
                                return_mtype = to_mtype(model, ret_nodes.first)
                        end
                        var mtype = new MSignature(mparameters, return_mtype)
-                       mentities[node] = mtype
+                       mentities[node.id.as(Int)] = mtype
+                       return mtype
+               else if node.labels.has("MRawType") then
+                       var mtype = new MRawType(model)
+                       var parts = node["text"]
+                       if parts isa JsonArray then
+                               for p in parts do
+                                       mtype.parts.add(new MTypePart(model, p.to_s, null))
+                               end
+                               for pnode in node.out_nodes("LINK") do
+                                       assert pnode.labels.has("MTypePart")
+                                       if not pnode.out_nodes("TARGET").is_empty then
+                                               var rank = pnode["rank"]
+                                               var target = to_mentity(model, pnode.out_nodes("TARGET").first)
+                                               assert rank isa Int
+                                               mtype.parts[rank] = mtype.parts[rank].link_to(target)
+                                       end
+                               end
+                       end
+                       mentities[node.id.as(Int)] = mtype
                        return mtype
                end
                print "not yet implemented to_mtype for {node.labels.join(",")}"
@@ -791,13 +833,15 @@ class NeoModel
        #
        # REQUIRE `node.labels.has("MParameter")`
        private fun to_mparameter(model: Model, node: NeoNode): MParameter do
-               if mentities.has_key(node) then return mentities[node].as(MParameter)
+               var m = mentities.get_or_null(node.id.as(Int))
+               if m isa MParameter then return m
+
                assert node.labels.has("MParameter")
                var name = node["name"].to_s
                var mtype = to_mtype(model, node.out_nodes("TYPE").first)
                var is_vararg = node["is_vararg"].as(Bool)
                var mparameter = new MParameter(name, mtype, is_vararg)
-               mentities[node] = mparameter
+               mentities[node.id.as(Int)] = mparameter
                return mparameter
        end
 
@@ -827,6 +871,8 @@ class NeoModel
                        return protected_visibility
                else if vis == private_visibility.to_s then
                        return private_visibility
+               else if vis == package_visibility.to_s then
+                       return package_visibility
                else
                        return none_visibility
                end
@@ -844,8 +890,9 @@ class NeoModel
                        return enum_kind
                else if kind == extern_kind.to_s then
                        return extern_kind
+               else
+                       return raw_kind(kind)
                end
-               abort
        end
 
        # Extract the `MDoc` from `node` and link it to `mentity`.
index 9a95194..3785ff5 100644 (file)
@@ -23,6 +23,7 @@ import parser_util
 
 # Create a tool context to handle options and paths
 var toolcontext = new ToolContext
+toolcontext.option_context.options_before_rest = true
 toolcontext.tooldescription = "Usage: nit [OPTION]... <file.nit>...\nInterprets and debugs Nit programs."
 # Add an option "-o" to enable compatibilit with the tests.sh script
 var opt = new OptionString("compatibility (does noting)", "-o")
index f6a0959..631421a 100644 (file)
@@ -150,5 +150,6 @@ end
 # Length of the signature of a C function (long version hase the module name as prefix)
 class SignatureLength
        private var long: Bool
-       private init(long: Bool) do self.long = long
+
+       # TODO: private init because singleton class.
 end
index 0a8973d..c057beb 100644 (file)
@@ -73,9 +73,8 @@ end
 var file = toolcontext.opt_output.value
 if file == null then file = "nitunit.xml"
 page.write_to_file(file)
-print "Results saved in {file}"
 # print docunits results
-print "\nDocUnits:"
+print "DocUnits:"
 if modelbuilder.unit_entities == 0 then
        print "No doc units found"
 else if modelbuilder.failed_entities == 0 and not toolcontext.opt_noact.value then
index 0353560..68d9a47 100644 (file)
@@ -23,11 +23,11 @@ import modelize
 # then wait for query on std in to display documentation
 class NitIndex
        private var toolcontext: ToolContext
-       private var model: Model
-       private var mbuilder: ModelBuilder
-       private var mainmodule: MModule
-       private var arguments: Array[String]
-       private var renderer: PagerMatchesRenderer
+       private var model: Model is noinit
+       private var mbuilder: ModelBuilder is noinit
+       private var mainmodule: MModule is noinit
+       private var arguments: Array[String] is noinit
+       private var renderer: PagerMatchesRenderer is noinit
 
        # New constructor to use the pre-calculated model when interpreting a module
        init with_infos(mbuilder: ModelBuilder, mmodule: MModule) do
@@ -42,9 +42,8 @@ class NitIndex
                renderer = new PagerMatchesRenderer(self)
        end
 
-       init(toolcontext: ToolContext) do
+       init do
                # We need a model to collect stufs
-               self.toolcontext = toolcontext
                self.arguments = toolcontext.option_context.rest
 
                if arguments.length > 2 then
@@ -234,19 +233,11 @@ end
 private class IndexQuery
        var string: String
        var keyword: String
-       init(string: String, keyword: String) do
-               self.string = string
-               self.keyword = keyword
-       end
 end
 
 private class IndexQueryPair
        super IndexQuery
        var category: String
-       init(string: String, keyword: String, category: String) do
-               super(string, keyword)
-               self.category = category
-       end
 end
 
 # A match to a query in the nit index
@@ -298,7 +289,6 @@ end
 
 private class PagerMatchesRenderer
        var index: NitIndex
-       init(index: NitIndex) do self.index = index
 
        fun render_matches(query: IndexQuery, matches: Collection[IndexMatch]) do
                var pager = new Pager
index d8c287a..b933208 100644 (file)
@@ -80,8 +80,9 @@ end
 # It is better user with the Parser
 class Lexer
        super TablesCapable
+
        # Last peeked token
-       var token: nullable Token
+       var token: nullable Token = null
 
        # Lexer current state
        private var state: Int = 0
@@ -104,12 +105,6 @@ class Lexer
        # Constante state values
        private fun state_initial: Int do return 0 end
 
-       # Create a new lexer for a stream (and a name)
-       init(file: SourceFile)
-       do
-               self.file = file
-       end
-
        # The last peeked token to chain them
        private var last_token: nullable Token = null
 
index a4d6d44..a7f8071 100644 (file)
@@ -2070,10 +2070,5 @@ end
 class Start
        super Prod
        var n_base: nullable AModule is writable
-       var n_eof: EOF is writable, noinit
-       init(n_base: nullable AModule, n_eof: EOF)
-       do
-               self._n_base = n_base
-               self._n_eof = n_eof
-       end
+       var n_eof: EOF is writable
 end
index 4d67908..41d6741 100644 (file)
@@ -24,12 +24,6 @@ private class State
 
        # The node stored with the state in the stack
        var nodes: nullable Object
-
-       init(state: Int, nodes: nullable Object)
-       do
-               _state = state
-               _nodes = nodes
-       end
 end
 
 # The parser of the Nit language.
@@ -39,17 +33,13 @@ class Parser
        var lexer: Lexer
 
        # Stack of pushed states and productions
-       private var stack: Array[State]
+       private var stack = new Array[State]
 
        # Position in the stack
-       private var stack_pos: Int
+       private var stack_pos: Int = -1
 
-       # Create a new parser based on a given lexer
-       init(lexer: Lexer)
+       init
        do
-               _lexer = lexer
-               _stack = new Array[State]
-               _stack_pos = -1
                build_reduce_table
        end
 
@@ -163,7 +153,7 @@ class Parser
                end
        end
 
-       private var reduce_table: Array[ReduceAction]
+       private var reduce_table: Array[ReduceAction] is noinit
        private fun build_reduce_table is abstract
 end
 
@@ -269,5 +259,4 @@ private abstract class ReduceAction
                return l1
        end
        var goto: Int
-       init(g: Int) do _goto = g
 end
index ff97a78..82aec57 100644 (file)
@@ -269,7 +269,6 @@ end
 private class CollectTokensByTextVisitor
        super Visitor
        var text: String
-       init(text: String) do self.text = text
        var result = new Array[Token]
        redef fun visit(node)
        do
@@ -281,7 +280,6 @@ end
 private class CollectAnnotationsByNameVisitor
        super Visitor
        var name: String
-       init(name: String) do self.name = name
        var result = new Array[AAnnotation]
        redef fun visit(node)
        do
index 57b8b53..2011cd8 100644 (file)
@@ -163,13 +163,16 @@ abstract class Phase
        var toolcontext: ToolContext
 
        # The dependence relation of the phase with the other phases
-       var in_hierarchy: POSetElement[Phase]
+       var in_hierarchy: POSetElement[Phase] is noinit
+
+       # The explicit dependences, used to initialize `in_importation`
+       var depends: nullable Collection[Phase]
 
        # Initialize and register a phase to the toolcontext
-       init(toolcontext: ToolContext, depends: nullable Collection[Phase])
+       init
        do
-               self.toolcontext = toolcontext
                in_hierarchy = toolcontext.phases.add_node(self)
+               var depends = self.depends
                if depends != null then
                        for d in depends do
                                toolcontext.phases.add_edge(self, d)
index 378c31d..9f97e45 100644 (file)
@@ -441,11 +441,8 @@ class RapidTypeVisitor
        var receiver: MClassType
        var mpropdef: MPropDef
 
-       init(analysis: RapidTypeAnalysis, receiver: MClassType, mpropdef: MPropDef)
+       init
        do
-               self.analysis = analysis
-               self.receiver = receiver
-               self.mpropdef = mpropdef
                assert not receiver.need_anchor
        end
 
index 31a508a..ac7763e 100644 (file)
@@ -65,7 +65,7 @@ redef class AMethPropdef
                var nosuper = get_single_annotation("nosuper", modelbuilder)
 
                # Collect only for constructors
-               if not mpropdef.mproperty.is_init then
+               if not mpropdef.mproperty.is_init or mpropdef.mproperty.is_new then
                        if nosuper != null then modelbuilder.error(nosuper, "Error: nosuper only in `init`")
                        return
                end
index 522a347..02ce863 100644 (file)
@@ -33,19 +33,17 @@ end
 private class FlowVisitor
        super Visitor
 
-       var current_flow_context: FlowContext
+       var current_flow_context = new FlowContext
 
        var toolcontext: ToolContext
 
-       init(toolcontext: ToolContext)
+       init
        do
-               self.toolcontext = toolcontext
-               current_flow_context = new FlowContext
                flows.add(current_flow_context)
                current_flow_context.is_start = true
        end
 
-       var first: nullable ANode
+       var first: nullable ANode = null
 
        redef fun visit(node)
        do
index 4889866..4b3fd52 100644 (file)
@@ -44,11 +44,6 @@ private class LocalVarInitVisitor
 
        var toolcontext: ToolContext
 
-       init(toolcontext: ToolContext)
-       do
-               self.toolcontext = toolcontext
-       end
-
        # Local variables that are possibly unset (ie local variable without an initial value)
        var maybe_unset_vars: Set[Variable] = new HashSet[Variable]
 
index 00702d0..ad6bcd8 100644 (file)
@@ -71,9 +71,8 @@ private class ScopeVisitor
 
        var selfvariable = new Variable("self")
 
-       init(toolcontext: ToolContext)
+       init
        do
-               self.toolcontext = toolcontext
                scopes.add(new Scope)
        end
 
index 1fb3e07..3140de5 100644 (file)
@@ -39,10 +39,10 @@ private class TypeVisitor
 
        # The static type of the receiver
        # Mainly used for type tests and type resolutions
-       var anchor: nullable MClassType
+       var anchor: nullable MClassType = null
 
        # The analyzed mclassdef
-       var mclassdef: nullable MClassDef
+       var mclassdef: nullable MClassDef = null
 
        # The analyzed property
        var mpropdef: nullable MPropDef
@@ -54,10 +54,9 @@ private class TypeVisitor
        # * method called on the implicit self must be top-level
        var is_toplevel_context = false
 
-       init(modelbuilder: ModelBuilder, mmodule: MModule, mpropdef: nullable MPropDef)
+       init
        do
-               self.modelbuilder = modelbuilder
-               self.mmodule = mmodule
+               var mpropdef = self.mpropdef
 
                if mpropdef != null then
                        self.mpropdef = mpropdef
@@ -1725,7 +1724,7 @@ redef class ANewExpr
                if not callsite.mproperty.is_new then
                        var kind = recvtype.mclass.kind
                        if kind != concrete_kind then
-                               v.error(self, "Cannot instantiate {kind} {recvtype}.")
+                               v.error(self, "Type Error: Cannot instantiate {kind} {recvtype}.")
                                return
                        end
                        self.mtype = recvtype
index 566e014..f393950 100644 (file)
@@ -22,24 +22,15 @@ intrude import markdown
 class NitUnitExecutor
        super Doc2Mdwn
 
-       # The module to import
-       var mmodule: MModule
-
        # The prefix of the generated Nit source-file
        var prefix: String
 
+       # The module to import
+       var mmodule: MModule
+
        # The XML node associated to the module
        var testsuite: HTMLTag
 
-       # Initialize a new e
-       init(toolcontext: ToolContext, prefix: String, mmodule: MModule, testsuite: HTMLTag)
-       do
-               super(toolcontext)
-               self.prefix = prefix
-               self.mmodule = mmodule
-               self.testsuite = testsuite
-       end
-
        # All blocks of code from a same `ADoc`
        var blocks = new Array[Array[String]]
 
@@ -80,7 +71,7 @@ class NitUnitExecutor
        end
 
        # The associated node to localize warnings
-       var ndoc: nullable ADoc
+       var ndoc: nullable ADoc = null
 
        # used to generate distinct names
        var cpt = 0
@@ -127,8 +118,8 @@ class NitUnitExecutor
                if toolcontext.opt_noact.value then return
 
                var nit_dir = toolcontext.nit_dir
-               var nitg = "{nit_dir or else ""}/bin/nitg"
-               if nit_dir == null or not nitg.file_exists then
+               var nitg = nit_dir/"bin/nitg"
+               if not nitg.file_exists then
                        toolcontext.error(null, "Cannot find nitg. Set envvar NIT_DIR.")
                        toolcontext.check_errors
                end
index 5936038..1a3006d 100644 (file)
@@ -214,8 +214,8 @@ class TestCase
        fun compile do
                # find nitg
                var nit_dir = toolcontext.nit_dir
-               var nitg = "{nit_dir or else ""}/bin/nitg"
-               if nit_dir == null or not nitg.file_exists then
+               var nitg = nit_dir/"bin/nitg"
+               if not nitg.file_exists then
                        toolcontext.error(null, "Cannot find nitg. Set envvar NIT_DIR.")
                        toolcontext.check_errors
                end
index a443b0a..ec91130 100644 (file)
@@ -246,6 +246,9 @@ class ToolContext
        # Option --log-dir
        var opt_log_dir = new OptionString("Directory where to generate log files", "--log-dir")
 
+       # Option --nit-dir
+       var opt_nit_dir = new OptionString("Base directory of the Nit installation", "--nit-dir")
+
        # Option --help
        var opt_help = new OptionBool("Show Help (This screen)", "-h", "-?", "--help")
 
@@ -275,7 +278,12 @@ class ToolContext
 
        init
        do
-               option_context.add_option(opt_warn, opt_warning, opt_quiet, opt_stop_on_first_error, opt_no_color, opt_log, opt_log_dir, opt_help, opt_version, opt_set_dummy_tool, opt_verbose, opt_bash_completion, opt_stub_man)
+               option_context.add_option(opt_warn, opt_warning, opt_quiet, opt_stop_on_first_error, opt_no_color, opt_log, opt_log_dir, opt_nit_dir, opt_help, opt_version, opt_set_dummy_tool, opt_verbose, opt_bash_completion, opt_stub_man)
+
+               # Hide some internal options
+               opt_stub_man.hidden = true
+               opt_bash_completion.hidden = true
+               opt_set_dummy_tool.hidden = true
        end
 
        # Name, usage and synopsis of the tool.
@@ -365,6 +373,8 @@ The Nit language documentation and the source code of its tools and libraries ma
                        exit 1
                end
 
+               nit_dir = compute_nit_dir
+
                if option_context.rest.is_empty and not accept_no_arguments then
                        print tooldescription
                        print "Use --help for help"
@@ -382,7 +392,6 @@ The Nit language documentation and the source code of its tools and libraries ma
                        log_directory.mkdir
                end
 
-               nit_dir = compute_nit_dir
        end
 
        # Get the current `nit_version` or "DUMMY_VERSION" if `--set-dummy-tool` is set.
@@ -402,34 +411,54 @@ The Nit language documentation and the source code of its tools and libraries ma
        end
 
        # The identified root directory of the Nit project
-       var nit_dir: nullable String = null
+       var nit_dir: String is noinit
 
-       private fun compute_nit_dir: nullable String
+       private fun compute_nit_dir: String
        do
-               # a environ variable has precedence
-               var res = "NIT_DIR".environ
-               if not res.is_empty then return res
+               # the option has precedence
+               var res = opt_nit_dir.value
+               if res != null then
+                       if not check_nit_dir(res) then
+                               fatal_error(null, "Fatal Error: the value of --nit-dir does not seem to be a valid base Nit directory: {res}")
+                       end
+                       return res
+               end
+
+               # then the environ variable has precedence
+               res = "NIT_DIR".environ
+               if not res.is_empty then
+                       if not check_nit_dir(res) then
+                               fatal_error(null, "Fatal Error: the value of NIT_DIR does not seem to be a valid base Nit directory: {res}")
+                       end
+                       return res
+               end
 
                # find the runpath of the program from argv[0]
                res = "{sys.program_name.dirname}/.."
-               if res.file_exists and "{res}/src/nit.nit".file_exists then return res.simplify_path
+               if check_nit_dir(res) then return res.simplify_path
 
                # find the runpath of the process from /proc
                var exe = "/proc/self/exe"
                if exe.file_exists then
                        res = exe.realpath
                        res = res.dirname.join_path("..")
-                       if res.file_exists and "{res}/src/nit.nit".file_exists then return res.simplify_path
+                       if check_nit_dir(res) then return res.simplify_path
                end
 
                # search in the PATH
                var ps = "PATH".environ.split(":")
                for p in ps do
                        res = p/".."
-                       if res.file_exists and "{res}/src/nit.nit".file_exists then return res.simplify_path
+                       if check_nit_dir(res) then return res.simplify_path
                end
 
-               return null
+               fatal_error(null, "Fatal Error: Cannot locate a valid base nit directory. It is quite unexpected. Try to set the environment variable `NIT_DIR` or to use the `--nit-dir` option.")
+               abort
+       end
+
+       private fun check_nit_dir(res: String): Bool
+       do
+               return res.file_exists and "{res}/src/nit.nit".file_exists
        end
 end
 
@@ -455,10 +484,6 @@ class BashCompletion
 
        var toolcontext: ToolContext
 
-       init(toolcontext: ToolContext) do
-               self.toolcontext = toolcontext
-       end
-
        private fun extract_options_names: Array[String] do
                var names = new Array[String]
                for option in toolcontext.option_context.options do
index 6c8208a..2212380 100644 (file)
@@ -41,7 +41,7 @@ private class TransformPhase
        do
                var val
 
-               var v = new TransformVisitor(self, npropdef)
+               var v = new TransformVisitor(self, npropdef.mpropdef.as(not null))
                v.enter_visit(npropdef)
 
                val = new ASTValidationVisitor
@@ -53,15 +53,13 @@ private class TransformVisitor
        super Visitor
 
        var phase: TransformPhase
-       var mmodule: MModule
-       var mclassdef: MClassDef
+       var mmodule: MModule is noinit
+       var mclassdef: MClassDef is noinit
        var mpropdef: MPropDef
-       var builder: ASTBuilder
+       var builder: ASTBuilder is noinit
 
-       init(phase: TransformPhase, npropdef: APropdef)
+       init
        do
-               self.phase = phase
-               self.mpropdef = npropdef.mpropdef.as(not null)
                self.mclassdef = mpropdef.mclassdef
                self.mmodule = mclassdef.mmodule
                self.builder = new ASTBuilder(mmodule, mpropdef.mclassdef.bound_mtype)
index 3807ab7..9e9c778 100644 (file)
@@ -49,9 +49,9 @@ class VirtualMachine super NaiveInterpreter
 
        init(modelbuilder: ModelBuilder, mainmodule: MModule, arguments: Array[String])
        do
-               super
                var init_type = new MInitType(mainmodule.model)
                initialization_value = new MutableInstance(init_type)
+               super
        end
 
        # Subtyping test for the virtual machine
@@ -145,12 +145,30 @@ class VirtualMachine super NaiveInterpreter
 
                recv.vtable = recv.mtype.as(MClassType).mclass.vtable
 
-               assert(recv isa MutableInstance)
+               assert recv isa MutableInstance
 
                recv.internal_attributes = init_internal_attributes(initialization_value, recv.mtype.as(MClassType).mclass.all_mattributes(mainmodule, none_visibility).length)
                super
        end
 
+       # Associate a `PrimitiveInstance` to its `VTable`
+       redef fun init_instance_primitive(recv: Instance)
+       do
+               if not recv.mtype.as(MClassType).mclass.loaded then create_class(recv.mtype.as(MClassType).mclass)
+
+               recv.vtable = recv.mtype.as(MClassType).mclass.vtable
+       end
+
+       # Create a virtual table for this `MClass` if not already done
+       redef fun get_primitive_class(name: String): MClass
+       do
+               var mclass = super
+
+               if not mclass.loaded then create_class(mclass)
+
+               return mclass
+       end
+
        # Initialize the internal representation of an object (its attribute values)
        # `init_instance` is the initial value of attributes
        private fun init_internal_attributes(init_instance: Instance, size: Int): Pointer
@@ -169,6 +187,40 @@ class VirtualMachine super NaiveInterpreter
        # Creates the runtime structures for this class
        fun create_class(mclass: MClass) do     mclass.make_vt(self)
 
+       # Execute `mproperty` for a `args` (where `args[0]` is the receiver).
+       redef fun send(mproperty: MMethod, args: Array[Instance]): nullable Instance
+       do
+               var recv = args.first
+               var mtype = recv.mtype
+               var ret = send_commons(mproperty, args, mtype)
+               if ret != null then return ret
+
+               var propdef = method_dispatch(mproperty, recv.vtable.as(not null))
+
+               return self.call(propdef, args)
+       end
+
+       # Method dispatch, for a given global method `mproperty`
+       # returns the most specific local method in the class corresponding to `vtable`
+       private fun method_dispatch(mproperty: MMethod, vtable: VTable): MMethodDef
+       do
+               return method_dispatch_ph(vtable.internal_vtable, vtable.mask,
+                               mproperty.intro_mclassdef.mclass.vtable.id, mproperty.offset)
+       end
+
+       # Execute a method dispatch with perfect hashing
+       private fun method_dispatch_ph(vtable: Pointer, mask: Int, id: Int, offset: Int): MMethodDef `{
+               // Perfect hashing position
+               int hv = mask & id;
+               long unsigned int *pointer = (long unsigned int*)(((long int *)vtable)[-hv]);
+
+               // pointer+2 is the position where methods are
+               // Add the offset of property and get the method implementation
+               MMethodDef propdef = (MMethodDef)*(pointer + 2 + offset);
+
+               return propdef;
+       `}
+
        # Return the value of the attribute `mproperty` for the object `recv`
        redef fun read_attribute(mproperty: MAttribute, recv: Instance): Instance
        do
@@ -317,7 +369,12 @@ redef class MClass
                # When all super-classes have their identifiers and vtables, allocate current one
                allocate_vtable(v, ids, nb_methods, nb_attributes, offset_attributes, offset_methods)
                loaded = true
+
                # The virtual table now needs to be filled with pointer to methods
+               superclasses.add(self)
+               for cl in superclasses do
+                       fill_vtable(v, vtable.as(not null), cl)
+               end
        end
 
        # Allocate a single vtable
@@ -347,14 +404,19 @@ redef class MClass
                var self_methods = 0
                var nb_introduced_attributes = 0
 
-               # For self attributes, fixing offsets
-               var relative_offset = 0
+               # Fixing offsets for self attributes and methods
+               var relative_offset_attr = 0
+               var relative_offset_meth = 0
                for p in intro_mproperties(none_visibility) do
-                       if p isa MMethod then self_methods += 1
+                       if p isa MMethod then
+                               self_methods += 1
+                               p.offset = relative_offset_meth
+                               relative_offset_meth += 1
+                       end
                        if p isa MAttribute then
                                nb_introduced_attributes += 1
-                               p.offset = relative_offset
-                               relative_offset += 1
+                               p.offset = relative_offset_attr
+                               relative_offset_attr += 1
                        end
                end
 
@@ -374,6 +436,24 @@ redef class MClass
                vtable.internal_vtable = v.memory_manager.init_vtable(ids_total, nb_methods_total, d, vtable.mask)
        end
 
+       # Fill the vtable with methods of `self` class
+       #     `v` : Current instance of the VirtualMachine
+       #     `table` : the table of self class, will be filled with its methods
+       private fun fill_vtable(v:VirtualMachine, table: VTable, cl: MClass)
+       do
+               var methods = new Array[MMethodDef]
+               for m in cl.intro_mproperties(none_visibility) do
+                       if m isa MMethod then
+                               # `propdef` is the most specific implementation for this MMethod
+                               var propdef = m.lookup_first_definition(v.mainmodule, self.intro.bound_mtype)
+                               methods.push(propdef)
+                       end
+               end
+
+               # Call a method in C to put propdefs of self methods in the vtables
+               v.memory_manager.put_methods(vtable.internal_vtable, vtable.mask, cl.vtable.id, methods)
+       end
+
        # Computes delta for each class
        # A delta represents the offset for this group of attributes in the object
        #     `nb_attributes` : number of attributes for each class (classes are linearized from Object to current)
@@ -482,6 +562,11 @@ redef class MAttribute
        var offset: Int
 end
 
+redef class MMethod
+       # Represents the relative offset of this attribute in the runtime instance
+       var offset: Int
+end
+
 # Redef MutableInstance to improve implementation of attributes in objects
 redef class MutableInstance
 
@@ -489,6 +574,11 @@ redef class MutableInstance
        var internal_attributes: Pointer
 end
 
+# Redef to associate an `Instance` to its `VTable`
+redef class Instance
+       var vtable: nullable VTable
+end
+
 # Is the type of the initial value inside attributes
 class MInitType
        super MType
@@ -528,10 +618,6 @@ class VTable
        var classname: String is noinit
 end
 
-redef class Instance
-       var vtable: nullable VTable
-end
-
 # Handle memory, used for allocate virtual table and associated structures
 class MemoryManager
 
@@ -594,4 +680,29 @@ class MemoryManager
 
                return vtable;
        `}
+
+       # Put implementation of methods of a class in `vtable`
+       # `vtable` : Pointer to the C-virtual table
+       # `mask` : perfect-hashing mask of the class corresponding to the vtable
+       # `id` : id of the target class
+       # `methods` : array of MMethodDef of the target class
+       fun put_methods(vtable: Pointer, mask: Int, id: Int, methods: Array[MMethodDef])
+               import Array[MMethodDef].length, Array[MMethodDef].[] `{
+
+               // Get the area to fill with methods by a sequence of perfect hashing
+               int hv = mask & id;
+               long unsigned int *pointer = (long unsigned int*)(((long unsigned int *)vtable)[-hv]);
+
+               // pointer+2 is the beginning of the area for methods implementation
+               int length = Array_of_MMethodDef_length(methods);
+               long unsigned int *area = (pointer + 2);
+               int i;
+
+               for(i=0; i<length; i++)
+               {
+                       MMethodDef method = Array_of_MMethodDef__index(methods, i);
+                       area[i] = (long unsigned int)method;
+                       MMethodDef_incr_ref(method);
+               }
+       `}
 end
index 8fdf39a..d36a68b 100644 (file)
@@ -49,6 +49,11 @@ class C
        end
 end
 
+class D
+       super C
+       new(z: Bool): B do return new C(1111)
+end
+
 redef class Int
        new z do return 0
        new a: A do return new A
@@ -79,6 +84,10 @@ end
 
 '\n'.output
 
+(new D(true)).output
+
+'\n'.output
+
 #alt8#(new Int).output
 (new Int.z).output
 (new Int.a).output
index 3dff2fc..c99dc83 100644 (file)
@@ -14,6 +14,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+#alt1 import standard
+#alt1 import standard::ropes
+
 var n = 7
 if not args.is_empty then
        n = args.first.to_i
@@ -22,7 +25,8 @@ end
 var s = "*"
 var i = 0
 while i < n do
-       var s2 = new FlatBuffer.from("Je dis «")
+       var s2: Buffer = new FlatBuffer.from("Je dis «")
+       #alt1 s2 = new RopeBuffer.from("Je dis «")
        s2.append(s)
        s2.append("» et redis «")
        s2.append(s)
index c00d979..e8d5c50 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+#alt1 import standard
+#alt1 import standard::ropes
+
 # A procedural program (without explicit class).
 
 fun first_word(s: String): String
 do
-       var result = new FlatBuffer
+       var result: Buffer = new FlatBuffer
+       #alt1 result = new RopeBuffer
        var i = 0
        while i < s.length and s.chars[i] != ' ' do
                result.add(s.chars[i])
index f066eac..aad8297 100644 (file)
@@ -18,6 +18,9 @@
 # It displays the value of a local variable.
 # It exhibs ways to concatenate strings.
 
+#alt1 import standard
+#alt1 import standard::ropes
+
 var a = 10
 # First way: Multiple parameters.
 # Pro: Simple.
@@ -27,7 +30,8 @@ printn("The value of a is: ", a, ".\n")
 # Second way: Build a string and display it.
 # Pro: Eiffel way (rigourous).
 # Con: Eiffel way (heavy).
-var s = new FlatBuffer.from("The value of a is: ")
+var s: Buffer = new FlatBuffer.from("The value of a is: ")
+#alt1 s = new RopeBuffer.from("The value of a is: ")
 s.append(a.to_s)
 s.append(".\n")
 printn(s)
index 087e573..778d0d3 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/sh
-printf "%s\n" "$@" *.nit \
+printf "%s\n" "$@" \
+       ../src/nit*.nit \
+       ../src/test_*.nit \
        ../examples/*.nit \
        ../examples/*/*.nit \
        ../examples/shoot/src/shoot_logic.nit \
@@ -12,5 +14,4 @@ printf "%s\n" "$@" *.nit \
        ../lib/*/examples/*.nit \
        ../contrib/friendz/src/solver_cmd.nit \
        ../contrib/pep8analysis/src/pep8analysis.nit \
-       ../src/nit*.nit \
-       ../src/test_*.nit
+       *.nit
index 0c14c1c..8a91562 100644 (file)
@@ -1,4 +1,4 @@
 --log --log-dir out/test_nitc_logs ../examples/hello_world.nit
 base_simple3.nit
 -m test_mixin.nit ../examples/hello_world.nit
-test_define.nit -D text=hello -D num=42 -D flag
+-D text=hello -D num=42 -D flag test_define.nit
index e23154d..a3c8000 100644 (file)
@@ -1 +1 @@
-base_error_new_abstract.nit:21,9--13: Cannot instantiate abstract class A.
+base_error_new_abstract.nit:21,9--13: Type Error: Cannot instantiate abstract class A.
index 0e64d98..c0c2c1b 100644 (file)
@@ -1 +1 @@
-base_error_new_interface.nit:21,9--13: Cannot instantiate interface A.
+base_error_new_interface.nit:21,9--13: Type Error: Cannot instantiate interface A.
index fe346a1..510c2e4 100644 (file)
@@ -13,5 +13,7 @@ B11
 
 B111
 
+B1111
+
 0
 B1
index 15d625a..e9c98c9 100644 (file)
@@ -1 +1 @@
-alt/base_new_alt5.nit:58,1--9: Error: Method 'i' doesn't exists in A.
+alt/base_new_alt5.nit:63,1--9: Error: Method 'i' doesn't exists in A.
index 53c4091..3ac7e2a 100644 (file)
@@ -1 +1 @@
-alt/base_new_alt6.nit:60,1--12: Error: Method 'i' doesn't exists in A.
+alt/base_new_alt6.nit:65,1--12: Error: Method 'i' doesn't exists in A.
index 698bfbf..99ce3e1 100644 (file)
@@ -1 +1 @@
-alt/base_new_alt7.nit:78,2--9: Error: Method 'n2' doesn't exists in C.
+alt/base_new_alt7.nit:83,2--9: Error: Method 'n2' doesn't exists in C.
index 1eed641..51ee855 100644 (file)
@@ -1 +1 @@
-alt/base_new_alt8.nit:82,2--8: Cannot instantiate enum Int.
+alt/base_new_alt8.nit:91,2--8: Type Error: Cannot instantiate enum Int.
diff --git a/tests/sav/bench_string_append_alt1.res b/tests/sav/bench_string_append_alt1.res
new file mode 100644 (file)
index 0000000..24c2167
--- /dev/null
@@ -0,0 +1,3 @@
+1092
+1365
+147447
index e95a0c5..14ced87 100644 (file)
@@ -1 +1 @@
-alt/error_needed_method_alt2.nit:47,10--27: Cannot instantiate interface Collection[Int].
+alt/error_needed_method_alt2.nit:47,10--27: Type Error: Cannot instantiate interface Collection[Int].
diff --git a/tests/sav/example_procedural_string_alt1.res b/tests/sav/example_procedural_string_alt1.res
new file mode 100644 (file)
index 0000000..e965047
--- /dev/null
@@ -0,0 +1 @@
+Hello
diff --git a/tests/sav/example_string_alt1.res b/tests/sav/example_string_alt1.res
new file mode 100644 (file)
index 0000000..02444a6
--- /dev/null
@@ -0,0 +1,5 @@
+The value of a is: 10.
+The value of a is: 10.
+The value of a is: 10.
+The value of a is: 10.
+The value of a is: 10.
index 3494b3f..7b0f4e6 100644 (file)
@@ -4,34 +4,34 @@ class_module_0__Sys.html
 class_module_1__A.html
 class_module_1__B.html
 css/
-dep_A.dot
-dep_A.map
-dep_A.png
-dep_A.s.dot
-dep_B.dot
-dep_B.map
-dep_B.png
-dep_B.s.dot
-dep_Int.dot
-dep_Int.map
-dep_Int.png
-dep_Int.s.dot
-dep_Object.dot
-dep_Object.map
-dep_Object.png
-dep_Object.s.dot
-dep_Sys.dot
-dep_Sys.map
-dep_Sys.png
-dep_Sys.s.dot
-dep_module_0.dot
-dep_module_0.map
-dep_module_0.png
-dep_module_0.s.dot
-dep_module_1.dot
-dep_module_1.map
-dep_module_1.png
-dep_module_1.s.dot
+dep_class_module_0__Int.dot
+dep_class_module_0__Int.map
+dep_class_module_0__Int.png
+dep_class_module_0__Int.s.dot
+dep_class_module_0__Object.dot
+dep_class_module_0__Object.map
+dep_class_module_0__Object.png
+dep_class_module_0__Object.s.dot
+dep_class_module_0__Sys.dot
+dep_class_module_0__Sys.map
+dep_class_module_0__Sys.png
+dep_class_module_0__Sys.s.dot
+dep_class_module_1__A.dot
+dep_class_module_1__A.map
+dep_class_module_1__A.png
+dep_class_module_1__A.s.dot
+dep_class_module_1__B.dot
+dep_class_module_1__B.map
+dep_class_module_1__B.png
+dep_class_module_1__B.s.dot
+dep_module_module_0__module_0__module_0.dot
+dep_module_module_0__module_0__module_0.map
+dep_module_module_0__module_0__module_0.png
+dep_module_module_0__module_0__module_0.s.dot
+dep_module_module_1__module_1__module_1.dot
+dep_module_module_1__module_1__module_1.map
+dep_module_module_1__module_1__module_1.png
+dep_module_module_1__module_1__module_1.s.dot
 group_module_0__module_0.html
 group_module_1__module_1.html
 index.html
diff --git a/tests/sav/nitg-e/fixme/base_conflict_submodule_name.res b/tests/sav/nitg-e/fixme/base_conflict_submodule_name.res
deleted file mode 100644 (file)
index 7f85acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Compilation error
diff --git a/tests/sav/nitg-e/fixme/base_conflict_submodule_name_alt1.res b/tests/sav/nitg-e/fixme/base_conflict_submodule_name_alt1.res
deleted file mode 100644 (file)
index 7f85acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Compilation error
diff --git a/tests/sav/nitg-e/fixme/base_conflict_submodule_name_alt2.res b/tests/sav/nitg-e/fixme/base_conflict_submodule_name_alt2.res
deleted file mode 100644 (file)
index 7f85acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Compilation error
diff --git a/tests/sav/nitg-g/fixme/base_conflict_submodule_name.res b/tests/sav/nitg-g/fixme/base_conflict_submodule_name.res
deleted file mode 100644 (file)
index 7f85acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Compilation error
diff --git a/tests/sav/nitg-g/fixme/base_conflict_submodule_name_alt1.res b/tests/sav/nitg-g/fixme/base_conflict_submodule_name_alt1.res
deleted file mode 100644 (file)
index 7f85acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Compilation error
diff --git a/tests/sav/nitg-g/fixme/base_conflict_submodule_name_alt2.res b/tests/sav/nitg-g/fixme/base_conflict_submodule_name_alt2.res
deleted file mode 100644 (file)
index 7f85acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Compilation error
diff --git a/tests/sav/nitg-s/fixme/base_conflict_submodule_name.res b/tests/sav/nitg-s/fixme/base_conflict_submodule_name.res
deleted file mode 100644 (file)
index 7f85acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Compilation error
diff --git a/tests/sav/nitg-s/fixme/base_conflict_submodule_name_alt1.res b/tests/sav/nitg-s/fixme/base_conflict_submodule_name_alt1.res
deleted file mode 100644 (file)
index 7f85acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Compilation error
diff --git a/tests/sav/nitg-s/fixme/base_conflict_submodule_name_alt2.res b/tests/sav/nitg-s/fixme/base_conflict_submodule_name_alt2.res
deleted file mode 100644 (file)
index 7f85acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Compilation error
diff --git a/tests/sav/nitg-sg/fixme/base_conflict_submodule_name.res b/tests/sav/nitg-sg/fixme/base_conflict_submodule_name.res
deleted file mode 100644 (file)
index 7f85acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Compilation error
diff --git a/tests/sav/nitg-sg/fixme/base_conflict_submodule_name_alt1.res b/tests/sav/nitg-sg/fixme/base_conflict_submodule_name_alt1.res
deleted file mode 100644 (file)
index 7f85acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Compilation error
diff --git a/tests/sav/nitg-sg/fixme/base_conflict_submodule_name_alt2.res b/tests/sav/nitg-sg/fixme/base_conflict_submodule_name_alt2.res
deleted file mode 100644 (file)
index 7f85acf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Compilation error
index 481e468..e5ac8bd 100644 (file)
@@ -470,8 +470,8 @@ Average number of composing class definition by runtime class: 2.00
 Total size of tables (classes and instances): 38 (not including stuff like info for subtyping or call-next-method)
 Average size of table by runtime class: 6.33
 Values never redefined: 32 (84.21%)
-generating out/nitmetrics_args1.write/project_hierarchy.dot
-generating out/nitmetrics_args1.write/module_hierarchy.dot
+generating project_hierarchy.dot
+generating module_hierarchy.dot
 
 # Inheritance metrics
 
index 3b5b590..3a07d20 100644 (file)
@@ -4,8 +4,6 @@ test_nitunit.nit:23,2--25,0: FAILURE: nitunit.test_nitunit.test_nitunit::X.test_
 
 test_test_nitunit.nit:36,2--40,4: ERROR: test_foo1 (in file .nitunit/test_test_nitunit_TestX_test_foo1.nit): Runtime error: Assert failed (test_test_nitunit.nit:39)
 
-Results saved in out/nitunit_args1.write
-
 DocUnits:
 Entities: 27; Documented ones: 3; With nitunits: 3; Failures: 2
 
index 17ccd5a..6c361fe 100644 (file)
@@ -2,5 +2,5 @@ Initial: eabf.cdgh
 eab
 f.c
 dgh
-Solved, after looking at 14 positions during 0.0s
+Solved, after looking at 14 positions
 Solution in 10 moves: right(>) down(v) left(<) left(<) up(^) right(>) right(>) up(^) left(<) left(<)
diff --git a/tests/sav/splay_test.res b/tests/sav/splay_test.res
deleted file mode 100644 (file)
index a8191ea..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-digraph g {
-[label = 6];
- ->  [label = "left"];
-[label = "AB" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = AB"];
- ->  [label = "right"];
-[label = 4];
- ->  [label = "left"];
-[label = "CD" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = CD"];
- ->  [label = "right"];
-[label = "EF" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = EF"];
-}
-
-ABCDEF
-digraph g {
-[label = 6];
- ->  [label = "left"];
-[label = 4];
- ->  [label = "left"];
-[label = "AB" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = AB"];
- ->  [label = "right"];
-[label = "CD" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = CD"];
- ->  [label = "right"];
-[label = "EF" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = EF"];
-}
-
-ABCDEF
-ABCDEFGH
-digraph g {
-[label = 8];
- ->  [label = "left"];
-[label = 6];
- ->  [label = "left"];
-[label = 4];
- ->  [label = "left"];
-[label = "AB" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = AB"];
- ->  [label = "right"];
-[label = "CD" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = CD"];
- ->  [label = "right"];
-[label = "EF" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = EF"];
- ->  [label = "right"];
-[label = "GH" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = GH"];
-}
-
-ABCDEFGH
-digraph g {
-[label = 8];
- ->  [label = "left"];
-[label = "AB" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = AB"];
- ->  [label = "right"];
-[label = 6];
- ->  [label = "left"];
-[label = 4];
- ->  [label = "left"];
-[label = "CD" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = CD"];
- ->  [label = "right"];
-[label = "EF" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = EF"];
- ->  [label = "right"];
-[label = "GH" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = GH"];
-}
-
-ABCDEFGH
-digraph g {
-[label = 8];
- ->  [label = "left"];
-[label = "AB" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = AB"];
- ->  [label = "right"];
-[label = 6];
- ->  [label = "left"];
-[label = "CD" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = CD"];
- ->  [label = "right"];
-[label = 4];
- ->  [label = "left"];
-[label = "EF" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = EF"];
- ->  [label = "right"];
-[label = "GH" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = GH"];
-}
-
-ABCDEFGH
-digraph g {
-[label = 8];
- ->  [label = "left"];
-[label = 6];
- ->  [label = "left"];
-[label = "AB" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = AB"];
- ->  [label = "right"];
-[label = 4];
- ->  [label = "left"];
-[label = "CD" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = CD"];
- ->  [label = "right"];
-[label = "EF" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = EF"];
- ->  [label = "right"];
-[label = "GH" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = GH"];
-}
-
-ABCDEFGH
-digraph g {
-[label = 8];
- ->  [label = "left"];
-[label = 6];
- ->  [label = "left"];
-[label = "AB" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = AB"];
- ->  [label = "right"];
-[label = 4];
- ->  [label = "left"];
-[label = "CD" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = CD"];
- ->  [label = "right"];
-[label = "EF" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = EF"];
- ->  [label = "right"];
-[label = "GH" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = GH"];
-}
-
-ABCDEFGH
-digraph g {
-[label = 8];
- ->  [label = "left"];
-[label = 4];
- ->  [label = "left"];
-[label = "AB" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = AB"];
- ->  [label = "right"];
-[label = "CD" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = CD"];
- ->  [label = "right"];
-[label = 4];
- ->  [label = "left"];
-[label = "EF" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = EF"];
- ->  [label = "right"];
-[label = "GH" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = GH"];
-}
-
-ABCDEFGH
-digraph g {
-[label = 8];
- ->  [label = "left"];
-[label = "AB" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = AB"];
- ->  [label = "right"];
-[label = 6];
- ->  [label = "left"];
-[label = 4];
- ->  [label = "left"];
-[label = "CD" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = CD"];
- ->  [label = "right"];
-[label = "EF" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = EF"];
- ->  [label = "right"];
-[label = "GH" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = GH"];
-}
-
-ABCDEFGH
-digraph g {
-[label = 8];
- ->  [label = "left"];
-[label = 4];
- ->  [label = "left"];
-[label = "AB" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = AB"];
- ->  [label = "right"];
-[label = "CD" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = CD"];
- ->  [label = "right"];
-[label = 4];
- ->  [label = "left"];
-[label = "EF" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = EF"];
- ->  [label = "right"];
-[label = "GH" shape = rect];
- -> [label = "contains"];
- [label="FlatString\nindex_from = 0\nindex_to = 1\nNativeString = GH"];
-}
-
diff --git a/tests/sav/string_trim_alt1.res b/tests/sav/string_trim_alt1.res
new file mode 100644 (file)
index 0000000..24d9987
--- /dev/null
@@ -0,0 +1,13 @@
+resulttrim = nono nono
+returntrim + nono nono
+thirdtrim = nono nono
+emptytrim = 
+bufferemptytrim = 
+onelettertrim = d
+oneletterbuftest = d
+twolettertrim = hg
+twoletterbuftest = hg
+firstlettertrimtest = d
+firstlettertrimbuftest = d
+lastlettertrimtest = d
+lastlettertrimbuftest = d
diff --git a/tests/sav/test_ffi_c_duplicated_callback_a.res b/tests/sav/test_ffi_c_duplicated_callback_a.res
new file mode 100644 (file)
index 0000000..479d9d1
--- /dev/null
@@ -0,0 +1 @@
+Hello from `a`.
diff --git a/tests/sav/test_ffi_c_duplicated_callback_b.res b/tests/sav/test_ffi_c_duplicated_callback_b.res
new file mode 100644 (file)
index 0000000..8c51d75
--- /dev/null
@@ -0,0 +1,2 @@
+Hello from `a`.
+Hello from `b`.
diff --git a/tests/sav/test_ffi_cpp_duplicated_callback_a.res b/tests/sav/test_ffi_cpp_duplicated_callback_a.res
new file mode 100644 (file)
index 0000000..479d9d1
--- /dev/null
@@ -0,0 +1 @@
+Hello from `a`.
diff --git a/tests/sav/test_ffi_cpp_duplicated_callback_b.res b/tests/sav/test_ffi_cpp_duplicated_callback_b.res
new file mode 100644 (file)
index 0000000..8c51d75
--- /dev/null
@@ -0,0 +1,2 @@
+Hello from `a`.
+Hello from `b`.
index 422ca5b..bf79e4b 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:778)
+Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:789)
 NativeString
 N
 Nit
index 7e4b7c1..8c7831d 100644 (file)
@@ -13,7 +13,6 @@ now step live...
 now step live...
  live...
 .
- live stepnow
 ...evil pets won
 n
 now step live... step live...
diff --git a/tests/sav/test_ropes_alt1.res b/tests/sav/test_ropes_alt1.res
deleted file mode 100644 (file)
index 7e4b7c1..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-NODEATTEST
-INZZ
-INDDZZ
-EEINDDZZ
-EEINDDZZFF
-eeinddzzff
-EEINDDZZFF
-FFZZDDNIEE
-hello_world.types.1.o
-now step live...
-...evil pets won
-now step live...
-now step live...
- live...
-.
- live stepnow
-...evil pets won
-n
-now step live... step live...
-w s
-ZZ
-ZZZZZZZZZZ
-ZZAAZZZZZZZZ
-NNZZAAZZZZZZZZ
-NIINZZAAZZZZZZZZ
-NINIINZZAAZZZZZZZZINZZAAZZZZZZZZ
diff --git a/tests/sav/test_ropes_alt2.res b/tests/sav/test_ropes_alt2.res
deleted file mode 100644 (file)
index 3fa08b9..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-NODEATTEST
-INZZ
-INDDZZ
-EEINDDZZ
-EEINDDZZFF
-eeinddzzff
-EEINDDZZFF
-FFZZDDNIEE
-hello_world.types.1.o
-now step live...
-...evil pets won
-now step live...
-now step live...
- live...
-.
-now step live
-...evil pets won
-n
-now step live... step live...
-w s
-ZZ
-ZZZZZZZZZZ
-ZZAAZZZZZZZZ
-NNZZAAZZZZZZZZ
-NIINZZAAZZZZZZZZ
-NINIINZZAAZZZZZZZZINZZAAZZZZZZZZ
diff --git a/tests/sav/test_string_long_alt1.res b/tests/sav/test_string_long_alt1.res
new file mode 100644 (file)
index 0000000..21373ff
--- /dev/null
@@ -0,0 +1,10000 @@
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
+Bonjour !
diff --git a/tests/sav/test_to_upper_lower_buffer_alt1.res b/tests/sav/test_to_upper_lower_buffer_alt1.res
new file mode 100644 (file)
index 0000000..e69de29
index 800327a..6e0ca35 100644 (file)
@@ -5,7 +5,7 @@ _DUMMY_TOOL()
        COMPREPLY=()
        cur="${COMP_WORDS[COMP_CWORD]}"
        prev="${COMP_WORDS[COMP_CWORD-1]}"
-       opts="--warn --warning --quiet --stop-on-first-error --no-color --log --log-dir --help --version --set-dummy-tool --verbose --bash-completion --stub-man --option-a --option-b"
+       opts="--warn --warning --quiet --stop-on-first-error --no-color --log --log-dir --nit-dir --help --version --set-dummy-tool --verbose --bash-completion --stub-man --option-a --option-b"
        if [[ ${cur} == -* ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
                return 0
index 91fa2fa..b14caf6 100644 (file)
@@ -7,12 +7,10 @@ Test for ToolContext, try --bash-completion.
   --no-color              Do not use color to display errors and warnings
   --log                   Generate various log files
   --log-dir               Directory where to generate log files
+  --nit-dir               Base directory of the Nit installation
   -h, -?, --help          Show Help (This screen)
   --version               Show version and exit
-  --set-dummy-tool        Set toolname and version to DUMMY. Useful for testing
   -v, --verbose           Verbose
-  --bash-completion       Generate bash_completion file for this program
-  --stub-man              Generate a stub manpage in pandoc markdown format
   -a, --option-a          option a, do nothing
   -b, --option-b          option b, do nothing
   -c                      option c, do nothing
index acc2856..2137a3a 100644 (file)
@@ -17,7 +17,7 @@
 fun nsieve(n: Int): Int
 do
        var count = 0
-       var array = new FlatBuffer.with_capacity(n)
+       var array: Buffer = new FlatBuffer.with_capacity(n)
        for i in [0..n[ do
                array.chars[i] = 'o'
        end
diff --git a/tests/splay_test.nit b/tests/splay_test.nit
deleted file mode 100644 (file)
index dae8aef..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-# 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.
-
-intrude import splay_ropes
-intrude import standard::ropes
-intrude import ropes_debug
-
-redef class Leaf
-       redef fun to_dot(s): String
-       do
-               s += "[label = \"{str}\" shape = rect];\n"
-               s += " -> [label = \"contains\"];\n"
-               s = str.to_dot(s)
-               return s
-       end
-end
-
-redef class Concat
-       redef fun to_dot(s): String
-       do
-               s += "[label = {length}];\n"
-               if left != null then
-                       s += " ->  [label = \"left\"];\n"
-                       s = left.to_dot(s)
-               end
-               if right != null then
-                       s += " ->  [label = \"right\"];\n"
-                       s = right.to_dot(s)
-               end
-               return s
-       end
-end
-
-redef class FlatString
-       redef fun to_dot(s: String): String
-       do
-               return s + " [label=\"FlatString\\nindex_from = {index_from}\\nindex_to = {index_to}\\nNativeString = {items.to_s_with_length(items.cstring_length)}\"];\n"
-       end
-end
-
-redef class FlatBuffer
-       redef fun to_dot(s: String): String
-       do
-               return s + " [label=\"FlatBuffer\\length = {length}\\ncapacity = {capacity}\\nitems = {items.to_s_with_length(items.cstring_length)}\"];\n"
-       end
-end
-
-
-redef class RopeString
-
-       redef fun to_dot(f)
-       do
-               var ret: String = new RopeString.from("digraph g \{\n")
-               ret = root.to_dot(ret).as(RopeString)
-               ret += "\}\n"
-               print ret
-               return ret
-       end
-
-end
-
-var ab = new StringLeaf("AB".as(FlatString))
-var cd = new StringLeaf("CD".as(FlatString))
-var ef = new StringLeaf("EF".as(FlatString))
-var gh = new StringLeaf("GH".as(FlatString))
-
-# Zig test
-
-var c = new Concat(cd,ef)
-c = new Concat(ab,c)
-var ro = new RopeString.from_root(c)
-
-ro.to_dot("Zig-Before_splay.dot")
-print ro
-
-var p = ro.node_at(5)
-
-ro = new RopeString.from_root(ro.splay(p).as(not null))
-
-ro.to_dot("Zig-After_splay.dot")
-print ro
-
-# Zig-zig test left left
-
-var d = new Concat(ab,cd)
-var e = new Concat(d,ef)
-var f = new Concat(e,gh)
-ro = new RopeString.from_root(f)
-
-p = ro.node_at(0)
-
-print ro
-ro.to_dot("Zig-zigll-Before_splay.dot")
-
-ro = new RopeString.from_root(ro.splay(p).as(not null))
-
-print ro
-ro.to_dot("Zig-zigll-After_splay.dot")
-
-# Zig-zig test right right
-
-d = new Concat(ef,gh)
-e = new Concat(cd,d)
-f = new Concat(ab,e)
-ro = new RopeString.from_root(f)
-
-p = ro.node_at(7)
-
-print ro
-ro.to_dot("Zig-zigrr-Before_splay.dot")
-
-ro = new RopeString.from_root(ro.splay(p).as(not null))
-
-print ro
-ro.to_dot("Zig-zigrr-After_splay.dot")
-
-# Zig-zag test left right
-
-d = new Concat(cd,ef)
-e = new Concat(ab,d)
-f = new Concat(e,gh)
-ro = new RopeString.from_root(f)
-
-p = ro.node_at(4)
-
-print ro
-ro.to_dot("Zig-zaglr-Before_splay.dot")
-
-ro = new RopeString.from_root(ro.splay(p).as(not null))
-
-print ro
-ro.to_dot("Zig-zaglr-After_splay.dot")
-
-# Zig-zag test right left
-
-d = new Concat(cd,ef)
-e = new Concat(d,gh)
-f = new Concat(ab,e)
-ro = new RopeString.from_root(f)
-
-p = ro.node_at(4)
-
-print ro
-ro.to_dot("Zig-zagrl-Before_splay.dot")
-
-ro = new RopeString.from_root(ro.splay(p).as(not null))
-
-print ro
-ro.to_dot("Zig-zagrl-After_splay.dot")
-
index 387c8b1..81ce2bd 100644 (file)
@@ -1,10 +1,12 @@
-module string_trim
+#alt1 import standard::ropes
+#alt1 import standard
 
 var trimtest = "   \t nono nono   \n \t"
 
 var subtrim = trimtest.substring(2,15)
 
-var buffertrimtest = new FlatBuffer.from(trimtest)
+var buffertrimtest: Buffer = new FlatBuffer.from(trimtest)
+#alt1 buffertrimtest = new RopeBuffer.from(trimtest)
 
 print "resulttrim = {buffertrimtest.trim}"
 
@@ -14,7 +16,8 @@ print "thirdtrim = {subtrim.trim}"
 
 var emptytrim = "         \t  "
 
-var bufferemptytest = new FlatBuffer.from(emptytrim)
+var bufferemptytest: Buffer = new FlatBuffer.from(emptytrim)
+#alt1 bufferemptytest = new RopeBuffer.from(emptytrim)
 
 print "emptytrim = {emptytrim.trim}"
 
@@ -22,7 +25,8 @@ print "bufferemptytrim = {bufferemptytest.trim}"
 
 var onelettertrim = "    \n   d      \n\t  "
 
-var oneletterbuftest = new FlatBuffer.from(onelettertrim)
+var oneletterbuftest: Buffer = new FlatBuffer.from(onelettertrim)
+#alt1 oneletterbuftest = new RopeBuffer.from(onelettertrim)
 
 print "onelettertrim = {onelettertrim.trim}"
 
@@ -30,7 +34,8 @@ print "oneletterbuftest = {oneletterbuftest.trim}"
 
 var twolettertrim = "    \n   hg      \n\t  "
 
-var twoletterbuftest = new FlatBuffer.from(twolettertrim)
+var twoletterbuftest: Buffer = new FlatBuffer.from(twolettertrim)
+#alt1 twoletterbuftest = new RopeBuffer.from(twolettertrim)
 
 print "twolettertrim = {twolettertrim.trim}"
 
@@ -38,7 +43,8 @@ print "twoletterbuftest = {twoletterbuftest.trim}"
 
 var firstlettertrim = "d                "
 
-var firstlettertrimbuf = new FlatBuffer.from(firstlettertrim)
+var firstlettertrimbuf: Buffer = new FlatBuffer.from(firstlettertrim)
+#alt1 firstlettertrimbuf = new RopeBuffer.from(firstlettertrim)
 
 print "firstlettertrimtest = {firstlettertrim.trim}"
 
@@ -46,7 +52,8 @@ print "firstlettertrimbuftest = {firstlettertrimbuf.trim}"
 
 var lastlettertrim = "                     d"
 
-var lastlettertrimbuf = new FlatBuffer.from(lastlettertrim)
+var lastlettertrimbuf: Buffer = new FlatBuffer.from(lastlettertrim)
+#alt1 lastlettertrimbuf = new RopeBuffer.from(lastlettertrim)
 
 print "lastlettertrimtest = {lastlettertrim.trim}"
 
index f9a416d..3f080c1 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var rp: String = new RopeString.from("xxx")
-rp += "yyy"
+import standard
+intrude import standard::ropes
+
+var rp: String = new Concat("xxx", "yyy")
 rp += "zzz"
 var arr = ["FlatString", rp]
 print arr.to_s
diff --git a/tests/test_ffi_c_duplicated_callback_a.nit b/tests/test_ffi_c_duplicated_callback_a.nit
new file mode 100644 (file)
index 0000000..3347747
--- /dev/null
@@ -0,0 +1,23 @@
+# 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.
+
+`{
+       #include <stdio.h>
+`}
+
+fun print_a(str: String) import String.to_cstring `{
+       puts(String_to_cstring(str));
+`}
+
+print_a "Hello from `a`."
diff --git a/tests/test_ffi_c_duplicated_callback_b.nit b/tests/test_ffi_c_duplicated_callback_b.nit
new file mode 100644 (file)
index 0000000..d55db5e
--- /dev/null
@@ -0,0 +1,26 @@
+# 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 test_ffi_c_duplicated_callback_a
+
+`{
+       #include <stdio.h>
+`}
+
+fun print_b(str: String) import String.to_cstring `{
+       puts(String_to_cstring(str));
+`}
+
+print_a "Hello from `a`."
+print_b "Hello from `b`."
diff --git a/tests/test_ffi_cpp_duplicated_callback_a.nit b/tests/test_ffi_cpp_duplicated_callback_a.nit
new file mode 100644 (file)
index 0000000..76c1172
--- /dev/null
@@ -0,0 +1,23 @@
+# 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.
+
+in "C++ Header" `{
+       #include <stdio.h>
+`}
+
+fun print_a(str: String) import String.to_cstring in "C++" `{
+       puts(String_to_cstring(str));
+`}
+
+print_a "Hello from `a`."
diff --git a/tests/test_ffi_cpp_duplicated_callback_b.nit b/tests/test_ffi_cpp_duplicated_callback_b.nit
new file mode 100644 (file)
index 0000000..01eb25c
--- /dev/null
@@ -0,0 +1,26 @@
+# 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 test_ffi_cpp_duplicated_callback_a
+
+in "C++ header" `{
+       #include <stdio.h>
+`}
+
+fun print_b(str: String) import String.to_cstring in "C++" `{
+       puts(String_to_cstring(str));
+`}
+
+print_a "Hello from `a`."
+print_b "Hello from `b`."
diff --git a/tests/test_ffi_java_global.nit b/tests/test_ffi_java_global.nit
new file mode 100644 (file)
index 0000000..8dd7b71
--- /dev/null
@@ -0,0 +1,27 @@
+# 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 java
+
+# Called method
+fun foo import String.output in "Java" `{
+`}
+
+# Dead method
+fun bar import Text.output in "Java" `{
+`}
+
+foo
index d08aa03..1e54bee 100644 (file)
@@ -12,8 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-#alt1 import splay_ropes
-#alt2 import bufferized_ropes
+#alt1 import standard
+#alt1 import buffered_ropes
 
 var st = "quick brown fox over the lazy dog"
 
index 2d03f50..c8829ee 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-#alt1 import splay_ropes
-#alt2 import bufferized_ropes
+import standard
+intrude import standard::ropes
 
-var x :String = new RopeString
+# Force building a Rope
+redef fun maxlen: Int do return once 2
 
-x = x + "NODE"
-x = x + "AT"
-x = x + "TEST"
+var x :String = new Concat("NODE", "AT")
+
+x += "TEST"
 
 print x
 
 var lst = new List[String]
 
-lst.push(new RopeString.from("ZZ"))
+lst.push("ZZ")
 
 lst.push((lst.last * 5))
 
@@ -41,7 +42,7 @@ var ss = lst.last.substring(4,4)
 
 print ss
 
-ss = ss.as(RopeString).insert_at("DD", 2)
+ss = ss.insert_at("DD", 2)
 
 print ss
 
@@ -67,15 +68,14 @@ print ss
 
 var atb = new Array[String]
 
-var s: String = new RopeString
-s = s + "./examples/hello_world.nit".substring(11,11) + ".types"
+var s: String = "./examples/hello_world.nit".substring(11,11) + ".types"
 s += "."
 s += "1"
 s += ".o"
 
 print s
 
-var str = new RopeString.from("now") + " step" + " live..."
+var str = "now" + " step" + " live..."
 
 print str
 
@@ -101,16 +101,13 @@ printn "\n"
 for i in str.chars.iterator_from(str.length-1) do printn i
 printn "\n"
 
-for i in str.as(RopeString).reverse_substrings_from(12) do printn i
-printn "\n"
-
 for i in str.chars.reverse_iterator do printn i
 printn "\n"
 
 for i in str.chars.reverse_iterator_from(0) do printn i
 printn "\n"
 
-var str2 = str.as(RopeString).insert_at(str.substring_from(3), 3)
+var str2 = str.insert_at(str.substring_from(3), 3)
 
 print str2
 
index 04655ba..6bfb034 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+#alt1 import standard
+#alt1 import standard::ropes
 
 var s = "Bonjour !\n"
-var r = new FlatBuffer.with_capacity(50)
-var r2 = new FlatBuffer
+var r: Buffer = new FlatBuffer.with_capacity(50)
+#alt1 r = new RopeBuffer
+var r2: Buffer = new FlatBuffer
+#alt1 r2 = new RopeBuffer
 
 var i = 0
 while i < 5000 do
index 2b6ef28..3e7da27 100644 (file)
@@ -12,7 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-#alt3 import bufferized_ropes
+#alt2 import standard
+#alt2 import buffered_ropes
 
 var str = "Woe to you, oh earth and sea for the Devil sends the beast with wrath because he knows the time is short. Let him who hath understanding reckon the number of the beast, for it is a human number, its number is Six Hundred and Sixty-Six."
 var spaces = "           "
@@ -32,17 +33,11 @@ num = numstr
 #alt1 trimable.append(spaces)
 #alt1 num = new FlatBuffer.from(numstr)
 
-#alt2 txt = new RopeString.from(str)
-#alt2 trimable = new RopeString.from(spaces)
-#alt2 trimable = trimable + str
-#alt2 trimable = trimable + spaces
-#alt2 num = new RopeString.from(numstr)
-
-#alt3 txt = new RopeString.from(str)
-#alt3 trimable = new RopeString.from(spaces)
-#alt3 trimable = trimable + str
-#alt3 trimable = trimable + spaces
-#alt3 num = new RopeString.from(numstr)
+#alt3 txt = new RopeBuffer.from(str)
+#alt3 trimable = new RopeBuffer.from(spaces)
+#alt3 trimable.append(str)
+#alt3 trimable.append(spaces)
+#alt3 num = new RopeBuffer.from(numstr)
 
 # Test Text methods on all types of receivers
 
index d8b7eb5..e856eff 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var x = new FlatBuffer.from("test")
-var y = new FlatBuffer.from("TEST")
+#alt1 import standard::ropes
+
+var x: Buffer = new FlatBuffer.from("test")
+#alt1 x = new RopeBuffer.from("test")
+var y: Buffer = new FlatBuffer.from("TEST")
+#alt1 y = new RopeBuffer.from("TEST")
 
 x.upper
 y.lower
index 966dee1..76ecf2c 100755 (executable)
@@ -457,7 +457,9 @@ todos=""
 if [ "x$XMLDIR" = "x" ]; then
        xml="tests-$engine.xml"
 else
-       xml="$XMLDIR/tests-$engine.xml"
+       sum=`echo $@ | md5sum | cut -f1 -d " "`
+       xml="$XMLDIR/tests-$engine-$sum.xml"
+       mkdir -p "$XMLDIR"
 fi
 
 echo >$xml "<testsuites><testsuite>"
@@ -505,7 +507,7 @@ for ii in "$@"; do
 
                if [ -n "$isinterpret" ]; then
                        cat > "$ff.bin" <<END
-exec $NITC --no-color $OPT "$i" $includes -- "\$@"
+exec $NITC --no-color $OPT $includes -- "$i" "\$@"
 END
                        chmod +x "$ff.bin"
                        > "$ff.cmp.err"
@@ -521,10 +523,10 @@ END
                        # Compile
                        if [ "x$verbose" = "xtrue" ]; then
                                echo ""
-                               echo $NITC --no-color $OPT -o "$ffout" "$i" "$includes" $nocc
+                               echo $NITC --no-color $OPT -o "$ffout" "$includes" $nocc "$i"
                        fi
                        NIT_NO_STACK=1 JNI_LIB_PATH=$JNI_LIB_PATH JAVA_HOME=$JAVA_HOME \
-                               saferun -o "$ff.time.out" $NITC --no-color $OPT -o "$ffout" "$i" $includes $nocc 2> "$ff.cmp.err" > "$ff.compile.log"
+                               saferun -o "$ff.time.out" $NITC --no-color $OPT -o "$ffout" $includes $nocc "$i" 2> "$ff.cmp.err" > "$ff.compile.log"
                        ERR=$?
                        if [ "x$verbose" = "xtrue" ]; then
                                cat "$ff.compile.log"