From: Jean Privat Date: Fri, 3 Apr 2015 01:27:33 +0000 (+0700) Subject: Merge: Unite app.nit metadata annotations common to Android and iOS X-Git-Tag: v0.7.4~42 X-Git-Url: http://nitlanguage.org?hp=613dcd6586af2019658a01140a85c062e152ea98 Merge: Unite app.nit metadata annotations common to Android and iOS * 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 Reviewed-by: Alexandre Terrasa --- diff --git a/benchmarks/markdown/README.md b/benchmarks/markdown/README.md index a739cd8..29219c5 100644 --- a/benchmarks/markdown/README.md +++ b/benchmarks/markdown/README.md @@ -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 diff --git a/benchmarks/markdown/bench_markdown.sh b/benchmarks/markdown/bench_markdown.sh index 4cb0f15..aaa34f0 100755 --- a/benchmarks/markdown/bench_markdown.sh +++ b/benchmarks/markdown/bench_markdown.sh @@ -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 diff --git a/benchmarks/markdown/engines/Makefile b/benchmarks/markdown/engines/Makefile index 588e744..7301d01 100644 --- a/benchmarks/markdown/engines/Makefile +++ b/benchmarks/markdown/engines/Makefile @@ -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 diff --git a/benchmarks/markdown/engines/nitmd/Makefile b/benchmarks/markdown/engines/nitmd/Makefile index aa79fbc..6424382 100644 --- a/benchmarks/markdown/engines/nitmd/Makefile +++ b/benchmarks/markdown/engines/nitmd/Makefile @@ -14,11 +14,17 @@ # 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 index 0000000..ca4a354 --- /dev/null +++ b/benchmarks/markdown/engines/pandoc/Makefile @@ -0,0 +1,27 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2015 Alexandre Terrasa +# +# 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 index 0000000..5c5db42 --- /dev/null +++ b/benchmarks/markdown/engines/pandoc/pandoc.hs @@ -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 index 0000000..82118c9 --- /dev/null +++ b/benchmarks/strings/Makefile @@ -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 index 0000000..b87b981 --- /dev/null +++ b/benchmarks/strings/README.md @@ -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. diff --git a/benchmarks/strings/array_to_s_vars/array_to_s_buffer.nit b/benchmarks/strings/array_to_s_vars/array_to_s_buffer.nit index d61b742..f18ece7 100644 --- a/benchmarks/strings/array_to_s_vars/array_to_s_buffer.nit +++ b/benchmarks/strings/array_to_s_vars/array_to_s_buffer.nit @@ -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 diff --git a/benchmarks/strings/array_to_s_vars/array_to_s_flatstr.nit b/benchmarks/strings/array_to_s_vars/array_to_s_flatstr.nit index 0240d5b..7028e3f 100644 --- a/benchmarks/strings/array_to_s_vars/array_to_s_flatstr.nit +++ b/benchmarks/strings/array_to_s_vars/array_to_s_flatstr.nit @@ -13,6 +13,27 @@ # 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 diff --git a/benchmarks/strings/array_to_s_vars/array_to_s_man_buf.nit b/benchmarks/strings/array_to_s_vars/array_to_s_man_buf.nit index ec81322..c5dbd00 100644 --- a/benchmarks/strings/array_to_s_vars/array_to_s_man_buf.nit +++ b/benchmarks/strings/array_to_s_vars/array_to_s_man_buf.nit @@ -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 diff --git a/benchmarks/strings/array_to_s_vars/array_to_s_rope.nit b/benchmarks/strings/array_to_s_vars/array_to_s_rope.nit index c162dff..9f86a8a 100644 --- a/benchmarks/strings/array_to_s_vars/array_to_s_rope.nit +++ b/benchmarks/strings/array_to_s_vars/array_to_s_rope.nit @@ -13,19 +13,21 @@ # 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 index 0000000..c7e3e7b --- /dev/null +++ b/benchmarks/strings/array_to_s_vars/array_to_s_rope_buf.nit @@ -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 diff --git a/benchmarks/bench_strings.sh b/benchmarks/strings/bench_strings.sh similarity index 53% rename from benchmarks/bench_strings.sh rename to benchmarks/strings/bench_strings.sh index 16992e9..a710dc0 100755 --- a/benchmarks/bench_strings.sh +++ b/benchmarks/strings/bench_strings.sh @@ -13,12 +13,12 @@ # 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 diff --git a/benchmarks/strings/chain_concat.nit b/benchmarks/strings/chain_concat.nit index a45075f..a70dd14 100644 --- a/benchmarks/strings/chain_concat.nit +++ b/benchmarks/strings/chain_concat.nit @@ -11,35 +11,78 @@ # 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 diff --git a/benchmarks/strings/iteration_bench.nit b/benchmarks/strings/iteration_bench.nit index 0e36c49..b37ad26 100644 --- a/benchmarks/strings/iteration_bench.nit +++ b/benchmarks/strings/iteration_bench.nit @@ -12,16 +12,33 @@ 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) diff --git a/benchmarks/strings/substr_bench.nit b/benchmarks/strings/substr_bench.nit index effb9ec..3727960 100644 --- a/benchmarks/strings/substr_bench.nit +++ b/benchmarks/strings/substr_bench.nit @@ -12,15 +12,16 @@ 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 index d720403..0000000 --- a/benchmarks/strings/utf_chain_concat.nit +++ /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 index 80277c0..0000000 --- a/benchmarks/strings/utf_iteration_bench.nit +++ /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 index 7d71a8b..0000000 --- a/benchmarks/strings/utf_substr_bench.nit +++ /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 index 0000000..45a278a --- /dev/null +++ b/bin/Makefile @@ -0,0 +1,27 @@ +# Copyright 2013 Alexandre Terrasa . +# +# 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 index 0000000..66befa3 --- /dev/null +++ b/lib/html/bootstrap.nit @@ -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 `` 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 == "Nit" +# ~~~ +# +# Creates a link with a title attribute: +# ~~~ +# lnk = new Link.with_title("http://nitlanguage.org", "Nit", "Nit homepage") +# assert lnk.write_to_string == "Nit" +# ~~~ +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 "{text}" + end +end + +# A `

` to `

` 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 == "

Title

" +# ~~~ +# +# With subtext: +# ~~~ +# var h6 = new Header.with_subtext(6, "Title", "with subtext") +# assert h6.write_to_string == "
Titlewith subtext
" +# ~~~ +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 "{text.write_to_string}" + if subtext != null then add "{subtext.write_to_string}" + add "" + 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 `
  • ` 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 `
      ` 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 == """ +#
        +#
      1. foo
      2. +#
      3. bar
      4. +#
      5. baz
      6. +#
      +# """ +# ~~~ +class OrderedList + super HTMLList + + redef fun rendering do + addn "" + for item in items do add item + addn "
    " + end +end + +# A `
      ` 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 == """ +#
        +#
      • foo
      • +#
      • bar
      • +#
      • baz
      • +#
      +# """ +# ~~~ +class UnorderedList + super HTMLList + + redef fun rendering do + addn "" + for item in items do add item + addn "
    " + end +end + +# A `
  • ` tag. +class ListItem + super BSComponent + + # Content to display in this list item. + var text: Writable is writable + + redef fun rendering do addn "{text.write_to_string}
  • " +end + +# A Boostrap icon. +# +# See http://getbootstrap.com/components/#glyphicons +# +# Example: +# +# ~~~ +# var icon = new BSIcon("star") +# assert icon.write_to_string == "" +# ~~~ +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 "" + 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 == """ +#
      +#
    1. foo
    2. +#
    3. bar
    4. +#
    5. baz
    6. +#
    +# """ +# ~~~ +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 == "Danger!" +# ~~~ +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 "{text.write_to_string}" + end +end + +# A Bootstrap badge component. +# +# See http://getbootstrap.com/components/#badges +# +# Example: +# +# ~~~ +# var b = new BSBadge("42 messages") +# assert b.write_to_string == "42 messages" +# ~~~ +class BSBadge + super BSComponent + + # Text to display in the label. + var text: Writable + + init do css_classes.add "badge" + + redef fun rendering do + add "{text.write_to_string}" + 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 == """ +#
    +# Welcome +#
    +# """ +# ~~~ +class BSPageHeader + super BSComponent + + # Text to display as title. + var text: Writable + + init do css_classes.add "page-header" + + redef fun rendering do + addn "" + addn text.write_to_string + addn "" + end +end + +# A Bootstrap alert component. +# +# See http://getbootstrap.com/components/#alerts +# +# Example: +# +# ~~~ +# var alert = new BSAlert("danger", "Danger!") +# assert alert.write_to_string == """ +#
    +# Danger! +#
    +# """ +# ~~~ +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 "" + if is_dismissible then + add "" + end + addn text.write_to_string + addn "" + 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 == """ +#
    +#
    +# Panel content +#
    +#
    +# """ +# ~~~ +# +# Panel with heading: +# +# ~~~ +# p = new BSPanel("danger", "Panel content") +# p.heading = "Panel heading" +# +# assert p.write_to_string == """ +#
    +#
    +# Panel heading +#
    +#
    +# Panel content +#
    +#
    +# """ +# ~~~ +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 "" + if heading != null then + addn "
    " + addn heading.write_to_string + addn "
    " + end + addn "
    " + addn body.write_to_string + addn "
    " + if footer != null then + addn "
    " + addn footer.write_to_string + addn "
    " + end + addn "" + end +end diff --git a/lib/standard/string.nit b/lib/standard/string.nit index e974d91..409b4ed 100644 --- a/lib/standard/string.nit +++ b/lib/standard/string.nit @@ -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 diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index 011b146..894a13d 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -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 diff --git a/src/doc/doc_base.nit b/src/doc/doc_base.nit index e947ee2..64b2022 100644 --- a/src/doc/doc_base.nit +++ b/src/doc/doc_base.nit @@ -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 diff --git a/src/doc/doc_phases/doc_graphs.nit b/src/doc/doc_phases/doc_graphs.nit index aff25d4..66ef564 100644 --- a/src/doc/doc_phases/doc_graphs.nit +++ b/src/doc/doc_phases/doc_graphs.nit @@ -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 diff --git a/src/doc/doc_phases/doc_hierarchies.nit b/src/doc/doc_phases/doc_hierarchies.nit index 39ad273..23da906 100644 --- a/src/doc/doc_phases/doc_hierarchies.nit +++ b/src/doc/doc_phases/doc_hierarchies.nit @@ -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 diff --git a/src/doc/doc_phases/doc_html.nit b/src/doc/doc_phases/doc_html.nit index a11e187..7d38bc0 100644 --- a/src/doc/doc_phases/doc_html.nit +++ b/src/doc/doc_phases/doc_html.nit @@ -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 "" 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 diff --git a/src/doc/doc_phases/doc_structure.nit b/src/doc/doc_phases/doc_structure.nit index 1e0d773..9c32c8c 100644 --- a/src/doc/doc_phases/doc_structure.nit +++ b/src/doc/doc_phases/doc_structure.nit @@ -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. diff --git a/src/doc/html_templates/html_components.nit b/src/doc/html_templates/html_components.nit index c3126f7..e65059b 100644 --- a/src/doc/html_templates/html_components.nit +++ b/src/doc/html_templates/html_components.nit @@ -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 `
  • ` tags - fun add_item(content: Writable, is_active: Bool) do - var tpl = new Template - tpl.add "" - tpl.add content - tpl.addn "
  • " - 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 "" - end -end - # A sidebar template class TplSidebar super Template diff --git a/src/doc/html_templates/html_model.nit b/src/doc/html_templates/html_model.nit index 15b2963..2908fad 100644 --- a/src/doc/html_templates/html_model.nit +++ b/src/doc/html_templates/html_model.nit @@ -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 diff --git a/src/doc/html_templates/html_templates.nit b/src/doc/html_templates/html_templates.nit index 83c1842..53fc0cf 100644 --- a/src/doc/html_templates/html_templates.nit +++ b/src/doc/html_templates/html_templates.nit @@ -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 "
    " - add topmenu - addn "
    " - 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 "
    " - render_topmenu + addn "
    " + add topmenu + addn "
    " addn "
    " if sidebar != null then addn "
    " @@ -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 "" + end +end diff --git a/src/interpreter/naive_interpreter.nit b/src/interpreter/naive_interpreter.nit index aba779a..8818874 100644 --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@ -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]) diff --git a/src/loader.nit b/src/loader.nit index 492584b..9d1297b 100644 --- a/src/loader.nit +++ b/src/loader.nit @@ -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 diff --git a/src/test_phase.nit b/src/test_phase.nit index 8fd5908..767cf95 100644 --- a/src/test_phase.nit +++ b/src/test_phase.nit @@ -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 index 0000000..90f398d --- /dev/null +++ b/tests/sav/hello_ios.res @@ -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 index 0000000..3c5611a --- /dev/null +++ b/tests/sav/test_platform_ios.res @@ -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 index 0000000..8976424 --- /dev/null +++ b/tests/testosx.sh @@ -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 diff --git a/tests/tests.sh b/tests/tests.sh index 6c76366..ead5484 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -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