Introduce the `with` statement that is analogous to the `with` of Python or the `uning` of C#.
~~~nit
with x = something do
x.work
end
~~~
That is equivalent with
~~~nit
do
var x = something
x.start
x.work
x.finish
end
~~~
Note that an alternative syntax, without the local variable exists:
~~~nit
with something do
work
end
~~~
that is used when we want some automatic control or whatever. Eg resource allocation or critical section.
~~~nit
do
var tmp = something
tmp.start
work
tmp.stop
end
~~~
Most real-world examples could be
~~~nit
with file = path.create do
file.write("Bla")
end
~~~
and
~~~nit
with a_mutex do
work
end
~~~
## Names
I reused the `finish` method from Iterator.
I introduced the antonym `start` for the other side.
Note that the `start` is important because it helps the object to know it has to prepare itself for a `finish`.
I did not introduce an interface, mainly because I have no idea for a name. C# names it `IDisposable` and the `finish` method is called `Dispose`. There is no `start` because C# designers are lunatic sometime.
In python there is no interface (obviously) and the method are called
`__enter__` and `__exit__` because Python likes identifiers that resemble words eaten by boas.
Note that the returned variable is not the original expression but the result of `__enter__`.
With the Python semantic, but the Nit syntax, the first example will be equivalent to
~~~nit
do
var tmp = something
var x = tmp.start
x.work
x.finish
end
~~~
I am not sure of the benefits of the additional complexity, but the the more I thing about it the more I think this could be useful, ex for the control case the `start` can return the handler to `finish`.
The issue is that proposed syntax: `with x = something` does not make sense (because `tmp=something` and `x=tmp.start`) thus should be replaced with something else; Python uses `with something as x:` that we can reuse but I do not want because it is ugly.
An other alternative I tough of was to reuse the `for` keyword. but It is convoluted.
The two previous real world examples will then be
~~~nit
for file = path.create do
file.write("Bla")
end
~~~
and
~~~nit
for a_mutex do
work
end
~~~
Pull-Request: #1243
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Etienne M. Gagnon <egagnon@j-meg.com>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
run_command "$@" ../src/nit.nit -o "nit.$title.bin"
bench_command "nit-queens" "nit queens.nit 8" "./nit.$title.bin" ../lib/ai/examples/queens.nit -q 8
bench_command "nit-nitcc" "nit nitcc.nit calc.sablecc" "./nit.$title.bin" ../contrib/nitcc/src/nitcc.nit ../contrib/nitcc/examples/calc.sablecc
+ rm calc* 2> /dev/null # remove generated cruft
run_command "$@" ../src/nitdoc.nit -o "nitdoc.$title.bin"
rm -r out 2> /dev/null
mkdir out 2> /dev/null
--- /dev/null
+benches/gen_benches
+benches/out/
+
+engines/nitmd/nitmd
+engines/nitmd/nitmd-o
+
+engines/markdown4j/Markdown4j.class
+engines/markdown4j/markdown4j-2.2.jar
+
+engines/pandoc/pandoc
+engines/pandoc/pandoc.hi
+engines/pandoc/pandoc.o
+
+engines/txtmark/Txtmark.class
+engines/txtmark/txtmark-0.11.jar
--- /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.
+
+all:
+ ./bench_markdown.sh all
+
+clean:
+ $(MAKE) clean -C benches
+ $(MAKE) clean -C engines
+ rm -rf out/
* 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.
+NITC=../../../bin/nitc
+
all: out
gen_benches:
- nitc gen_benches.nit
+ $(NITC) gen_benches.nit
out: gen_benches
./gen_benches ./plain.md -o ./out
# 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.
+NITC=../../../../bin/nitc
+
+all: nitmd nitmd-o
+
nitmd:
- nitc nitmd.nit
+ $(NITC) nitmd.nit
+
+nitmd-o:
+ $(NITC) --semi-global nitmd.nit -o $@
-test: nitmd
+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
+arraytos/
+string_concat/
+string_iter/
+string_substr/
--- /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
+
+clean:
+ rm -rf arraytos/ string_concat/ string_iter/ string_substr/ 2>/dev/null
--- /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
end
var ben = new Benitlux("sherbrooke")
-ben.run(opts.send_emails.value or else false)
+ben.run(opts.send_emails.value)
# The parsing logic for the wellington locaiton is active (to gather data)
# but the web interface do not allow to subscribe to its mailing list.
#
# TODO revamp mailing list Web interface
ben = new Benitlux("wellington")
-ben.run(opts.send_emails.value or else false)
+ben.run(opts.send_emails.value)
end
if current_in != null then
- in_set(block) = current_in.as(not null)
+ in_set(block) = current_in
else
continue
end
var old_out = out_set(block)
for line in block.lines do
- self.current_in = current_in.as(not null)
+ self.current_in = current_in
self.current_out = empty_set
pre_line_visit(line)
enter_visit(line)
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
if x < width-1 then res.add(1)
if y >= 1 then res.add(-width)
if y < width-1 then res.add(width)
- return res.as_random.take_all
+ return res
end
# Return the state where the tile at hole+action has moved
print "result:{state}"
for n in path do
var a = n.action
- if a != null then print " + {a or else ""}"
+ if a != null then print " + {a}"
print " {n.steps}: {n.state} ({n.cost}$)"
end
end
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
# An abstract 2d line segment
interface ILine[N: Numeric]
+ # The type of points that ends the segment
type P: IPoint[N]
+ # The point that is the left-end of the segment
fun point_left: P is abstract
+
+ # The point that is the right-end of the segment
fun point_right: P is abstract
redef fun to_s do return "{point_left}--{point_right}"
if obj isa JsonObject then
if obj.keys.has("message") then
var title = "GithubAPIError"
- var msg = obj["message"].to_s or else ""
+ var msg = obj["message"].to_s
var err = new GithubError(msg, title)
err.json["requested_uri"] = uri
err.json["status_code"] = response.status_code
--- /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
--- /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.
+
+# Basic structure for Nit apps on iOS
+module app
+
+import platform
+import ::app
+
+in "ObjC Header" `{
+ #import <UIKit/UIKit.h>
+
+ // Our interface to the iOS system
+ @interface AppDelegate: UIResponder <UIApplicationDelegate>
+
+ // The main window
+ @property (strong, nonatomic) UIWindow *window;
+ @end
+`}
+
+in "ObjC" `{
+
+ // Global reference to the App from app.nit
+ App app_nit_ios_app;
+
+ // Our own C argc and argv
+ int app_nit_ios_argc;
+ char **app_nit_ios_argv;
+
+ @implementation AppDelegate
+
+ - (BOOL)application:(UIApplication *)application
+ willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+
+ // Set aside `application` to be used from Nit
+ App_ui_application__assign(app_nit_ios_app, application);
+ App_app_delegate__assign(app_nit_ios_app, self);
+
+ // Complete the callback
+ return App_will_finish_launching_with_options(app_nit_ios_app);
+ }
+
+ - (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+
+ return App_did_finish_launching_with_options(app_nit_ios_app);
+ }
+
+ - (void)applicationWillResignActive:(UIApplication *)application {
+ App_will_resign_active(app_nit_ios_app);
+ }
+
+ - (void)applicationDidEnterBackground:(UIApplication *)application {
+ App_did_enter_background(app_nit_ios_app);
+ }
+
+ - (void)applicationWillEnterForeground:(UIApplication *)application {
+ App_will_enter_foreground(app_nit_ios_app);
+ }
+
+ - (void)applicationDidBecomeActive:(UIApplication *)application {
+ App_did_become_active(app_nit_ios_app);
+ }
+
+ - (void)applicationWillTerminate:(UIApplication *)application {
+ App_will_terminate(app_nit_ios_app);
+ }
+
+ @end
+`}
+
+# Application interface to the iOS system
+extern class AppDelegate in "ObjC" `{ AppDelegate * `}
+end
+
+# Graphical application to which events are sent
+extern class UIApplication in "ObjC" `{ UIApplication * `}
+end
+
+redef class App
+
+ # Main graphical application
+ var ui_application: UIApplication
+
+ # Application interface to the iOS system
+ var app_delegate: AppDelegate
+
+ # Copy back to C the command line arguments
+ #
+ # Nit extracts the first arguments from the `args` sequence,
+ # so we need to add it back. That's why Nit's `args` is smaller than in C.
+ private fun register_args(program_name: NativeString, argc: Int,
+ argv: Sequence[String]) import Sequence[String].[], String.to_cstring in "ObjC" `{
+ app_nit_ios_argc = argc+1;
+
+ // TODO copy or pin the strings when needed
+ app_nit_ios_argv = malloc(argc * sizeof(char*));
+ app_nit_ios_argv[0] = program_name;
+ for (int i = 0; i < argc; i ++) {
+ String arg = Sequence_of_String__index(argv, i);
+ app_nit_ios_argv[i+1] = String_to_cstring(arg);
+ }
+ `}
+
+ # Register `self` globally in C so it can be retrieved from iOS callbacks
+ private fun register_globally in "ObjC" `{
+ App_incr_ref(recv);
+ app_nit_ios_app = recv;
+ `}
+
+ # Entry point to the iOS framework
+ private fun ui_application_main: Bool import did_finish_launching_with_options,
+ will_finish_launching_with_options,
+ will_resign_active, did_enter_background, will_enter_foreground,
+ did_become_active, will_terminate, ui_application=, app_delegate= in "ObjC" `{
+
+ @autoreleasepool {
+ return UIApplicationMain(app_nit_ios_argc, app_nit_ios_argv,
+ nil, NSStringFromClass([AppDelegate class]));
+ }
+ `}
+
+ # The application is about to launch
+ #
+ # Redef this method to set the very first custom code to be executed.
+ fun will_finish_launching_with_options: Bool do return true
+
+ # The application just launched but is not yet displayed to the user
+ #
+ # Redef this method to customize the behavior.
+ fun did_finish_launching_with_options: Bool do return true
+
+ # The application is about to move from active to inactive state
+ #
+ # This can occur for certain types of temporary interruptions
+ # (such as an incoming phone call or SMS message) or when the
+ # user quits the application and it begins the transition to
+ # the background state.
+ #
+ # Redef this method to pause ongoing tasks, disable timers, and
+ # throttle down OpenGL ES frame rates. Games should use this
+ # method to pause.
+ fun will_resign_active do end
+
+ # The application just left foreground it can be suspended at any time
+ #
+ # Redef this method to release shared resources, save user data,
+ # invalidate timers, and store application state to restore your
+ # application to its current state in case it is terminated later.
+ #
+ # If your application supports background execution, this method
+ # is called instead of `will_terminate` when the user quits.
+ fun did_enter_background do end
+
+ # The application will enter the foreground
+ #
+ # Called as part of the transition from the background to the
+ # inactive state.
+ #
+ # Redef to und changes made on entering the background.
+ fun will_enter_foreground do end
+
+ # The application just became active
+ #
+ # Redef to restart any tasks that were paused (or not yet started) while
+ # the application was inactive. If the application was previously
+ # in the background, optionally refresh the user interface.
+ fun did_become_active do end
+
+ # The application is about to terminate (not suspended)
+ #
+ # Redef to save data if appropriate.
+ fun will_terminate do end
+end
+
+app.register_args(program_name.to_cstring, args.length, args)
+app.register_globally
+
+var ret = app.ui_application_main
+exit if ret then 0 else 1
--- /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.
+
+# Simple iOS app with a single label
+module hello_ios is
+ app_name "Hello iOS"
+ app_namespace "nit.app.hello_ios"
+ app_version(0, 5, git_revision)
+end
+
+import ios
+
+redef class App
+ redef fun did_finish_launching_with_options
+ do
+ return app_delegate.hello_world
+ end
+end
+
+redef class AppDelegate
+
+ # Print and show "Hello World!"
+ private fun hello_world: Bool in "ObjC" `{
+
+ // Print to the console
+ NSLog(@"Hello World!");
+
+ // Display "Hello world!" on the screen
+ recv.window = [[UIWindow alloc] initWithFrame:
+ [[UIScreen mainScreen] bounds]];
+ recv.window.backgroundColor = [UIColor whiteColor];
+
+ UILabel *label = [[UILabel alloc] init];
+ label.text = @"Hello World!";
+ label.center = CGPointMake(100, 100);
+ [label sizeToFit];
+
+ [recv.window addSubview: label];
+ [recv.window makeKeyAndVisible];
+
+ return YES;
+ `}
+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.
+
+# iOS services for Nit app on iOS
+module ios
+
+import platform
+import app
--- /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.
+
+# Triggers compilation for the iOS platform
+module platform is platform "ios"
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2015 Romain Chanoir <romain.chanoir@viacesi.fr>
+#
+# 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.
+
+# test for threaded annotation
+module threaded_example
+
+import pthreads
+
+# the "is threaded" annotation makes this fun run on an other thread
+fun foo is threaded do
+ sys.nanosleep(1,0)
+ print "threaded"
+end
+
+foo
+print "main"
+sys.nanosleep(2,0)
cflags "-pthread"
ldflags "-pthread"
pkgconfig "bdw-gc"
+ new_annotation threaded
end
#
# assert [1..1[.is_empty == true
fun is_empty: Bool do return length == 0
+ # Alias for `not is_empty`.
+ #
+ # Some people prefer to have conditions grammatically easier to read.
+ #
+ # assert [1,2,3].not_empty == true
+ # assert [1..1[.not_empty == false
+ fun not_empty: Bool do return not self.is_empty
+
# Number of items in the collection.
#
# assert [10,20,30].length == 3
# This module introduces the standard array structure.
# It also implements two other abstract collections : ArrayMap and ArraySet
-module array
+module array is
+ no_warning "useless-type-test" # to avoid warning with nitc while compiling with c_src
+end
import abstract_collection
end
+redef class MapRead[K,V]
+ # Return an array of all values sorted with their keys using `comparator`.
+ #
+ # ~~~
+ # var map = new HashMap[Int, String]
+ # map[10] = "ten"
+ # map[2] = "two"
+ # map[1] = "one"
+ # assert map.values_sorted_by_key(default_comparator) == ["one", "two", "ten"]
+ # assert map.values_sorted_by_key(alpha_comparator) == ["one", "ten", "two"]
+ # ~~~
+ fun values_sorted_by_key(comparator: Comparator): Array[V]
+ do
+ var keys = self.keys.to_a
+ comparator.sort(keys)
+ return [for k in keys do self[k]]
+ end
+
+ # Return an array of all keys sorted with their values using `comparator`.
+ #
+ # ~~~
+ # var map = new HashMap[String, Int]
+ # map["ten"] = 10
+ # map["two"] = 2
+ # map["one"] = 1
+ # assert map.keys_sorted_by_values(default_comparator) == ["one", "two", "ten"]
+ # assert map.keys_sorted_by_values(alpha_comparator) == ["one", "ten", "two"]
+ # ~~~
+ #
+ # See: `to_map_comparator` to get the comparator used internally.
+ fun keys_sorted_by_values(comparator: Comparator): Array[K]
+ do
+ var keys = self.keys.to_a
+ var map_cmp = to_map_comparator(comparator)
+ map_cmp.sort(keys)
+ return keys
+ end
+
+ # A comparator that compares things with their values in self.
+ #
+ # See `MapComparator` for details.
+ fun to_map_comparator(comparator: Comparator): MapComparator[K, V] do return new MapComparator[K,V](self, comparator)
+end
+
+# A comparator that compares things with their values in a map.
+#
+# ~~~
+# var map = new HashMap[String, Int]
+# map["ten"] = 10
+# map["two"] = 2
+# map["one"] = 1
+#
+# var map_cmp = map.to_map_comparator(default_comparator)
+# var a = ["ten", "one", "two"]
+# map_cmp.sort(a)
+# assert a == ["one", "two", "ten"]
+# map_cmp = map.to_map_comparator(alpha_comparator)
+# map_cmp.sort(a)
+# assert a == ["one", "ten", "two"]
+# ~~~
+class MapComparator[K,V]
+ super Comparator
+
+ # What is compared are the keys of the values
+ redef type COMPARED: K
+
+ # The map that associates compared elements to the value used to compare them
+ var map: MapRead[K,V]
+
+ # The comparator used to compare values
+ var comparator: Comparator
+
+ redef fun compare(a,b) do return comparator.compare(map[a], map[b])
+end
+
# This comparator uses the operator `<=>` to compare objects.
# see `default_comparator` for an easy-to-use general stateless default comparator.
class DefaultComparator
# The methods `in_same_subset`, `to_partitions`, and their variations are offered instead.
class DisjointSet[E]
super SimpleCollection[E]
+ super Cloneable
# The node in the hiearchical structure for each element
private var nodes = new HashMap[E, DisjointSetNode]
+ # Copy constructor
+ init from(other: DisjointSet[E])
+ do
+ # Associate a root node in other to the associated root node in self
+ var map = new HashMap[DisjointSetNode, DisjointSetNode]
+ for e, v in other.nodes do
+ # Create the associated node
+ var n2 = new DisjointSetNode
+ nodes[e] = n2
+
+ # Get the root node in other and the associated one in self
+ var p = other.find(e)
+ var p2 = map.get_or_null(p)
+ if p2 == null then
+ # if no associated root node, then a new subset is created
+ map[p] = n2.parent
+ number_of_subsets += 1
+ else
+ # else attach the new node to the subset of the root node
+ n2.parent = p2
+ end
+ end
+ end
+
+ # Shallow copy
+ #
+ # var s = new DisjointSet[Int]
+ # s.add_all([1,2,3,4,5])
+ # s.union_all([1,4,5])
+ # var s2 = s.clone
+ # assert s2.number_of_subsets == 3
+ # assert s2.all_in_same_subset([1,4,5]) == true
+ # assert s2.in_same_subset(1,2) == false
+ redef fun clone do return new DisjointSet[E].from(self)
+
# The number of subsets in the partition
#
# var s = new DisjointSet[Int]
// cmd exited on SIGINT: in my opinion the user wants the main to be discontinued
kill(getpid(), SIGINT);
}
+ return status;
}
# File descriptor of this file
fun fd: Int do return _file.fileno
+ redef fun close
+ do
+ if _file == null then return
+ if _file.address_is_null then
+ if last_error != null then return
+ last_error = new IOError("Cannot close unopened file")
+ return
+ end
+ var i = _file.io_close
+ if i != 0 then
+ last_error = new IOError("Close failed due to error {sys.errno.strerror}")
+ end
+ _file = null
+ end
+
# Sets the buffering mode for the current FileStream
#
# If the buf_size is <= 0, its value will be 512 by default
redef fun close
do
- if _file == null or _file.address_is_null then return
- var i = _file.io_close
+ super
_buffer.clear
end_reached = true
- _file = null
end
redef fun fill_buffer
end
end
+ # Creates a new File stream from a file descriptor
init from_fd(fd: Int) do
self.path = ""
prepare_buffer(1)
redef fun close
do
- if _file == null then return
- if _file.address_is_null then
- if last_error != null then return
- last_error = new IOError("Cannot close unopened write stream")
- _is_writable = false
- return
- end
- var i = _file.io_close
- if i != 0 then
- last_error = new IOError("Close failed due to error {sys.errno.strerror}")
- end
+ super
_is_writable = false
- _file = null
end
redef var is_writable = false
#
# assert "abAB12<>&".escape_to_c == "abAB12<>&"
# assert "\n\"'\\".escape_to_c == "\\n\\\"\\'\\\\"
+ #
+ # Most non-printable characters (bellow ASCII 32) are escaped to an octal form `\nnn`.
+ # Three digits are always used to avoid following digits to be interpreted as an element
+ # of the octal sequence.
+ #
+ # assert "{0.ascii}{1.ascii}{8.ascii}{31.ascii}{32.ascii}".escape_to_c == "\\000\\001\\010\\037 "
+ #
+ # The exceptions are the common `\t` and `\n`.
fun escape_to_c: String
do
var b = new FlatBuffer
var c = chars[i]
if c == '\n' then
b.append("\\n")
+ else if c == '\t' then
+ b.append("\\t")
else if c == '\0' then
- b.append("\\0")
+ b.append("\\000")
else if c == '"' then
b.append("\\\"")
else if c == '\'' then
else if c == '\\' then
b.append("\\\\")
else if c.ascii < 32 then
- b.append("\\{c.ascii.to_base(8, false)}")
+ b.add('\\')
+ var oct = c.ascii.to_base(8, false)
+ # Force 3 octal digits since it is the
+ # maximum allowed in the C specification
+ if oct.length == 1 then
+ b.add('0')
+ b.add('0')
+ else if oct.length == 2 then
+ b.add('0')
+ end
+ b.append(oct)
else
b.add(c)
end
# 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
# Short name
var name: String
- init(name: String) do self.name = name
-
redef fun rendering do add "- {name}\n"
end
var birth: Int
var death: Int
- init(firstname, lastname: String, birth, death: Int) do
- self.firstname = firstname
- self.lastname = lastname
- self.birth = birth
- self.death = death
- end
-
redef fun rendering do add """
COMPOSER: {{{firstname}}} {{{lastname}}}
import c_tools
private import annotation
import mixin
+import counter
# Add compiling options
redef class ToolContext
protected fun write_and_make(compiler: AbstractCompiler)
do
var platform = compiler.target_platform
- var toolchain = platform.toolchain(toolcontext)
+ var toolchain = platform.toolchain(toolcontext, compiler)
compile_dir = toolchain.compile_dir
- toolchain.write_and_make compiler
+ toolchain.write_and_make
end
end
redef class Platform
# The specific tool-chain associated to the platform
- fun toolchain(toolcontext: ToolContext): Toolchain do return new MakefileToolchain(toolcontext)
+ fun toolchain(toolcontext: ToolContext, compiler: AbstractCompiler): Toolchain
+ do
+ return new MakefileToolchain(toolcontext, compiler)
+ end
end
+# Build toolchain for a specific target program, varies per `Platform`
class Toolchain
+
+ # Toolcontext
var toolcontext: ToolContext
+ # Compiler of the target program
+ var compiler: AbstractCompiler
+
+ # Directory where to generate all C files
fun compile_dir: String
do
var compile_dir = toolcontext.opt_compile_dir.value
return compile_dir
end
- fun write_and_make(compiler: AbstractCompiler) is abstract
+ # Write all C files and compile them
+ fun write_and_make is abstract
end
+# Default toolchain using a Makefile
class MakefileToolchain
super Toolchain
- redef fun write_and_make(compiler)
+ redef fun write_and_make
do
var compile_dir = compile_dir
compile_dir.mkdir
var cfiles = new Array[String]
- write_files(compiler, compile_dir, cfiles)
+ write_files(compile_dir, cfiles)
# Generate the Makefile
- write_makefile(compiler, compile_dir, cfiles)
+ write_makefile(compile_dir, cfiles)
var time1 = get_time
self.toolcontext.info("*** END WRITING C: {time1-time0} ***", 2)
time0 = time1
self.toolcontext.info("*** COMPILING C ***", 1)
- compile_c_code(compiler, compile_dir)
+ compile_c_code(compile_dir)
time1 = get_time
self.toolcontext.info("*** END COMPILING C: {time1-time0} ***", 2)
end
- fun write_files(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String])
+ # Write all source files to the `compile_dir`
+ fun write_files(compile_dir: String, cfiles: Array[String])
do
var platform = compiler.target_platform
if self.toolcontext.opt_stacktrace.value == "nitstack" and platform.supports_libunwind then compiler.build_c_to_nit_bindings
self.toolcontext.info("Total C source files to compile: {cfiles.length}", 2)
end
- fun makefile_name(mainmodule: MModule): String do return "{mainmodule.c_name}.mk"
+ # Get the name of the Makefile to use
+ fun makefile_name: String do return "{compiler.mainmodule.c_name}.mk"
- fun default_outname(mainmodule: MModule): String
+ # Get the default name of the executable to produce
+ fun default_outname: String
do
- # 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
do
var res = self.toolcontext.opt_output.value
if res != null then return res
- res = default_outname(mainmodule)
+ res = default_outname
var dir = self.toolcontext.opt_dir.value
if dir != null then return dir.join_path(res)
return res
end
- fun write_makefile(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String])
+ # Write the Makefile
+ fun write_makefile(compile_dir: String, cfiles: Array[String])
do
var mainmodule = compiler.mainmodule
var platform = compiler.target_platform
# 2. copy the binary at the right place in the `all` goal.
outpath = mainmodule.c_name
end
- var makename = makefile_name(mainmodule)
+ var makename = makefile_name
var makepath = "{compile_dir}/{makename}"
var makefile = new FileWriter.open(makepath)
makepath.file_copy_to "{compile_dir}/Makefile"
end
- fun compile_c_code(compiler: AbstractCompiler, compile_dir: String)
+ # The C code is generated, compile it to an executable
+ fun compile_c_code(compile_dir: String)
do
- var makename = makefile_name(compiler.mainmodule)
+ var makename = makefile_name
var makeflags = self.toolcontext.opt_make_flags.value
if makeflags == null then makeflags = ""
self.header.add_decl("#include <stdlib.h>")
self.header.add_decl("#include <stdio.h>")
self.header.add_decl("#include <string.h>")
+ self.header.add_decl("#include <sys/types.h>\n")
+ self.header.add_decl("#include <unistd.h>\n")
self.header.add_decl("#include \"gc_chooser.h\"")
self.header.add_decl("#ifdef ANDROID")
self.header.add_decl(" #include <android/log.h>")
end
fun finalize_ffi_for_module(mmodule: MModule) do mmodule.finalize_ffi(self)
-
- # Division facility
- # Avoid division by zero by returning the string "n/a"
- fun div(a,b:Int):String
- do
- if b == 0 then return "n/a"
- return ((a*10000/b).to_f / 100.0).to_precision(2)
- end
end
# A file unit (may be more than one file if
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
var oldnode = v.current_node
v.current_node = self
var old_frame = v.frame
- var frame = new StaticFrame(v, self.mpropdef.as(not null), recv.mcasttype.as_notnullable.as(MClassType), [recv])
+ var frame = new StaticFrame(v, self.mpropdef.as(not null), recv.mcasttype.undecorate.as(MClassType), [recv])
v.frame = frame
var value
import poset
# Build a conflict graph from a POSet
-class POSetConflictGraph[E: Object]
+class POSetConflictGraph[E]
# Core is composed by:
# * elements that have mutiple direct parents
# REQUIRE: is_colored
var conflicts = new HashMap[E, Set[E]]
+ # The associated poset
var poset: POSet[E]
+ # The linearisation order to visit elements in the poset
+ var order: Array[E] is noinit
+
init do
extract_core
extract_border
extract_crown
compute_conflicts
+ order = poset.linearize(poset)
end
# Compute the set of elements forming the core of the poset hierarchy.
#print "border: {border.join(" ")} ({border.length})"
#print "crown: {crown.join(" ")} ({crown.length})"
print "conflicts:"
- for e, c in conflicts do print " {e}: {c.join(" ")}"
+ for e, c in conflicts do print " {e or else "NULL"}: {c.join(" ")}"
end
end
+redef class POSet[E]
+ fun to_conflict_graph: POSetConflictGraph[E] do return new POSetConflictGraph[E](self)
+end
+
# Colorize elements from a POSet
# Two elements from a POSet cannot have the same color if they share common subelements
#
end
end
+# Colorize elements `E` introduced by holders `H` in a `POSet`.
+#
+# Two elements cannot have the same color if they are introduced or inherited by a same holder.
+class POSetGroupColorer[H: Object, E: Object]
+
+ # The associated conflict graph containing the poset.
+ #
+ # The conflict graph is used instead of the original poset so that the conflict graph can be reused
+ # in different coloration based on the same poset.
+ var graph: POSetConflictGraph[H]
+
+ # The elements to color.
+ #
+ # For each holder, the collection of introduced elements is given.
+ #
+ # A single element must not be introduced in more than one holder.
+ var buckets: Map[H, Collection[E]]
+
+ # The associated poset.
+ #
+ # alias for `graph.poset`
+ fun poset: POSet[H] do return graph.poset
+
+ # The resulting coloring
+ #
+ # Each element from buckets is associated to its own color
+ var colors: Map[E, Int] is lazy do
+ for h in graph.poset do
+ used_colors[h] = new HashSet[Int]
+ end
+ compute_colors
+ return colors_cache
+ end
+
+ # Resulting colors
+ private var colors_cache = new HashMap[E, Int]
+
+ # Set of known used colors
+ private var used_colors = new HashMap[H, HashSet[Int]]
+
+ # Build table layout of elements `E` for the holder `h`.
+ #
+ # `null` is used to fill places without elements (holes).
+ fun build_layout(h: H): Array[nullable E]
+ do
+ var table = new Array[nullable E]
+ for s in poset[h].greaters do
+ var bucket = buckets.get_or_null(s)
+ if bucket == null then continue
+ for e in bucket do
+ var color = colors[e]
+ if table.length <= color then
+ for i in [table.length .. color[ do
+ table[i] = null
+ end
+ else
+ assert table[color] == null else print "in {h}, for {color}: {table[color] or else ""} vs {e}"
+ end
+ table[color] = e
+ end
+ end
+ return table
+ end
+
+ # Colorize core, border and crown in that order
+ private fun compute_colors do
+ colors_cache.clear
+ colorize_core
+ colorize_set(graph.border)
+ colorize_set(graph.crown)
+ end
+
+ # Core elements cannot have the same color than:
+ # * one of their parents
+ # * one of their conflicting elements
+ private fun colorize_core do
+ for h in graph.order do
+ if not graph.core.has(h) then continue
+
+ var color = inherit_color(h)
+ var mincolor = color
+ var bucket = buckets.get_or_null(h)
+ if bucket == null then continue
+ var conflicts = graph.conflicts[h]
+ var parents = poset[h].greaters
+ for e in bucket do
+ color = next_free_color(color, parents)
+ color = next_free_color(color, conflicts)
+ colors_cache[e] = color
+ used_colors[h].add color
+ #print "{h}: color[{color}] <- {e}"
+ if mincolor == color then mincolor += 1
+ color += 1
+ end
+ min_colors[h] = mincolor
+ end
+ end
+
+ # Other elements inherit color from their direct parents
+ private fun colorize_set(set: Set[H]) do
+ for h in graph.order do
+ if not set.has(h) then continue
+
+ var color = inherit_color(h)
+ var mincolor = color
+ var bucket = buckets.get_or_null(h)
+ if bucket == null then continue
+ var parents = poset[h].greaters
+ for e in bucket do
+ color = next_free_color(color, parents)
+ colors_cache[e] = color
+ used_colors[h].add color
+ #print "{h}: color[{color}] <- {e} (set)"
+ if mincolor == color then mincolor += 1
+ color += 1
+ end
+ min_colors[h] = mincolor
+ end
+ end
+
+ # Get the first available free color.
+ private fun inherit_color(h: H): Int
+ do
+ var res = 0
+ for p in poset[h].direct_greaters do
+ var m = min_colors[p]
+ if m > res then res = m
+ end
+ min_colors[h] = res
+ return res
+ end
+
+ # The first available color for each holder.
+ #
+ # Is used by children to start their coloring.
+ #
+ # Is updated at the end of a coloring step.
+ private var min_colors = new HashMap[H, Int]
+
+ private fun next_free_color(color: Int, set: Collection[H]): Int do
+ loop
+ for h in set do
+ if used_colors[h].has(color) then
+ #print "\tin {h}, {color} is used"
+ color += 1
+ continue label
+ end
+ end
+ break
+ end label
+ return color
+ end
+
+ # Used for debugging only
+ fun pretty_print do
+ print "colors:"
+ for e, c in colors do print " {e}: {c}"
+ end
+end
+
# Colorize a collection of buckets
# Two elements cannot have the same color if they both appear in the same bucket
# No coloring order is garantied
import platform::android
import platform::pnacl
import platform::emscripten
+import platform::ios
var opt_colo_dead_methods = new OptionBool("Force colorization of dead methods", "--colo-dead-methods")
# --tables-metrics
var opt_tables_metrics = new OptionBool("Enable static size measuring of tables used for vft, typing and resolution", "--tables-metrics")
+ # --type-poset
+ var opt_type_poset = new OptionBool("Build a poset of types to create more condensed tables.", "--type-poset")
redef init
do
self.option_context.add_option(self.opt_inline_coloring_numbers, opt_inline_some_methods, opt_direct_call_monomorph, opt_skip_dead_methods, opt_semi_global)
self.option_context.add_option(self.opt_colo_dead_methods)
self.option_context.add_option(self.opt_tables_metrics)
+ self.option_context.add_option(self.opt_type_poset)
end
redef fun process_options(args)
private var type_ids: Map[MType, Int] is noinit
private var type_colors: Map[MType, Int] is noinit
private var opentype_colors: Map[MType, Int] is noinit
- protected var method_colors: Map[PropertyLayoutElement, Int] is noinit
- protected var attr_colors: Map[MAttribute, Int] is noinit
init do
var file = new_file("nit.common")
private var color_consts_done = new HashSet[Object]
+ # The conflict graph of classes used for coloration
+ var class_conflict_graph: POSetConflictGraph[MClass] is noinit
+
# colorize classe properties
fun do_property_coloring do
var rta = runtime_type_analysis
- # Layouts
- var poset = mainmodule.flatten_mclass_hierarchy
- var mclasses = new HashSet[MClass].from(poset)
- var colorer = new POSetColorer[MClass]
- colorer.colorize(poset)
-
- # The dead methods, still need to provide a dead color symbol
- var dead_methods = new Array[MMethod]
+ # Class graph
+ var mclasses = mainmodule.flatten_mclass_hierarchy
+ class_conflict_graph = mclasses.to_conflict_graph
- # lookup properties to build layout with
+ # Prepare to collect elements to color and build layout with
var mmethods = new HashMap[MClass, Set[PropertyLayoutElement]]
var mattributes = new HashMap[MClass, Set[MAttribute]]
+
+ # The dead methods and super-call, still need to provide a dead color symbol
+ var dead_methods = new Array[PropertyLayoutElement]
+
for mclass in mclasses do
mmethods[mclass] = new HashSet[PropertyLayoutElement]
mattributes[mclass] = new HashSet[MAttribute]
- for mprop in self.mainmodule.properties(mclass) do
- if mprop isa MMethod then
- if not modelbuilder.toolcontext.opt_colo_dead_methods.value and rta != null and not rta.live_methods.has(mprop) then
- dead_methods.add(mprop)
- continue
- end
- mmethods[mclass].add(mprop)
- else if mprop isa MAttribute then
- mattributes[mclass].add(mprop)
- end
+ end
+
+ # Pre-collect known live things
+ if rta != null then
+ for m in rta.live_methods do
+ mmethods[m.intro_mclassdef.mclass].add m
+ end
+ for m in rta.live_super_sends do
+ var mclass = m.mclassdef.mclass
+ mmethods[mclass].add m
end
end
- # Collect all super calls (dead or not)
- var all_super_calls = new HashSet[MMethodDef]
- for mmodule in self.mainmodule.in_importation.greaters do
- for mclassdef in mmodule.mclassdefs do
- for mpropdef in mclassdef.mpropdefs do
- if not mpropdef isa MMethodDef then continue
- if mpropdef.has_supercall then
- all_super_calls.add(mpropdef)
+ for m in mainmodule.in_importation.greaters do for cd in m.mclassdefs do
+ var mclass = cd.mclass
+ # Collect methods ad attributes
+ for p in cd.intro_mproperties do
+ if p isa MMethod then
+ if rta == null then
+ mmethods[mclass].add p
+ else if not rta.live_methods.has(p) then
+ dead_methods.add p
end
+ else if p isa MAttribute then
+ mattributes[mclass].add p
end
end
- end
- # lookup super calls and add it to the list of mmethods to build layout with
- var super_calls
- if rta != null then
- super_calls = rta.live_super_sends
- else
- super_calls = all_super_calls
- end
-
- for mmethoddef in super_calls do
- var mclass = mmethoddef.mclassdef.mclass
- mmethods[mclass].add(mmethoddef)
- for descendant in mclass.in_hierarchy(self.mainmodule).smallers do
- mmethods[descendant].add(mmethoddef)
+ # Collect all super calls (dead or not)
+ for mpropdef in cd.mpropdefs do
+ if not mpropdef isa MMethodDef then continue
+ if mpropdef.has_supercall then
+ if rta == null then
+ mmethods[mclass].add mpropdef
+ else if not rta.live_super_sends.has(mpropdef) then
+ dead_methods.add mpropdef
+ end
+ end
end
end
# methods coloration
- var meth_colorer = new POSetBucketsColorer[MClass, PropertyLayoutElement](poset, colorer.conflicts)
- method_colors = meth_colorer.colorize(mmethods)
- method_tables = build_method_tables(mclasses, super_calls)
+ var meth_colorer = new POSetGroupColorer[MClass, PropertyLayoutElement](class_conflict_graph, mmethods)
+ var method_colors = meth_colorer.colors
compile_color_consts(method_colors)
- # attribute null color to dead methods and supercalls
- for mproperty in dead_methods do
- compile_color_const(new_visitor, mproperty, -1)
- end
- for mpropdef in all_super_calls do
- if super_calls.has(mpropdef) then continue
- compile_color_const(new_visitor, mpropdef, -1)
- end
+ # give null color to dead methods and supercalls
+ for mproperty in dead_methods do compile_color_const(new_visitor, mproperty, -1)
- # attributes coloration
- var attr_colorer = new POSetBucketsColorer[MClass, MAttribute](poset, colorer.conflicts)
- attr_colors = attr_colorer.colorize(mattributes)
- attr_tables = build_attr_tables(mclasses)
+ # attribute coloration
+ var attr_colorer = new POSetGroupColorer[MClass, MAttribute](class_conflict_graph, mattributes)
+ var attr_colors = attr_colorer.colors#ize(poset, mattributes)
compile_color_consts(attr_colors)
- end
- fun build_method_tables(mclasses: Set[MClass], super_calls: Set[MMethodDef]): Map[MClass, Array[nullable MPropDef]] do
- var tables = new HashMap[MClass, Array[nullable MPropDef]]
+ # Build method and attribute tables
+ method_tables = new HashMap[MClass, Array[nullable MPropDef]]
+ attr_tables = new HashMap[MClass, Array[nullable MProperty]]
for mclass in mclasses do
- var table = new Array[nullable MPropDef]
- tables[mclass] = table
+ if not mclass.has_new_factory and (mclass.kind == abstract_kind or mclass.kind == interface_kind) then continue
+ if rta != null and not rta.live_classes.has(mclass) then continue
- var mproperties = self.mainmodule.properties(mclass)
var mtype = mclass.intro.bound_mtype
- for mproperty in mproperties do
- if not mproperty isa MMethod then continue
- if not method_colors.has_key(mproperty) then continue
- var color = method_colors[mproperty]
- if table.length <= color then
- for i in [table.length .. color[ do
- table[i] = null
- end
- end
- table[color] = mproperty.lookup_first_definition(mainmodule, mtype)
- end
-
- for supercall in super_calls do
- if not mtype.collect_mclassdefs(mainmodule).has(supercall.mclassdef) then continue
-
- var color = method_colors[supercall]
- if table.length <= color then
- for i in [table.length .. color[ do
- table[i] = null
- end
+ # Resolve elements in the layout to get the final table
+ var meth_layout = meth_colorer.build_layout(mclass)
+ var meth_table = new Array[nullable MPropDef].with_capacity(meth_layout.length)
+ method_tables[mclass] = meth_table
+ for e in meth_layout do
+ if e == null then
+ meth_table.add null
+ else if e isa MMethod then
+ # Standard method call of `e`
+ meth_table.add e.lookup_first_definition(mainmodule, mtype)
+ else if e isa MMethodDef then
+ # Super-call in the methoddef `e`
+ meth_table.add e.lookup_next_definition(mainmodule, mtype)
+ else
+ abort
end
- var mmethoddef = supercall.lookup_next_definition(mainmodule, mtype)
- table[color] = mmethoddef
end
+ # Do not need to resolve attributes as only the position is used
+ attr_tables[mclass] = attr_colorer.build_layout(mclass)
end
- return tables
- end
- fun build_attr_tables(mclasses: Set[MClass]): Map[MClass, Array[nullable MPropDef]] do
- var tables = new HashMap[MClass, Array[nullable MPropDef]]
- for mclass in mclasses do
- var table = new Array[nullable MPropDef]
- tables[mclass] = table
- var mproperties = self.mainmodule.properties(mclass)
- var mtype = mclass.intro.bound_mtype
-
- for mproperty in mproperties do
- if not mproperty isa MAttribute then continue
- if not attr_colors.has_key(mproperty) then continue
- var color = attr_colors[mproperty]
- if table.length <= color then
- for i in [table.length .. color[ do
- table[i] = null
- end
- end
- table[color] = mproperty.lookup_first_definition(mainmodule, mtype)
- end
- end
- return tables
end
# colorize live types of the program
- private fun do_type_coloring: POSet[MType] do
+ private fun do_type_coloring: Collection[MType] do
# Collect types to colorize
var live_types = runtime_type_analysis.live_types
var live_cast_types = runtime_type_analysis.live_cast_types
- # Compute colors
- var poset = poset_from_mtypes(live_types, live_cast_types)
- var colorer = new POSetColorer[MType]
- colorer.colorize(poset)
- type_ids = colorer.ids
- type_colors = colorer.colors
- type_tables = build_type_tables(poset)
+ var res = new HashSet[MType]
+ res.add_all live_types
+ res.add_all live_cast_types
+
+ if modelbuilder.toolcontext.opt_type_poset.value then
+ # Compute colors with a type poset
+ var poset = poset_from_mtypes(live_types, live_cast_types)
+ var colorer = new POSetColorer[MType]
+ colorer.colorize(poset)
+ type_ids = colorer.ids
+ type_colors = colorer.colors
+ type_tables = build_type_tables(poset)
+ else
+ # Compute colors using the class poset
+ # Faster to compute but the number of holes can degenerate
+ compute_type_test_layouts(live_types, live_cast_types)
+
+ type_ids = new HashMap[MType, Int]
+ for x in res do type_ids[x] = type_ids.length + 1
+ end
# VT and FT are stored with other unresolved types in the big resolution_tables
self.compute_resolution_tables(live_types)
- return poset
+ return res
end
private fun poset_from_mtypes(mtypes, cast_types: Set[MType]): POSet[MType] do
var mtypes_by_class = new MultiHashMap[MClass, MType]
for e in mtypes do
- var c = e.as_notnullable.as(MClassType).mclass
+ var c = e.undecorate.as(MClassType).mclass
mtypes_by_class[c].add(e)
poset.add_node(e)
end
var casttypes_by_class = new MultiHashMap[MClass, MType]
for e in cast_types do
- var c = e.as_notnullable.as(MClassType).mclass
+ var c = e.undecorate.as(MClassType).mclass
casttypes_by_class[c].add(e)
poset.add_node(e)
end
return tables
end
+
+ private fun compute_type_test_layouts(mtypes: Set[MClassType], cast_types: Set[MType]) do
+ # Group cast_type by their classes
+ var bucklets = new HashMap[MClass, Set[MType]]
+ for e in cast_types do
+ var c = e.undecorate.as(MClassType).mclass
+ if not bucklets.has_key(c) then
+ bucklets[c] = new HashSet[MType]
+ end
+ bucklets[c].add(e)
+ end
+
+ # Colorize cast_types from the class hierarchy
+ var colorer = new POSetGroupColorer[MClass, MType](class_conflict_graph, bucklets)
+ type_colors = colorer.colors
+
+ var layouts = new HashMap[MClass, Array[nullable MType]]
+ for c in runtime_type_analysis.live_classes do
+ layouts[c] = colorer.build_layout(c)
+ end
+
+ # Build the table for each live type
+ for t in mtypes do
+ # A live type use the layout of its class
+ var c = t.mclass
+ var layout = layouts[c]
+ var table = new Array[nullable MType].with_capacity(layout.length)
+ type_tables[t] = table
+
+ # For each potential super-type in the layout
+ for sup in layout do
+ if sup == null then
+ table.add null
+ else if t.is_subtype(mainmodule, null, sup) then
+ table.add sup
+ else
+ table.add null
+ end
+ end
+ end
+ end
+
# resolution_tables is used to perform a type resolution at runtime in O(1)
private fun compute_resolution_tables(mtypes: Set[MType]) do
# During the visit of the body of classes, live_unresolved_types are collected
# Collect all live_unresolved_types (visited in the body of classes)
# Determinate fo each livetype what are its possible requested anchored types
- var mtype2unresolved = new HashMap[MClassType, Set[MType]]
+ var mtype2unresolved = new HashMap[MClass, Set[MType]]
for mtype in self.runtime_type_analysis.live_types do
- var set = new HashSet[MType]
+ var mclass = mtype.mclass
+ var set = mtype2unresolved.get_or_null(mclass)
+ if set == null then
+ set = new HashSet[MType]
+ mtype2unresolved[mclass] = set
+ end
for cd in mtype.collect_mclassdefs(self.mainmodule) do
if self.live_unresolved_types.has_key(cd) then
set.add_all(self.live_unresolved_types[cd])
end
end
- mtype2unresolved[mtype] = set
end
# Compute the table layout with the prefered method
- var colorer = new BucketsColorer[MType, MType]
+ var colorer = new BucketsColorer[MClass, MType]
+
opentype_colors = colorer.colorize(mtype2unresolved)
- resolution_tables = self.build_resolution_tables(mtype2unresolved)
+ resolution_tables = self.build_resolution_tables(self.runtime_type_analysis.live_types, mtype2unresolved)
# Compile a C constant for each collected unresolved type.
# Either to a color, or to -1 if the unresolved type is dead (no live receiver can require it)
#print ""
end
- fun build_resolution_tables(elements: Map[MClassType, Set[MType]]): Map[MClassType, Array[nullable MType]] do
+ fun build_resolution_tables(elements: Set[MClassType], map: Map[MClass, Set[MType]]): Map[MClassType, Array[nullable MType]] do
var tables = new HashMap[MClassType, Array[nullable MType]]
- for mclasstype, mtypes in elements do
+ for mclasstype in elements do
+ var mtypes = map[mclasstype.mclass]
var table = new Array[nullable MType]
for mtype in mtypes do
var color = opentype_colors[mtype]
# resolution table (for receiver)
if is_live then
- var mclass_type = mtype.as_notnullable
+ var mclass_type = mtype.undecorate
assert mclass_type isa MClassType
if resolution_tables[mclass_type].is_empty then
v.add_decl("NULL, /*NO RESOLUTIONS*/")
fun compile_type_resolution_table(mtype: MType) do
- var mclass_type = mtype.as_notnullable.as(MClassType)
+ var mclass_type = mtype.undecorate.as(MClassType)
# extern const struct resolution_table_X resolution_table_X
self.provide_declaration("resolution_table_{mtype.c_name}", "extern const struct types resolution_table_{mtype.c_name};")
var mtype = mclass.intro.bound_mtype
var c_name = mclass.c_name
- var vft = self.method_tables[mclass]
- var attrs = self.attr_tables[mclass]
var v = new_visitor
var rta = runtime_type_analysis
v.add_decl("const struct class class_{c_name} = \{")
v.add_decl("{self.box_kind_of(mclass)}, /* box_kind */")
v.add_decl("\{")
- for i in [0 .. vft.length[ do
+ var vft = self.method_tables.get_or_null(mclass)
+ if vft != null then for i in [0 .. vft.length[ do
var mpropdef = vft[i]
if mpropdef == null then
v.add_decl("NULL, /* empty */")
else
var res = v.new_named_var(mtype, "self")
res.is_exact = true
- v.add("{res} = nit_alloc(sizeof(struct instance) + {attrs.length}*sizeof(nitattribute_t));")
+ var attrs = self.attr_tables.get_or_null(mclass)
+ if attrs == null then
+ v.add("{res} = nit_alloc(sizeof(struct instance));")
+ else
+ v.add("{res} = nit_alloc(sizeof(struct instance) + {attrs.length}*sizeof(nitattribute_t));")
+ end
v.add("{res}->type = type;")
hardening_live_type(v, "type")
v.require_declaration("class_{c_name}")
v.add("{res}->class = &class_{c_name};")
- self.generate_init_attr(v, res, mtype)
- v.set_finalizer res
+ if attrs != null then
+ self.generate_init_attr(v, res, mtype)
+ v.set_finalizer res
+ end
v.add("return {res};")
end
v.add("\}")
private var type_tables: Map[MType, Array[nullable MType]] = new HashMap[MType, Array[nullable MType]]
private var resolution_tables: Map[MClassType, Array[nullable MType]] = new HashMap[MClassType, Array[nullable MType]]
protected var method_tables: Map[MClass, Array[nullable MPropDef]] = new HashMap[MClass, Array[nullable MPropDef]]
- protected var attr_tables: Map[MClass, Array[nullable MPropDef]] = new HashMap[MClass, Array[nullable MPropDef]]
+ protected var attr_tables: Map[MClass, Array[nullable MProperty]] = new HashMap[MClass, Array[nullable MProperty]]
redef fun display_stats
do
fun can_be_primitive(value: RuntimeVariable): Bool
do
- var t = value.mcasttype.as_notnullable
+ var t = value.mcasttype.undecorate
if not t isa MClassType then return false
var k = t.mclass.kind
return k == interface_kind or t.is_c_primitive
var v2 = compiler.new_visitor
v2.add "{c_ret} {n2}{c_sig} \{"
v2.require_declaration(m.const_color)
- var call = "(({c_funptrtype})({selfvar}->class->vft[{m.const_color}]))({arguments.join(", ")});"
+ var call = "(({c_funptrtype})({v2.class_info(selfvar)}->vft[{m.const_color}]))({arguments.join(", ")});"
if ret != null then
v2.add "return {call}"
else
var v2 = compiler.new_visitor
v2.add "{c_ret} {n2}{c_sig} \{"
v2.require_declaration(m.const_color)
- var call = "(({c_funptrtype})({selfvar}->class->vft[{m.const_color}]))({arguments.join(", ")});"
+ var call = "(({c_funptrtype})({v2.class_info(selfvar)}->vft[{m.const_color}]))({arguments.join(", ")});"
if ret != null then
v2.add "return {call}"
else
var mtype = mclass.intro.bound_mtype
var c_name = mclass.c_name
- var vft = self.method_tables[mclass]
- var attrs = self.attr_tables[mclass]
var class_table = self.class_tables[mclass]
var v = self.new_visitor
end
v.add_decl("&type_table_{c_name},")
v.add_decl("\{")
- for i in [0 .. vft.length[ do
+ var vft = self.method_tables.get_or_null(mclass)
+ if vft != null then for i in [0 .. vft.length[ do
var mpropdef = vft[i]
if mpropdef == null then
v.add_decl("NULL, /* empty */")
var res = v.new_named_var(mtype, "self")
res.is_exact = true
- v.add("{res} = nit_alloc(sizeof(struct instance) + {attrs.length}*sizeof(nitattribute_t));")
+ var attrs = self.attr_tables.get_or_null(mclass)
+ if attrs == null then
+ v.add("{res} = nit_alloc(sizeof(struct instance));")
+ else
+ v.add("{res} = nit_alloc(sizeof(struct instance) + {attrs.length}*sizeof(nitattribute_t));")
+ end
v.require_declaration("class_{c_name}")
v.add("{res}->class = &class_{c_name};")
- self.generate_init_attr(v, res, mtype)
- v.set_finalizer res
+ if attrs != null then
+ self.generate_init_attr(v, res, mtype)
+ v.set_finalizer res
+ end
v.add("return {res};")
end
v.add("\}")
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
if not nclassdef isa AStdClassdef then return
var mclassdef = nclassdef.mclassdef
- var mclass = nclassdef.mclass
+ if mclassdef == null then return
+ var mclass = mclassdef.mclass
# We only need to do this once per class
- if mclass.intro != mclassdef then return
+ if not mclassdef.is_intro then return
if mclass.kind != extern_kind then return
do
# Get the mmodule
var mmodule = nmodule.mmodule
- assert mmodule != null
+ if mmodule == null then return
self.mmodule = mmodule
# If no decl block then quit
if primtives_annotations.has(name) then return
var mmodule = self.mmodule
- assert mmodule != null
+ if mmodule == null then return
# Lazily build the full user-list
var annots = user_annotations.get_or_null(mmodule)
redef fun process_nmodule(nmodule)
do
# The AST node is not enough, we need also the associated model element
- var mmodule = nmodule.mmodule.as(not null)
+ var mmodule = nmodule.mmodule
+ if mmodule == null then return
# For the specific job we have, the simpler it to launch a visitor on
# all elements of the AST.
var visitor = new DivByZeroVisitor(toolcontext, mmodule)
import deriving
import check_annotation
import glsl_validation
+import parallelization_phase
redef class ToolContext
# FIXME: there is conflict in linex in nitc, so use this trick to force invocation
# Code genrated by the serialization phase must be analyzed for literals
phases.add_edge(literal_phase, serialization_phase_pre_model)
phases.add_edge(modelize_class_phase, serialization_phase_pre_model)
+ phases.add_edge(modelize_class_phase, parallelization_phase)
return true
end
end
do
# Get the mmodule
var mmodule = nmodule.mmodule
- assert mmodule != null
+ if mmodule == null then return
var source = nmodule.location.file
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2015 Romain Chanoir <romain.chanoir@viacesi.fr>
+#
+# 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.
+
+
+# Phase generating threads for functions annotated with `threaded` annotation
+module parallelization_phase
+
+private import parser_util
+import modelize
+import astbuilder
+private import annotation
+
+redef class ToolContext
+ # Transforms a function annotated with "threaded"
+ var parallelization_phase: Phase = new ParallelizationPhase(self, null)
+end
+
+private class ParallelizationPhase
+ super Phase
+
+ redef fun process_annotated_node(nmethdef, nat)
+ do
+ if nat.n_atid.n_id.text != "threaded" then return
+
+ if not nmethdef isa AMethPropdef then
+ toolcontext.error(nmethdef.location, "Syntax error: only a method can be threaded.")
+ return
+ end
+ if nmethdef.n_signature.n_params.length != 0 then
+ toolcontext.error(nmethdef.location, "Syntax error: parametrized method not supported yet.")
+ return
+ end
+ if nmethdef.n_signature.n_type != null then
+ toolcontext.error(nmethdef.location, "Syntax error: method with a return value not supported yet.")
+ return
+ end
+
+ # Get the module associated with this method
+ var amod = nmethdef.parent.parent
+ assert amod isa AModule
+
+ # Construct the name of the generated class
+ var modulename = amod.n_moduledecl.n_name.n_id.text
+ var classname = "Threaded" + modulename
+
+ # Try to get the name of the class
+ if nmethdef.parent isa AStdClassdef then
+ classname += nmethdef.parent.as(AStdClassdef).n_id.text
+ end
+
+ # Try to get the name of the method
+ if nmethdef.n_methid isa AIdMethid then
+ classname += nmethdef.n_methid.as(AIdMethid).n_id.text
+ end
+
+ # Create a string corresponding to the threaded class
+ var s ="""
+class {{{classname}}}
+ super Thread
+
+ redef fun main do
+ end
+end
+"""
+
+ # Parse newly obtained classdef
+ var classdef = toolcontext.parse_classdef(s).as(AStdClassdef)
+
+ # Get the `main` fun of the class
+ var mainfun : nullable AMethPropdef = null
+ for prop in classdef.n_propdefs do
+ if prop isa AMethPropdef then mainfun = prop
+ end
+ assert mainfun != null
+
+ # Make the statements from `main` fun be the statements from the "threaded" fun
+ mainfun.n_block = nmethdef.n_block
+
+ # Add "return null" to the end of the `main` function
+ var s_nullreturn = "return null"
+ var nullreturn = toolcontext.parse_something(s_nullreturn)
+ assert nullreturn isa AExpr
+ mainfun.n_block.as(ABlockExpr).n_expr.add(nullreturn)
+
+ # Create new body for the annotated fun
+ var s_newbody ="""
+var thread = new {{{classname}}}
+thread.start
+"""
+
+ var newbody = toolcontext.parse_something(s_newbody)
+ nmethdef.n_block = newbody.as(ABlockExpr)
+
+ # Add the new class to the module
+ amod.n_classdefs.add(classdef)
+ end
+end
redef fun process_nmodule(nmodule)
do
for npropdef in nmodule.inits_to_retype do
- var v = new PreciseTypeVisitor(npropdef, npropdef.mpropdef.mclassdef, toolcontext)
+ var mpropdef = npropdef.mpropdef
+ if mpropdef == null then continue # skip error
+ var v = new PreciseTypeVisitor(npropdef, mpropdef.mclassdef, toolcontext)
npropdef.accept_precise_type_visitor v
end
end
end
end
+redef class MNotNullType
+ redef fun infobox(v)
+ do
+ return mtype.infobox(v)
+ end
+ redef fun linkto
+ do
+ var res = new HTMLTag("span")
+ res.append("not null ").add(mtype.linkto)
+ return res
+ end
+end
+
+redef class MNullType
+ redef fun infobox(v)
+ do
+ var res = new HInfoBox(v, to_s)
+ return res
+ end
+ redef fun linkto
+ do
+ var res = new HTMLTag("span")
+ res.append("null")
+ return res
+ end
+end
+
redef class MSignature
redef fun linkto
do
do
var mt = mtype
if mt == null then return null
- mt = mt.as_notnullable
- if mt isa MVirtualType or mt isa MParameterType then
+ mt = mt.undecorate
+ if mt isa MFormalType then
res.add_class("nc_vt")
end
return mt.infobox(v)
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])
if nmodule == null then continue # Skip error
# Load imported module
build_module_importation(nmodule)
-
- mmodules.add(nmodule.mmodule.as(not null))
+ var mmodule = nmodule.mmodule
+ if mmodule == null then continue # skip error
+ mmodules.add mmodule
end
var time1 = get_time
self.toolcontext.info("*** END PARSE: {time1-time0} ***", 2)
if nmodule == null then continue # Skip error
# Load imported module
build_module_importation(nmodule)
-
- res.add(nmodule.mmodule.as(not null))
+ var mmodule = nmodule.mmodule
+ if mmodule == null then continue # Skip error
+ res.add mmodule
end
end
return res
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)
+ var mmodule = nmodule.mmodule
+ if mmodule == null then continue # Skip error
+ mmodules.add mmodule
+ 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
build_module_importation(nmodule)
-
- mmodules.add(nmodule.mmodule.as(not null))
+ var mmodule = nmodule.mmodule
+ if mmodule == null then continue # Skip error
+ mmodules.add mmodule
end
var time1 = get_time
self.toolcontext.info("*** END PARSE: {time1-time0} ***", 2)
if res == null then return null # Forward error
# Load imported module
build_module_importation(res)
- return res.mmodule.as(not null)
+ return res.mmodule
end
# Search a module `name` from path `lookpaths`.
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
if aimport.n_name.n_quad != null then mgroup = null # Start from top level
for grp in aimport.n_name.n_path do
var path = search_mmodule_by_name(grp, mgroup, grp.text)
- if path == null then return # Skip error
+ if path == null then
+ nmodule.mmodule = null # invalidate the module
+ return # Skip error
+ end
mgroup = path.mgroup
end
var mod_name = aimport.n_name.n_id.text
var sup = self.get_mmodule_by_name(aimport.n_name, mgroup, mod_name)
- if sup == null then continue # Skip error
+ if sup == null then
+ nmodule.mmodule = null # invalidate the module
+ continue # Skip error
+ end
aimport.mmodule = sup
imported_modules.add(sup)
var mvisibility = aimport.n_visibility.mvisibility
if mvisibility == protected_visibility then
error(aimport.n_visibility, "Error: only properties can be protected.")
+ nmodule.mmodule = null # invalidate the module
return
end
if sup == mmodule then
error(aimport.n_name, "Error: Dependency loop in module {mmodule}.")
+ nmodule.mmodule = null # invalidate the module
end
if sup.in_importation < mmodule then
error(aimport.n_name, "Error: Dependency loop between modules {mmodule} and {sup}.")
+ nmodule.mmodule = null # invalidate the module
return
end
mmodule.set_visibility_for(sup, mvisibility)
if stdimport then
var mod_name = "standard"
var sup = self.get_mmodule_by_name(nmodule, null, mod_name)
- if sup != null then # Skip error
+ if sup == null then
+ nmodule.mmodule = null # invalidate the module
+ else # Skip error
imported_modules.add(sup)
mmodule.set_visibility_for(sup, public_visibility)
end
# Returns true if the test concern real generic covariance
fun count_types(node, elem: ANode, sub, sup: MType, mmodule: MModule, anchor: nullable MClassType): Bool
do
- sub = sub.as_notnullable
- sup = sup.as_notnullable
+ sub = sub.undecorate
+ sup = sup.undecorate
# Category of the target type
if sub isa MGenericType then
fun count_cast(node: ANode, sub, sup: MType, mmodule: MModule, anchor: nullable MClassType)
do
var nsup = sup
- sup = sup.as_notnullable
- sub = sub.as_notnullable
+ sup = sup.undecorate
+ sub = sub.undecorate
if sub == nsup then
cpt_cast_pattern.inc("monomorphic cast!?!")
# Now the case of direct null and nullable is over.
# If `sub` is a formal type, then it is accepted if its bound is accepted
- while sub isa MParameterType or sub isa MVirtualType do
+ while sub isa MFormalType do
#print "3.is {sub} a {sup}?"
# A unfixed formal type can only accept itself
assert sub isa MClassType # It is the only remaining type
# A unfixed formal type can only accept itself
- if sup isa MParameterType or sup isa MVirtualType then
+ if sup isa MFormalType then
return false
end
if pd isa MMethodDef then
# Parameters (contravariant)
for p in pd.msignature.mparameters do
- var t = p.mtype.as_notnullable
+ var t = p.mtype.undecorate
if not t.need_anchor then
# OK
else if t isa MParameterType then
# Return (covariant)
var t = pd.msignature.return_mtype
if t != null and t.need_anchor then
- t = t.as_notnullable
+ t = t.undecorate
if t isa MParameterType then
covar_pt.add(t)
else if t isa MVirtualType then
# Attribute (invariant)
var t = pd.static_mtype
if t != null and t.need_anchor then
- t = t.as_notnullable
+ t = t.undecorate
if t isa MParameterType then
covar_pt.add t
contravar_pt.add t
# Virtual type bound (covariant)
var t = pd.bound
if t != null and t.need_anchor then
- t = t.as_notnullable
+ t = t.undecorate
if t isa MParameterType then
covar_pt.add t
else if t isa MVirtualType then
# Process the generic types in a covariant position
for c in covar_classes do for i in [0..c.mclass.arity[ do
# The type used in the argument
- var ta = c.arguments[i].as_notnullable
+ var ta = c.arguments[i].undecorate
# The associated formal parameter
var tp = c.mclass.mparameters[i]
# Process the generic types in a contravariant position
for c in contravar_classes do for i in [0..c.mclass.arity[ do
# The type used in the argument
- var ta = c.arguments[i].as_notnullable
+ var ta = c.arguments[i].undecorate
# The associated formal parameter
var tp = c.mclass.mparameters[i]
super
tnlc.values.inc(mtype)
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
if mtype isa MClassType then
cnlc.values.inc(mtype.mclass)
end
redef class MType
private fun signature_depth: Int do
- var mtype = self.as_notnullable
+ var mtype = self.undecorate
if not mtype isa MGenericType then return 0
var depth = 0
# 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
fun get_primitive_class(name: String): MClass
do
var cla = self.model.get_mclasses_by_name(name)
- if cla == null then
+ # Filter classes by introducing module
+ if cla != null then cla = [for c in cla do if self.in_importation <= c.intro_mmodule then c]
+ if cla == null or cla.is_empty then
if name == "Bool" and self.model.get_mclasses_by_name("Object") != null then
# Bool is injected because it is needed by engine to code the result
# of the implicit casts.
cladef.add_in_hierarchy
return c
end
- print("Fatal Error: no primitive class {name}")
+ print("Fatal Error: no primitive class {name} in {self}")
exit(1)
end
if cla.length != 1 then
- var msg = "Fatal Error: more than one primitive class {name}:"
+ var msg = "Fatal Error: more than one primitive class {name} in {self}:"
for c in cla do msg += " {c.full_name}"
print msg
#exit(1)
#
# Warning: such a definition may not exist in the early life of the object.
# In this case, the method will abort.
+ #
+ # Use `try_intro` instead
var intro: MClassDef is noinit
+ # The definition that introduces the class or null if not yet known.
+ #
+ # See `intro`
+ fun try_intro: nullable MClassDef do
+ if isset _intro then return _intro else return null
+ end
+
# Return the class `self` in the class hierarchy of the module `mmodule`.
#
# SEE: `MModule::flatten_mclass_hierarchy`
end
private var get_mtype_cache = new HashMap[Array[MType], MGenericType]
+
+ # Is there a `new` factory to allow the pseudo instantiation?
+ var has_new_factory = false is writable
end
var in_hierarchy: nullable POSetElement[MClassDef] = null
# Is the definition the one that introduced `mclass`?
- fun is_intro: Bool do return mclass.intro == self
+ fun is_intro: Bool do return isset mclass._intro and mclass.intro == self
# All properties introduced by the classdef
var intro_mproperties = new Array[MProperty]
if sup isa MNullableType then
sup_accept_null = true
sup = sup.mtype
+ else if sup isa MNotNullType then
+ sup = sup.mtype
else if sup isa MNullType then
sup_accept_null = true
end
# Can `sub` provide null or not?
# Thus we can match with `sup_accept_null`
# Also discard the nullable marker if it exists
+ var sub_reject_null = false
if sub isa MNullableType then
if not sup_accept_null then return false
sub = sub.mtype
+ else if sub isa MNotNullType then
+ sub_reject_null = true
+ sub = sub.mtype
else if sub isa MNullType then
return sup_accept_null
end
# Now the case of direct null and nullable is over.
# If `sub` is a formal type, then it is accepted if its bound is accepted
- while sub isa MParameterType or sub isa MVirtualType do
+ while sub isa MFormalType do
#print "3.is {sub} a {sup}?"
# A unfixed formal type can only accept itself
assert anchor != null
sub = sub.lookup_bound(mmodule, anchor)
+ if sub_reject_null then sub = sub.as_notnull
#print "3.is {sub} a {sup}?"
# Manage the second layer of null/nullable
if sub isa MNullableType then
- if not sup_accept_null then return false
+ if not sup_accept_null and not sub_reject_null then return false
+ sub = sub.mtype
+ else if sub isa MNotNullType then
+ sub_reject_null = true
sub = sub.mtype
else if sub isa MNullType then
return sup_accept_null
end
#print "4.is {sub} a {sup}? <- no more resolution"
- assert sub isa MClassType # It is the only remaining type
+ assert sub isa MClassType else print "{sub} <? {sub}" # It is the only remaining type
# A unfixed formal type can only accept itself
- if sup isa MParameterType or sup isa MVirtualType then
+ if sup isa MFormalType then
return false
end
return res
end
- # Return the not nullable version of the type
- # Is the type is already not nullable, then self is returned.
+ # Remove the base type of a decorated (proxy) type.
+ # Is the type is not decorated, then self is returned.
#
- # Note: this just remove the `nullable` notation, but the result can still contains null.
+ # Most of the time it is used to return the not nullable version of a nullable type.
+ # In this case, this just remove the `nullable` notation, but the result can still contains null.
# For instance if `self isa MNullType` or self is a formal type bounded by a nullable type.
- fun as_notnullable: MType
+ # If you really want to exclude the `null` value, then use `as_notnull`
+ fun undecorate: MType
do
return self
end
+ # Returns the not null version of the type.
+ # That is `self` minus the `null` value.
+ #
+ # For most types, this return `self`.
+ # For formal types, this returns a special `MNotNullType`
+ fun as_notnull: MType do return self
+
private var as_nullable_cache: nullable MType = null
end
end
+# A formal type (either virtual of parametric).
+#
+# The main issue with formal types is that they offer very little information on their own
+# and need a context (anchor and mmodule) to be useful.
+abstract class MFormalType
+ super MType
+
+ redef var as_notnull = new MNotNullType(self) is lazy
+end
+
# A virtual formal type.
class MVirtualType
- super MType
+ super MFormalType
# The property associated with the type.
# Its the definitions of this property that determine the bound or the virtual type.
redef fun lookup_fixed(mmodule: MModule, resolved_receiver: MType): MType
do
assert not resolved_receiver.need_anchor
- resolved_receiver = resolved_receiver.as_notnullable
+ resolved_receiver = resolved_receiver.undecorate
assert resolved_receiver isa MClassType # It is the only remaining type
var prop = lookup_single_definition(mmodule, resolved_receiver)
# Note that parameter types are shared among class refinements.
# Therefore parameter only have an internal name (see `to_s` for details).
class MParameterType
- super MType
+ super MFormalType
# The generic class where the parameter belong
var mclass: MClass
redef fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType
do
assert not resolved_receiver.need_anchor
- resolved_receiver = resolved_receiver.as_notnullable
+ resolved_receiver = resolved_receiver.undecorate
assert resolved_receiver isa MClassType # It is the only remaining type
var goalclass = self.mclass
if resolved_receiver.mclass == goalclass then
redef fun lookup_fixed(mmodule: MModule, resolved_receiver: MType): MType
do
assert not resolved_receiver.need_anchor
- resolved_receiver = resolved_receiver.as_notnullable
+ resolved_receiver = resolved_receiver.undecorate
assert resolved_receiver isa MClassType # It is the only remaining type
var res = self.resolve_for(resolved_receiver.mclass.mclass_type, resolved_receiver, mmodule, false)
return res
end
end
-# A type prefixed with "nullable"
-class MNullableType
+# A type that decorates another type.
+#
+# The point of this class is to provide a common implementation of sevices that just forward to the original type.
+# Specific decorator are expected to redefine (or to extend) the default implementation as this suit them.
+abstract class MProxyType
super MType
-
- # The base type of the nullable type
+ # The base type
var mtype: MType
redef fun model do return self.mtype.model
-
- init
- do
- self.to_s = "nullable {mtype}"
- end
-
- redef var to_s: String is noinit
-
- redef var full_name is lazy do return "nullable {mtype.full_name}"
-
- redef var c_name is lazy do return "nullable__{mtype.c_name}"
-
redef fun need_anchor do return mtype.need_anchor
- redef fun as_nullable do return self
- redef fun as_notnullable do return mtype
+ redef fun as_nullable do return mtype.as_nullable
+ redef fun as_notnull do return mtype.as_notnull
+ redef fun undecorate do return mtype.undecorate
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
do
var res = self.mtype.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
- return res.as_nullable
+ return res
end
redef fun can_resolve_for(mtype, anchor, mmodule)
return self.mtype.can_resolve_for(mtype, anchor, mmodule)
end
- # Efficiently returns `mtype.lookup_fixed(mmodule, resolved_receiver).as_nullable`
redef fun lookup_fixed(mmodule, resolved_receiver)
do
var t = mtype.lookup_fixed(mmodule, resolved_receiver)
- if t == mtype then return self
- return t.as_nullable
+ return t
end
redef fun depth do return self.mtype.depth
end
end
+# A type prefixed with "nullable"
+class MNullableType
+ super MProxyType
+
+ init
+ do
+ self.to_s = "nullable {mtype}"
+ end
+
+ redef var to_s: String is noinit
+
+ redef var full_name is lazy do return "nullable {mtype.full_name}"
+
+ redef var c_name is lazy do return "nullable__{mtype.c_name}"
+
+ redef fun as_nullable do return self
+ redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
+ do
+ var res = super
+ return res.as_nullable
+ end
+
+ # Efficiently returns `mtype.lookup_fixed(mmodule, resolved_receiver).as_nullable`
+ redef fun lookup_fixed(mmodule, resolved_receiver)
+ do
+ var t = super
+ if t == mtype then return self
+ return t.as_nullable
+ end
+end
+
+# A non-null version of a formal type.
+#
+# When a formal type in bounded to a nullable type, this is the type of the not null version of it.
+class MNotNullType
+ super MProxyType
+
+ redef fun to_s do return "not null {mtype}"
+ redef var full_name is lazy do return "not null {mtype.full_name}"
+ redef var c_name is lazy do return "notnull__{mtype.c_name}"
+
+ redef fun as_notnull do return self
+
+ redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
+ do
+ var res = super
+ return res.as_notnull
+ end
+
+ # Efficiently returns `mtype.lookup_fixed(mmodule, resolved_receiver).as_notnull`
+ redef fun lookup_fixed(mmodule, resolved_receiver)
+ do
+ var t = super
+ if t == mtype then return self
+ return t.as_notnull
+ end
+end
+
# The type of the only value null
#
# The is only one null type per model, see `MModel::null_type`.
redef fun full_name do return "null"
redef fun c_name do return "null"
redef fun as_nullable do return self
+
+ # Aborts on `null`
+ redef fun as_notnull do abort # sorry...
redef fun need_anchor do return false
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self
redef fun can_resolve_for(mtype, anchor, mmodule) do return true
fun lookup_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
do
assert not mtype.need_anchor
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
var cache = self.lookup_definitions_cache[mmodule, mtype]
if cache != null then return cache
fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
do
assert not mtype.need_anchor
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
# First, select all candidates
var candidates = new Array[MPROPDEF]
# REQUIRE: `mtype.has_mproperty(mmodule, self)`
fun lookup_all_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
do
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
var cache = self.lookup_all_definitions_cache[mmodule, mtype]
if cache != null then return cache
# Run `process_mainmodule` on all phases
fun run_global_phases(mmodules: Array[MModule])
do
- var mainmodule = make_main_module(mmodules)
- for phase in phases_list do
- if phase.disabled then continue
- phase.process_mainmodule(mainmodule, mmodules)
+ if not mmodules.is_empty then
+ var mainmodule = make_main_module(mmodules)
+ for phase in phases_list do
+ if phase.disabled then continue
+ phase.process_mainmodule(mainmodule, mmodules)
+ end
end
+
+ check_errors
+ errors_info
end
end
return res
end
+ # Like `try_get_mclass_by_name` but display an error message when the class is not found
+ fun get_mclass_by_name(node: ANode, mmodule: MModule, name: String): nullable MClass
+ do
+ var mclass = try_get_mclass_by_name(node, mmodule, name)
+ if mclass == null then
+ error(node, "Type Error: missing primitive class `{name}'.")
+ end
+ return mclass
+ end
+
# Return a property named `name` on the type `mtype` visible in the module `mmodule`.
# Visibility in modules is correctly handled.
# Protected properties are returned (it is up to the caller to check and reject protected properties).
if mtype isa MGenericType then
var mclass = mtype.mclass
for i in [0..mclass.arity[ do
- var bound = mclass.intro.bound_mtype.arguments[i]
+ var intro = mclass.try_intro
+ if intro == null then return null # skip error
+ var bound = intro.bound_mtype.arguments[i]
var nt = ntype.n_types[i]
var mt = resolve_mtype(mmodule, mclassdef, nt)
if mt == null then return null # forward error
var mclasses = model.get_mclasses_by_name(name)
if mclasses != null then for other in mclasses do
if other.intro_mmodule.mgroup != null and other.intro_mmodule.mgroup.mproject == mmodule.mgroup.mproject then
- error(nclassdef, "Error: A class named `{other.full_name}` is already defined in module `{other.intro_mmodule}` at {other.intro.location}.")
+ # Skip classes that are buggy
+ if other.try_intro == null then continue
+ warning(nclassdef, "full-name-conflict", "Error: A class named `{other.full_name}` is already defined in module `{other.intro_mmodule}` at {other.intro.location}.")
break
end
end
# Visit the AST and set the super-types of the `MClassDef` objects
private fun collect_a_mclassdef_inheritance(nmodule: AModule, nclassdef: AClassdef)
do
- var mmodule = nmodule.mmodule.as(not null)
+ var mmodule = nmodule.mmodule
+ if mmodule == null then return
var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
var pointerclass = try_get_mclass_by_name(nmodule, mmodule, "Pointer")
- var mclass = nclassdef.mclass.as(not null)
- var mclassdef = nclassdef.mclassdef.as(not null)
+ var mclass = nclassdef.mclass
+ if mclass == null then return
+ var mclassdef = nclassdef.mclassdef
+ if mclassdef == null then return
# Do we need to specify Object as a super class?
var specobject = true
# Check the validity of the specialization heirarchy
private fun check_supertypes(nmodule: AModule, nclassdef: AClassdef)
do
- var mmodule = nmodule.mmodule.as(not null)
- var mclass = nclassdef.mclass.as(not null)
- var mclassdef = nclassdef.mclassdef.as(not null)
+ var mmodule = nmodule.mmodule
+ if mmodule == null then return
+ var mclass = nclassdef.mclass
+ if mclass == null then return
+ var mclassdef = nclassdef.mclassdef
+ if mclassdef == null then return
for s in mclassdef.supertypes do
if s.is_subtype(mmodule, mclassdef.bound_mtype, mclassdef.bound_mtype) then
# Force building recursively
if nmodule.build_classes_is_done then return
nmodule.build_classes_is_done = true
- var mmodule = nmodule.mmodule.as(not null)
+ var mmodule = nmodule.mmodule
+ if mmodule == null then return
for imp in mmodule.in_importation.direct_greaters do
var nimp = mmodule2node(imp)
if nimp != null then build_classes(nimp)
# Check clash of ancestors
for nclassdef in nmodule.n_classdefs do
- var mclassdef = nclassdef.mclassdef.as(not null)
+ var mclassdef = nclassdef.mclassdef
+ if mclassdef == null then continue
var superclasses = new HashMap[MClass, MClassType]
for scd in mclassdef.in_hierarchy.greaters do
for st in scd.supertypes do
# Check that the superclasses are not already known (by transitivity)
for nclassdef in nmodule.n_classdefs do
if not nclassdef isa AStdClassdef then continue
- var mclassdef = nclassdef.mclassdef.as(not null)
+ var mclassdef = nclassdef.mclassdef
+ if mclassdef == null then continue
# Get the direct superclasses
# Since we are a mclassdef, just look at the mclassdef hierarchy
# Force building recursively
if nclassdef.build_properties_is_done then return
nclassdef.build_properties_is_done = true
- var mclassdef = nclassdef.mclassdef.as(not null)
+ var mclassdef = nclassdef.mclassdef
+ if mclassdef == null then return # skip error
if mclassdef.in_hierarchy == null then return # Skip error
for superclassdef in mclassdef.in_hierarchy.direct_greaters do
if not mclassdef2nclassdef.has_key(superclassdef) then continue
npropdef.build_signature(self)
end
for npropdef in nclassdef2.n_propdefs do
+ if not npropdef isa ATypePropdef then continue
+ # Check circularity
+ var mpropdef = npropdef.mpropdef
+ if mpropdef == null then continue
+ if mpropdef.bound == null then continue
+ if not check_virtual_types_circularity(npropdef, mpropdef.mproperty, mclassdef.bound_mtype, mclassdef.mmodule) then
+ # Invalidate the bound
+ mpropdef.bound = mclassdef.mmodule.model.null_type
+ end
+ end
+ for npropdef in nclassdef2.n_propdefs do
+ # Check ATypePropdef first since they may be required for the other properties
+ if not npropdef isa ATypePropdef then continue
+ npropdef.check_signature(self)
+ end
+
+ for npropdef in nclassdef2.n_propdefs do
+ if npropdef isa ATypePropdef then continue
npropdef.check_signature(self)
end
end
for p in spd.initializers do
if p != longest.initializers[i] then
self.error(nclassdef, "Error: conflict for inherited inits {spd}({spd.initializers.join(", ")}) and {longest}({longest.initializers.join(", ")})")
+ # TODO: invalidate the initializer to avoid more errors
return
end
i += 1
# It is a case-by case
var vis_type: nullable MVisibility = null # The own visibility of the type
var mmodule_type: nullable MModule = null # The original module of the type
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
if mtype isa MClassType then
vis_type = mtype.mclass.visibility
mmodule_type = mtype.mclass.intro.mmodule
mmodule_type = mtype.mproperty.intro_mclassdef.mmodule
else if mtype isa MParameterType then
# nothing, always visible
+ else if mtype isa MNullType then
+ # nothing to do.
else
node.debug "Unexpected type {mtype}"
abort
for t in mtype.arguments do check_visibility(node, t, mpropdef)
end
end
+
+ # Detect circularity errors for virtual types.
+ fun check_virtual_types_circularity(node: ANode, mproperty: MVirtualTypeProp, recv: MType, mmodule: MModule): Bool
+ do
+ # Check circularity
+ # Slow case: progress on each resolution until we visit all without getting a loop
+
+ # The graph used to detect loops
+ var mtype = mproperty.mvirtualtype
+ var poset = new POSet[MType]
+
+ # The work-list of types to resolve
+ var todo = new List[MType]
+ todo.add mtype
+
+ while not todo.is_empty do
+ # The visited type
+ var t = todo.pop
+
+ if not t.need_anchor then continue
+
+ # Get the types derived of `t` (subtypes and bounds)
+ var nexts
+ if t isa MNullableType then
+ nexts = [t.mtype]
+ else if t isa MGenericType then
+ nexts = t.arguments
+ else if t isa MVirtualType then
+ var vt = t.mproperty
+ # Because `vt` is possibly unchecked, we have to do the bound-lookup manually
+ var defs = vt.lookup_definitions(mmodule, recv)
+ # TODO something to manage correctly bound conflicts
+ assert not defs.is_empty
+ nexts = new Array[MType]
+ for d in defs do
+ var next = defs.first.bound
+ if next == null then return false
+ nexts.add next
+ end
+ else if t isa MClassType then
+ # Basic type, nothing to to
+ continue
+ else if t isa MParameterType then
+ # Parameter types cannot depend on virtual types, so nothing to do
+ continue
+ else
+ abort
+ end
+
+ # For each one
+ for next in nexts do
+ if poset.has_edge(next, t) then
+ if mtype == next then
+ error(node, "Error: circularity of virtual type definition: {next} <-> {t}")
+ else
+ error(node, "Error: circularity of virtual type definition: {mtype} -> {next} <-> {t}")
+ end
+ return false
+ else
+ poset.add_edge(t, next)
+ todo.add next
+ end
+ end
+ end
+ return true
+ end
end
redef class MPropDef
param_names.add(np.n_id.text)
var ntype = np.n_type
if ntype != null then
- var mtype = modelbuilder.resolve_mtype(mmodule, mclassdef, ntype)
+ var mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, ntype, true)
if mtype == null then return false # Skip error
for i in [0..param_names.length-param_types.length[ do
param_types.add(mtype)
end
var ntype = self.n_type
if ntype != null then
- self.ret_type = modelbuilder.resolve_mtype(mmodule, mclassdef, ntype)
+ self.ret_type = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, ntype, true)
if self.ret_type == null then return false # Skip error
end
return true
end
- # Build a visited signature
- fun build_signature(modelbuilder: ModelBuilder): nullable MSignature
+ private fun check_signature(modelbuilder: ModelBuilder, mclassdef: MClassDef): Bool
do
- if param_names.length != param_types.length then
- # Some parameters are typed, other parameters are not typed.
- modelbuilder.error(self.n_params[param_types.length], "Error: Untyped parameter `{param_names[param_types.length]}'.")
- return null
+ var res = true
+ for np in self.n_params do
+ var ntype = np.n_type
+ if ntype != null then
+ if modelbuilder.resolve_mtype(mclassdef.mmodule, mclassdef, ntype) == null then
+ res = false
+ end
+ end
end
-
- var mparameters = new Array[MParameter]
- for i in [0..param_names.length[ do
- var mparameter = new MParameter(param_names[i], param_types[i], i == vararg_rank)
- self.n_params[i].mparameter = mparameter
- mparameters.add(mparameter)
+ var ntype = self.n_type
+ if ntype != null then
+ if modelbuilder.resolve_mtype(mclassdef.mmodule, mclassdef, ntype) == null then
+ res = false
+ end
end
-
- var msignature = new MSignature(mparameters, ret_type)
- return msignature
+ return res
end
end
end
mprop.is_init = is_init
mprop.is_new = n_kwnew != null
+ if mprop.is_new then mclassdef.mclass.has_new_factory = true
if parent isa ATopClassdef then mprop.is_toplevel = true
self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mprop)
else
var mysignature = self.mpropdef.msignature
if mysignature == null then return # Error thus skiped
+ # Check
+ if nsig != null then
+ if not nsig.check_signature(modelbuilder, mclassdef) then
+ self.mpropdef.msignature = null # invalidate
+ return # Forward error
+ end
+ end
+
# Lookup for signature in the precursor
# FIXME all precursors should be considered
if not mpropdef.is_intro then
var ret_type = mysignature.return_mtype
if ret_type != null and precursor_ret_type == null then
modelbuilder.error(nsig.n_type.as(not null), "Redef Error: {mpropdef.mproperty} is a procedure, not a function.")
+ self.mpropdef.msignature = null
return
end
var node = nsig.n_params[i]
if not modelbuilder.check_sametype(node, mmodule, mclassdef.bound_mtype, myt, prt) then
modelbuilder.error(node, "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt} as in {mpropdef.mproperty.intro}.")
+ self.mpropdef.msignature = null
end
end
end
ret_type = precursor_ret_type
else if not modelbuilder.check_subtype(node, mmodule, mclassdef.bound_mtype, ret_type, precursor_ret_type) then
modelbuilder.error(node, "Redef Error: Wrong return type. found {ret_type}, expected {precursor_ret_type} as in {mpropdef.mproperty.intro}.")
+ self.mpropdef.msignature = null
end
end
end
else if atautoinit != null then
modelbuilder.error(atautoinit, "Error: a autoinit attribute needs a value")
end
+ has_value = true
return
end
is_lazy = true
var ntype = self.n_type
if ntype != null then
- mtype = modelbuilder.resolve_mtype(mmodule, mclassdef, ntype)
+ mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, ntype, true)
if mtype == null then return
end
if mtype == null then
if nexpr != null then
if nexpr isa ANewExpr then
- mtype = modelbuilder.resolve_mtype(mmodule, mclassdef, nexpr.n_type)
+ mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, nexpr.n_type, true)
else if nexpr isa AIntExpr then
var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
if cla != null then mtype = cla.mclass_type
end
else if ntype != null and inherited_type == mtype then
if nexpr isa ANewExpr then
- var xmtype = modelbuilder.resolve_mtype(mmodule, mclassdef, nexpr.n_type)
+ var xmtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, nexpr.n_type, true)
if xmtype == mtype then
modelbuilder.advice(ntype, "useless-type", "Warning: useless type definition")
end
var mtype = self.mpropdef.static_mtype
if mtype == null then return # Error thus skipped
+ var mclassdef = mpropdef.mclassdef
+ var mmodule = mclassdef.mmodule
+
+ # Check types
+ if ntype != null then
+ if modelbuilder.resolve_mtype(mmodule, mclassdef, ntype) == null then return
+ end
+ var nexpr = n_expr
+ if nexpr isa ANewExpr then
+ if modelbuilder.resolve_mtype(mmodule, mclassdef, nexpr.n_type) == null then return
+ end
+
# Lookup for signature in the precursor
# FIXME all precursors should be considered
if not mpropdef.is_intro then
var mtype: nullable MType = null
var ntype = self.n_type
- mtype = modelbuilder.resolve_mtype(mmodule, mclassdef, ntype)
+ mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, ntype, true)
if mtype == null then return
mpropdef.bound = mtype
var mpropdef = self.mpropdef
if mpropdef == null then return # Error thus skipped
- var bound = self.mpropdef.bound
+ var bound = mpropdef.bound
if bound == null then return # Error thus skipped
modelbuilder.check_visibility(n_type, bound, mpropdef)
var mmodule = mclassdef.mmodule
var anchor = mclassdef.bound_mtype
- # Check circularity
- if bound isa MVirtualType then
- # Slow case: progress on each resolution until: (i) we loop, or (ii) we found a non formal type
- var seen = [self.mpropdef.mproperty.mvirtualtype]
- loop
- if seen.has(bound) then
- seen.add(bound)
- modelbuilder.error(self, "Error: circularity of virtual type definition: {seen.join(" -> ")}")
- return
- end
- seen.add(bound)
- var next = bound.lookup_bound(mmodule, anchor)
- if not next isa MVirtualType then break
- bound = next
- end
+ var ntype = self.n_type
+ if modelbuilder.resolve_mtype(mmodule, mclassdef, ntype) == null then
+ mpropdef.bound = null
+ return
end
# Check redefinitions
- bound = mpropdef.bound.as(not null)
for p in mpropdef.mproperty.lookup_super_definitions(mmodule, anchor) do
var supbound = p.bound
if supbound == null then break # broken super bound, skip error
end
print "[HOST ADDRESS] : {debug.address}"
-print "[HOST] : {debug.host or else "unamed"}"
+print "[HOST] : {debug.host}"
print "[PORT] : {debug.port}"
print "Connecting ... {debug.connected}"
# return type
var rmt = mpropdef.msignature.return_mtype
if rmt != null then
- if rmt isa MParameterType or rmt isa MVirtualType then
+ if rmt isa MFormalType then
var mclass_type = mpropdef.mclassdef.bound_mtype
rmt = rmt.anchor_to(mmodule, mclass_type)
end
# params
for p in mpropdef.msignature.mparameters do
var mtype = p.mtype.resolve_for(recv_type, recv_type, mmodule, true)
- if mtype isa MParameterType or mtype isa MVirtualType then
+ if mtype isa MFormalType then
var mclass_type = mpropdef.mclassdef.bound_mtype
mtype = mtype.anchor_to(mmodule, mclass_type)
end
if mtype == null then return
- if mtype isa MParameterType or mtype isa MVirtualType then
+ if mtype isa MFormalType then
mtype = mtype.anchor_to(mmodule, mclass_type)
end
redef fun from_mtype do return n_type.mtype.as_nullable
redef fun to_mtype do
var mtype = n_type.mtype.as(not null)
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
return mtype
end
--- /dev/null
+*.class
+org/nitlanguage/gen/analysis/
+org/nitlanguage/gen/lexer/
+org/nitlanguage/gen/node/
+org/nitlanguage/gen/parser/
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
rm -f -- parser.nit parser_abs.nit parser_prod.nit lexer.nit || true
+
+java: .nit.sablecc3
+ rm -r org/nitlanguage/gen/analysis/ org/nitlanguage/gen/lexer/ org/nitlanguage/gen/node/ org/nitlanguage/gen/parser/
+ ${SABLECC3ALTGEN} .nit.sablecc3 -c .nit.sablecc3.dump
+ javac org/nitlanguage/gen/TestParser.java
* parser_nodes.nit: token and nodes classes hierarchy used by the parser and the lexer
* tables.nit, tables_nit.h: Interfaces to access the tables needed by the parser and the lexer
* xss/*.xss: alternate SableCC3 template files for the Nit language
-
+* org/nitlanguage/gen: A Nit parser in Java, used for tests. use the `make java` rule to build it.
The following are generated but present to avoid the need of sablecc3:
--- /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.
+ */
+
+package org.nitlanguage.gen;
+
+import java.io.*;
+import java.nio.file.*;
+
+import org.nitlanguage.gen.lexer.*;
+import org.nitlanguage.gen.parser.*;
+import org.nitlanguage.gen.analysis.*;
+import org.nitlanguage.gen.node.*;
+
+public class TestParser extends DepthFirstAdapter {
+ public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ BufferedReader ir = new BufferedReader(new InputStreamReader(System.in));
+ work(ir);
+ } else {
+ for(int i=0; i<args.length; i++) {
+ //System.out.println(args[i]);
+
+ //Here we use "ISO-8859-1" because we want to opaquely treat Bytes as characters.
+ //Unfortunately "US-ASCII" does not seems to do the job for values>127.
+ BufferedReader ir = new BufferedReader(new InputStreamReader(new FileInputStream(args[i]), "ISO-8859-1"));
+
+ work(ir);
+ }
+ }
+ }
+
+ public static void work(BufferedReader ir) {
+ TestParser testParser = new TestParser();
+ try {
+ PushbackReader r = new PushbackReader(ir, 1024);
+ Parser parser = new Parser(new Lexer(r));
+ Node syntaxTree = parser.parse();
+ syntaxTree.apply(testParser);
+ } catch (LexerException e) {
+ System.out.println(e.getMessage() + ".");
+ } catch (ParserException e) {
+ System.out.println(e.getMessage() + ".");
+ } catch (IOException e) {
+ System.out.println(e.getMessage() + ".");
+ System.exit(1);
+ }
+ }
+}
var time1 = get_time
self.info("*** END SEMANTIC ANALYSIS: {time1-time0} ***", 2)
- errors_info
+ self.check_errors
end
# Process the given `phase` on the `npropdef`
redef fun supports_linker_script do return false
- redef fun toolchain(toolcontext) do return new AndroidToolchain(toolcontext)
+ redef fun toolchain(toolcontext, compiler) do return new AndroidToolchain(toolcontext, compiler)
end
class AndroidToolchain
return "{android_project_root}/jni/nit_compile/"
end
- redef fun default_outname(mainmodule) do return "{mainmodule.name}.apk"
+ redef fun default_outname do return "{super}.apk"
- redef fun write_files(compiler, compile_dir, cfiles)
+ 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
if not dir.file_exists then dir.mkdir
# compile normal C files
- super(compiler, compile_dir, cfiles)
+ super
# Gather extra C files generated elsewhere than in super
for f in compiler.extern_bodies do
end
end
- redef fun write_makefile(compiler, compile_dir, cfiles)
+ redef fun write_makefile(compile_dir, cfiles)
do
# Do nothing, already done in `write_files`
end
- redef fun compile_c_code(compiler, compile_dir)
+ redef fun compile_c_code(compile_dir)
do
var android_project_root = android_project_root.as(not null)
var short_project_name = compiler.mainmodule.name.replace("-", "_")
# 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}}}
+namespace: {{{namespace}}}
+version: {{{version}}}"""
+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
redef fun supports_libunwind do return false
redef fun supports_libgc do return false
redef fun supports_linker_script do return false
- redef fun toolchain(toolcontext) do return new EnscriptenToolchain(toolcontext)
+ redef fun toolchain(toolcontext, compiler) do return new EnscriptenToolchain(toolcontext, compiler)
end
class EnscriptenToolchain
super MakefileToolchain
- redef fun makefile_name(mainmodule) do return "{mainmodule.name}.js.mk"
+ redef fun makefile_name do return "{super}.js.mk"
- redef fun default_outname(mainmodule) do return "{super}.js"
+ redef fun default_outname do return "{super}.js"
- redef fun write_makefile(compiler, compile_dir, cfiles)
+ redef fun write_makefile(compile_dir, cfiles)
do
super
--- /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.
+
+# Compile programs for the iOS platform
+module ios
+
+import platform
+import compiler::abstract_compiler
+import xcode_templates
+import app_annotations
+
+redef class ToolContext
+ redef fun platform_from_name(name)
+ do
+ if name == "ios" then return new IOSPlatform
+ return super
+ end
+end
+
+private class IOSPlatform
+ super Platform
+
+ redef fun supports_libunwind do return false
+ redef fun supports_libgc do return false
+ redef fun toolchain(toolcontext, compiler) do return new IOSToolchain(toolcontext, compiler)
+end
+
+private class IOSToolchain
+ super MakefileToolchain
+
+ # Root of the iOS project, usually `.nit_compile/ios/`
+ var ios_project_root: String is noinit
+
+ # `app.nit` project for the current compilation target
+ var app_project = new AppProject(compiler.modelbuilder, compiler.mainmodule) is lazy
+
+ redef fun default_outname do return "{super}.app"
+
+ # Compile C files in `ios_project_root/app_project.name`
+ redef fun compile_dir
+ do
+ ios_project_root = super/"ios"
+ return ios_project_root/app_project.short_name
+ end
+
+ redef fun write_files(compile_dir, cfiles)
+ do
+ # Clear the project directory before writing anything
+ if ios_project_root.file_exists then ios_project_root.rmdir
+ compile_dir.mkdir
+
+ super
+ end
+
+ redef fun write_makefile(compile_dir, cfiles)
+ do
+ var project_name = app_project.short_name
+
+ # Create an XCode project directory
+ var dir = ios_project_root/project_name+".xcodeproj"
+ if not dir.file_exists then dir.mkdir
+
+ # Create a PBX project file
+ var pbx = new PbxprojectTemplate(project_name)
+
+ ## Register all source files
+ for file in cfiles do pbx.add_file new PbxFile(file)
+ for file in compiler.extern_bodies do
+ pbx.add_file new PbxFile(file.filename.basename(""))
+ end
+
+ ## TODO Register asset files
+
+ pbx.write_to_file dir/"project.pbxproj"
+
+ # 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(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 = app_project.short_name
+ var release = toolcontext.opt_release.value
+ var outfile = outfile(compiler.mainmodule)
+
+ # Compile with `xcodebuild`
+ #
+ # TODO support more than the iPhone and the simulator.
+ var args = ["sh", "-c", "cd {ios_project_root}; " +
+ "xcodebuild -target '{project_name}' " +
+ "-destination 'platform=iOS Simulator,name=iPhone' " +
+ "-configuration {if release then "Release" else "Debug"} " +
+ "-sdk iphonesimulator build"]
+ toolcontext.exec_and_check(args, "iOS project error")
+
+ # Move compiled app to destination
+ if outfile.file_exists then outfile.rmdir
+ args = ["mv", "{ios_project_root}/build/Debug-iphonesimulator/{project_name}.app", outfile]
+ toolcontext.exec_and_check(args, "iOS project error")
+ end
+end
redef fun no_main do return true
- redef fun toolchain(toolcontext) do return new PnaclToolchain(toolcontext)
+ redef fun toolchain(toolcontext, compiler) do return new PnaclToolchain(toolcontext, compiler)
end
class PnaclToolchain
super MakefileToolchain
- redef fun write_files(compiler, compile_dir, cfiles)
+ redef fun write_files(compile_dir, cfiles)
do
var app_name = compiler.mainmodule.name
if not dir.file_exists then dir.mkdir
# compile normal C files
- super(compiler, compile_dir, cfiles)
+ super
# Gather extra C files generated elsewhere than in super
for f in compiler.extern_bodies do
""".write_to_file(file)
end
- redef fun write_makefile(compiler, compile_dir, cfiles)
+ redef fun write_makefile(compile_dir, cfiles)
do
# Do nothing, already done in `write_files`
end
- redef fun compile_c_code(compiler, compile_dir)
+ redef fun compile_c_code(compile_dir)
do
# Generate the pexe
toolcontext.exec_and_check(["make", "-C", compile_dir, "-j", "4"], "PNaCl project error")
--- /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.
+
+# Templates and other services to create XCode projects
+module xcode_templates
+
+import template
+
+import platform
+import compiler::abstract_compiler
+
+redef class Sys
+ # Map to identify the PBX file type for a given file extension
+ private var pbx_file_types: Map[String, String] is lazy do
+ var map = new HashMap[String, String]
+
+ # Source code
+ map["m"] = "sourcecode.c.objc"
+ map["c"] = "sourcecode.c.c"
+ map["h"] = "sourcecode.c.h"
+ map["cpp"] = "sourcecode.cpp.cpp"
+ map["hpp"] = "sourcecode.cpp.h"
+ map["vsh"] = "sourcecode.glsl"
+ map["fsh"] = "sourcecode.glsl"
+
+ # Images
+ map["png"] = "image.png"
+ map["gif"] = "image.gif"
+ map["jpg"] = "image.jpeg"
+ map["jpeg"] = "image.jpeg"
+ map["pdf"] = "image.pdf"
+ map["ico"] = "image.ico"
+
+ # Others
+ map["app"] = "wrapper.application"
+ map["plist"] = "text.plist.xml"
+ map["storyboard"] = "file.storyboard"
+ map["xib"] = "file.xib"
+ map["xcassets"] = "folder.assetcatalog"
+ map["xctest"] = "wrapper.cfbundle"
+
+ return map
+ end
+
+ # Generator of PBX UUIDs quique to an execution of the compiler
+ private var pbx_uuid_generator = new PbxUUIDGenerator is lazy
+end
+
+# Generator of PBX UUIDs
+#
+# PBX UUID are composed of 24 hex characters.
+# They only need to be unique within the same project.
+#
+# This implementation simply counts upward from 0.
+class PbxUUIDGenerator
+ private var seed = 0
+
+ # Generate a new UUID
+ fun next_uuid: String
+ do
+ seed += 1
+
+ var hex_val = seed.to_hex.to_upper
+ return "0"*(24-hex_val.length) + hex_val
+ end
+end
+
+# Reference to a file for the PBX format of a project file
+#
+# TODO create subclasses for different file types, this is currently for
+# compilable source files only.
+class PbxFile
+
+ # Path to `self`
+ var path: String
+
+ # UUID for build elements
+ private var build_uuid: String = sys.pbx_uuid_generator.next_uuid is lazy
+
+ # File reference UUID
+ private var ref_uuid: String = sys.pbx_uuid_generator.next_uuid is lazy
+
+ # Documentation to add besides this file in the template
+ private fun doc: String do return path
+
+ # PBX file type for `self`
+ fun file_type: String
+ do
+ var map = sys.pbx_file_types
+ var ext = path.file_extension
+ if ext != null and map.keys.has(ext) then return map[ext]
+ return "unknown"
+ end
+
+ # PBX description of this file
+ private fun description: Writable do return """
+ {{{ref_uuid}}} /* {{{doc}}} */ = {
+ isa = PBXFileReference;
+ fileEncoding = 4;
+ lastKnownFileType = {{{file_type}}};
+ path = {{{path}}};
+ sourceTree = "<group>";
+ };
+"""
+
+ private fun add_to_project(project: PbxprojectTemplate)
+ do
+ project.source_files.add self
+ project.files.add self
+ end
+end
+
+# Template for a PBX project file, usually a `project.pbcproj`
+#
+# This file list all information required to build an XCode project.
+# It would usually be written and read by XCode.
+# From the command line, xcodebuild can read this file but not write it.
+#
+# Information in the file (simplified list):
+#
+# * Compilable source files
+# * Asset files
+# * Build configurations (Release and debug modes, cflags, etc.)
+# * List of files composing the project
+class PbxprojectTemplate
+ super Template
+
+ # Name of the project
+ var name: String
+
+ # All body/implementation source files to be compiled
+ private var source_files = new Array[PbxFile]
+
+ # All asset files added to the app package
+ private var asset_files = new Array[PbxFile]
+
+ # All files used by this project
+ private var files = new Array[PbxFile]
+
+ # Add `file` to this project
+ fun add_file(file: PbxFile) do file.add_to_project(self)
+
+ redef fun rendering
+ do
+ add """
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+"""
+
+ # List build files (compilable sources and assets) with their reference UUID
+ for array in [source_files, asset_files] do for file in array do add """
+ {{{file.build_uuid}}} /* {{{file.doc}}} */ = {
+ isa = PBXBuildFile;
+ fileRef = {{{file.ref_uuid}}} /* {{{file.doc}}} */;
+ };
+"""
+
+ add """
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ AF9F83EA1A5F0D21004B62C0 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = AF9F83C41A5F0D21004B62C0 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = AF9F83CB1A5F0D21004B62C0;
+ remoteInfo = {{{name}}};
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ /* Static generated files */
+ AF9F83CC1A5F0D21004B62C0 /* {{{name}}}.app */ = {
+ isa = PBXFileReference;
+ explicitFileType = wrapper.application;
+ includeInIndex = 0;
+ path = {{{name}}}.app;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ AF9F83D01A5F0D21004B62C0 /* Info.plist */ = {
+ isa = PBXFileReference;
+ lastKnownFileType = text.plist.xml;
+ path = Info.plist;
+ sourceTree = "<group>";
+ };
+ AF9F83DE1A5F0D21004B62C0 /* Base */ = {
+ isa = PBXFileReference;
+ lastKnownFileType = file.storyboard;
+ name = Base;
+ path = Base.lproj/Main.storyboard;
+ sourceTree = "<group>";
+ };
+ AF9F83E01A5F0D21004B62C0 /* Images.xcassets */ = {
+ isa = PBXFileReference;
+ lastKnownFileType = folder.assetcatalog;
+ path = Images.xcassets;
+ sourceTree = "<group>";
+ };
+ AF9F83E31A5F0D21004B62C0 /* Base */ = {
+ isa = PBXFileReference;
+ lastKnownFileType = file.xib;
+ name = Base;
+ path = Base.lproj/LaunchScreen.xib;
+ sourceTree = "<group>";
+ };
+ AF9F83E91A5F0D21004B62C0 /* {{{name}}}Tests.xctest */ = {
+ isa = PBXFileReference;
+ explicitFileType = wrapper.cfbundle;
+ includeInIndex = 0;
+ path = {{{name}}}Tests.xctest;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ AF9F83EE1A5F0D21004B62C0 /* Info.plist */ = {
+ isa = PBXFileReference;
+ lastKnownFileType = text.plist.xml;
+ path = Info.plist;
+ sourceTree = "<group>";
+ };
+ AF9F83EF1A5F0D21004B62C0 /* {{{name}}}Tests.m */ = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ path = {{{name}}}Tests.m;
+ sourceTree = "<group>";
+ };
+
+ /* Changing generated files */
+"""
+ # Describe all known files
+ for file in files do add file.description
+
+ add """
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ AF9F83C91A5F0D21004B62C0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ AF9F83E61A5F0D21004B62C0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ AF9F83C31A5F0D21004B62C0 = {
+ isa = PBXGroup;
+ children = (
+ AF9F83CE1A5F0D21004B62C0 /* {{{name}}} */,
+ AF9F83EC1A5F0D21004B62C0 /* {{{name}}}Tests */,
+ AF9F83CD1A5F0D21004B62C0 /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ AF9F83CD1A5F0D21004B62C0 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ AF9F83CC1A5F0D21004B62C0 /* {{{name}}}.app */,
+ AF9F83E91A5F0D21004B62C0 /* {{{name}}}Tests.xctest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ AF9F83CE1A5F0D21004B62C0 /* {{{name}}} */ = {
+ isa = PBXGroup;
+ children = (
+"""
+ # Reference all known files
+ for file in files do add """
+ {{{file.ref_uuid}}} /* {{{file.doc}}} */,
+"""
+
+ add """
+ );
+ path = {{{name}}};
+ sourceTree = "<group>";
+ };
+ AF9F83CF1A5F0D21004B62C0 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ AF9F83D01A5F0D21004B62C0 /* Info.plist */,
+ AF9F83D11A5F0D21004B62C0 /* main.m */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+ AF9F83EC1A5F0D21004B62C0 /* {{{name}}}Tests */ = {
+ isa = PBXGroup;
+ children = (
+ AF9F83EF1A5F0D21004B62C0 /* {{{name}}}Tests.m */,
+ AF9F83ED1A5F0D21004B62C0 /* Supporting Files */,
+ );
+ path = {{{name}}}Tests;
+ sourceTree = "<group>";
+ };
+ AF9F83ED1A5F0D21004B62C0 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ AF9F83EE1A5F0D21004B62C0 /* Info.plist */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ AF9F83CB1A5F0D21004B62C0 /* {{{name}}} */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = AF9F83F31A5F0D21004B62C0 /* Build configuration list for PBXNativeTarget "{{{name}}}" */;
+ buildPhases = (
+ AF9F83C81A5F0D21004B62C0 /* Sources */,
+ AF9F83C91A5F0D21004B62C0 /* Frameworks */,
+ AF9F83CA1A5F0D21004B62C0 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = {{{name}}};
+ productName = {{{name}}};
+ productReference = AF9F83CC1A5F0D21004B62C0 /* {{{name}}}.app */;
+ productType = "com.apple.product-type.application";
+ };
+ AF9F83E81A5F0D21004B62C0 /* {{{name}}}Tests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = AF9F83F61A5F0D21004B62C0 /* Build configuration list for PBXNativeTarget "{{{name}}}Tests" */;
+ buildPhases = (
+ AF9F83E51A5F0D21004B62C0 /* Sources */,
+ AF9F83E61A5F0D21004B62C0 /* Frameworks */,
+ AF9F83E71A5F0D21004B62C0 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ AF9F83EB1A5F0D21004B62C0 /* PBXTargetDependency */,
+ );
+ name = {{{name}}}Tests;
+ productName = {{{name}}}Tests;
+ productReference = AF9F83E91A5F0D21004B62C0 /* {{{name}}}Tests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ AF9F83C41A5F0D21004B62C0 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0610;
+ TargetAttributes = {
+ AF9F83CB1A5F0D21004B62C0 = {
+ CreatedOnToolsVersion = 6.1.1;
+ };
+ AF9F83E81A5F0D21004B62C0 = {
+ CreatedOnToolsVersion = 6.1.1;
+ TestTargetID = AF9F83CB1A5F0D21004B62C0;
+ };
+ };
+ };
+ buildConfigurationList = AF9F83C71A5F0D21004B62C0 /* Build configuration list for PBXProject "{{{name}}}" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = AF9F83C31A5F0D21004B62C0;
+ productRefGroup = AF9F83CD1A5F0D21004B62C0 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ AF9F83CB1A5F0D21004B62C0 /* {{{name}}} */,
+ AF9F83E81A5F0D21004B62C0 /* {{{name}}}Tests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ AF9F83CA1A5F0D21004B62C0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+"""
+ # Reference all asset files by their build UUID
+ for file in asset_files do add """
+ {{{file.build_uuid}}} /* {{{file.doc}}} */,
+"""
+
+ add """
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ AF9F83E71A5F0D21004B62C0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ AF9F83C81A5F0D21004B62C0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+"""
+ # Reference all compilable source files by their build UUID
+ for file in source_files do add """
+ {{{file.build_uuid}}} /* {{{file.doc}}} */,
+"""
+ add """
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ AF9F83E51A5F0D21004B62C0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ AF9F83F01A5F0D21004B62C0 /* {{{name}}}Tests.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ AF9F83EB1A5F0D21004B62C0 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = AF9F83CB1A5F0D21004B62C0 /* {{{name}}} */;
+ targetProxy = AF9F83EA1A5F0D21004B62C0 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ AF9F83DD1A5F0D21004B62C0 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ AF9F83DE1A5F0D21004B62C0 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "<group>";
+ };
+ AF9F83E21A5F0D21004B62C0 /* LaunchScreen.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ AF9F83E31A5F0D21004B62C0 /* Base */,
+ );
+ name = LaunchScreen.xib;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ AF9F83F11A5F0D21004B62C0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.1;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ AF9F83F21A5F0D21004B62C0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.1;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ AF9F83F41A5F0D21004B62C0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ INFOPLIST_FILE = {{{name}}}/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ AF9F83F51A5F0D21004B62C0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ INFOPLIST_FILE = {{{name}}}/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ AF9F83F71A5F0D21004B62C0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(SDKROOT)/Developer/Library/Frameworks",
+ "$(inherited)",
+ );
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ INFOPLIST_FILE = {{{name}}}Tests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{{name}}}.app/{{{name}}}";
+ };
+ name = Debug;
+ };
+ AF9F83F81A5F0D21004B62C0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(SDKROOT)/Developer/Library/Frameworks",
+ "$(inherited)",
+ );
+ INFOPLIST_FILE = {{{name}}}Tests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{{name}}}.app/{{{name}}}";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ AF9F83C71A5F0D21004B62C0 /* Build configuration list for PBXProject "{{{name}}}" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ AF9F83F11A5F0D21004B62C0 /* Debug */,
+ AF9F83F21A5F0D21004B62C0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ AF9F83F31A5F0D21004B62C0 /* Build configuration list for PBXNativeTarget "{{{name}}}" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ AF9F83F41A5F0D21004B62C0 /* Debug */,
+ AF9F83F51A5F0D21004B62C0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ };
+ AF9F83F61A5F0D21004B62C0 /* Build configuration list for PBXNativeTarget "{{{name}}}Tests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ AF9F83F71A5F0D21004B62C0 /* Debug */,
+ AF9F83F81A5F0D21004B62C0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = AF9F83C41A5F0D21004B62C0 /* Project object */;
+}
+"""
+ end
+end
+
+# Template for a property list used by XCode for iOS projects
+class PlistTemplate
+ super Template
+
+ # 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
+ add """
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>{{{bundle_identifier}}}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>{{{product_name}}}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>{{{short_version}}}</string>
+ <key>CFBundleSignature</key>
+ <string>\\?\\?\\?\\?</string>
+ <key>CFBundleVersion</key>
+ <string>{{{bundle_version}}}</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
+"""
+ end
+end
var mtype = callsite.recv
var anchor = callsite.anchor
if anchor != null then mtype = mtype.anchor_to(callsite.mmodule, anchor)
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
if mtype isa MClassType then mtype = mtype.mclass.intro.bound_mtype
var mproperty = callsite.mproperty
var res = live_targets_cache[mtype, mproperty]
do
mtype = mtype.anchor_to(self.analysis.mainmodule, self.receiver)
if mtype isa MNullType then return null
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
assert mtype isa MClassType
assert not mtype.need_anchor
return mtype
# Collect initializers and build the auto-init
fun do_auto_super_init(modelbuilder: ModelBuilder)
do
- var mclassdef = self.parent.as(AClassdef).mclassdef.as(not null)
- var mpropdef = self.mpropdef.as(not null)
+ var mclassdef = self.parent.as(AClassdef).mclassdef
+ if mclassdef == null then return # skip error
+ var mpropdef = self.mpropdef
+ if mpropdef == null then return # skip error
var mmodule = mpropdef.mclassdef.mmodule
var anchor = mclassdef.bound_mtype
var recvtype = mclassdef.mclass.mclass_type
#node.debug("Unsafe typing: expected {sup}, got {sub}")
return sup
end
- self.modelbuilder.error(node, "Type error: expected {sup}, got {sub}")
+ if sub.need_anchor then
+ var u = anchor_to(sub)
+ self.modelbuilder.error(node, "Type error: expected {sup}, got {sub}: {u}")
+ else
+ self.modelbuilder.error(node, "Type error: expected {sup}, got {sub}")
+ end
return null
end
return sup
end
+ # Can `mtype` be null (up to the current knowledge)?
+ fun can_be_null(mtype: MType): Bool
+ do
+ if mtype isa MNullableType or mtype isa MNullType then return true
+ if mtype isa MFormalType then
+ var x = anchor_to(mtype)
+ if x isa MNullableType or x isa MNullType then return true
+ end
+ return false
+ end
+
+ # Check that `mtype` can be null (up to the current knowledge).
+ #
+ # If not then display a `useless-null-test` warning on node and return false.
+ # Else return true.
+ fun check_can_be_null(anode: ANode, mtype: MType): Bool
+ do
+ if can_be_null(mtype) then return true
+
+ if mtype isa MFormalType then
+ var res = anchor_to(mtype)
+ modelbuilder.warning(anode, "useless-null-test", "Warning: expression is not null, since it is a `{mtype}: {res}`.")
+ else
+ modelbuilder.warning(anode, "useless-null-test", "Warning: expression is not null, since it is a `{mtype}`.")
+ end
+ return false
+ end
+
# Special verification on != and == for null
# Return true
fun null_test(anode: ABinopExpr)
if not mtype2 isa MNullType then return
+ if mtype isa MNullType then return
+
# Check of useless null
- if not mtype isa MNullableType then
- if not anchor_to(mtype) isa MNullableType then
- modelbuilder.warning(anode, "useless-null-test", "Warning: expression is not null, since it is a `{mtype}`.")
- end
- return
- end
+ if not check_can_be_null(anode.n_expr, mtype) then return
+
+ mtype = mtype.as_notnull
# Check for type adaptation
var variable = anode.n_expr.its_variable
if variable == null then return
+ # One is null (mtype2 see above) the other is not null
if anode isa AEqExpr then
anode.after_flow_context.when_true.set_var(variable, mtype2)
- anode.after_flow_context.when_false.set_var(variable, mtype.mtype)
+ anode.after_flow_context.when_false.set_var(variable, mtype)
else if anode isa ANeExpr then
anode.after_flow_context.when_false.set_var(variable, mtype2)
- anode.after_flow_context.when_true.set_var(variable, mtype.mtype)
+ anode.after_flow_context.when_true.set_var(variable, mtype)
else
abort
end
fun get_mclass(node: ANode, name: String): nullable MClass
do
- var mclass = modelbuilder.try_get_mclass_by_name(node, mmodule, name)
- if mclass == null then
- self.modelbuilder.error(node, "Type Error: missing primitive class `{name}'.")
- end
+ var mclass = modelbuilder.get_mclass_by_name(node, mmodule, name)
return mclass
end
if recvtype isa MNullType then
# `null` only accepts some methods of object.
if name == "==" or name == "!=" or name == "is_same_instance" then
- unsafe_type = mmodule.object_type.as_nullable
+ var objclass = get_mclass(node, "Object")
+ if objclass == null then return null # Forward error
+ unsafe_type = objclass.mclass_type
else
self.error(node, "Error: Method '{name}' call on 'null'.")
return null
end
- var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null)
+ var msignature = mpropdef.new_msignature or else mpropdef.msignature
+ if msignature == null then return null # skip error
msignature = resolve_for(msignature, recvtype, recv_is_self).as(MSignature)
var erasure_cast = false
var rettype = mpropdef.msignature.return_mtype
if not recv_is_self and rettype != null then
- rettype = rettype.as_notnullable
+ rettype = rettype.undecorate
if rettype isa MParameterType then
var erased_rettype = msignature.return_mtype
assert erased_rettype != null
var found = true
for t2 in col do
if t2 == null then continue # return null
- if t2 isa MNullableType or t2 isa MNullType then
+ if can_be_null(t2) and not can_be_null(t1) then
t1 = t1.as_nullable
end
if not is_subtype(t2, t1) then found = false
var nblock = self.n_block
if nblock == null then return
- var mpropdef = self.mpropdef.as(not null)
+ var mpropdef = self.mpropdef
+ if mpropdef == null then return # skip error
+
var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
self.selfvariable = v.selfvariable
var mmethoddef = self.mpropdef.as(not null)
- for i in [0..mmethoddef.msignature.arity[ do
- var mtype = mmethoddef.msignature.mparameters[i].mtype
- if mmethoddef.msignature.vararg_rank == i then
+ var msignature = mmethoddef.msignature
+ if msignature == null then return # skip error
+ for i in [0..msignature.arity[ do
+ var mtype = msignature.mparameters[i].mtype
+ if msignature.vararg_rank == i then
var arrayclass = v.get_mclass(self.n_signature.n_params[i], "Array")
if arrayclass == null then return # Skip error
mtype = arrayclass.get_mtype([mtype])
end
v.visit_stmt(nblock)
- if not nblock.after_flow_context.is_unreachable and mmethoddef.msignature.return_mtype != null then
+ if not nblock.after_flow_context.is_unreachable and msignature.return_mtype != null then
# We reach the end of the function without having a return, it is bad
v.error(self, "Control error: Reached end of function (a 'return' with a value was expected).")
end
do
if not has_value then return
- var mpropdef = self.mpropdef.as(not null)
+ var mpropdef = self.mpropdef
+ if mpropdef == null then return # skip error
+
var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
self.selfvariable = v.selfvariable
var decltype = mtype
if mtype == null or mtype isa MNullType then
- decltype = v.get_mclass(self, "Object").mclass_type.as_nullable
+ var objclass = v.get_mclass(self, "Object")
+ if objclass == null then return # skip error
+ decltype = objclass.mclass_type.as_nullable
if mtype == null then mtype = decltype
end
# anchor formal and virtual types
if mtype.need_anchor then mtype = v.anchor_to(mtype)
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
self.coltype = mtype.as(MClassType)
# get methods is_ok, next, item
return # Skip error
end
- t1 = t1.as_notnullable
+ if t1 isa MNullType then
+ v.error(n_expr, "Type error: or else on null")
+ else if v.check_can_be_null(n_expr, t1) then
+ t1 = t1.as_notnull
+ end
var t = v.merge_types(self, [t1, t2])
if t == null then
- t = v.mmodule.object_type
- if t2 isa MNullableType then
+ var c = v.get_mclass(self, "Object")
+ if c == null then return # forward error
+ t = c.mclass_type
+ if v.can_be_null(t2) then
t = t.as_nullable
end
#v.error(self, "Type Error: ambiguous type {t1} vs {t2}")
var mclass = v.get_mclass(self, "String")
if mclass == null then return # Forward error
self.mtype = mclass.mclass_type
+ var objclass = v.get_mclass(self, "Object")
+ if objclass == null then return # Forward error
+ var objtype = objclass.mclass_type
for nexpr in self.n_exprs do
- v.visit_expr_subtype(nexpr, v.mmodule.object_type)
+ v.visit_expr_subtype(nexpr, objtype)
end
end
end
v.error(self, "Type error: as(not null) on null")
return
end
- if mtype isa MNullableType then
- self.mtype = mtype.mtype
- return
- end
- self.mtype = mtype
- if mtype isa MClassType then
- v.modelbuilder.warning(self, "useless-type-test", "Warning: expression is already not null, since it is a `{mtype}`.")
- return
- end
- assert mtype.need_anchor
- var u = v.anchor_to(mtype)
- if not u isa MNullableType then
- v.modelbuilder.warning(self, "useless-type-test", "Warning: expression is already not null, since it is a `{mtype}: {u}`.")
- return
+ if v.check_can_be_null(n_expr, mtype) then
+ mtype = mtype.as_notnull
end
+
+ self.mtype = mtype
end
end
var mpropdefs = mproperty.lookup_definitions(v.mmodule, unsafe_type)
assert mpropdefs.length == 1
var mpropdef = mpropdefs.first
- var attr_type = mpropdef.static_mtype.as(not null)
+ var attr_type = mpropdef.static_mtype
+ if attr_type == null then return # skip error
attr_type = v.resolve_for(attr_type, recvtype, self.n_expr isa ASelfExpr)
self.attr_type = attr_type
end
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)
return tags.has("all") or tags.has(tag)
end
- # Output all current stacked messages and display total error informations
+ # Output all current stacked messages
#
# Return true if no errors occurred.
#
# If some errors occurred, the behavior depends on the value of `keep_going`.
- # If `keep_going` is false, then the program exits.
- # Else, the error count and the warning count are reset and false is returned.
+ # If `keep_going` is false, then the total error informations is displayed and the program exits.
+ # Else, false is returned.
fun check_errors: Bool
do
if messages.length > 0 then
end
if error_count > 0 then
- errors_info
- if not keep_going then exit(1)
+ if not keep_going then
+ errors_info
+ exit(1)
+ end
return false
end
return true
end
- # Display (and reset) total error informations
+ # Display total error informations
fun errors_info
do
if error_count == 0 and warning_count == 0 then return
if opt_no_color.value then return
sys.stderr.write "Errors: {error_count}. Warnings: {warning_count}.\n"
- error_count = 0
- warning_count = 0
end
# Display an error
var anchor = self.frame.arguments.first.mtype.as(MClassType)
# `sub` or `sup` are formal or virtual types, resolve them to concrete types
- if sub isa MParameterType or sub isa MVirtualType then
+ if sub isa MFormalType then
sub = sub.resolve_for(anchor.mclass.mclass_type, anchor, mainmodule, false)
end
- if sup isa MParameterType or sup isa MVirtualType then
+ if sup isa MFormalType then
sup = sup.resolve_for(anchor.mclass.mclass_type, anchor, mainmodule, false)
end
end
# Now the case of direct null and nullable is over
- if sub isa MParameterType or sub isa MVirtualType then
+ if sub isa MFormalType then
sub = sub.anchor_to(mainmodule, anchor)
# Manage the second layer of null/nullable
if sub isa MNullableType then
cocoa_extern_types
cocoa_message_box
hello_cocoa
+hello_ios
+test_platform_ios
--- /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.
+
+import standard::kernel
+
+class A[E] #alt2# class A[E: Object]
+ type V: nullable Object #alt2# type V: Object
+
+ fun foo(e: E, v: E) do #1alt1# fun foo(e: nullable E, v: nullable E) do
+ assert e != null#alt1# #alt3# assert e == null #alt4# if false then e = null
+ assert v != null#alt1# #alt3# assert v == null #alt4# if false then e = null
+ bar(e)
+ bar(v)
+ if e != null then
+ bar(e)
+ else bar(e)
+ if v != null then
+ bar(v)
+ else bar(v)
+ bar(e.as(not null))
+ bar(v.as(not null))
+ bar(e or else 0)
+ bar(v or else 0)
+ bar(e or else v)
+ bar(v or else e)
+ end
+
+ fun bar(o: Object) do o.output
+end
+
+var a = new A[Object]
+a.foo (1, 2)
--- /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.
+
+class A[E: nullable Discrete]
+ fun array(e, f: E): Object
+ do
+ assert e != null
+ assert f != null #alt1# #alt2# assert f == null
+ return [e, f]
+ end
+
+ fun range(e, f: E): Object
+ do
+ assert e != null
+ assert f != null #alt1#
+ return [e..f]
+ end
+end
+
+var a = new A[nullable Int]
+
+var ar = a.array(1, 5)
+ar.output_class_name
+ar.as(Array[Int]).add 6
+print ar
+
+var ra = a.range(1, 5)
+ra.output_class_name
+print ra
--- /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.
+
+import standard::kernel
+
+class G[E: Object]
+end
+
+class A
+ fun foo(t: T): Comparable do return t
+ type T: Comparable #alt1-5#
+ #alt1#type T: T
+ #alt2#type T: nullable T
+ #alt3#type T: G[T]
+ #alt4#type T: U
+ #alt4#type U: FAIL
+ #alt5#type T: U
+ #alt5#type U: T
+ fun bar(t: T): Comparable do return t
+end
+
+var a = new A
+a.foo(1)
+a.bar('1')
--- /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.
+
+import standard::kernel
+
+class G[E]
+end
+
+class A
+ fun foo(t: T): Comparable do return t
+ #fun foog: nullable G[T] do return barg
+ type T: Comparable #alt1-5#
+ type GT: G[T]
+ #alt1#type T: T
+ #alt2#type T: nullable T
+ #alt3#type T: G[T]
+ #alt4#type T: U
+ #alt4#type U: FAIL
+ #alt5#type T: U
+ #alt5#type U: T
+ fun bar(t: T): Comparable do return t
+ #fun barg: nullable G[T] do return foog
+end
+
+class B
+ super A
+ redef fun foo(t: T): T do return t
+ #redef fun foog: GT do return barg
+ redef type GT: G[Discrete]
+ #alt6#redef type GT: G[Bool]
+ redef fun bar(t: T): T do return t
+ #redef fun barg: GT do return foog
+end
+
+var a = new A
+a.foo(1)
+a.bar('1')
+
+var b = new B
+b.foo(2)
+b.bar('3')
-base_as_notnull.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-base_as_notnull.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-base_as_notnull.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-base_as_notnull.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+base_as_notnull.nit:41,6: Warning: expression is not null, since it is a `A`.
+base_as_notnull.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+base_as_notnull.nit:43,6: Warning: expression is not null, since it is a `B`.
+base_as_notnull.nit:52,6: Warning: expression is not null, since it is a `B`.
1
2
3
-base_as_notnull2.nit:30,12--25: Warning: expression is already not null, since it is a `Object`.
-base_as_notnull2.nit:50,12--25: Warning: expression is already not null, since it is a `F: Object`.
+base_as_notnull2.nit:30,12: Warning: expression is not null, since it is a `Object`.
+base_as_notnull2.nit:50,12: Warning: expression is not null, since it is a `F: Object`.
1
1
2
-alt/base_as_notnull2_alt1.nit:30,12--25: Warning: expression is already not null, since it is a `Object`.
-alt/base_as_notnull2_alt1.nit:50,12--25: Warning: expression is already not null, since it is a `F: Object`.
+alt/base_as_notnull2_alt1.nit:30,12: Warning: expression is not null, since it is a `Object`.
+alt/base_as_notnull2_alt1.nit:50,12: Warning: expression is not null, since it is a `F: Object`.
alt/base_as_notnull2_alt1.nit:58,7--10: Type error: expected Object, got null
-alt/base_as_notnull2_alt2.nit:30,12--25: Warning: expression is already not null, since it is a `Object`.
-alt/base_as_notnull2_alt2.nit:50,12--25: Warning: expression is already not null, since it is a `F: Object`.
+alt/base_as_notnull2_alt2.nit:30,12: Warning: expression is not null, since it is a `Object`.
+alt/base_as_notnull2_alt2.nit:50,12: Warning: expression is not null, since it is a `F: Object`.
Runtime error: Cast failed (alt/base_as_notnull2_alt2.nit:40)
1
1
-alt/base_as_notnull2_alt3.nit:30,12--25: Warning: expression is already not null, since it is a `Object`.
-alt/base_as_notnull2_alt3.nit:50,12--25: Warning: expression is already not null, since it is a `F: Object`.
+alt/base_as_notnull2_alt3.nit:30,12: Warning: expression is not null, since it is a `Object`.
+alt/base_as_notnull2_alt3.nit:50,12: Warning: expression is not null, since it is a `F: Object`.
alt/base_as_notnull2_alt3.nit:64,7--10: Type error: expected Int, got null
-alt/base_as_notnull_alt1.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt1.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt1.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt1.nit:50,6--19: Warning: expression is already not null, since it is a `A`.
+alt/base_as_notnull_alt1.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt1.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt1.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt1.nit:50,6: Warning: expression is not null, since it is a `A`.
alt/base_as_notnull_alt1.nit:50,6--19: Type error: expected B, got A
-alt/base_as_notnull_alt1.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt1.nit:52,6: Warning: expression is not null, since it is a `B`.
-alt/base_as_notnull_alt2.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt2.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt2.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt2.nit:51,6--20: Warning: expression is already not null, since it is a `A`.
+alt/base_as_notnull_alt2.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt2.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt2.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt2.nit:51,6--7: Warning: expression is not null, since it is a `A`.
alt/base_as_notnull_alt2.nit:51,6--20: Type error: expected B, got A
-alt/base_as_notnull_alt2.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt2.nit:52,6: Warning: expression is not null, since it is a `B`.
-alt/base_as_notnull_alt3.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt3.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt3.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt3.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt3.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt3.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt3.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt3.nit:52,6: Warning: expression is not null, since it is a `B`.
alt/base_as_notnull_alt3.nit:53,6--20: Type error: expected B, got A
-alt/base_as_notnull_alt4.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt4.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt4.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt4.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt4.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt4.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt4.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt4.nit:52,6: Warning: expression is not null, since it is a `B`.
alt/base_as_notnull_alt4.nit:54,6--21: Type error: expected B, got A
-alt/base_as_notnull_alt5.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt5.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt5.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt5.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt5.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt5.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt5.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt5.nit:52,6: Warning: expression is not null, since it is a `B`.
Runtime error: Cast failed (alt/base_as_notnull_alt5.nit:59)
1
2
-alt/base_as_notnull_alt6.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt6.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt6.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt6.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt6.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt6.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt6.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt6.nit:52,6: Warning: expression is not null, since it is a `B`.
Runtime error: Cast failed (alt/base_as_notnull_alt6.nit:60)
1
2
-alt/base_as_notnull_alt7.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt7.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt7.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt7.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt7.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt7.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt7.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt7.nit:52,6: Warning: expression is not null, since it is a `B`.
alt/base_as_notnull_alt7.nit:61,1--17: Type error: as(not null) on null
-base_as_notnull_int.nit:18,1--14: Warning: expression is already not null, since it is a `Int`.
-base_as_notnull_int.nit:20,1--15: Warning: expression is already not null, since it is a `Object`.
+base_as_notnull_int.nit:18,1: Warning: expression is not null, since it is a `Int`.
+base_as_notnull_int.nit:20,1--2: Warning: expression is not null, since it is a `Object`.
1
1
1
-base_eq_null_notnull.nit:36,6--14: Warning: expression is not null, since it is a `A`.
-base_eq_null_notnull.nit:43,2--10: Warning: expression is not null, since it is a `A`.
+base_eq_null_notnull.nit:36,6: Warning: expression is not null, since it is a `A`.
+base_eq_null_notnull.nit:43,2: Warning: expression is not null, since it is a `A`.
true
true
true
--- /dev/null
+base_notnull.nit:25,6: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:28,6: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:31,7: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:32,7: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:33,7: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:34,7: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:35,7: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:36,7: Warning: expression is not null, since it is a `not null E`.
+1
+2
+1
+2
+1
+2
+1
+2
+1
+2
--- /dev/null
+alt/base_notnull_1alt1.nit:25,6: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:28,6: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:31,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:32,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:33,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:34,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:35,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:36,7: Warning: expression is not null, since it is a `not null E`.
+1
+2
+1
+2
+1
+2
+1
+2
+1
+2
--- /dev/null
+alt/base_notnull_1alt1_alt1.nit:23,7: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_1alt1_alt1.nit:24,7: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_1alt1_alt1.nit:27,12: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt1.nit:30,12: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt1.nit:35,7--17: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_1alt1_alt1.nit:36,7--17: Type error: expected Object, got nullable E: nullable Object
--- /dev/null
+alt/base_notnull_1alt1_alt2.nit:25,6: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:28,6: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:31,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:32,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:33,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:34,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:35,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:36,7: Warning: expression is not null, since it is a `not null E`.
+1
+2
+1
+2
+1
+2
+1
+2
+1
+2
--- /dev/null
+alt/base_notnull_1alt1_alt3.nit:23,7: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:24,7: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:26,8: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:27,12: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:29,8: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:30,12: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:31,7--20: Type error: as(not null) on null
+alt/base_notnull_1alt1_alt3.nit:32,7--20: Type error: as(not null) on null
+alt/base_notnull_1alt1_alt3.nit:33,7: Type error: or else on null
+alt/base_notnull_1alt1_alt3.nit:33,7--17: Type error: expected Object, got nullable Int
+alt/base_notnull_1alt1_alt3.nit:34,7: Type error: or else on null
+alt/base_notnull_1alt1_alt3.nit:34,7--17: Type error: expected Object, got nullable Int
+alt/base_notnull_1alt1_alt3.nit:35,7: Type error: or else on null
+alt/base_notnull_1alt1_alt3.nit:35,7--17: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:36,7: Type error: or else on null
+alt/base_notnull_1alt1_alt3.nit:36,7--17: Type error: expected Object, got null
--- /dev/null
+alt/base_notnull_1alt1_alt4.nit:23,7: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_1alt1_alt4.nit:24,7: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_1alt1_alt4.nit:27,12: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt4.nit:30,12: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt4.nit:35,7--17: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_1alt1_alt4.nit:36,7--17: Type error: expected Object, got nullable E: nullable Object
--- /dev/null
+alt/base_notnull_alt1.nit:23,7: Type error: expected Object, got E: nullable Object
+alt/base_notnull_alt1.nit:24,7: Type error: expected Object, got E: nullable Object
+alt/base_notnull_alt1.nit:27,12: Type error: expected Object, got null
+alt/base_notnull_alt1.nit:30,12: Type error: expected Object, got null
+alt/base_notnull_alt1.nit:35,7--17: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_alt1.nit:36,7--17: Type error: expected Object, got nullable E: nullable Object
--- /dev/null
+alt/base_notnull_alt2.nit:21,10: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:22,10: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:25,6: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:28,6: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:31,7: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:32,7: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:33,7: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:34,7: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:35,7: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:36,7: Warning: expression is not null, since it is a `E: Object`.
+1
+2
+1
+2
+1
+2
+1
+2
+1
+2
--- /dev/null
+alt/base_notnull_alt3.nit:23,7: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:24,7: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:26,8: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:27,12: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:29,8: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:30,12: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:31,7--20: Type error: as(not null) on null
+alt/base_notnull_alt3.nit:32,7--20: Type error: as(not null) on null
+alt/base_notnull_alt3.nit:33,7: Type error: or else on null
+alt/base_notnull_alt3.nit:33,7--17: Type error: expected Object, got nullable Int
+alt/base_notnull_alt3.nit:34,7: Type error: or else on null
+alt/base_notnull_alt3.nit:34,7--17: Type error: expected Object, got nullable Int
+alt/base_notnull_alt3.nit:35,7: Type error: or else on null
+alt/base_notnull_alt3.nit:35,7--17: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:36,7: Type error: or else on null
+alt/base_notnull_alt3.nit:36,7--17: Type error: expected Object, got null
--- /dev/null
+alt/base_notnull_alt4.nit:23,7: Type error: expected Object, got E: nullable Object
+alt/base_notnull_alt4.nit:24,7: Type error: expected Object, got E: nullable Object
+alt/base_notnull_alt4.nit:27,12: Type error: expected Object, got null
+alt/base_notnull_alt4.nit:30,12: Type error: expected Object, got null
+alt/base_notnull_alt4.nit:35,7--17: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_alt4.nit:36,7--17: Type error: expected Object, got nullable E: nullable Object
--- /dev/null
+Array[Int]
+156
+Range[Int]
+12345
--- /dev/null
+alt/base_notnull_lit_alt1.nit:27,14: Type error: expected Discrete, got E: nullable Discrete
--- /dev/null
+Runtime error: Assert failed (alt/base_notnull_lit_alt2.nit:19)
-base_null.nit:28,2--13: Warning: expression is not null, since it is a `null`.
-base_null.nit:42,2--13: Warning: expression is not null, since it is a `null`.
false
false
true
-alt/base_upcast2_1alt1_alt10.nit:36,21: Type error: expected C, got T
+alt/base_upcast2_1alt1_alt10.nit:36,21: Type error: expected C, got T: A[Int]
-alt/base_upcast2_1alt1_alt7.nit:33,22: Type error: expected A[Bool], got T
+alt/base_upcast2_1alt1_alt7.nit:33,22: Type error: expected A[Bool], got T: A[Int]
-alt/base_upcast2_1alt1_alt8.nit:34,22: Type error: expected B[Int], got T
+alt/base_upcast2_1alt1_alt8.nit:34,22: Type error: expected B[Int], got T: A[Int]
-alt/base_upcast2_1alt1_alt9.nit:35,22: Type error: expected B[Bool], got T
+alt/base_upcast2_1alt1_alt9.nit:35,22: Type error: expected B[Bool], got T: A[Int]
-alt/base_upcast2_1alt2_alt10.nit:36,21: Type error: expected C, got T
+alt/base_upcast2_1alt2_alt10.nit:36,21: Type error: expected C, got T: A[Bool]
-alt/base_upcast2_1alt2_alt6.nit:32,22: Type error: expected A[Int], got T
+alt/base_upcast2_1alt2_alt6.nit:32,22: Type error: expected A[Int], got T: A[Bool]
-alt/base_upcast2_1alt2_alt8.nit:34,22: Type error: expected B[Int], got T
+alt/base_upcast2_1alt2_alt8.nit:34,22: Type error: expected B[Int], got T: A[Bool]
-alt/base_upcast2_1alt2_alt9.nit:35,22: Type error: expected B[Bool], got T
+alt/base_upcast2_1alt2_alt9.nit:35,22: Type error: expected B[Bool], got T: A[Bool]
-alt/base_upcast2_1alt3_alt10.nit:36,21: Type error: expected C, got T
+alt/base_upcast2_1alt3_alt10.nit:36,21: Type error: expected C, got T: B[Int]
-alt/base_upcast2_1alt3_alt7.nit:33,22: Type error: expected A[Bool], got T
+alt/base_upcast2_1alt3_alt7.nit:33,22: Type error: expected A[Bool], got T: B[Int]
-alt/base_upcast2_1alt3_alt9.nit:35,22: Type error: expected B[Bool], got T
+alt/base_upcast2_1alt3_alt9.nit:35,22: Type error: expected B[Bool], got T: B[Int]
-alt/base_upcast2_1alt4_alt10.nit:36,21: Type error: expected C, got T
+alt/base_upcast2_1alt4_alt10.nit:36,21: Type error: expected C, got T: B[Bool]
-alt/base_upcast2_1alt4_alt7.nit:33,22: Type error: expected A[Bool], got T
+alt/base_upcast2_1alt4_alt7.nit:33,22: Type error: expected A[Bool], got T: B[Bool]
-alt/base_upcast2_1alt4_alt8.nit:34,22: Type error: expected B[Int], got T
+alt/base_upcast2_1alt4_alt8.nit:34,22: Type error: expected B[Int], got T: B[Bool]
-alt/base_upcast2_1alt5_alt7.nit:33,22: Type error: expected A[Bool], got T
+alt/base_upcast2_1alt5_alt7.nit:33,22: Type error: expected A[Bool], got T: C
-alt/base_upcast2_1alt5_alt8.nit:34,22: Type error: expected B[Int], got T
+alt/base_upcast2_1alt5_alt8.nit:34,22: Type error: expected B[Int], got T: C
-base_var_type_evolution_null3.nit:52,5--13: Warning: expression is not null, since it is a `Object`.
+base_var_type_evolution_null3.nit:52,5: Warning: expression is not null, since it is a `Object`.
1
1
5
-alt/base_var_type_evolution_null3_alt1.nit:52,5--13: Warning: expression is not null, since it is a `Object`.
+alt/base_var_type_evolution_null3_alt1.nit:52,5: Warning: expression is not null, since it is a `Object`.
1
1
5
-base_virtual_type7.nit:20,2--10: Error: circularity of virtual type definition: E -> F -> E
-base_virtual_type7.nit:21,2--10: Error: circularity of virtual type definition: F -> E -> F
+base_virtual_type7.nit:20,2--10: Error: circularity of virtual type definition: E <-> F
alt/base_virtual_type_self_alt5.nit:44,9: Type error: expected A[U], got Float
-alt/base_virtual_type_self_alt5.nit:45,7--12: Type error: expected Float, got A[U]
-alt/base_virtual_type_self_alt5.nit:47,7--12: Type error: expected Float, got A[A[U]]
+alt/base_virtual_type_self_alt5.nit:45,7--12: Type error: expected Float, got A[U]: A[Int]
+alt/base_virtual_type_self_alt5.nit:47,7--12: Type error: expected Float, got A[A[U]]: A[A[Int]]
alt/error_expr_not_ok_alt4.nit:149,7--24: Type error: expected A, got String
alt/error_expr_not_ok_alt4.nit:150,7--18: Warning: Expression is already a Int.
alt/error_expr_not_ok_alt4.nit:150,7--18: Type error: expected A, got Int
-alt/error_expr_not_ok_alt4.nit:151,7--23: Warning: expression is already not null, since it is a `Int`.
+alt/error_expr_not_ok_alt4.nit:151,7--10: Warning: expression is not null, since it is a `Int`.
alt/error_expr_not_ok_alt4.nit:151,7--23: Type error: expected A, got Int
alt/error_expr_not_ok_alt4.nit:152,7--18: Warning: Expression is already a Int.
alt/error_expr_not_ok_alt4.nit:152,7--18: Type error: expected A, got Bool
alt/error_expr_not_ok_alt5.nit:149,7--24: Type error: expected A, got String
alt/error_expr_not_ok_alt5.nit:150,7--18: Warning: Expression is already a Int.
alt/error_expr_not_ok_alt5.nit:150,7--18: Type error: expected A, got Int
-alt/error_expr_not_ok_alt5.nit:151,7--23: Warning: expression is already not null, since it is a `Int`.
+alt/error_expr_not_ok_alt5.nit:151,7--10: Warning: expression is not null, since it is a `Int`.
alt/error_expr_not_ok_alt5.nit:151,7--23: Type error: expected A, got Int
alt/error_expr_not_ok_alt5.nit:152,7--18: Warning: Expression is already a Int.
alt/error_expr_not_ok_alt5.nit:152,7--18: Type error: expected A, got Bool
alt/error_expr_not_ok_alt6.nit:149,7--24: Type error: expected A, got String
alt/error_expr_not_ok_alt6.nit:150,7--18: Warning: Expression is already a Int.
alt/error_expr_not_ok_alt6.nit:150,7--18: Type error: expected A, got Int
-alt/error_expr_not_ok_alt6.nit:151,7--23: Warning: expression is already not null, since it is a `Int`.
+alt/error_expr_not_ok_alt6.nit:151,7--10: Warning: expression is not null, since it is a `Int`.
alt/error_expr_not_ok_alt6.nit:151,7--23: Type error: expected A, got Int
alt/error_expr_not_ok_alt6.nit:152,7--18: Warning: Expression is already a Int.
alt/error_expr_not_ok_alt6.nit:152,7--18: Type error: expected A, got Bool
-Fatal Error: no primitive class NativeArray
+Fatal Error: no primitive class NativeArray in error_needed_method_alt4
-Fatal Error: no primitive class NativeArray
+Fatal Error: no primitive class NativeArray in error_needed_method_alt7
--- /dev/null
+error_virtual_type2.nit:40,17--26: Redef Error: Wrong bound type. Found G[Discrete], expected a subtype of G[T], as in error_virtual_type2#A#GT.
--- /dev/null
+alt/error_virtual_type2_alt1.nit:22,2--24,13: Error: circularity of virtual type definition: GT -> T <-> T
+alt/error_virtual_type2_alt1.nit:25,2--10: Error: circularity of virtual type definition: T <-> T
+alt/error_virtual_type2_alt1.nit:38,23: Redef Error: Wrong return type. found T, expected Comparable as in error_virtual_type2_alt1#A#foo.
+alt/error_virtual_type2_alt1.nit:40,17--26: Redef Error: Wrong bound type. Found G[Discrete], expected a subtype of null, as in error_virtual_type2_alt1#A#GT.
+alt/error_virtual_type2_alt1.nit:42,23: Redef Error: Wrong return type. found T, expected Comparable as in error_virtual_type2_alt1#A#bar.
--- /dev/null
+alt/error_virtual_type2_alt2.nit:22,2--24,13: Error: circularity of virtual type definition: GT -> T <-> nullable T
+alt/error_virtual_type2_alt2.nit:25,2--26,19: Error: circularity of virtual type definition: T <-> nullable T
+alt/error_virtual_type2_alt2.nit:38,23: Redef Error: Wrong return type. found T, expected Comparable as in error_virtual_type2_alt2#A#foo.
+alt/error_virtual_type2_alt2.nit:40,17--26: Redef Error: Wrong bound type. Found G[Discrete], expected a subtype of null, as in error_virtual_type2_alt2#A#GT.
+alt/error_virtual_type2_alt2.nit:42,23: Redef Error: Wrong return type. found T, expected Comparable as in error_virtual_type2_alt2#A#bar.
--- /dev/null
+alt/error_virtual_type2_alt3.nit:22,2--24,13: Error: circularity of virtual type definition: GT -> G[T] <-> T
+alt/error_virtual_type2_alt3.nit:25,2--27,12: Error: circularity of virtual type definition: T <-> G[T]
+alt/error_virtual_type2_alt3.nit:38,23: Redef Error: Wrong return type. found T, expected Comparable as in error_virtual_type2_alt3#A#foo.
+alt/error_virtual_type2_alt3.nit:40,17--26: Redef Error: Wrong bound type. Found G[Discrete], expected a subtype of null, as in error_virtual_type2_alt3#A#GT.
+alt/error_virtual_type2_alt3.nit:42,23: Redef Error: Wrong return type. found T, expected Comparable as in error_virtual_type2_alt3#A#bar.
--- /dev/null
+alt/error_virtual_type2_alt4.nit:29,10--13: Type error: class FAIL not found in module error_virtual_type2_alt4.
+alt/error_virtual_type2_alt4.nit:38,23: Redef Error: Wrong return type. found T, expected Comparable as in error_virtual_type2_alt4#A#foo.
+alt/error_virtual_type2_alt4.nit:40,17--26: Redef Error: Wrong bound type. Found G[Discrete], expected a subtype of null, as in error_virtual_type2_alt4#A#GT.
+alt/error_virtual_type2_alt4.nit:42,23: Redef Error: Wrong return type. found T, expected Comparable as in error_virtual_type2_alt4#A#bar.
--- /dev/null
+alt/error_virtual_type2_alt5.nit:22,2--24,13: Error: circularity of virtual type definition: GT -> T <-> U
+alt/error_virtual_type2_alt5.nit:25,2--30,10: Error: circularity of virtual type definition: T <-> U
+alt/error_virtual_type2_alt5.nit:38,23: Redef Error: Wrong return type. found T, expected Comparable as in error_virtual_type2_alt5#A#foo.
+alt/error_virtual_type2_alt5.nit:40,17--26: Redef Error: Wrong bound type. Found G[Discrete], expected a subtype of null, as in error_virtual_type2_alt5#A#GT.
+alt/error_virtual_type2_alt5.nit:42,23: Redef Error: Wrong return type. found T, expected Comparable as in error_virtual_type2_alt5#A#bar.
--- /dev/null
+alt/error_virtual_type2_alt6.nit:40,17--26: Redef Error: Wrong bound type. Found G[Discrete], expected a subtype of G[T], as in error_virtual_type2_alt6#A#GT.
+alt/error_virtual_type2_alt6.nit:41,2--22: Error: A property GT is already defined in class B at line 39.
--- /dev/null
+alt/error_virtual_type_alt1.nit:22,2--23,10: Error: circularity of virtual type definition: T <-> T
--- /dev/null
+alt/error_virtual_type_alt2.nit:22,2--24,19: Error: circularity of virtual type definition: T <-> nullable T
--- /dev/null
+alt/error_virtual_type_alt3.nit:25,12: Type error: expected Object, got T
+alt/error_virtual_type_alt3.nit:22,2--25,12: Error: circularity of virtual type definition: T <-> G[T]
--- /dev/null
+alt/error_virtual_type_alt4.nit:27,10--13: Type error: class FAIL not found in module error_virtual_type_alt4.
--- /dev/null
+alt/error_virtual_type_alt5.nit:22,2--28,10: Error: circularity of virtual type definition: T <-> U
--- /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
+Array
+156
+Range
+12345
-Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:909)
+Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:911)
NativeString
N
Nit
AParExprs ../src/test_parser.nit:71,7--36
TOpar "(" ../src/test_parser.nit:71,7
AStringExpr ../src/test_parser.nit:71,8--35
- TString "\" -n\11do not print anything\"" ../src/test_parser.nit:71,8--35
+ TString "\" -n\tdo not print anything\"" ../src/test_parser.nit:71,8--35
TCpar ")" ../src/test_parser.nit:71,36
ACallExpr ../src/test_parser.nit:72,2--25
AImplicitSelfExpr ../src/test_parser.nit:72,2
AParExprs ../src/test_parser.nit:72,7--25
TOpar "(" ../src/test_parser.nit:72,7
AStringExpr ../src/test_parser.nit:72,8--24
- TString "\" -l\11only lexer\"" ../src/test_parser.nit:72,8--24
+ TString "\" -l\tonly lexer\"" ../src/test_parser.nit:72,8--24
TCpar ")" ../src/test_parser.nit:72,25
ACallExpr ../src/test_parser.nit:73,2--41
AImplicitSelfExpr ../src/test_parser.nit:73,2
AParExprs ../src/test_parser.nit:73,7--41
TOpar "(" ../src/test_parser.nit:73,7
AStringExpr ../src/test_parser.nit:73,8--40
- TString "\" -p\11lexer and parser (default)\"" ../src/test_parser.nit:73,8--40
+ TString "\" -p\tlexer and parser (default)\"" ../src/test_parser.nit:73,8--40
TCpar ")" ../src/test_parser.nit:73,41
ACallExpr ../src/test_parser.nit:74,2--68
AImplicitSelfExpr ../src/test_parser.nit:74,2
AParExprs ../src/test_parser.nit:74,7--68
TOpar "(" ../src/test_parser.nit:74,7
AStringExpr ../src/test_parser.nit:74,8--67
- TString "\" -e\11instead on files, each argument is a content to parse\"" ../src/test_parser.nit:74,8--67
+ TString "\" -e\tinstead on files, each argument is a content to parse\"" ../src/test_parser.nit:74,8--67
TCpar ")" ../src/test_parser.nit:74,68
ACallExpr ../src/test_parser.nit:75,2--51
AImplicitSelfExpr ../src/test_parser.nit:75,2
AParExprs ../src/test_parser.nit:75,7--51
TOpar "(" ../src/test_parser.nit:75,7
AStringExpr ../src/test_parser.nit:75,8--50
- TString "\" -i\11tree to parse are read interactively\"" ../src/test_parser.nit:75,8--50
+ TString "\" -i\ttree to parse are read interactively\"" ../src/test_parser.nit:75,8--50
TCpar ")" ../src/test_parser.nit:75,51
ACallExpr ../src/test_parser.nit:76,2--30
AImplicitSelfExpr ../src/test_parser.nit:76,2
AParExprs ../src/test_parser.nit:76,7--30
TOpar "(" ../src/test_parser.nit:76,7
AStringExpr ../src/test_parser.nit:76,8--29
- TString "\" -h\11print this help\"" ../src/test_parser.nit:76,8--29
+ TString "\" -h\tprint this help\"" ../src/test_parser.nit:76,8--29
TCpar ")" ../src/test_parser.nit:76,30
AIfExpr ../src/test_parser.nit:77,6--146,3
TKwif "if" ../src/test_parser.nit:77,6--7
--- /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
+main
+threaded
--- /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.
+
+import 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