Merge: Unite app.nit metadata annotations common to Android and iOS
authorJean Privat <jean@pryen.org>
Fri, 3 Apr 2015 01:27:33 +0000 (08:27 +0700)
committerJean Privat <jean@pryen.org>
Fri, 3 Apr 2015 01:27:33 +0000 (08:27 +0700)
* Rename the annotation `java_package` to `app_namespace`.
* Move up `app_name`, `app_version` and `app_namespace` and their default values from the Android platform.
* Apply these annotations in iOS too.
* Use the annotations in Hello iOS.

Pull-Request: #1233
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

39 files changed:
benchmarks/markdown/README.md
benchmarks/markdown/bench_markdown.sh
benchmarks/markdown/engines/Makefile
benchmarks/markdown/engines/nitmd/Makefile
benchmarks/markdown/engines/pandoc/Makefile [new file with mode: 0644]
benchmarks/markdown/engines/pandoc/pandoc.hs [new file with mode: 0644]
benchmarks/strings/Makefile [new file with mode: 0644]
benchmarks/strings/README.md [new file with mode: 0644]
benchmarks/strings/array_to_s_vars/array_to_s_buffer.nit
benchmarks/strings/array_to_s_vars/array_to_s_flatstr.nit
benchmarks/strings/array_to_s_vars/array_to_s_man_buf.nit
benchmarks/strings/array_to_s_vars/array_to_s_rope.nit
benchmarks/strings/array_to_s_vars/array_to_s_rope_buf.nit [new file with mode: 0644]
benchmarks/strings/bench_strings.sh [moved from benchmarks/bench_strings.sh with 53% similarity]
benchmarks/strings/chain_concat.nit
benchmarks/strings/iteration_bench.nit
benchmarks/strings/substr_bench.nit
benchmarks/strings/utf_chain_concat.nit [deleted file]
benchmarks/strings/utf_iteration_bench.nit [deleted file]
benchmarks/strings/utf_substr_bench.nit [deleted file]
bin/Makefile [new file with mode: 0644]
lib/html/bootstrap.nit [new file with mode: 0644]
lib/standard/string.nit
src/compiler/abstract_compiler.nit
src/doc/doc_base.nit
src/doc/doc_phases/doc_graphs.nit
src/doc/doc_phases/doc_hierarchies.nit
src/doc/doc_phases/doc_html.nit
src/doc/doc_phases/doc_structure.nit
src/doc/html_templates/html_components.nit
src/doc/html_templates/html_model.nit
src/doc/html_templates/html_templates.nit
src/interpreter/naive_interpreter.nit
src/loader.nit
src/test_phase.nit
tests/sav/hello_ios.res [new file with mode: 0644]
tests/sav/test_platform_ios.res [new file with mode: 0644]
tests/testosx.sh [new file with mode: 0755]
tests/tests.sh

index a739cd8..29219c5 100644 (file)
@@ -11,6 +11,7 @@ Benches markdown parsers.
 * nitmd
 * txtmark 0.11 (https://github.com/rjeschke/txtmark)
 * markdown4j 2.2 (https://code.google.com/p/markdown4j/)
+* pandoc (last version installed from `cabal`)
 
 ## Benches
 
index 4cb0f15..aaa34f0 100755 (executable)
@@ -74,7 +74,7 @@ engdir="./engines"
 bncdir="./benches/out"
 mkdir -p $outdir
 
-s=50
+s=200
 
 function bench_nitmd()
 {
@@ -88,6 +88,18 @@ function bench_nitmd()
 }
 bench_nitmd
 
+function bench_nitmd-o()
+{
+       name="$FUNCNAME"
+       skip_test "$name" && return
+       prepare_res $outdir/nitmd-o.dat "nitmd-o" "nitmd-o"
+       for file in $bncdir/*.md; do
+               bench=`basename $file .md`
+               bench_command "$bench" "" "$engdir/nitmd/nitmd-o" "$file" "$s"
+       done
+}
+bench_nitmd-o
+
 function bench_txtmark()
 {
        name="$FUNCNAME"
@@ -112,6 +124,18 @@ function bench_markdown4j()
 }
 bench_markdown4j
 
+function bench_pandoc()
+{
+       name="$FUNCNAME"
+       skip_test "$name" && return
+       prepare_res $outdir/pandoc.dat "pandoc" "pandoc"
+       for file in $bncdir/*.md; do
+               name=`basename $file .md`
+               bench_command "$bench" "" "$engdir/pandoc/pandoc" "$file" "$s"
+       done
+}
+bench_pandoc
+
 if test "$#" -gt 0; then
     plot $outdir/bench_markdown.gnu
 fi
index 588e744..7301d01 100644 (file)
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-all: nitmd/nitmd txtmark/Txtmark.class markdown4j/Markdown4j.class
+all: nitmd/nitmd txtmark/Txtmark.class markdown4j/Markdown4j.class pandoc/pandoc
 
 nitmd/nitmd:
        make -C nitmd
@@ -25,7 +25,11 @@ txtmark/Txtmark.class:
 markdown4j/Markdown4j.class:
        make -C markdown4j
 
+pandoc/pandoc:
+       make -C pandoc
+
 clean:
        make -C nitmd clean
        make -C txtmark clean
        make -C markdown4j clean
+       make -C pandoc clean
index aa79fbc..6424382 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+all: nitmd nitmd-o
+
 nitmd:
        nitc nitmd.nit
 
-test: nitmd
+nitmd-o:
+       nitc --semi-global nitmd.nit -o $@
+
+test: all
        ./nitmd ../../benches/hello.md 5
+       ./nitmd-o ../../benches/hello.md 5
 
 clean:
-       rm -rf nitmd
+       rm -rf nitmd nitmd-o
diff --git a/benchmarks/markdown/engines/pandoc/Makefile b/benchmarks/markdown/engines/pandoc/Makefile
new file mode 100644 (file)
index 0000000..ca4a354
--- /dev/null
@@ -0,0 +1,27 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2015 Alexandre Terrasa <alexandre@moz-code.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.
+
+pandoc:
+       cabal install pandoc
+       ghc pandoc.hs -O
+
+test: pandoc
+       ./pandoc ../../benches/hello.md 5
+
+clean:
+       rm pandoc.hi
+       rm pandoc.o
+       rm pandoc
diff --git a/benchmarks/markdown/engines/pandoc/pandoc.hs b/benchmarks/markdown/engines/pandoc/pandoc.hs
new file mode 100644 (file)
index 0000000..5c5db42
--- /dev/null
@@ -0,0 +1,33 @@
+module Main where
+
+       import System.Environment (getArgs)
+       import Text.Pandoc
+
+       -- Reads a String and parses it as a Pandoc instance
+       readDoc :: String -> Pandoc
+       readDoc = readMarkdown def
+
+       -- Writes a Pandoc instances as a String
+       writeDoc :: Pandoc -> String
+       writeDoc = writeHtmlString def
+
+       -- Reads markdown, writes HTML and prints it in stdout
+       doBench :: String -> IO ()
+       doBench fileName        = do
+               content                 <- readFile fileName
+               let markdown    = readDoc content
+               let html                =  writeDoc markdown
+               print html
+
+       -- Executes `doBench` n times
+       loop :: Int -> String -> IO ()
+       loop 0 _ = return ()
+       loop n fileName = do
+               doBench fileName
+               loop (n  - 1) fileName
+               return ()
+
+       main :: IO ()
+       main = do
+               (fileName:count:_)      <- getArgs
+               loop (read count::Int) fileName
diff --git a/benchmarks/strings/Makefile b/benchmarks/strings/Makefile
new file mode 100644 (file)
index 0000000..82118c9
--- /dev/null
@@ -0,0 +1,13 @@
+all:   concat iter substr array
+
+concat:
+       ./bench_strings.sh cct 10 10000000 1
+
+substr:
+       ./bench_strings.sh substr 10 10000000 10
+
+iter:
+       ./bench_strings.sh iter 10 10000000 10
+
+array:
+       ./bench_strings.sh array 10 10000000 10
diff --git a/benchmarks/strings/README.md b/benchmarks/strings/README.md
new file mode 100644 (file)
index 0000000..b87b981
--- /dev/null
@@ -0,0 +1,41 @@
+# Strings
+
+Strings are a building block of programming.
+Since they are that necessary, we must keep them as performing as possible.
+
+This series of benchmarks works on different structures for handling strings on the most common operations done on them.
+
+## Structures
+
+Some more structures are susceptible to be added as the project advances.
+At the moment, what is available consists of
+
+* Flat strings
+* Flat buffers
+* Rope strings
+* Rope buffers
+
+A String is defined as an immutable string.
+A Buffer is defined as a mutable string.
+
+Flat strings are arrays of characters, the most basic implementation of a string.
+Ropes are a tree-like structure where strings are bound through concatenation nodes.
+
+## Tests
+
+`concat`: Benches the concatenation speed of strings and buffers.
+
+`iter`: Benches the time of iteration of a string, through iterators or indexed access
+
+`substr`: Benches the time required to produce a substring.
+
+`arraytos`: Special bench, it measures the speed of `Array::to_s` through the use of various strategies.
+
+## Usage
+
+To pass a series of benches you can use the `make` command to bench all the aforementioned tests with default values.
+
+Each bench will be executed 5 times and the mean time will be represented in the final graph.
+
+The alternative is to use `bench_strings.sh` with custom arguments to it.
+For more information on the arguments and the format, execute it with the -h option for help.
index d61b742..f18ece7 100644 (file)
@@ -13,6 +13,9 @@
 # To be used as a Mixin at compile-time for benchmarking purposes.
 module array_to_s_buffer
 
+intrude import standard::collection::array
+import standard::string
+
 redef class Array[E]
        redef fun to_s: String do
                var s = new FlatBuffer
index 0240d5b..7028e3f 100644 (file)
 # To be used as a Mixin at compile-time for benchmarking purposes.
 module array_to_s_flatstr
 
+intrude import standard::string
+
+redef class FlatString
+       redef fun +(o) do
+               var mlen = length
+               var slen = o.length
+               var nns = new NativeString(mlen + slen)
+               items.copy_to(nns, mlen, index_from, 0)
+               if o isa FlatString then
+                       o.items.copy_to(nns, slen, o.index_from, mlen)
+               else
+                       var pos = mlen
+                       for i in o.chars do
+                               nns[pos] = i
+                               pos += 1
+                       end
+               end
+               return nns.to_s_with_length(mlen)
+       end
+end
+
 redef class Array[E]
 
        redef fun to_s do
index ec81322..c5dbd00 100644 (file)
@@ -13,9 +13,8 @@
 # To be used as a Mixin at compile-time for benchmarking purposes.
 module array_to_s_man_buf
 
-redef class NativeArray[E]
-       new(length: Int) is intern
-end
+intrude import standard::collection::array
+import standard::string
 
 redef class Array[E]
        redef fun to_s: String do
index c162dff..9f86a8a 100644 (file)
 # To be used as a Mixin at compile-time for benchmarking purposes.
 module array_to_s_rope
 
+intrude import standard::collection::array
+intrude import standard::ropes
+
 redef class Array[E]
 
        redef fun to_s do
-               var i = 1
                var l = length
+               var it = _items
                if l == 0 then return ""
-               var s: String = new RopeString.from(self[0].to_s)
-               var its = _items
-               while i < l do
-                       var e = its[i]
-                       if e != null then s += e.to_s
-                       i += 1
+               if l == 1 then return it[0].to_s
+               var c = new Concat(it[0].to_s, it[1].to_s)
+               for i in [2 .. l[ do
+                       c = new Concat(c, it[i].to_s)
                end
-               return s
+               return c
        end
+
 end
diff --git a/benchmarks/strings/array_to_s_vars/array_to_s_rope_buf.nit b/benchmarks/strings/array_to_s_vars/array_to_s_rope_buf.nit
new file mode 100644 (file)
index 0000000..c7e3e7b
--- /dev/null
@@ -0,0 +1,32 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Implementation of Array::to_s with RopeBuffer exclusively
+#
+# To be used as a Mixin at compile-time for benchmarking purposes.
+module array_to_s_rope_buf
+
+intrude import standard::collection::array
+import standard::ropes
+
+redef class Array[E]
+       redef fun to_s: String do
+               var s = new RopeBuffer
+               var i = 0
+               var l = length
+               var its = _items
+               while i < l do
+                       var e = its[i]
+                       if e != null then s.append(e.to_s)
+                       i += 1
+               end
+               return s.to_s
+       end
+end
similarity index 53%
rename from benchmarks/bench_strings.sh
rename to benchmarks/strings/bench_strings.sh
index 16992e9..a710dc0 100755 (executable)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-source ./bench_common.sh
-source ./bench_plot.sh
+source ../bench_common.sh
+source ../bench_plot.sh
 
 # Default number of times a command must be run with bench_command
 # Can be overrided with 'the option -n'
-count=2
+count=5
 
 function usage()
 {
@@ -28,8 +28,6 @@ function usage()
        echo "  -h: this help"
        echo ""
        echo "Benches : "
-       echo "  all : all benches"
-       echo "    - usage : * max_nb_cct loops strlen"
        echo "  iter: bench iterations"
        echo "    - usage : iter max_nb_cct loops strlen"
        echo "  cct: concatenation benching"
@@ -40,21 +38,20 @@ function usage()
        echo "    - usage : array nb_cct loops max_arrlen"
 }
 
-function benches()
-{
-       bench_concat $@;
-       bench_iteration $@;
-       bench_substr $@;
-       bench_array $@;
-}
-
 function bench_array()
 {
+       if [ -d arraytos ]; then
+               rm arraytos/*
+       else
+               mkdir arraytos
+       fi
+       cd arraytos
+
        if $verbose; then
                echo "*** Benching Array.to_s performance ***"
        fi
 
-       ../bin/nitc --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\""
+       ../../../bin/nitc --global ../array_tos.nit -m ../array_to_s_vars/array_to_s_rope.nit
 
        prepare_res arr_tos_ropes.out arr_tos_ropes ropes
        if $verbose; then
@@ -64,23 +61,10 @@ function bench_array()
                if $verbose; then
                        echo "String length = $i, Concats/loop = $1, Loops = $2"
                fi
-               bench_command $i ropes$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
+               bench_command $i ropes$i ./array_tos --loops $2 --strlen $i --ccts $1
        done
 
-       ../bin/nitc --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/nitc --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_flatstr.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+       ../../../bin/nitc --global ../array_tos.nit -m ../array_to_s_vars/array_to_s_flatstr.nit
 
        prepare_res arr_tos_flat.out arr_tos_flat flatstring
        if $verbose; then
@@ -90,10 +74,10 @@ function bench_array()
                if $verbose; then
                        echo "String length = $i, Concats/loop = $1, Loops = $2"
                fi
-               bench_command $i flatstring$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
+               bench_command $i flatstring$i ./array_tos --loops $2 --strlen $i --ccts $1
        done
 
-       ../bin/nitc --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_buffer.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+       ../../../bin/nitc --global ../array_tos.nit -m ../array_to_s_vars/array_to_s_buffer.nit
 
        prepare_res arr_tos_buf.out arr_tos_buf flatbuffer
        if $verbose; then
@@ -103,10 +87,10 @@ function bench_array()
                if $verbose; then
                        echo "String length = $i, Concats/loop = $1, Loops = $2"
                fi
-               bench_command $i flatbuffer$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
+               bench_command $i flatbuffer$i ./array_tos --loops $2 --strlen $i --ccts $1
        done
 
-       ../bin/nitc --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_manual.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+       ../../../bin/nitc --global ../array_tos.nit -m ../array_to_s_vars/array_to_s_manual.nit
 
        prepare_res arr_tos_man.out arr_tos_man memmove
        if $verbose; then
@@ -116,10 +100,10 @@ function bench_array()
                if $verbose; then
                        echo "String length = $i, Concats/loop = $1, Loops = $2"
                fi
-               bench_command $i memmove$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
+               bench_command $i memmove$i ./array_tos --loops $2 --strlen $i --ccts $1
        done
 
-       ../bin/nitc --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_man_buf.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+       ../../../bin/nitc --global ../array_tos.nit -m ../array_to_s_vars/array_to_s_man_buf.nit
 
        prepare_res arr_tos_man_buf.out arr_tos_man_buf flatbuf_with_capacity
        if $verbose; then
@@ -129,10 +113,10 @@ function bench_array()
                if $verbose; then
                        echo "String length = $i, Concats/loop = $1, Loops = $2"
                fi
-               bench_command $i flatbuf_with_capacity$i ./array_tos --loops $2 --strlen $i --ccts $1 "NIT_GC_CHOOSER=large"
+               bench_command $i flatbuf_with_capacity$i ./array_tos --loops $2 --strlen $i --ccts $1
        done
 
-       ../bin/nitc --global ./strings/array_tos.nit -m ./strings/array_to_s_vars/array_to_s_rope_buf.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+       ../../../bin/nitc --global ../array_tos.nit -m ../array_to_s_vars/array_to_s_rope_buf.nit
 
        prepare_res arr_tos_rope_buf.out arr_tos_rope_buf ropebuf
        if $verbose; then
@@ -142,16 +126,24 @@ function bench_array()
                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"
+               bench_command $i ropebuf$i ./array_tos --loops $2 --strlen $i --ccts $1
        done
 
        plot array_tos.gnu
+
+       cd ..
 }
 
 function bench_concat()
 {
-       ../bin/nitc --global ./strings/chain_concat.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-       ../bin/nitc --global ./strings/utf_chain_concat.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+       if [ -d string_concat ]; then
+               rm string_concat/*
+       else
+               mkdir string_concat
+       fi
+       cd string_concat
+
+       ../../../bin/nitc --global ../chain_concat.nit
 
        if $verbose; then
                echo "*** Benching concat performance ***"
@@ -165,7 +157,7 @@ function bench_concat()
                if $verbose; then
                        echo "String length = $i, Concats/loop = $2, Loops = $3"
                fi
-               bench_command $i flatstring$i ./chain_concat -m flatstr --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i flatstring$i ./chain_concat -m flatstr --loops $2 --strlen $3 --ccts $i
        done
 
        prepare_res concat_buf.out concat_buf flatbuffer
@@ -176,22 +168,9 @@ function bench_concat()
                if $verbose; then
                        echo "String length = $i, Concats/loop = $2, Loops = $3"
                fi
-               bench_command $i flatbuffer$i ./chain_concat -m flatbuf --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i flatbuffer$i ./chain_concat -m flatbuf --loops $2 --strlen $3 --ccts $i
        done
 
-       prepare_res concat_flatstr_utf8_noindex.out concat_flatstr_utf8_noindex flatstring_utf8_noindex
-       if $verbose; then
-               echo "FlatString UTF-8 (without index) :"
-       fi
-       for i in `seq 1 "$1"`; do
-               if $verbose; then
-                       echo "String length = $i, Concats/loop = $2, Loops = $3"
-               fi
-               bench_command $i flatstr_utf8_noindex$i ./utf_chain_concat -m flatstr_utf8_noindex --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
-       done
-
-       ../bin/nitc --global ./strings/chain_concat.nit -m ../lib/standard/ropes.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-
        prepare_res concat_ropes.out concat_ropes ropes
        if $verbose; then
                echo "Ropes :"
@@ -200,46 +179,39 @@ function bench_concat()
                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"
+               bench_command $i ropes$i ./chain_concat -m ropestr --loops $2 --strlen $3 --ccts $i
        done
 
-       ../bin/nitc --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 "buffered 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 buf_ropes$i ./chain_concat -m flatstr --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
-       done
-
-       ../bin/nitc --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 "buffered ropes :"
+               echo "Rope Buffer:"
        fi
        for i in `seq 1 "$1"`; do
                if $verbose; then
                        echo "string length = $i, concats/loop = $2, loops = $3"
                fi
-               bench_command $i cctbuf_ropes$i ./chain_cct_ropebuf --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i buf_ropes$i ./chain_concat -m ropebuf --loops $2 --strlen $3 --ccts $i
        done
 
        plot concat.gnu
+
+       cd ..
 }
 
 function bench_iteration()
 {
+       if [ -d string_iter ]; then
+               rm string_iter/*
+       else
+               mkdir string_iter
+       fi
+       cd string_iter
+
        if $verbose; then
                echo "*** Benching iteration performance ***"
        fi
 
-       ../bin/nitc --global ./strings/iteration_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-       ../bin/nitc --global ./strings/utf_iteration_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+       ../../../bin/nitc --global ../iteration_bench.nit
 
        prepare_res iter_flat_iter.out iter_flat_iter flatstring_iter
        if $verbose; then
@@ -249,7 +221,7 @@ function bench_iteration()
                if $verbose; then
                        echo "String base length = $1, Concats = $i, Loops = $3"
                fi
-               bench_command $i flatstr_iter$i ./iteration_bench -m flatstr --iter-mode iterator --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i flatstr_iter$i ./iteration_bench -m flatstr --iter-mode iterator --loops $2 --strlen $3 --ccts $i
        done
 
        prepare_res iter_flat_index.out iter_flat_index flatstring_index
@@ -260,7 +232,7 @@ function bench_iteration()
                if $verbose; then
                        echo "String base length = $1, Concats = $i, Loops = $3"
                fi
-               bench_command $i flatstr_index$i ./iteration_bench -m flatstr --iter-mode index --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i flatstr_index$i ./iteration_bench -m flatstr --iter-mode index --loops $2 --strlen $3 --ccts $i
        done
 
        prepare_res iter_buf_iter.out iter_buf_iter flatbuffer_iter
@@ -271,7 +243,7 @@ function bench_iteration()
                if $verbose; then
                        echo "String base length = $1, Concats = $i, Loops = $3"
                fi
-               bench_command $i flatbuf_iter$i ./iteration_bench -m flatbuf --iter-mode iterator --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i flatbuf_iter$i ./iteration_bench -m flatbuf --iter-mode iterator --loops $2 --strlen $3 --ccts $i
        done
 
        prepare_res iter_buf_index.out iter_buf_index flatbuffer_index
@@ -282,33 +254,9 @@ function bench_iteration()
                if $verbose; then
                        echo "String base length = $1, Concats = $i, Loops = $3"
                fi
-               bench_command $i flatbuf_index$i ./iteration_bench -m flatbuf --iter-mode index --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i flatbuf_index$i ./iteration_bench -m flatbuf --iter-mode index --loops $2 --strlen $3 --ccts $i
        done
 
-       prepare_res iter_flat_utf8_noindex_iter.out iter_flat_iter_utf8_noindex flatstring_utf8_noindex_iter
-       if $verbose; then
-               echo "FlatStrings by iterator :"
-       fi
-       for i in `seq 1 "$1"`; do
-               if $verbose; then
-                       echo "String base length = $1, Concats = $i, Loops = $3"
-               fi
-               bench_command $i flatstr_iter_utf8_noindex$i ./utf_iteration_bench -m flatstr_utf8_noindex --iter-mode iterator --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
-       done
-
-       prepare_res iter_flat_utf8_noindex_index.out iter_flat_index_utf8_noindex flatstring_utf8_noindex_index
-       if $verbose; then
-               echo "FlatStrings by index :"
-       fi
-       for i in `seq 1 "$1"`; do
-               if $verbose; then
-                       echo "String base length = $1, Concats = $i, Loops = $3"
-               fi
-               bench_command $i flatstr_index_utf8_noindex$i ./utf_iteration_bench -m flatstr_utf8_noindex --iter-mode index --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
-       done
-
-       ../bin/nitc --global ./strings/iteration_bench.nit -m ../lib/standard/ropes.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-
        prepare_res iter_ropes_iter.out iter_ropes_iter ropes_iter
        if $verbose; then
                echo "Ropes by iterator :"
@@ -317,7 +265,7 @@ function bench_iteration()
                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"
+               bench_command $i ropes_iter$i ./iteration_bench -m ropestr --iter-mode iterator --loops $2 --strlen $3 --ccts $i
        done
 
        prepare_res iter_ropes_index.out iter_ropes_index ropes_index
@@ -328,44 +276,50 @@ function bench_iteration()
                if $verbose; then
                        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"
+               bench_command $i ropes_index$i ./iteration_bench -m ropestr --iter-mode index --loops $2 --strlen $3 --ccts $i
        done
 
-       ../bin/nitc --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 :"
+               echo "RopeBuffer 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"
+               bench_command $i buf_ropes_iter$i ./iteration_bench -m ropebuf --iter-mode iterator --loops $2 --strlen $3 --ccts $i
        done
 
        prepare_res iter_buf_ropes_index.out iter_buf_ropes_index buf_ropes_index
        if $verbose; then
-               echo "Buffered Ropes by index :"
+               echo "RopeBuffer 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 buf_ropes_index$i ./iteration_bench -m flatstr --iter-mode index --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i buf_ropes_index$i ./iteration_bench -m ropebuf --iter-mode index --loops $2 --strlen $3 --ccts $i
        done
 
        plot iter.gnu
+
+       cd ..
 }
 
 function bench_substr()
 {
+       if [ -d string_substr ]; then
+               rm string_substr/*
+       else
+               mkdir string_substr
+       fi
+       cd string_substr
+
        if $verbose; then
                echo "*** Benching substring performance ***"
        fi
 
-       ../bin/nitc --global ./strings/substr_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
-       ../bin/nitc --global ./strings/utf_substr_bench.nit --make-flags "CFLAGS=\"-g -O2 -DNOBOEHM\""
+       ../../../bin/nitc --global ../substr_bench.nit
 
        prepare_res substr_flat.out substr_flat flatstring
        if $verbose; then
@@ -375,7 +329,7 @@ function bench_substr()
                if $verbose; then
                        echo "String length = $i, loops = $2, Loops = $3"
                fi
-               bench_command $i flatstring$i ./substr_bench -m flatstr --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i flatstring$i ./substr_bench -m flatstr --loops $2 --strlen $3 --ccts $i
        done
 
        prepare_res substr_buf.out substr_buf flatbuffer
@@ -386,22 +340,9 @@ function bench_substr()
                if $verbose; then
                        echo "String length = $i, loops = $2, Loops = $3"
                fi
-               bench_command $i flatbuffer$i ./substr_bench -m flatbuf --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
-       done
-
-       prepare_res substr_flat_utf8_noindex.out substr_flat_utf8_noindex flatstring_utf8_noindex
-       if $verbose; then
-               echo "FlatStrings UTF-8 (without index) :"
-       fi
-       for i in `seq 1 "$1"`; do
-               if $verbose; then
-                       echo "String length = $i, loops = $2, Loops = $3"
-               fi
-               bench_command $i flatstring_utf8_noindex$i ./utf_substr_bench -m flatstr_utf8_noindex --loops $2 --strlen $3 --ccts $i "NIT_GC_CHOOSER=large"
+               bench_command $i flatbuffer$i ./substr_bench -m flatbuf --loops $2 --strlen $3 --ccts $i
        done
 
-       ../bin/nitc --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 :"
@@ -410,22 +351,23 @@ function bench_substr()
                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"
+               bench_command $i ropes$i ./substr_bench -m ropestr --loops $2 --strlen $3 --ccts $i
        done
 
-       ../bin/nitc --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 :"
+               echo "RopeBuffers :"
        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"
+               bench_command $i buf_ropes$i ./substr_bench -m ropebuf --loops $2 --strlen $3 --ccts $i
        done
+
        plot substr.gnu
+
+       cd ..
 }
 
 stop=false
@@ -448,6 +390,5 @@ case "$1" in
        cct) shift; bench_concat $@ ;;
        substr) shift; bench_substr $@ ;;
        array) shift; bench_array $@ ;;
-       all) shift; benches $@ ;;
        *) usage; exit;;
 esac
index a45075f..a70dd14 100644 (file)
 # Benches measuring the performance of several concatenations on Text variants
 module chain_concat
 
+intrude import standard::ropes
 import opts
 
+redef class FlatString
+       redef fun +(o) do
+               var mlen = length
+               var slen = o.length
+               var nlen = mlen + slen
+               var ns = new NativeString(nlen + 1)
+               items.copy_to(ns, mlen, index_from, 0)
+               if o isa FlatString then
+                       o.items.copy_to(ns, slen, o.index_from, 0)
+               else
+                       var pos = mlen
+                       for i in o.chars do
+                               ns[pos] = i
+                               pos += 1
+                       end
+               end
+               return ns.to_s_with_length(nlen)
+       end
+end
+
 fun bench_flatstr(str_size: Int, nb_ccts: Int, loops: Int)
 do
        var lft = "a" * str_size
 
-       for i in [0..loops] do
-               var str: String = lft
-               for j in [0..nb_ccts] do
+       for i in [0 .. loops[ do
+               var str: String = ""
+               for j in [0 .. nb_ccts[ do
                        str += lft
                end
        end
 end
 
+fun bench_ropestr(str_size, nb_ccts, loops: Int) do
+       var lft = "a" * str_size
+
+       for i in [0 .. loops[ do
+               var str: String = ""
+               for j in [0 .. nb_ccts[ do
+                       str = new Concat(str, lft)
+               end
+       end
+end
+
 fun bench_flatbuf(str_size: Int, nb_ccts: Int, loops: Int)
 do
        var lft = "a" * str_size
 
-       for i in [0..loops] do
-               var buf = new FlatBuffer.from(lft)
-               for j in [0..nb_ccts] do
+       for i in [0 .. loops[ do
+               var buf = new FlatBuffer
+               for j in [0 .. nb_ccts[ do
+                       buf.append(lft)
+               end
+       end
+end
+
+fun bench_ropebuf(str_size: Int, nb_ccts: Int, loops: Int)
+do
+       var lft = "a" * str_size
+
+       for i in [0 .. loops[ do
+               var buf = new RopeBuffer
+               for j in [0 .. nb_ccts[ do
                        buf.append(lft)
                end
-               buf.to_s
        end
 end
 
 var opts = new OptionContext
-var mode = new OptionEnum(["flatstr", "flatbuf"], "Mode", -1, "-m")
+var mode = new OptionEnum(["flatstr", "ropestr", "flatbuf", "ropebuf"], "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")
@@ -57,7 +100,12 @@ var modval = mode.value
 if modval == 0 then
        bench_flatstr(strlen.value, nb_ccts.value, loops.value)
 else if modval == 1 then
+       bench_ropestr(strlen.value, nb_ccts.value, loops.value)
+else if modval == 2 then
        bench_flatbuf(strlen.value, nb_ccts.value, loops.value)
+else if modval == 3 then
+       bench_ropebuf(strlen.value, nb_ccts.value, loops.value)
+
 else
        opts.usage
        exit -1
index 0e36c49..b37ad26 100644 (file)
 module iteration_bench
 
 import opts
+intrude import standard::ropes
+
+redef class Concat
+       redef fun +(o) do
+               var s = o.to_s
+               return new Concat(self, s)
+       end
+end
+
+redef class FlatString
+       redef fun +(o) do
+               var s = o.to_s
+               var b = new FlatBuffer.with_capacity(length + s.length)
+               b.append self
+               for i in s.substrings do b.append i
+               return b.to_s
+       end
+end
 
 fun bench_flatstr_iter(nb_cct: Int, loops: Int, strlen: Int)
 do
        var a = "a" * strlen
-       var x = a
-       for i in [0 .. nb_cct] do x += a
+       a = a * nb_cct
        var cnt = 0
        var c: Char
        while cnt != loops do
-               for i in x do
+               for i in a do
                        c = i
                end
                cnt += 1
@@ -31,8 +48,40 @@ end
 fun bench_flatstr_index(nb_cct: Int, loops: Int, strlen: Int)
 do
        var a = "a" * strlen
-       var x = a
-       for i in [0 .. nb_cct] do x += a
+       a = a * nb_cct
+       var cnt = 0
+       var c: Char
+       var pos = 0
+       while cnt != loops do
+               pos = 0
+               while pos < a.length do
+                       c = a[pos]
+                       pos += 1
+               end
+               cnt += 1
+       end
+end
+
+fun bench_ropestr_iter(nb_cct: Int, loops: Int, strlen: Int)
+do
+       var a = "a" * strlen
+       var x: String = new Concat(a, a)
+       for i in [2 .. nb_cct[ do x = new Concat(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_ropestr_index(nb_cct: Int, loops: Int, strlen: Int)
+do
+       var a = "a" * strlen
+       var x: String = new Concat(a, a)
+       for i in [2 .. nb_cct[ do x = new Concat(x, a)
        var cnt = 0
        var c: Char
        var pos = 0
@@ -49,8 +98,8 @@ end
 fun bench_flatbuf_iter(nb_cct: Int, loops: Int, strlen: Int)
 do
        var a = "a" * strlen
+       a = a * nb_cct
        var x = new FlatBuffer.from(a)
-       for i in [0 .. nb_cct] do x.append a
        var cnt = 0
        var c: Char
        while cnt != loops do
@@ -64,8 +113,41 @@ end
 fun bench_flatbuf_index(nb_cct: Int, loops: Int, strlen: Int)
 do
        var a = "a" * strlen
+       a = a * nb_cct
        var x = new FlatBuffer.from(a)
-       for i in [0 .. nb_cct] do x.append 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_ropebuf_iter(nb_cct: Int, loops: Int, strlen: Int)
+do
+       var a = "a" * strlen
+       var x = new RopeBuffer.from(a)
+       for i in [0 .. nb_cct[ do x.append 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_ropebuf_index(nb_cct: Int, loops: Int, strlen: Int)
+do
+       var a = "a" * strlen
+       var x = new RopeBuffer.from(a)
+       for i in [0 .. nb_cct[ do x.append a
        var cnt = 0
        var c: Char
        var pos = 0
@@ -80,7 +162,7 @@ do
 end
 
 var opts = new OptionContext
-var mode = new OptionEnum(["flatstr", "flatbuf"], "Mode", -1, "-m")
+var mode = new OptionEnum(["flatstr", "flatbuf", "ropestr", "ropebuf"], "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")
@@ -115,6 +197,24 @@ else if modval == 1 then
                opts.usage
                exit(-1)
        end
+else if modval == 2 then
+       if iterval == 0 then
+               bench_ropestr_iter(nb_ccts.value, loops.value, strlen.value)
+       else if iterval == 1 then
+               bench_ropestr_index(nb_ccts.value, loops.value, strlen.value)
+       else
+               opts.usage
+               exit(-1)
+       end
+else if modval == 3 then
+       if iterval == 0 then
+               bench_ropebuf_iter(nb_ccts.value, loops.value, strlen.value)
+       else if iterval == 1 then
+               bench_ropebuf_index(nb_ccts.value, loops.value, strlen.value)
+       else
+               opts.usage
+               exit(-1)
+       end
 else
        opts.usage
        exit(-1)
index effb9ec..3727960 100644 (file)
 module substr_bench
 
 import opts
+intrude import standard::ropes
 
 fun bench_flatstr(nb_cct: Int, loops: Int, strlen: Int)
 do
        var a = "a" * strlen
-       var x = a
-       for i in [0 .. nb_cct] do x += a
+       a = a * nb_cct
+       var maxl = a.length - 1
        var cnt = 0
        while cnt != loops do
-               x.substring(0,5)
+               a.substring(maxl.rand, maxl.rand)
                cnt += 1
        end
 end
@@ -28,17 +29,44 @@ end
 fun bench_flatbuf(nb_cct: Int, loops: Int, strlen: Int)
 do
        var a = "a" * strlen
+       a = a * nb_cct
+       var maxl = a.length - 1
        var x = new FlatBuffer.from(a)
-       for i in [0 .. nb_cct] do x.append a
        var cnt = 0
        while cnt != loops do
-               x.substring(0,5)
+               x.substring(maxl.rand, maxl.rand)
+               cnt += 1
+       end
+end
+
+fun bench_ropestr(nb_cct: Int, loops: Int, strlen: Int)
+do
+       var a = "a" * strlen
+       var x = new Concat(a, a)
+       for i in [2 .. nb_cct[ do x = new Concat(x, a)
+       var maxl = x.length - 1
+       var cnt = 0
+       while cnt != loops do
+               x.substring(maxl.rand, maxl.rand)
+               cnt += 1
+       end
+end
+
+fun bench_ropebuf(nb_cct: Int, loops: Int, strlen: Int)
+do
+       var a = "a" * strlen
+       var x = new RopeBuffer.from(a)
+       for i in [1 .. nb_cct[ do x.append a
+       var maxl = x.length - 1
+       var cnt = 0
+       while cnt != loops do
+               x.substring(maxl.rand, maxl.rand)
                cnt += 1
        end
 end
 
 var opts = new OptionContext
-var mode = new OptionEnum(["flatstr", "flatbuf"], "Mode", -1, "-m")
+var mode = new OptionEnum(["flatstr", "flatbuf", "ropestr", "ropebuf"], "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")
@@ -52,11 +80,16 @@ if nb_ccts.value == -1 or loops.value == -1 or strlen.value == -1 then
 end
 
 var modval = mode.value
+srand_from(0)
 
 if modval == 0 then
        bench_flatstr(nb_ccts.value, loops.value, strlen.value)
 else if modval == 1 then
        bench_flatbuf(nb_ccts.value, loops.value, strlen.value)
+else if modval == 2 then
+       bench_ropestr(nb_ccts.value, loops.value, strlen.value)
+else if modval == 3 then
+       bench_ropebuf(nb_ccts.value, loops.value, strlen.value)
 else
        opts.usage
        exit(-1)
diff --git a/benchmarks/strings/utf_chain_concat.nit b/benchmarks/strings/utf_chain_concat.nit
deleted file mode 100644 (file)
index d720403..0000000
+++ /dev/null
@@ -1,42 +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.
-
-# Benches measuring the performance of several concatenations on Text variants
-module utf_chain_concat
-
-import opts
-import string_experimentations::utf8_noindex
-
-fun bench_flatstr(str_size: Int, nb_ccts: Int, loops: Int)
-do
-       var lft = "a" * str_size
-
-       for i in [0..loops] do
-               var str: String = lft
-               for j in [0..nb_ccts] do
-                       str += lft
-               end
-       end
-end
-
-var opts = new OptionContext
-var nb_ccts = new OptionInt("Number of concatenations per loop", -1, "--ccts")
-var loops = new OptionInt("Number of loops to be done", -1, "--loops")
-var strlen = new OptionInt("Length of the base string", -1, "--strlen")
-opts.add_option(nb_ccts, loops, strlen)
-
-opts.parse(args)
-
-if nb_ccts.value == -1 or loops.value == -1 or strlen.value == -1 then
-       opts.usage
-       exit -1
-end
-
-bench_flatstr(strlen.value, nb_ccts.value, loops.value)
diff --git a/benchmarks/strings/utf_iteration_bench.nit b/benchmarks/strings/utf_iteration_bench.nit
deleted file mode 100644 (file)
index 80277c0..0000000
+++ /dev/null
@@ -1,74 +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.
-
-# Benches for iteration on variants of Text
-module utf_iteration_bench
-
-import opts
-import string_experimentations::utf8_noindex
-
-fun bench_flatstr_iter(nb_cct: Int, loops: Int, strlen: Int)
-do
-       var a = "a" * strlen
-       var x = a.as(FlatString)
-       for i in [0 .. nb_cct] do x = (x + a).as(FlatString)
-       var cnt = 0
-       var c: UnicodeChar
-       while cnt != loops do
-               var it = new FlatStringIter(x)
-               for i in it do
-                       c = i
-               end
-               cnt += 1
-       end
-end
-
-fun bench_flatstr_index(nb_cct: Int, loops: Int, strlen: Int)
-do
-       var a = "a" * strlen
-       var x = a.as(FlatString)
-       for i in [0 .. nb_cct] do x = (x + a).as(FlatString)
-       var cnt = 0
-       var c: UnicodeChar
-       var pos = 0
-       while cnt != loops do
-               pos = 0
-               while pos < x.length do
-                       c = x.char_at(pos)
-                       pos += 1
-               end
-               cnt += 1
-       end
-end
-
-var opts = new OptionContext
-var access_mode = new OptionEnum(["iterator", "index"], "Iteration mode", -1, "--iter-mode")
-var nb_ccts = new OptionInt("Number of concatenations done to the string (in the case of the rope, this will increase its depth)", -1, "--ccts")
-var loops = new OptionInt("Number of loops to be done", -1, "--loops")
-var strlen = new OptionInt("Length of the base string", -1, "--strlen")
-opts.add_option(nb_ccts, loops, strlen, access_mode)
-
-opts.parse(args)
-
-if nb_ccts.value == -1 or loops.value == -1 or strlen.value == -1 then
-       opts.usage
-       exit(-1)
-end
-
-var iterval = access_mode.value
-
-if iterval == 0 then
-       bench_flatstr_iter(nb_ccts.value, loops.value, strlen.value)
-else if iterval == 1 then
-       bench_flatstr_index(nb_ccts.value, loops.value, strlen.value)
-else
-       opts.usage
-       exit(-1)
-end
diff --git a/benchmarks/strings/utf_substr_bench.nit b/benchmarks/strings/utf_substr_bench.nit
deleted file mode 100644 (file)
index 7d71a8b..0000000
+++ /dev/null
@@ -1,42 +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.
-
-# Benches on the substring operation on variants of Text
-module utf_substr_bench
-
-import opts
-import string_experimentations::utf8_noindex
-
-fun bench_flatstr(nb_cct: Int, loops: Int, strlen: Int)
-do
-       var a = "a" * strlen
-       var x = a
-       for i in [0 .. nb_cct] do x += a
-       var cnt = 0
-       while cnt != loops do
-               x.substring(0,5)
-               cnt += 1
-       end
-end
-
-var opts = new OptionContext
-var nb_ccts = new OptionInt("Number of concatenations done to the string (in the case of the rope, this will increase its depth)", -1, "--ccts")
-var loops = new OptionInt("Number of loops to be done", -1, "--loops")
-var strlen = new OptionInt("Length of the base string", -1, "--strlen")
-opts.add_option(nb_ccts, loops, strlen)
-
-opts.parse(args)
-
-if nb_ccts.value == -1 or loops.value == -1 or strlen.value == -1 then
-       opts.usage
-       exit(-1)
-end
-
-bench_flatstr(nb_ccts.value, loops.value, strlen.value)
diff --git a/bin/Makefile b/bin/Makefile
new file mode 100644 (file)
index 0000000..45a278a
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright 2013 Alexandre Terrasa <alexandre@moz-code.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.
+
+all: run
+
+run: hello_world.jar
+       java -jar hello_world.jar
+
+hello_world.jar: nitj
+       NIT_DIR= ./nitj ../examples/hello_world.nit
+
+nitj:
+       NIT_DIR= ./nitg ../src/nitj.nit
+
+clean:
+       rm -rf -- hello_world.jar .nit_jcompile 2> /dev/null || true
diff --git a/lib/html/bootstrap.nit b/lib/html/bootstrap.nit
new file mode 100644 (file)
index 0000000..66befa3
--- /dev/null
@@ -0,0 +1,466 @@
+# 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.
+
+# HTML templates for Bootstrap components.
+#
+# See http://getbootstrap.com/components/
+module bootstrap
+
+import template
+
+# Bootstrap component abstraction.
+#
+# Mainly used to factoryze CSS treatments.
+# Can be used in the future to handle generic stuff like attributes or escaping.
+#
+# TODO merge with html::HTMTag without init conflict?
+# HTMLTag requires the main init to pass a tagname,
+# this was so much verbose here.
+abstract class BSComponent
+       super Template
+
+       # CSS classes to add on this element.
+       var css_classes = new Array[String]
+
+       # Render `self` css clases as a `class` attribute.
+       fun render_css_classes: String do
+               if css_classes.is_empty then return ""
+               return " class=\"{css_classes.join(" ")}\""
+       end
+end
+
+# A `<a>` tag.
+#
+# Not really a Bootstrap component but used in other components
+# that it required its own abstraction.
+#
+# Example:
+# ~~~
+# var lnk = new Link("http://nitlanguage.org", "Nit")
+# assert lnk.write_to_string == "<a href=\"http://nitlanguage.org\">Nit</a>"
+# ~~~
+#
+# Creates a link with a title attribute:
+# ~~~
+# lnk = new Link.with_title("http://nitlanguage.org", "Nit", "Nit homepage")
+# assert lnk.write_to_string == "<a href=\"http://nitlanguage.org\" title=\"Nit homepage\">Nit</a>"
+# ~~~
+class Link
+       super BSComponent
+
+       # URL pointed by this link.
+       var href: String is writable
+
+       # Displayed text.
+       var text: Writable is writable
+
+       # Optional title.
+       var title: nullable String is noinit, writable
+
+       # Creates a link with a `title` attribute.
+       init with_title(href: String, text: Writable, title: nullable String) do
+               self.href = href
+               self.text = text
+               self.title = title
+       end
+
+       redef fun rendering do
+               add "<a{render_css_classes} href=\"{href}\""
+               if title != null then add " title=\"{title.write_to_string}\""
+               add ">{text}</a>"
+       end
+end
+
+# A `<h1>` to `<h6>` tag.
+#
+# Not really a Bootstrap component but used in other components
+# that it required its own abstraction.
+#
+# Example:
+# ~~~
+# var h1 = new Header(1, "Title")
+# assert h1.write_to_string == "<h1>Title</h1>"
+# ~~~
+#
+# With subtext:
+# ~~~
+# var h6 = new Header.with_subtext(6, "Title", "with subtext")
+# assert h6.write_to_string == "<h6>Title<small>with subtext</small></h6>"
+# ~~~
+class Header
+       super BSComponent
+
+       # Header level between 1 and 6.
+       var level: Int
+
+       # Displayed text.
+       var text: Writable
+
+       # Optional subtext.
+       var subtext: nullable Writable is noinit, writable
+
+       # Creates a link with a `title` attribute.
+       init with_subtext(level: Int, text: Writable, subtext: String) do
+               self.level = level
+               self.text = text
+               self.subtext = subtext
+       end
+
+       redef fun rendering do
+               add "<h{level}{render_css_classes}>{text.write_to_string}"
+               if subtext != null then add "<small>{subtext.write_to_string}</small>"
+               add "</h{level}>"
+       end
+end
+
+# An abstract HTML list.
+#
+# Many Bootstrap components are built around a HTML list.
+#
+# Used to factorize behavior between OrderedList and UnorderedList.
+abstract class HTMLList
+       super BSComponent
+
+       # A list contains `<li>` tags as children.
+       #
+       # See ListItem.
+       var items = new Array[ListItem]
+
+       # Adds a new ListItem to `self`.
+       fun add_li(item: ListItem) do items.add item
+
+       # Does `self` contains no items?
+       fun is_empty: Bool do return items.is_empty
+end
+
+# A `<ol>` list tag.
+#
+# Example:
+#
+# ~~~
+# var lst = new OrderedList
+# lst.add_li(new ListItem("foo"))
+# lst.add_li(new ListItem("bar"))
+# lst.add_li(new ListItem("baz"))
+#
+# assert lst.write_to_string == """
+# <ol>
+# <li>foo</li>
+# <li>bar</li>
+# <li>baz</li>
+# </ol>
+# """
+# ~~~
+class OrderedList
+       super HTMLList
+
+       redef fun rendering do
+               addn "<ol{render_css_classes}>"
+               for item in items do add item
+               addn "</ol>"
+       end
+end
+
+# A `<ul>` list tag.
+#
+# Example:
+#
+# ~~~
+# var lst = new UnorderedList
+# lst.add_li(new ListItem("foo"))
+# lst.add_li(new ListItem("bar"))
+# lst.add_li(new ListItem("baz"))
+#
+# assert lst.write_to_string == """
+# <ul>
+# <li>foo</li>
+# <li>bar</li>
+# <li>baz</li>
+# </ul>
+# """
+# ~~~
+class UnorderedList
+       super HTMLList
+
+       redef fun rendering do
+               addn "<ul{render_css_classes}>"
+               for item in items do add item
+               addn "</ul>"
+       end
+end
+
+# A `<li>` tag.
+class ListItem
+       super BSComponent
+
+       # Content to display in this list item.
+       var text: Writable is writable
+
+       redef fun rendering do addn "<li{render_css_classes}>{text.write_to_string}</li>"
+end
+
+# A Boostrap icon.
+#
+# See http://getbootstrap.com/components/#glyphicons
+#
+# Example:
+#
+# ~~~
+# var icon = new BSIcon("star")
+# assert icon.write_to_string == "<span class=\"glyphicon glyphicon-star\" aria-hidden=\"true\"></span>"
+# ~~~
+class BSIcon
+       super BSComponent
+
+       # Glyphicon name to display.
+       #
+       # See full list at http://getbootstrap.com/components/#glyphicons.
+       var icon: String
+
+       init do css_classes.add "glyphicon glyphicon-{icon}"
+
+       redef fun rendering do
+               add "<span{render_css_classes} aria-hidden=\"true\"></span>"
+       end
+end
+
+# A Bootstrap breadcrumbs component.
+#
+# See http://getbootstrap.com/components/#breadcrumbs
+#
+# Example:
+#
+# ~~~
+# var bc = new BSBreadCrumbs
+# bc.add_li(new ListItem("foo"))
+# bc.add_li(new ListItem("bar"))
+# bc.add_li(new ListItem("baz"))
+#
+# assert bc.write_to_string == """
+# <ol class=\"breadcrumbs\">
+# <li>foo</li>
+# <li>bar</li>
+# <li class=\"active\">baz</li>
+# </ol>
+# """
+# ~~~
+class BSBreadCrumbs
+       super OrderedList
+
+       init do css_classes.add "breadcrumbs"
+
+       redef fun rendering do
+               items.last.css_classes.add "active"
+               super
+       end
+end
+
+# A Bootstrap label component.
+#
+# See http://getbootstrap.com/components/#labels
+#
+# Example:
+#
+# ~~~
+# var lbl = new BSLabel("danger", "Danger!")
+# assert lbl.write_to_string == "<span class=\"label label-danger\">Danger!</span>"
+# ~~~
+class BSLabel
+       super BSComponent
+
+       # Class used to change the color of the label.
+       #
+       # Can be one of `default`, `primary`, `success`, `info`, `warning` or `danger`.
+       var color: String
+
+       # Text to display in the label.
+       var text: Writable
+
+       init do css_classes.add "label label-{color}"
+
+       redef fun rendering do
+               add "<span{render_css_classes}>{text.write_to_string}</span>"
+       end
+end
+
+# A Bootstrap badge component.
+#
+# See http://getbootstrap.com/components/#badges
+#
+# Example:
+#
+# ~~~
+# var b = new BSBadge("42 messages")
+# assert b.write_to_string == "<span class=\"badge\">42 messages</span>"
+# ~~~
+class BSBadge
+       super BSComponent
+
+       # Text to display in the label.
+       var text: Writable
+
+       init do css_classes.add "badge"
+
+       redef fun rendering do
+               add "<span{render_css_classes}>{text.write_to_string}</span>"
+       end
+end
+
+# A Bootstrap page header component.
+#
+# See http://getbootstrap.com/components/#page-header
+#
+# Example:
+#
+# ~~~
+# var h = new BSPageHeader("Welcome")
+# assert h.write_to_string == """
+# <div class=\"page-header\">
+# Welcome
+# </div>
+# """
+# ~~~
+class BSPageHeader
+       super BSComponent
+
+       # Text to display as title.
+       var text: Writable
+
+       init do css_classes.add "page-header"
+
+       redef fun rendering do
+               addn "<div{render_css_classes}>"
+               addn text.write_to_string
+               addn "</div>"
+       end
+end
+
+# A Bootstrap alert component.
+#
+# See http://getbootstrap.com/components/#alerts
+#
+# Example:
+#
+# ~~~
+# var alert = new BSAlert("danger", "Danger!")
+# assert alert.write_to_string == """
+# <div class="alert alert-danger">
+# Danger!
+# </div>
+# """
+# ~~~
+class BSAlert
+       super BSComponent
+
+       # Class used to change the color of the alert.
+       #
+       # Can be one of `primary`, `success`, `info`, `warning` or `danger`.
+       var color: String
+
+       # Text to display in the alert.
+       var text: Writable
+
+       # Can the alert be dismissed by clicking the close button?
+       #
+       # See http://getbootstrap.com/components/#alerts-dismissible
+       #
+       # Default is `false`.
+       var is_dismissible = false
+
+       init do css_classes.add "alert alert-{color}"
+
+       redef fun rendering do
+               addn "<div{render_css_classes}>"
+               if is_dismissible then
+                       add "<button type=\"button\" class=\"close\" data-dismiss=\"alert\""
+                       add "aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>"
+                       addn "</button>"
+               end
+               addn text.write_to_string
+               addn "</div>"
+       end
+end
+
+# A Bootstrap panel component.
+#
+# See http://getbootstrap.com/components/#panels
+#
+# Example:
+#
+# ~~~
+# var p = new BSPanel("default", "Panel content")
+#
+# assert p.write_to_string == """
+# <div class="panel panel-default">
+# <div class="panel-body">
+# Panel content
+# </div>
+# </div>
+# """
+# ~~~
+#
+# Panel with heading:
+#
+# ~~~
+# p = new BSPanel("danger", "Panel content")
+# p.heading = "Panel heading"
+#
+# assert p.write_to_string == """
+# <div class="panel panel-danger">
+# <div class="panel-heading">
+# Panel heading
+# </div>
+# <div class="panel-body">
+# Panel content
+# </div>
+# </div>
+# """
+# ~~~
+class BSPanel
+       super BSComponent
+
+       # Panel color.
+       #
+       # Can be one of `default`, `primary`, `success`, `info`, `warning` or `danger`.
+       var color: String
+
+       # Panel header if any.
+       var heading: nullable Writable is noinit, writable
+
+       # Body to display in the panel.
+       var body: Writable
+
+       # Panel footer is any.
+       var footer: nullable Writable is noinit, writable
+
+       init do css_classes.add "panel panel-{color}"
+
+       redef fun rendering do
+               addn "<div{render_css_classes}>"
+               if heading != null then
+                       addn "<div class=\"panel-heading\">"
+                       addn heading.write_to_string
+                       addn "</div>"
+               end
+               addn "<div class=\"panel-body\">"
+               addn body.write_to_string
+               addn "</div>"
+               if footer != null then
+                       addn "<div class=\"panel-footer\">"
+                       addn footer.write_to_string
+                       addn "</div>"
+               end
+               addn "</div>"
+       end
+end
index e974d91..409b4ed 100644 (file)
@@ -864,6 +864,23 @@ abstract class FlatText
        # Real items, used as cache for to_cstring is called
        private var real_items: nullable NativeString = null
 
+       # Returns a char* starting at position `index_from`
+       #
+       # WARNING: If you choose to use this service, be careful of the following.
+       #
+       # Strings and NativeString are *ideally* always allocated through a Garbage Collector.
+       # Since the GC tracks the use of the pointer for the beginning of the char*, it may be
+       # deallocated at any moment, rendering the pointer returned by this function invalid.
+       # Any access to freed memory may very likely cause undefined behaviour or a crash.
+       # (Failure to do so will most certainly result in long and painful debugging hours)
+       #
+       # The only safe use of this pointer is if it is ephemeral (e.g. read in a C function
+       # then immediately return).
+       #
+       # As always, do not modify the content of the String in C code, if this is what you want
+       # copy locally the char* as Nit Strings are immutable.
+       private fun fast_cstring: NativeString is abstract
+
        redef var length: Int = 0
 
        redef fun output
@@ -1119,6 +1136,8 @@ class FlatString
                return native.to_s_with_length(self.length)
        end
 
+       redef fun fast_cstring do return items.fast_cstring(index_from)
+
        redef fun substring(from, count)
        do
                assert count >= 0
@@ -1567,6 +1586,8 @@ class FlatBuffer
 
        private var capacity: Int = 0
 
+       redef fun fast_cstring do return items.fast_cstring(0)
+
        redef fun substrings do return new FlatSubstringsIter(self)
 
        # Re-copies the `NativeString` into a new one and sets it as the new `Buffer`
@@ -2289,6 +2310,12 @@ extern class NativeString `{ char* `}
        # Creates a new NativeString with a capacity of `length`
        new(length: Int) is intern
 
+       # Returns a char* starting at `index`.
+       #
+       # WARNING: Unsafe for extern code, use only for temporary
+       # pointer manipulation purposes (e.g. write to file or such)
+       fun fast_cstring(index: Int): NativeString is intern
+
        # Get char at `index`.
        fun [](index: Int): Char is intern
 
index 011b146..894a13d 100644 (file)
@@ -2197,6 +2197,9 @@ redef class AMethPropdef
                        else if pname == "atoi" then
                                v.ret(v.new_expr("atoi({arguments[0]});", ret.as(not null)))
                                return true
+                       else if pname == "fast_cstring" then
+                               v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
+                               return true
                        else if pname == "new" then
                                v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null)))
                                return true
index e947ee2..64b2022 100644 (file)
@@ -68,7 +68,7 @@ end
 abstract class DocComposite
 
        # Parent element.
-       var parent: nullable DocComposite = null
+       var parent: nullable DocComposite = null is writable
 
        # Does `self` have a `parent`?
        fun is_root: Bool do return parent == null
@@ -85,6 +85,7 @@ abstract class DocComposite
        #
        # Shortcut for `children.add`.
        fun add_child(child: DocComposite) do
+               child.parent = self
                children.add child
        end
 end
index aff25d4..66ef564 100644 (file)
@@ -41,7 +41,8 @@ class GraphPhase
                        if article == null then continue
                        # FIXME avoid diff
                        # page.root.add article
-                       page.root.children[1].children.insert(article, 0)
+                       article.parent = page.root.children.first.children[1]
+                       page.root.children.first.children[1].children.insert(article, 0)
                end
        end
 end
index 39ad273..23da906 100644 (file)
@@ -47,7 +47,8 @@ redef class MModulePage
                var clients = self.clients.to_a
                v.name_sorter.sort(clients)
                section.add_child new HierarchyListArticle(mentity, "Clients", clients)
-               root.children.insert(section, 1)
+               section.parent = root.children.first
+               root.children.first.children.insert(section, 1)
        end
 end
 
@@ -66,7 +67,8 @@ redef class MClassPage
                var descendants = self.descendants.to_a
                v.name_sorter.sort(descendants)
                section.add_child new HierarchyListArticle(mentity, "Descendants", descendants)
-               root.children.insert(section, 1)
+               section.parent = root.children.first
+               root.children.first.children.insert(section, 1)
        end
 end
 
index a11e187..7d38bc0 100644 (file)
@@ -191,7 +191,7 @@ redef class DocPage
 
        # Build top menu template if any.
        fun init_topmenu(v: RenderHTMLPhase, doc: DocModel) do
-               topmenu = new TplTopMenu(html_url)
+               topmenu = new DocTopMenu
                var brand = v.ctx.opt_custom_brand.value
                if brand != null then
                        var tpl = new Template
@@ -200,8 +200,13 @@ redef class DocPage
                        tpl.add "</span>"
                        topmenu.brand = tpl
                end
-               topmenu.add_link new TplLink("index.html", "Overview")
-               topmenu.add_link new TplLink("search.html", "Index")
+               var title = "Overview"
+               if v.ctx.opt_custom_title.value != null then
+                       title = v.ctx.opt_custom_title.value.to_s
+               end
+               topmenu.add_li new ListItem(new Link("index.html", title))
+               topmenu.add_li new ListItem(new Link("search.html", "Index"))
+               topmenu.active_item = topmenu.items.first
        end
 
        # Build page sidebar if any.
@@ -257,6 +262,12 @@ end
 redef class SearchPage
        redef var html_url = "search.html"
        redef fun init_title(v, doc) do title = "Index"
+
+       redef fun init_topmenu(v, doc) do
+               super
+               topmenu.active_item = topmenu.items.last
+       end
+
        redef fun init_sidebar(v, doc) do end
 
        # TODO this should be done in StructurePhase.
@@ -314,7 +325,7 @@ end
 
 redef class MEntityPage
        redef var html_url is lazy do return mentity.nitdoc_url
-       redef fun init_title(v, doc) do title = mentity.nitdoc_name
+       redef fun init_title(v, doc) do title = mentity.html_name
        redef fun init_content(v, doc) do add_section root.start_rendering(v, doc, self)
 end
 
@@ -327,9 +338,10 @@ redef class MGroupPage
                super
                var mproject = mentity.mproject
                if not mentity.is_root then
-                       topmenu.add_link new TplLink(mproject.nitdoc_url, mproject.nitdoc_name)
+                       topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
                end
-               topmenu.add_link new TplLink(html_url, mproject.nitdoc_name)
+               topmenu.add_li new ListItem(new Link(html_url, mproject.html_name))
+               topmenu.active_item = topmenu.items.last
        end
 
        redef fun init_sidebar(v, doc) do
@@ -366,8 +378,9 @@ redef class MModulePage
        redef fun init_topmenu(v, doc) do
                super
                var mproject = mentity.mproject
-               topmenu.add_link new TplLink(mproject.nitdoc_url, mproject.nitdoc_name)
-               topmenu.add_link new TplLink(mentity.nitdoc_url, mentity.nitdoc_name)
+               topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
+               topmenu.add_li new ListItem(new Link(mentity.nitdoc_url, mentity.html_name))
+               topmenu.active_item = topmenu.items.last
        end
 
        # Class list to display in sidebar
@@ -404,15 +417,12 @@ end
 
 redef class MClassPage
 
-       redef fun init_title(v, doc) do
-               title = "{mentity.nitdoc_name}{mentity.tpl_signature.write_to_string}"
-       end
-
        redef fun init_topmenu(v, doc) do
                super
                var mproject = mentity.intro_mmodule.mgroup.mproject
-               topmenu.add_link new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}")
-               topmenu.add_link new TplLink(html_url, mentity.nitdoc_name)
+               topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
+               topmenu.add_li new ListItem(new Link(html_url, mentity.html_name))
+               topmenu.active_item = topmenu.items.last
        end
 
        redef fun init_sidebar(v, doc) do
@@ -442,7 +452,7 @@ redef class MClassPage
                        classes.add "inherit"
                        var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
                        var def_url = "{cls_url}#{mprop.nitdoc_id}"
-                       var lnk = new TplLink(def_url, mprop.nitdoc_name)
+                       var lnk = new TplLink(def_url, mprop.html_name)
                        var mdoc = mprop.intro.mdoc_or_fallback
                        if mdoc != null then lnk.title = mdoc.short_comment
                        var item = new Template
@@ -486,7 +496,7 @@ end
 
 redef class MPropertyPage
        redef fun init_title(v, doc) do
-               title = "{mentity.nitdoc_name}{mentity.tpl_signature.write_to_string}"
+               title = "{mentity.html_name}{mentity.tpl_signature.write_to_string}"
        end
 
        redef fun init_topmenu(v, doc) do
@@ -494,9 +504,10 @@ redef class MPropertyPage
                var mmodule = mentity.intro_mclassdef.mmodule
                var mproject = mmodule.mgroup.mproject
                var mclass = mentity.intro_mclassdef.mclass
-               topmenu.add_link new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}")
-               topmenu.add_link new TplLink("{mclass.nitdoc_url}", "{mclass.nitdoc_name}")
-               topmenu.add_link new TplLink(html_url, mentity.nitdoc_name)
+               topmenu.add_li new ListItem(new Link(mproject.nitdoc_url, mproject.html_name))
+               topmenu.add_li new ListItem(new Link(mclass.nitdoc_url, mclass.html_name))
+               topmenu.add_li new ListItem(new Link(html_url, mentity.html_name))
+               topmenu.active_item = topmenu.items.last
        end
 end
 
@@ -515,18 +526,16 @@ redef class DocRoot
        fun start_rendering(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage): TplSection do
                var section = new TplSection("top")
                var mentity = page.mentity
-               section.title = mentity.nitdoc_name
+               section.title = mentity.html_name
                section.subtitle = mentity.tpl_declaration
                # FIXME ugly hack to avoid diff
                if mentity isa MGroup and mentity.is_root then
-                       section.title = mentity.mproject.nitdoc_name
+                       section.title = mentity.mproject.html_name
                        section.subtitle = mentity.mproject.tpl_declaration
-               else if mentity isa MClass then
-                       section.title = "{mentity.nitdoc_name}{mentity.tpl_signature.write_to_string}"
                else if mentity isa MProperty then
-                       section.title = "{mentity.nitdoc_name}{mentity.intro.tpl_signature.write_to_string}"
+                       section.title = "{mentity.html_name}{mentity.intro.tpl_signature.write_to_string}"
                        section.subtitle = mentity.tpl_namespace
-                       section.summary_title = mentity.nitdoc_name
+                       section.summary_title = mentity.html_name
                end
                render(v, doc, page, section)
                return section
@@ -561,10 +570,10 @@ redef class ConcernSection
                var title = new Template
                if mmodule == page.mentity then
                        title.add "in "
-                       section.summary_title = "in {mmodule.nitdoc_name}"
+                       section.summary_title = "in {mmodule.html_name}"
                else
                        title.add "from "
-                       section.summary_title = "from {mmodule.nitdoc_name}"
+                       section.summary_title = "from {mmodule.html_name}"
                end
                title.add mmodule.tpl_namespace
                section.title = title
@@ -575,7 +584,13 @@ redef class ConcernSection
                title.add "in "
                title.add mmodule.tpl_namespace
                section.title = title
-               section.summary_title = "in {mmodule.nitdoc_name}"
+               section.summary_title = "in {mmodule.html_name}"
+       end
+end
+
+redef class MEntitySection
+       redef fun render(v, doc, page, parent) do
+               for child in children do child.render(v, doc, page, parent)
        end
 end
 
@@ -690,14 +705,14 @@ redef class DefinitionArticle
                else
                        var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
                        var def_url = "{cls_url}#{mprop.nitdoc_id}"
-                       var lnk = new TplLink.with_title(def_url, mprop.nitdoc_name,
+                       var lnk = new TplLink.with_title(def_url, mprop.html_name,
                                        "Go to introduction")
                        title.add "redef "
                        title.add lnk
                end
                article.title = title
                article.title_classes.add "signature"
-               article.summary_title = "{mprop.nitdoc_name}"
+               article.summary_title = "{mprop.html_name}"
                article.subtitle = mpropdef.tpl_namespace
                if mpropdef.mdoc_or_fallback != null then
                        article.content = mpropdef.mdoc_or_fallback.tpl_comment
index 1e0d773..9c32c8c 100644 (file)
@@ -50,10 +50,12 @@ end
 
 redef class MGroupPage
        redef fun apply_structure(v, doc) do
+               var section = new MEntitySection(mentity)
+               root.add_child section
                if mentity.is_root then
-                       root.add_child new IntroArticle(mentity.mproject)
+                       section.add_child new IntroArticle(mentity.mproject)
                else
-                       root.add_child new IntroArticle(mentity)
+                       section.add_child new IntroArticle(mentity)
                end
                var concerns = self.concerns
                if concerns == null or concerns.is_empty then return
@@ -63,12 +65,12 @@ redef class MGroupPage
                concerns.sort_with(v.concerns_sorter)
                mentity.mproject.booster_rank = 0
                mentity.booster_rank = 0
-               root.add_child new ConcernsArticle(mentity, concerns)
+               section.add_child new ConcernsArticle(mentity, concerns)
                for mentity in concerns do
                        if mentity isa MModule then
-                               root.add_child new DefinitionArticle(mentity)
+                               section.add_child new DefinitionArticle(mentity)
                        else
-                               root.add_child new ConcernSection(mentity)
+                               section.add_child new ConcernSection(mentity)
                        end
                end
        end
@@ -76,7 +78,9 @@ end
 
 redef class MModulePage
        redef fun apply_structure(v, doc) do
-               root.add_child new IntroArticle(mentity)
+               var section = new MEntitySection(mentity)
+               root.add_child section
+               section.add_child new IntroArticle(mentity)
                var concerns = self.concerns
                if concerns == null or concerns.is_empty then return
                # FIXME avoid diff
@@ -87,10 +91,10 @@ redef class MModulePage
                mentity.mgroup.mproject.booster_rank = 0
                mentity.mgroup.booster_rank = 0
                mentity.booster_rank = 0
-               root.add_child new ConcernsArticle(mentity, concerns)
+               section.add_child new ConcernsArticle(mentity, concerns)
                # reference list
                for mentity in concerns do
-                       var section = new ConcernSection(mentity)
+                       var ssection = new ConcernSection(mentity)
                        if mentity isa MModule then
                                var mclasses = mclasses_for_mmodule(mentity).to_a
                                v.name_sorter.sort(mclasses)
@@ -104,10 +108,10 @@ redef class MModulePage
                                        for mclassdef in mclassdefs do
                                                article.add_child(new DefinitionArticle(mclassdef))
                                        end
-                                       section.add_child article
+                                       ssection.add_child article
                                end
                        end
-                       root.add_child section
+                       section.add_child ssection
                end
        end
 
@@ -136,7 +140,9 @@ end
 
 redef class MClassPage
        redef fun apply_structure(v, doc) do
-               root.add_child new IntroArticle(mentity)
+               var section = new MEntitySection(mentity)
+               root.add_child section
+               section.add_child new IntroArticle(mentity)
                var concerns = self.concerns
                if concerns == null or concerns.is_empty then return
                # FIXME diff hack
@@ -147,9 +153,9 @@ redef class MClassPage
                mentity.intro_mmodule.mgroup.mproject.booster_rank = 0
                mentity.intro_mmodule.mgroup.booster_rank = 0
                mentity.intro_mmodule.booster_rank = 0
-               root.add_child new ConcernsArticle(mentity, concerns)
+               section.add_child new ConcernsArticle(mentity, concerns)
                for mentity in concerns do
-                       var section = new ConcernSection(mentity)
+                       var ssection = new ConcernSection(mentity)
                        if mentity isa MModule then
                                var mprops = mproperties_for(mentity)
                                var by_kind = new PropertiesByKind.with_elements(mprops)
@@ -157,12 +163,12 @@ redef class MClassPage
                                        v.name_sorter.sort(group)
                                        for mprop in group do
                                                for mpropdef in mpropdefs_for(mprop, mentity) do
-                                                       section.add_child new DefinitionArticle(mpropdef)
+                                                       ssection.add_child new DefinitionArticle(mpropdef)
                                                end
                                        end
                                end
                        end
-                       root.add_child section
+                       section.add_child ssection
                end
        end
 
@@ -196,7 +202,9 @@ end
 
 redef class MPropertyPage
        redef fun apply_structure(v, doc) do
-               root.add_child new IntroArticle(mentity)
+               var section = new MEntitySection(mentity)
+               root.add_child section
+               section.add_child new IntroArticle(mentity)
                var concerns = self.concerns
                if concerns == null or concerns.is_empty then return
                # FIXME diff hack
@@ -207,18 +215,18 @@ redef class MPropertyPage
                mentity.intro.mclassdef.mmodule.mgroup.mproject.booster_rank = 0
                mentity.intro.mclassdef.mmodule.mgroup.booster_rank = 0
                mentity.intro.mclassdef.mmodule.booster_rank = 0
-               root.add_child new ConcernsArticle(mentity, concerns)
+               section.add_child new ConcernsArticle(mentity, concerns)
                for mentity in concerns do
-                       var section = new ConcernSection(mentity)
+                       var ssection = new ConcernSection(mentity)
                        if mentity isa MModule then
                                # Add mproperties
                                var mpropdefs = mpropdefs_for(mentity).to_a
                                v.name_sorter.sort(mpropdefs)
                                for mpropdef in mpropdefs do
-                                       section.add_child new DefinitionArticle(mpropdef)
+                                       ssection.add_child new DefinitionArticle(mpropdef)
                                end
                        end
-                       root.add_child section
+                       section.add_child ssection
                end
        end
 
@@ -258,6 +266,14 @@ abstract class MEntityArticle
        super DocArticle
 end
 
+# A section about a Mentity.
+#
+# Used to regroup content about a MEntity.
+class MEntitySection
+       super MEntityComposite
+       super DocSection
+end
+
 # An introduction article about a MEntity.
 #
 # Used at the top of a documentation page to introduce the documented MEntity.
index c3126f7..e65059b 100644 (file)
@@ -24,70 +24,6 @@ import json::static
 # general layout elements
 #########################
 
-# Top menu bar template
-class TplTopMenu
-       super Template
-
-       # Brand link to display in first position of the top menu
-       private var brand: nullable Writable = null is writable
-       # Elements of the topmenu
-       private var elts = new Array[Writable]
-
-       # The page url where the top menu is displayed.
-       #
-       # Used to select the active link.
-       private var current_url: String
-
-       # Add a new link to the menu.
-       fun add_link(content: TplLink) do
-               var is_active = content.href == current_url
-               add_item(content, is_active)
-       end
-
-       # Add a content between `<li>` tags
-       fun add_item(content: Writable, is_active: Bool) do
-               var tpl = new Template
-               tpl.add "<li"
-               if is_active then
-                       tpl.add " class=\"active\""
-               end
-               tpl.add ">"
-               tpl.add content
-               tpl.addn "</li>"
-               add_raw(tpl)
-       end
-
-       # Add a raw content to the menu
-       fun add_raw(content: Writable) do
-               elts.add content
-       end
-
-       redef fun rendering do
-               if brand == null and elts.is_empty then return
-               addn "<nav id='topmenu' class='navbar navbar-default navbar-fixed-top' role='navigation'>"
-               addn " <div class='container-fluid'>"
-               addn "  <div class='navbar-header'>"
-               add "   <button type='button' class='navbar-toggle' "
-               addn "       data-toggle='collapse' data-target='#topmenu-collapse'>"
-               addn "    <span class='sr-only'>Toggle menu</span>"
-               addn "    <span class='icon-bar'></span>"
-               addn "    <span class='icon-bar'></span>"
-               addn "    <span class='icon-bar'></span>"
-               addn "   </button>"
-               if brand != null then add brand.as(not null)
-               addn "  </div>"
-               addn "  <div class='collapse navbar-collapse' id='topmenu-collapse'>"
-               if not elts.is_empty then
-                       addn "<ul class='nav navbar-nav'>"
-                       for elt in elts do add elt
-                       addn "</ul>"
-               end
-               addn "  </div>"
-               addn " </div>"
-               addn "</nav>"
-       end
-end
-
 # A sidebar template
 class TplSidebar
        super Template
index 15b2963..2908fad 100644 (file)
@@ -45,9 +45,20 @@ redef class MEntity
        # URL of this entity’s Nitdoc page.
        fun nitdoc_url: String is abstract
 
+       # Returns the mentity name without short signature.
+       #
+       # * MProject: `foo`
+       # * MGroup: `foo`
+       # * MModule: `foo`
+       # * MClass: `Foo[E]`
+       # * MClassDef: `Foo[E]`
+       # * MProperty: `foo(e)`
+       # * MPropdef: `foo(e)`
+       var html_name: String is lazy do return name.html_escape
+
        # A template link to the mentity `nitdoc_id`
        fun tpl_anchor: TplLink do
-               var tpl = new TplLink("#{nitdoc_id}", nitdoc_name)
+               var tpl = new TplLink("#{nitdoc_id}", html_name)
                var mdoc = mdoc_or_fallback
                if mdoc != null then
                        tpl.title = mdoc.short_comment
@@ -57,7 +68,7 @@ redef class MEntity
 
        # A template link to the mentity `nitdoc_url`
        fun tpl_link: TplLink do
-               var tpl = new TplLink(nitdoc_url, nitdoc_name)
+               var tpl = new TplLink(nitdoc_url, html_name)
                var mdoc = mdoc_or_fallback
                if mdoc != null then
                        tpl.title = mdoc.short_comment
@@ -80,7 +91,7 @@ redef class MEntity
                var tpl = new TplArticle.with_title(nitdoc_id, tpl_title)
                tpl.title_classes.add "signature"
                tpl.subtitle = tpl_namespace
-               tpl.summary_title = nitdoc_name
+               tpl.summary_title = html_name
                return tpl
        end
 
@@ -252,6 +263,22 @@ redef class MClass
        redef fun nitdoc_url do return "class_{nitdoc_id}.html"
        redef fun mdoc_or_fallback do return intro.mdoc
 
+       # Format: `Foo[E]`
+       redef var html_name is lazy do
+               var tpl = new Template
+               tpl.add name.html_escape
+               if arity > 0 then
+                       tpl.add "["
+                       var parameter_names = new Array[String]
+                       for p in mparameters do
+                               parameter_names.add(p.html_name)
+                       end
+                       tpl.add parameter_names.join(", ")
+                       tpl.add "]"
+               end
+               return tpl.write_to_string
+       end
+
        redef fun tpl_declaration do return intro.tpl_declaration
        redef fun tpl_definition do return intro.tpl_definition
 
@@ -268,7 +295,6 @@ redef class MClass
                var title = new Template
                title.add tpl_icon
                title.add tpl_link
-               title.add tpl_signature
                return title
        end
 
@@ -280,7 +306,7 @@ redef class MClass
                        tpl.add "["
                        var parameter_names = new Array[String]
                        for p in mparameters do
-                               parameter_names.add(p.nitdoc_name)
+                               parameter_names.add(p.html_name)
                        end
                        tpl.add parameter_names.join(", ")
                        tpl.add "]"
@@ -288,12 +314,6 @@ redef class MClass
                return tpl
        end
 
-       redef fun tpl_article do
-               var tpl = super
-               tpl.summary_title = "{nitdoc_name}{tpl_signature.write_to_string}"
-               return tpl
-       end
-
        redef fun tpl_css_classes do return intro.tpl_css_classes
 end
 
@@ -314,7 +334,7 @@ redef class MClassDef
 
        redef fun tpl_article do
                var tpl = new TplArticle(nitdoc_id)
-               tpl.summary_title = "in {mmodule.nitdoc_name}"
+               tpl.summary_title = "in {mmodule.html_name}"
                tpl.title = tpl_declaration
                tpl.title_classes.add "signature"
                var title = new Template
@@ -332,7 +352,6 @@ redef class MClassDef
                var title = new Template
                title.add tpl_icon
                title.add tpl_link
-               title.add tpl_signature
                return title
        end
 
@@ -350,7 +369,7 @@ redef class MClassDef
                if not mparameters.is_empty then
                        tpl.add "["
                        for i in [0..mparameters.length[ do
-                               tpl.add "{mparameters[i].nitdoc_name}: "
+                               tpl.add "{mparameters[i].html_name}: "
                                tpl.add bound_mtype.arguments[i].tpl_signature
                                if i < mparameters.length - 1 then tpl.add ", "
                        end
@@ -428,7 +447,7 @@ redef class MPropDef
 
        redef fun tpl_article do
                var tpl = new TplArticle(nitdoc_id)
-               tpl.summary_title = "in {mclassdef.nitdoc_name}"
+               tpl.summary_title = "in {mclassdef.html_name}"
                var title = new Template
                title.add "in "
                title.add mclassdef.tpl_link
@@ -577,7 +596,9 @@ end
 redef class MGenericType
        redef fun tpl_signature do
                var tpl = new Template
-               tpl.add tpl_link
+               var lnk = tpl_link
+               lnk.text = mclass.name.html_escape
+               tpl.add lnk
                tpl.add "["
                for i in [0..arguments.length[ do
                        tpl.add arguments[i].tpl_signature
index 83c1842..53fc0cf 100644 (file)
@@ -16,6 +16,7 @@
 module html_templates
 
 import html_model
+import html::bootstrap
 
 # Renders the page as HTML.
 redef class DocPage
@@ -31,7 +32,7 @@ redef class DocPage
        var body_attrs = new Array[TagAttribute]
 
        # Top menu template if any.
-       var topmenu: TplTopMenu is writable, noinit
+       var topmenu: DocTopMenu is writable, noinit
 
        # Sidebar template if any.
        var sidebar: nullable TplSidebar = null is writable
@@ -74,13 +75,6 @@ redef class DocPage
                addn ">"
        end
 
-       # Renders the topmenu template.
-       private fun render_topmenu do
-               addn " <div class='row'>"
-               add topmenu
-               addn " </div>"
-       end
-
        # Renders the sidebar template.
        #
        # Sidebar is automatically populated with a summary of all sections
@@ -129,7 +123,9 @@ redef class DocPage
        redef fun rendering do
                render_head
                addn "<div class='container-fluid'>"
-               render_topmenu
+               addn " <div class='row'>"
+               add topmenu
+               addn " </div>"
                addn " <div class='row' id='content'>"
                if sidebar != null then
                        addn "<div class='col col-xs-3 col-lg-2'>"
@@ -148,3 +144,55 @@ redef class DocPage
                render_footer
        end
 end
+
+# Top menu bar template.
+#
+# FIXME should be a Bootstrap component template
+# At this moment, the topmenu structure stills to specific to Nitdoc to use the
+# generic component.
+class DocTopMenu
+       super UnorderedList
+
+       # Brand link to display in first position of the top menu.
+       #
+       # This is where you want to put your logo.
+       var brand: nullable Writable is noinit, writable
+
+       # Active menu item.
+       #
+       # Depends on the current page, this allows to hilighted the current item.
+       #
+       # FIXME should be using Boostrap breadcrumbs component.
+       # This will still like this to avoid diff and be changed in further fixes
+       # when we will modify the output.
+       var active_item: nullable ListItem is noinit, writable
+
+       redef fun rendering do
+               addn "<nav id='topmenu' class='navbar navbar-default navbar-fixed-top' role='navigation'>"
+               addn " <div class='container-fluid'>"
+               addn "  <div class='navbar-header'>"
+               add "   <button type='button' class='navbar-toggle' "
+               addn "       data-toggle='collapse' data-target='#topmenu-collapse'>"
+               addn "    <span class='sr-only'>Toggle menu</span>"
+               addn "    <span class='icon-bar'></span>"
+               addn "    <span class='icon-bar'></span>"
+               addn "    <span class='icon-bar'></span>"
+               addn "   </button>"
+               if brand != null then
+                       add "<span class='navbar-brand'>"
+                       add brand.write_to_string
+                       add "</span>"
+               end
+               addn "  </div>"
+               addn "  <div class='collapse navbar-collapse' id='topmenu-collapse'>"
+               addn "   <ul class='nav navbar-nav'>"
+               for item in items do
+                       if item == active_item then item.css_classes.add "active"
+                       add item.write_to_string
+               end
+               addn "   </ul>"
+               addn "  </div>"
+               addn " </div>"
+               addn "</nav>"
+       end
+end
index aba779a..8818874 100644 (file)
@@ -1016,6 +1016,9 @@ redef class AMethPropdef
                                return v.int_instance(res)
                        else if pname == "atof" then
                                return v.float_instance(recvval.to_f)
+                       else if pname == "fast_cstring" then
+                               var ns = recvval.to_cstring.to_s.substring_from(args[1].to_i)
+                               return v.native_string_instance(ns)
                        end
                else if cname == "String" then
                        var cs = v.send(v.force_get_primitive_method("to_cstring", args.first.mtype), [args.first])
index 492584b..9d1297b 100644 (file)
@@ -108,8 +108,19 @@ redef class ModelBuilder
        end
 
        # Load a bunch of modules and groups.
-       # Each name can be a module or a group.
-       # If it is a group then recursively all its modules are parsed.
+       #
+       # Each name can be:
+       #
+       # * a path to a module, a group or a directory of projects.
+       # * a short name of a module or a group that are looked in the `paths` (-I)
+       #
+       # Then, for each entry, if it is:
+       #
+       # * a module, then is it parser and returned.
+       # * a group then recursively all its modules are parsed.
+       # * a directory of projects then all the modules of all projects are parsed.
+       # * else an error is displayed.
+       #
        # See `parse` for details.
        fun parse_full(names: Sequence[String]): Array[MModule]
        do
@@ -118,11 +129,39 @@ redef class ModelBuilder
                self.toolcontext.info("*** PARSE ***", 1)
                var mmodules = new ArraySet[MModule]
                for a in names do
+                       # Case of a group
                        var mgroup = self.get_mgroup(a)
                        if mgroup != null then
                                mmodules.add_all parse_group(mgroup)
                                continue
                        end
+
+                       # Case of a directory that is not a group
+                       var stat = a.to_path.stat
+                       if stat != null and stat.is_dir then
+                               self.toolcontext.info("look in directory {a}", 2)
+                               var fs = a.files
+                               # Try each entry as a group or a module
+                               for f in fs do
+                                       var af = a/f
+                                       mgroup = get_mgroup(af)
+                                       if mgroup != null then
+                                               mmodules.add_all parse_group(mgroup)
+                                               continue
+                                       end
+                                       var mp = identify_file(af)
+                                       if mp != null then
+                                               var nmodule = self.load_module(af)
+                                               if nmodule == null then continue # Skip error
+                                               build_module_importation(nmodule)
+                                               mmodules.add(nmodule.mmodule.as(not null))
+                                       else
+                                               self.toolcontext.info("ignore file {af}", 2)
+                                       end
+                               end
+                               continue
+                       end
+
                        var nmodule = self.load_module(a)
                        if nmodule == null then continue # Skip error
                        # Load imported module
@@ -350,12 +389,15 @@ redef class ModelBuilder
                        return mgroups[rdp]
                end
 
-               # Hack, a group is determined by:
+               # Hack, a group is determined by one of the following:
                # * the presence of a honomymous nit file
                # * the fact that the directory is named `src`
+               # * the fact that there is a sub-directory named `src`
                var pn = rdp.basename(".nit")
                var mp = dirpath.join_path(pn + ".nit").simplify_path
 
+               # dirpath2 is the root directory
+               # dirpath is the src subdirectory directory, if any, else it is the same that dirpath2
                var dirpath2 = dirpath
                if not mp.file_exists then
                        if pn == "src" then
@@ -363,12 +405,17 @@ redef class ModelBuilder
                                dirpath2 = rdp.dirname
                                pn = dirpath2.basename("")
                        else
-                               return null
+                               # Check a `src` subdirectory
+                               dirpath = dirpath2 / "src"
+                               if not dirpath.file_exists then
+                                       # All rules failed, so return null
+                                       return null
+                               end
                        end
                end
 
                # check parent directory
-               var parentpath = dirpath.join_path("..").simplify_path
+               var parentpath = dirpath2.join_path("..").simplify_path
                var parent = get_mgroup(parentpath)
 
                var mgroup
@@ -382,15 +429,22 @@ redef class ModelBuilder
                        mgroup = new MGroup(pn, parent.mproject, parent)
                        toolcontext.info("found sub group `{mgroup.full_name}` at {dirpath}", 2)
                end
-               var readme = dirpath2.join_path("README.md")
+
+               # search documentation
+               # in src first so the documentation of the project code can be distinct for the documentation of the project usage
+               var readme = dirpath.join_path("README.md")
+               if not readme.file_exists then readme = dirpath.join_path("README")
+               if not readme.file_exists then readme = dirpath2.join_path("README.md")
                if not readme.file_exists then readme = dirpath2.join_path("README")
                if readme.file_exists then
                        var mdoc = load_markdown(readme)
                        mgroup.mdoc = mdoc
                        mdoc.original_mentity = mgroup
                end
+
                mgroup.filepath = dirpath
-               mgroups[rdp] = mgroup
+               mgroups[module_absolute_path(dirpath)] = mgroup
+               mgroups[module_absolute_path(dirpath2)] = mgroup
                return mgroup
        end
 
index 8fd5908..767cf95 100644 (file)
@@ -62,6 +62,6 @@ var model = new Model
 var modelbuilder = new ModelBuilder(model, toolcontext)
 
 # Here we load an process all modules passed on the command line
-var mmodules = modelbuilder.parse(arguments)
+var mmodules = modelbuilder.parse_full(arguments)
 modelbuilder.run_phases
 toolcontext.run_global_phases(mmodules)
diff --git a/tests/sav/hello_ios.res b/tests/sav/hello_ios.res
new file mode 100644 (file)
index 0000000..90f398d
--- /dev/null
@@ -0,0 +1,4 @@
+out/hello_ios.bin
+out/hello_ios.bin/Info.plist
+out/hello_ios.bin/PkgInfo
+out/hello_ios.bin/hello_ios
diff --git a/tests/sav/test_platform_ios.res b/tests/sav/test_platform_ios.res
new file mode 100644 (file)
index 0000000..3c5611a
--- /dev/null
@@ -0,0 +1,4 @@
+out/test_platform_ios.bin
+out/test_platform_ios.bin/Info.plist
+out/test_platform_ios.bin/PkgInfo
+out/test_platform_ios.bin/test_platform_ios
diff --git a/tests/testosx.sh b/tests/testosx.sh
new file mode 100755 (executable)
index 0000000..8976424
--- /dev/null
@@ -0,0 +1,21 @@
+#!/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.
+
+# Tests to run on OS X for the host platform and iOS
+./tests.sh $@ \
+       test_ffi_objc_*.nit \
+       test_*ios.nit \
+       ../lib/ios/examples/*.nit \
+       ../lib/cocoa*/examples/*.nit
index 6c76366..ead5484 100755 (executable)
@@ -69,7 +69,9 @@ saferun()
                        *) stop=true
                esac
        done
-       if test -n "$TIME"; then
+       if test -d "$1"; then
+               find $1 | sort
+       elif test -n "$TIME"; then
                $TIME -o "$o" $a $TIMEOUT "$@"
        else
                if test -n "$a"; then echo 0 >> "$o"; else echo 0 > "$o"; fi