So one can more easily play and compare parsers.
Sometime, when I have issues with the parser, it helps to understand if it is nit-related, sablecc-related or grammar-relater.
Pull-Request: #1240
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
* 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
bncdir="./benches/out"
mkdir -p $outdir
-s=50
+s=200
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"
}
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
# 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
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
# 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
--- /dev/null
+# 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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+# 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.
# 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
# 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
# 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
# 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
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT. This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. You can modify it is you want, provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You are allowed to redistribute it and sell it, alone or is a part of
+# another product.
+
+# Implementation of Array::to_s with 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
# 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()
{
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"
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
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
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
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
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
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
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 ***"
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
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 :"
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
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
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
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
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 :"
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
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
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
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 :"
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
cct) shift; bench_concat $@ ;;
substr) shift; bench_substr $@ ;;
array) shift; bench_array $@ ;;
- all) shift; benches $@ ;;
*) usage; exit;;
esac
# 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")
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
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
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
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
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
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")
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)
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
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")
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)
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# This file is free software, which comes along with NIT. This software is
-# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE. You can modify it is you want, provided this header
-# is kept unaltered, and a notification of the changes is added.
-# You are allowed to redistribute it and sell it, alone or is a part of
-# another product.
-
-# Benches measuring the performance of several concatenations on Text variants
-module utf_chain_concat
-
-import opts
-import string_experimentations::utf8_noindex
-
-fun bench_flatstr(str_size: Int, nb_ccts: Int, loops: Int)
-do
- var lft = "a" * str_size
-
- for i in [0..loops] do
- var str: String = lft
- for j in [0..nb_ccts] do
- str += lft
- end
- end
-end
-
-var opts = new OptionContext
-var nb_ccts = new OptionInt("Number of concatenations per loop", -1, "--ccts")
-var loops = new OptionInt("Number of loops to be done", -1, "--loops")
-var strlen = new OptionInt("Length of the base string", -1, "--strlen")
-opts.add_option(nb_ccts, loops, strlen)
-
-opts.parse(args)
-
-if nb_ccts.value == -1 or loops.value == -1 or strlen.value == -1 then
- opts.usage
- exit -1
-end
-
-bench_flatstr(strlen.value, nb_ccts.value, loops.value)
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# This file is free software, which comes along with NIT. This software is
-# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE. You can modify it is you want, provided this header
-# is kept unaltered, and a notification of the changes is added.
-# You are allowed to redistribute it and sell it, alone or is a part of
-# another product.
-
-# Benches for iteration on variants of Text
-module utf_iteration_bench
-
-import opts
-import string_experimentations::utf8_noindex
-
-fun bench_flatstr_iter(nb_cct: Int, loops: Int, strlen: Int)
-do
- var a = "a" * strlen
- var x = a.as(FlatString)
- for i in [0 .. nb_cct] do x = (x + a).as(FlatString)
- var cnt = 0
- var c: UnicodeChar
- while cnt != loops do
- var it = new FlatStringIter(x)
- for i in it do
- c = i
- end
- cnt += 1
- end
-end
-
-fun bench_flatstr_index(nb_cct: Int, loops: Int, strlen: Int)
-do
- var a = "a" * strlen
- var x = a.as(FlatString)
- for i in [0 .. nb_cct] do x = (x + a).as(FlatString)
- var cnt = 0
- var c: UnicodeChar
- var pos = 0
- while cnt != loops do
- pos = 0
- while pos < x.length do
- c = x.char_at(pos)
- pos += 1
- end
- cnt += 1
- end
-end
-
-var opts = new OptionContext
-var access_mode = new OptionEnum(["iterator", "index"], "Iteration mode", -1, "--iter-mode")
-var nb_ccts = new OptionInt("Number of concatenations done to the string (in the case of the rope, this will increase its depth)", -1, "--ccts")
-var loops = new OptionInt("Number of loops to be done", -1, "--loops")
-var strlen = new OptionInt("Length of the base string", -1, "--strlen")
-opts.add_option(nb_ccts, loops, strlen, access_mode)
-
-opts.parse(args)
-
-if nb_ccts.value == -1 or loops.value == -1 or strlen.value == -1 then
- opts.usage
- exit(-1)
-end
-
-var iterval = access_mode.value
-
-if iterval == 0 then
- bench_flatstr_iter(nb_ccts.value, loops.value, strlen.value)
-else if iterval == 1 then
- bench_flatstr_index(nb_ccts.value, loops.value, strlen.value)
-else
- opts.usage
- exit(-1)
-end
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# This file is free software, which comes along with NIT. This software is
-# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE. You can modify it is you want, provided this header
-# is kept unaltered, and a notification of the changes is added.
-# You are allowed to redistribute it and sell it, alone or is a part of
-# another product.
-
-# Benches on the substring operation on variants of Text
-module utf_substr_bench
-
-import opts
-import string_experimentations::utf8_noindex
-
-fun bench_flatstr(nb_cct: Int, loops: Int, strlen: Int)
-do
- var a = "a" * strlen
- var x = a
- for i in [0 .. nb_cct] do x += a
- var cnt = 0
- while cnt != loops do
- x.substring(0,5)
- cnt += 1
- end
-end
-
-var opts = new OptionContext
-var nb_ccts = new OptionInt("Number of concatenations done to the string (in the case of the rope, this will increase its depth)", -1, "--ccts")
-var loops = new OptionInt("Number of loops to be done", -1, "--loops")
-var strlen = new OptionInt("Length of the base string", -1, "--strlen")
-opts.add_option(nb_ccts, loops, strlen)
-
-opts.parse(args)
-
-if nb_ccts.value == -1 or loops.value == -1 or strlen.value == -1 then
- opts.usage
- exit(-1)
-end
-
-bench_flatstr(nb_ccts.value, loops.value, strlen.value)
--- /dev/null
+# 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
module calculator_android is
app_name "app.nit Calc."
app_version(0, 1, git_revision)
- java_package "org.nitlanguage.calculator"
+ app_namespace "org.nitlanguage.calculator"
# Lock in portrait mode
android_manifest_activity """android:screenOrientation="portrait""""
# limitations under the License.
module dino_android is
- java_package("org.nitlanguage.dino")
+ app_namespace "org.nitlanguage.dino"
end
import dino
# limitations under the License.
module complete_simple_android is
- java_package("org.nitlanguage.test_all")
- target_api_version(19)
+ app_namespace "org.nitlanguage.test_all"
+ target_api_version 19
end
import test_bundle
Example: `app_name "My App"`
-* `java_package` specifies the package used by the generated Java
+* `app_namespace` specifies the package used by the generated Java
classes and the APK file. Once the application is published, this
value should not be changed. By default, the compiler will use
the package `org.nitlanguage.{module_name}`.
# used to tag `ldflags` annotations.
module aware is
new_annotation android
- new_annotation java_package
new_annotation min_api_version
new_annotation max_api_version
new_annotation target_api_version
# Test for app.nit's UI services
module ui_test is
- app_name("app.nit UI test")
+ app_name "app.nit UI test"
app_version(0, 1, git_revision)
- java_package("org.nitlanguage.ui_test")
+ app_namespace "org.nitlanguage.ui_test"
android_manifest_activity """android:theme="@android:style/Theme.Light""""
end
module app_base is
new_annotation app_name
+ new_annotation app_namespace
new_annotation app_version
end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 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\">×</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
# limitations under the License.
# Simple iOS app with a single label
-module hello_ios
+module hello_ios is
+ app_name "Hello iOS"
+ app_namespace "nit.app.hello_ios"
+ app_version(0, 5, git_revision)
+end
import ios
# 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
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
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`
# 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
# Get the default name of the executable to produce
fun default_outname: String
do
- var mainmodule = compiler.mainmodule
-
- # Search a non fictive module
- var res = mainmodule.name
- while mainmodule.is_fictive do
- mainmodule = mainmodule.in_importation.direct_greaters.first
- res = mainmodule.name
- end
- return res
+ var mainmodule = compiler.mainmodule.first_real_mmodule
+ return mainmodule.name
end
# Combine options and platform informations to get the final path of the outfile
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
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
#
# Shortcut for `children.add`.
fun add_child(child: DocComposite) do
+ child.parent = self
children.add child
end
end
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
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
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
# 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
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.
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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)
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
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
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)
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
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
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
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.
# 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
# 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
# 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
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
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
var title = new Template
title.add tpl_icon
title.add tpl_link
- title.add tpl_signature
return title
end
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 "]"
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
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
var title = new Template
title.add tpl_icon
title.add tpl_link
- title.add tpl_signature
return title
end
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
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
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
module html_templates
import html_model
+import html::bootstrap
# Renders the page as HTML.
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
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
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'>"
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
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])
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
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
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
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
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
# Is `self` a unit test module used by `nitunit`?
var is_test_suite: Bool = false is writable
+ # Get the first non `is_fictive` module greater than self
+ fun first_real_mmodule: MModule
+ do
+ var mmodule = self
+ while mmodule.is_fictive do
+ mmodule = mmodule.in_importation.direct_greaters.first
+ end
+ return mmodule
+ end
+
redef fun parent_concern do return mgroup
end
redef fun write_files(compile_dir, cfiles)
do
var android_project_root = android_project_root.as(not null)
- var project = toolcontext.modelbuilder.android_project_for(compiler.mainmodule)
- var short_project_name = compiler.mainmodule.name.replace("-", "_")
+ var project = new AndroidProject(toolcontext.modelbuilder, compiler.mainmodule)
var release = toolcontext.opt_release.value
var app_name = project.name
- if app_name == null then app_name = compiler.mainmodule.name
if not release then app_name += " Debug"
- var app_package = project.java_package
- if app_package == null then app_package = "org.nitlanguage.{short_project_name}"
+ var short_project_name = project.short_name
+
+ var app_package = project.namespace
if not release then app_package += "_debug"
var app_version = project.version
- if app_version == null then app_version = "1.0"
var app_min_api = project.min_api
if app_min_api == null then app_min_api = 10
# See the License for the specific language governing permissions and
# limitations under the License.
-# Annotations to gather metadata on Android projects. Get the metadata
-# by calling `ModelBuilder::android_project_for`.
+# Additionnal annotations to gather metadata on Android projects
module android_annotations
-private import parser_util
-import modelize
-import literal
-import semantize
-private import annotation
+intrude import app_annotations
# Metadata associated to an Android project
class AndroidProject
- # Name of the resulting application
- var name: nullable String = null
-
- # Java package used to identify the APK
- var java_package: nullable String = null
-
- # Version of the Android application and APK
- var version: nullable String = null
-
- # Numerical version code of the Android application and APK
- var version_code: Int = 0
+ super AppProject
# Custom lines to add to the AndroidManifest.xml in the <manifest> node
var manifest_lines = new Array[String]
# Activities to declare in the manifest
var activities = new Array[String]
- redef fun to_s do return """
-name: {{{name or else "null"}}}
-namespace: {{{java_package or else "null"}}}
-version: {{{version or else "null"}}}"""
-end
-
-redef class ModelBuilder
- # Get the `AndroidProject` gathered from `mmodule` and its importations
- fun android_project_for(mmodule: MModule): AndroidProject
+ init
do
- var project = new AndroidProject
-
- var annot = lookup_annotation_on_modules("app_name", mmodule)
- if annot != null then project.name = annot.arg_as_string(self)
-
- annot = lookup_annotation_on_modules("app_version", mmodule)
- if annot != null then project.version = annot.as_version(self)
-
- annot = lookup_annotation_on_modules("java_package", mmodule)
- if annot != null then project.java_package = annot.arg_as_string(self)
-
- var annots = collect_annotations_on_modules("min_api_version", mmodule)
+ var annots = modelbuilder.collect_annotations_on_modules("min_api_version", mainmodule)
if not annots.is_empty then
- var i = annots.pop.arg_as_int(self)
+ var i = annots.pop.arg_as_int(modelbuilder)
if i == null then i = 0
- project.min_api = i
+ min_api = i
for an in annots do
- i = an.arg_as_int(self)
+ i = an.arg_as_int(modelbuilder)
if i == null then continue
- project.min_api = project.min_api.max(i)
+ min_api = min_api.max(i)
end
end
- annots = collect_annotations_on_modules("max_api_version", mmodule)
+ annots = modelbuilder.collect_annotations_on_modules("max_api_version", mainmodule)
if not annots.is_empty then
- var i = annots.pop.arg_as_int(self)
+ var i = annots.pop.arg_as_int(modelbuilder)
if i == null then i = 0
- project.max_api = i
+ max_api = i
for an in annots do
- i = an.arg_as_int(self)
+ i = an.arg_as_int(modelbuilder)
if i == null then continue
- project.max_api = project.max_api.min(i)
+ max_api = max_api.min(i)
end
end
- annot = lookup_annotation_on_modules("target_api_version", mmodule)
- if annot != null then project.target_api = annot.arg_as_int(self) or else 0
+ var annot = modelbuilder.lookup_annotation_on_modules("target_api_version", mainmodule)
+ if annot != null then target_api = annot.arg_as_int(modelbuilder) or else 0
- annots = collect_annotations_on_modules("android_manifest", mmodule)
- for an in annots do project.manifest_lines.add an.arg_as_string(self) or else ""
+ annots = modelbuilder.collect_annotations_on_modules("android_manifest", mainmodule)
+ for an in annots do manifest_lines.add an.arg_as_string(modelbuilder) or else ""
- annots = collect_annotations_on_modules("android_manifest_application", mmodule)
- for an in annots do project.manifest_application_lines.add an.arg_as_string(self) or else ""
+ annots = modelbuilder.collect_annotations_on_modules("android_manifest_application", mainmodule)
+ for an in annots do manifest_application_lines.add an.arg_as_string(modelbuilder) or else ""
- annots = collect_annotations_on_modules("android_manifest_activity", mmodule)
- for an in annots do project.manifest_activity_attributes.add an.arg_as_string(self) or else ""
+ annots = modelbuilder.collect_annotations_on_modules("android_manifest_activity", mainmodule)
+ for an in annots do manifest_activity_attributes.add an.arg_as_string(modelbuilder) or else ""
- annots = collect_annotations_on_modules("android_activity", mmodule)
+ annots = modelbuilder.collect_annotations_on_modules("android_activity", mainmodule)
for an in annots do
- var activity = an.arg_as_string(self)
- if activity != null then project.activities.add activity
+ var activity = an.arg_as_string(modelbuilder)
+ if activity != null then activities.add activity
end
-
- # Get the date and time (down to the minute) as string
- var local_time = new Tm.localtime
- var local_time_s = local_time.strftime("%y%m%d%H%M")
- project.version_code = local_time_s.to_i
-
- toolcontext.check_errors
-
- return project
- end
-end
-
-redef class AAnnotation
- # Returns a version string (example: "1.5.6b42a7c") from an annotation `version(1, 5, git_revision)`.
- #
- # The user can enter as many fields as needed. The call to `git_revision` will be replaced by the short
- # revision number. If the working tree is dirty, it will append another field with "d" for dirty.
- private fun as_version(modelbuilder: ModelBuilder): String
- do
- var version_fields = new Array[Object]
-
- var args = n_args
- if args.length < 1 then
- modelbuilder.error(self, "Annotation error: \"{name}\" expects at least a single argument.")
- return ""
- else
- for arg in args do
- var format_error = "Annotation error: \"{name}\" expects its arguments to be of type Int or a call to `git_revision`"
-
- var value
- value = arg.as_int
- if value != null then
- version_fields.add value
- continue
- end
-
- value = arg.as_string
- if value != null then
- version_fields.add value
- end
-
- value = arg.as_id
- if value == "git_revision" then
- # Get Git short revision
- var proc = new ProcessReader("git", "rev-parse", "--short", "HEAD")
- proc.wait
- assert proc.status == 0
- var lines = proc.read_all
- var revision = lines.split("\n").first
-
- # Is it dirty?
- # If not, the return of `git diff --shortstat` is an empty line
- proc = new ProcessReader("git", "diff-index", "--quiet", "HEAD")
- proc.wait
- var dirty = proc.status != 0
- if dirty then revision += ".d"
-
- version_fields.add revision
- continue
- end
-
- modelbuilder.error(self, format_error)
- return ""
- end
- end
-
- return version_fields.join(".")
end
end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Annotations to gather metadata on `app.nit` projects
+module app_annotations
+
+private import parser_util
+import modelize
+import literal
+import semantize
+private import annotation
+
+# Metadata associated to an `app.nit` project
+class AppProject
+ # Pretty name of the resulting application
+ var name: String = mainmodule.first_real_mmodule.name is lazy
+
+ # Short project name used in `namespace` and configuration files
+ var short_name: String = mainmodule.name.replace("-", "_") is lazy
+
+ # Namespace/package used to identify the application
+ var namespace = "org.nitlanguage.{short_name}" is lazy
+
+ # Version of the application
+ var version = "0.1"
+
+ # Numerical version code of the application
+ var version_code: Int is lazy do
+
+ # Get the date and time (down to the minute) as string
+ var local_time = new Tm.localtime
+ var local_time_s = local_time.strftime("%y%m%d%H%M")
+ return local_time_s.to_i
+ end
+
+ private var modelbuilder: ModelBuilder
+ private var mainmodule: MModule
+
+ init
+ do
+ var annot = modelbuilder.lookup_annotation_on_modules("app_name", mainmodule)
+ if annot != null then
+ var val = annot.arg_as_string(modelbuilder)
+ if val != null then name = val
+ end
+
+ annot = modelbuilder.lookup_annotation_on_modules("app_version", mainmodule)
+ if annot != null then version = annot.as_version(modelbuilder)
+
+ annot = modelbuilder.lookup_annotation_on_modules("app_namespace", mainmodule)
+ if annot != null then
+ var val = annot.arg_as_string(modelbuilder)
+ if val != null then namespace = val
+ end
+
+ modelbuilder.toolcontext.check_errors
+ end
+
+ redef fun to_s do return """
+name: {{{name or else "null"}}}
+namespace: {{{namespace or else "null"}}}
+version: {{{version or else "null"}}}"""
+end
+
+redef class AAnnotation
+ # Returns a version string (example: "1.5.6b42a7c") from an annotation `version(1, 5, git_revision)`.
+ #
+ # The user can enter as many fields as needed. The call to `git_revision` will be replaced by the short
+ # revision number. If the working tree is dirty, it will append another field with "d" for dirty.
+ private fun as_version(modelbuilder: ModelBuilder): String
+ do
+ var version_fields = new Array[Object]
+
+ var args = n_args
+ if args.length < 1 then
+ modelbuilder.error(self, "Annotation error: \"{name}\" expects at least a single argument.")
+ return ""
+ else
+ for arg in args do
+ var format_error = "Annotation error: \"{name}\" expects its arguments to be of type Int or a call to `git_revision`"
+
+ var value
+ value = arg.as_int
+ if value != null then
+ version_fields.add value
+ continue
+ end
+
+ value = arg.as_string
+ if value != null then
+ version_fields.add value
+ end
+
+ value = arg.as_id
+ if value == "git_revision" then
+ # Get Git short revision
+ var proc = new ProcessReader("git", "rev-parse", "--short", "HEAD")
+ proc.wait
+ assert proc.status == 0
+ var lines = proc.read_all
+ var revision = lines.split("\n").first
+
+ # Is it dirty?
+ # If not, the return of `git diff --shortstat` is an empty line
+ proc = new ProcessReader("git", "diff-index", "--quiet", "HEAD")
+ proc.wait
+ var dirty = proc.status != 0
+ if dirty then revision += ".d"
+
+ version_fields.add revision
+ continue
+ end
+
+ modelbuilder.error(self, format_error)
+ return ""
+ end
+ end
+
+ return version_fields.join(".")
+ end
+end
import platform
import compiler::abstract_compiler
import xcode_templates
-private import annotation
+import app_annotations
redef class ToolContext
redef fun platform_from_name(name)
# Root of the iOS project, usually `.nit_compile/ios/`
var ios_project_root: String is noinit
- redef fun default_outname do return "{super}.app"
+ # `app.nit` project for the current compilation target
+ var app_project = new AppProject(compiler.modelbuilder, compiler.mainmodule) is lazy
- # Name of the current project of `compiler`
- fun project_name: String
- do
- var project_name = null
- # TODO unite the app_name annotation from Android with iOS
- var annot = compiler.modelbuilder.lookup_annotation_on_modules("app_name", compiler.mainmodule)
- if annot != null then project_name = annot.arg_as_string(compiler.modelbuilder)
- if project_name == null then project_name = compiler.mainmodule.name
- return project_name
- end
+ redef fun default_outname do return "{super}.app"
- # Compile C files in `ios_project_root/project_name`
+ # Compile C files in `ios_project_root/app_project.name`
redef fun compile_dir
do
ios_project_root = super/"ios"
- return ios_project_root/project_name
+ return ios_project_root/app_project.short_name
end
redef fun write_files(compile_dir, cfiles)
redef fun write_makefile(compile_dir, cfiles)
do
- var project_name = project_name
+ var project_name = app_project.short_name
# Create an XCode project directory
var dir = ios_project_root/project_name+".xcodeproj"
# Create the plist in the same directory as the generated C code
if not compile_dir.file_exists then compile_dir.mkdir
- var plist = new PlistTemplate("org.nitlanguage") # TODO customize using an annotation
+ var plist = new PlistTemplate(app_project.name, app_project.namespace,
+ app_project.version, app_project.version_code.to_s)
plist.write_to_file compile_dir/"Info.plist"
end
redef fun compile_c_code(compile_dir)
do
- var project_name = project_name
+ var project_name = app_project.short_name
var release = toolcontext.opt_release.value
var outfile = outfile(compiler.mainmodule)
class PlistTemplate
super Template
- # Package of the app
- var package_name: String
+ # Value of CFBundleName, pretty name of the application
+ var product_name: String
+
+ # Value of CFBundleIdentifier, namespace of the app
+ var bundle_identifier: String
+
+ # Value of CFBundleShortVersionString, human readable version
+ var short_version: String
+
+ # Value of CFBundleVersion, often a revision number
+ var bundle_version: String
redef fun rendering
do
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
- <string>{{{package_name}}}.$(PRODUCT_NAME:rfc1034identifier)</string>
+ <string>{{{bundle_identifier}}}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
- <string>$(PRODUCT_NAME)</string>
+ <string>{{{product_name}}}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>1.0</string>
+ <string>{{{short_version}}}</string>
<key>CFBundleSignature</key>
<string>\\?\\?\\?\\?</string>
<key>CFBundleVersion</key>
- <string>1</string>
+ <string>{{{bundle_version}}}</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIRequiredDeviceCapabilities</key>
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)
--- /dev/null
+out/hello_ios.bin
+out/hello_ios.bin/Info.plist
+out/hello_ios.bin/PkgInfo
+out/hello_ios.bin/hello_ios
--- /dev/null
+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
--- /dev/null
+#!/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
*) 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