Merge: Fix the old bug where (-0.1).to_s == "0.-1"
authorJean Privat <jean@pryen.org>
Mon, 20 Oct 2014 13:48:17 +0000 (09:48 -0400)
committerJean Privat <jean@pryen.org>
Mon, 20 Oct 2014 13:48:17 +0000 (09:48 -0400)
Pull-Request: #820
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

68 files changed:
contrib/brainfuck/README.md [new file with mode: 0644]
contrib/brainfuck/brainfuck.nit [new file with mode: 0644]
contrib/brainfuck/examples/hello.bf [new file with mode: 0644]
contrib/brainfuck/examples/hello2.bf [new file with mode: 0644]
contrib/brainfuck/examples/rot13.bf [new file with mode: 0644]
lib/console.nit
lib/mnit/mnit_injected_input.nit
lib/nitcorn/http_request.nit
lib/opts.nit
lib/standard/file.nit
share/man/Makefile [new file with mode: 0644]
share/man/README.md [new file with mode: 0644]
share/man/nit.md [new file with mode: 0644]
share/man/nitdoc.md [new file with mode: 0644]
share/man/nitg.md [new file with mode: 0644]
share/man/nitlight.md [new file with mode: 0644]
share/man/nitls.md [new file with mode: 0644]
share/man/nitmetrics.md [new file with mode: 0644]
share/man/nitpick.md [new file with mode: 0644]
share/man/nitpretty.md [new file with mode: 0644]
share/man/nitserial.md [new file with mode: 0644]
share/man/nitunit.md [new file with mode: 0644]
share/man/nitx.md [new file with mode: 0644]
src/astbuilder.nit
src/compiler/abstract_compiler.nit
src/compiler/android_annotations.nit
src/compiler/coloring.nit
src/compiler/compiler_ffi.nit
src/compiler/global_compiler.nit
src/compiler/separate_compiler.nit
src/compiler/separate_erasure_compiler.nit
src/doc/doc_model.nit
src/ffi/java.nit
src/frontend/simple_misc_analysis.nit
src/highlight.nit
src/interpreter/breakpoint.nit [deleted file]
src/interpreter/debugger.nit
src/interpreter/naive_interpreter.nit
src/metrics/tables_metrics.nit
src/model/model.nit
src/model_utils.nit
src/modelize/modelize_class.nit
src/modelize/modelize_property.nit
src/neo.nit
src/nitpretty.nit
src/nitserial.nit
src/parser/parser_nodes.nit
src/parser/parser_work.nit
src/semantize/auto_super_init.nit
src/semantize/flow.nit
src/semantize/scope.nit
src/semantize/typing.nit
src/testing/testing_doc.nit
src/toolcontext.nit
src/transform.nit
src/vm.nit
tests/base_vararg3.nit [new file with mode: 0644]
tests/sav/base_eq_null_notnull.res
tests/sav/base_var_type_evolution_null3.res
tests/sav/base_var_type_evolution_null3_alt1.res
tests/sav/base_vararg3.res [new file with mode: 0644]
tests/sav/base_vararg3_alt1.res [new file with mode: 0644]
tests/sav/base_vararg3_alt2.res [new file with mode: 0644]
tests/sav/base_vararg3_alt3.res [new file with mode: 0644]
tests/sav/base_vararg3_alt4.res [new file with mode: 0644]
tests/sav/test_toolcontext_args1.res
tests/sav/test_toolcontext_args2.res
tests/test_jvm.nit

diff --git a/contrib/brainfuck/README.md b/contrib/brainfuck/README.md
new file mode 100644 (file)
index 0000000..136b674
--- /dev/null
@@ -0,0 +1,34 @@
+# Brainfuck
+
+Brainfuck is as its name implies a simple Brainfuck interpreter written in Nit.
+
+It has almost as much purposes as the language itself, except it provides a good example for Nit programs that work while being concise.
+
+[Specification](http://www.muppetlabs.com/~breadbox/bf/)
+
+The language is designed to need only a few things :
+
+* One instruction pointer to the current instruction
+* One array of Bytes for all manipulations of data
+* One data pointer to select where to write/read data
+
+Brainfuck a small instruction set, only eight instructions :
+
+* `>`: Increments the data pointer
+* `<`: Decrements the data pointer
+* `+`: Increments the byte in the current cell
+* `-`: Decrements the byte in the current cell
+* `[`: If the current cell's value is 0, jumps to the matching `]`
+* `]`: If the current cell's value is non-zero, jumps to the matching `[`
+* `.`: Writes the current cell's value to stdout
+* `,`: Reads a char from stdin and stores it in the current cell
+
+## How to use
+
+First, compile the interpreter with the Nit compiler/interpreter, and launch the program on a brainfuck source file for interpretation.
+
+Example:
+~~~
+nitg ./brainfuck.nit
+./brainfuck ./examples/hello.bf
+~~~
diff --git a/contrib/brainfuck/brainfuck.nit b/contrib/brainfuck/brainfuck.nit
new file mode 100644 (file)
index 0000000..b614776
--- /dev/null
@@ -0,0 +1,134 @@
+# 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 brainfuck interpreter
+module brainfuck
+
+# Interpreter for Brainfuck source code.
+class BFInterpret
+       # Data cells
+       var dr = new Array[Char]
+       # Data pointer
+       var dp = 0
+       # Instruction pointer
+       var ip = 0
+
+       # The program being interpreted
+       var program: String
+
+       # Contains the set of valid instructions, used in next
+       var valid_instr: Set[Char]
+
+       # Starts interpretation of file `filename`
+       init(filename: String) do
+               var ifs = new IFStream.open(filename.simplify_path)
+               valid_instr = new HashSet[Char]
+               valid_instr.add_all "><[].,+-".chars
+               dr.add 0.ascii
+               program = ifs.read_all
+               start
+       end
+
+       # Starts the interpretation of the loaded program
+       fun start do
+               loop
+                       if ip >= program.length then break
+                       eval
+                       next
+               end
+       end
+
+       # Go to the next executable instruction
+       fun next do
+               ip += 1
+               while ip < program.length and not valid_instr.has(program[ip]) do
+                       ip += 1
+               end
+       end
+
+       # Evaluates the current instruction
+       fun eval do
+               var instr = program[ip]
+               if instr == '.' then printn dr[dp]
+               if instr == '[' then
+                       if dr[dp] == 0.ascii then
+                               ip = find_matching_rbra
+                               return
+                       end
+               end
+               if instr == ']' then
+                       if dr[dp] != 0.ascii then
+                               ip = find_matching_lbra
+                               return
+                       end
+               end
+               if instr == '>' then
+                       dp += 1
+                       if dp >= dr.length then dr.add(0.ascii)
+               end
+               if instr == '<' then
+                       dp -= 1
+                       if dp < 0 then abort
+               end
+               if instr == '+' then
+                       dr[dp] = (dr[dp].ascii + 1).ascii
+               end
+               if instr == '-' then
+                       dr[dp] = (dr[dp].ascii - 1).ascii
+               end
+               if instr == ',' then
+                       dr[dp] = getc
+               end
+       end
+
+       # Seeks for the position of the matching `]` for the `[` located at `ip`
+       fun find_matching_rbra: Int do
+               var pos = ip + 1
+               var lbracnt = 0
+               loop
+                       if pos > program.length then abort
+                       if program[pos] == ']' then
+                               if lbracnt > 0 then
+                                       lbracnt -= 1
+                               else
+                                       break
+                               end
+                       end
+                       if program[pos] == '[' then lbracnt += 1
+                       pos += 1
+               end
+               return pos
+       end
+
+       # Seeks for the position of the matching `[` for the `]` located at `ip`
+       fun find_matching_lbra: Int do
+               var pos = ip - 1
+               var rbracnt = 0
+               loop
+                       if pos < 0 then abort
+                       if program[pos] == '[' then
+                               if rbracnt > 0 then
+                                       rbracnt -= 1
+                               else
+                                       break
+                               end
+                       end
+                       if program[pos] == ']' then rbracnt += 1
+                       pos -= 1
+               end
+               return pos
+       end
+end
+
+var i = new BFInterpret(args[0])
diff --git a/contrib/brainfuck/examples/hello.bf b/contrib/brainfuck/examples/hello.bf
new file mode 100644 (file)
index 0000000..8fa0f72
--- /dev/null
@@ -0,0 +1 @@
+++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
diff --git a/contrib/brainfuck/examples/hello2.bf b/contrib/brainfuck/examples/hello2.bf
new file mode 100644 (file)
index 0000000..8fc90f6
--- /dev/null
@@ -0,0 +1,38 @@
+[ This program prints "Hello World!" and a newline to the screen, its
+  length is 106 active command characters [it is not the shortest.]
+  This loop is a "comment loop", it's a simple way of adding a comment
+  to a BF program such that you don't have to worry about any command
+  characters. Any ".", ",", "+", "-", "<" and ">" characters are simply
+  ignored, the "[" and "]" characters just have to be balanced.
+]
++++++ +++               Set Cell #0 to 8
+[
+    >++++               Add 4 to Cell #1; this will always set Cell #1 to 4
+    [                   as the cell will be cleared by the loop
+        >++             Add 2 to Cell #2
+        >+++            Add 3 to Cell #3
+        >+++            Add 3 to Cell #4
+        >+              Add 1 to Cell #5
+        <<<<-           Decrement the loop counter in Cell #1
+    ]                   Loop till Cell #1 is zero; number of iterations is 4
+    >+                  Add 1 to Cell #2
+    >+                  Add 1 to Cell #3
+    >-                  Subtract 1 from Cell #4
+    >>+                 Add 1 to Cell #6
+    [<]                 Move back to the first zero cell you find; this will
+                        be Cell #1 which was cleared by the previous loop
+    <-                  Decrement the loop Counter in Cell #0
+]                       Loop till Cell #0 is zero; number of iterations is 8
+The result of this is:
+Cell No :   0   1   2   3   4   5   6
+Contents:   0   0  72 104  88  32   8
+Pointer :   ^
+>>.                     Cell #2 has value 72 which is 'H'
+>---.                   Subtract 3 from Cell #3 to get 101 which is 'e'
++++++++..+++.          Likewise for 'llo' from Cell #3
+>>.                     Cell #5 is 32 for the space
+<-.                     Subtract 1 from Cell #4 for 87 to give a 'W'
+<.                      Cell #3 was set to 'o' from the end of 'Hello'
++++.------.--------.    Cell #3 for 'rl' and 'd'
+>>+.                    Add 1 to Cell #5 gives us an exclamation point
+>++.                    And finally a newline from Cell #6
diff --git a/contrib/brainfuck/examples/rot13.bf b/contrib/brainfuck/examples/rot13.bf
new file mode 100644 (file)
index 0000000..85a97fa
--- /dev/null
@@ -0,0 +1,28 @@
+-,+[                         Read first character and start outer character reading loop
+    -[                       Skip forward if character is 0
+        >>++++[>++++++++<-]  Set up divisor (32) for division loop
+                               (MEMORY LAYOUT: dividend copy remainder divisor quotient zero zero)
+        <+<-[                Set up dividend (x minus 1) and enter division loop
+            >+>+>-[>>>]      Increase copy and remainder / reduce divisor / Normal case: skip forward
+            <[[>+<-]>>+>]    Special case: move remainder back to divisor and increase quotient
+            <<<<<-           Decrement dividend
+        ]                    End division loop
+    ]>>>[-]+                 End skip loop; zero former divisor and reuse space for a flag
+    >--[-[<->+++[-]]]<[         Zero that flag unless quotient was 2 or 3; zero quotient; check flag
+        ++++++++++++<[       If flag then set up divisor (13) for second division loop
+                               (MEMORY LAYOUT: zero copy dividend divisor remainder quotient zero zero)
+            >-[>+>>]         Reduce divisor; Normal case: increase remainder
+            >[+[<+>-]>+>>]   Special case: increase remainder / move it back to divisor / increase quotient
+            <<<<<-           Decrease dividend
+        ]                    End division loop
+        >>[<+>-]             Add remainder back to divisor to get a useful 13
+        >[                   Skip forward if quotient was 0
+            -[               Decrement quotient and skip forward if quotient was 1
+                -<<[-]>>     Zero quotient and divisor if quotient was 2
+            ]<<[<<->>-]>>    Zero divisor and subtract 13 from copy if quotient was 1
+        ]<<[<<+>>-]          Zero divisor and add 13 to copy if quotient was 0
+    ]                        End outer skip loop (jump to here if ((character minus 1)/32) was not 2 or 3)
+    <[-]                     Clear remainder from first division if second division was skipped
+    <.[-]                    Output ROT13ed character from copy and clear it
+    <-,+                     Read next character
+]                            End character reading loop
index d032886..04dcb6e 100644 (file)
@@ -70,7 +70,7 @@ class TermCharFormat
        fun inverse: TermCharFormat do return apply("7")
 
        # Apply normal weight and return `self`.
-       fun normalWeight: TermCharFormat do return apply("22")
+       fun normal_weight: TermCharFormat do return apply("22")
 
        # Add the attribute that disable inderlining and return `self`.
        fun not_underlined: TermCharFormat do return apply("24")
index c590a85..4ed9664 100644 (file)
@@ -76,12 +76,12 @@ redef class App
        redef fun setup
        do
                var env = "MNIT_SRAND".environ
-               if env != null and env != "" then
+               if env != "" then
                        srand_from(env.to_i)
                end
 
                var input = "MNIT_READ_INPUT".environ
-               if input != null and input != "" then
+               if input != "" then
                        injected_input_stream = new IFStream.open(input)
                        print "GET injected_input_stream {input}"
                end
index c52a4a5..47e6823 100644 (file)
@@ -149,10 +149,6 @@ class HttpRequestParser
                                var parts = line.split_once_on('=')
                                if parts.length > 1 then
                                        var decoded = parts[1].replace('+', " ").from_percent_encoding
-                                       if decoded == null then
-                                               print "decode error"
-                                               continue
-                                       end
                                        http_request.post_args[parts[0]] = decoded
                                        http_request.all_args[parts[0]] = decoded
                                else
index a1bffc1..c088325 100644 (file)
@@ -194,11 +194,7 @@ class OptionEnum
 
        redef fun pretty_default
        do
-               if default_value != null then
-                       return " ({values[default_value]})"
-               else
-                       return ""
-               end
+               return " ({values[default_value]})"
        end
 end
 
index b8f5bab..30e48e3 100644 (file)
@@ -328,24 +328,30 @@ redef class String
 
        # Correctly join two path using the directory separator.
        #
-       # Using a standard "{self}/{path}" does not work when `self` is the empty string.
-       # This method ensure that the join is valid.
+       # Using a standard "{self}/{path}" does not work in the following cases:
        #
-       #     assert "hello".join_path("world")      ==  "hello/world"
-       #     assert "hel/lo".join_path("wor/ld")      ==  "hel/lo/wor/ld"
-       #     assert "".join_path("world")      ==  "world"
-       #     assert "/hello".join_path("/world")      ==  "/world"
+       # * `self` is empty.
+       # * `path` ends with `'/'`.
+       # * `path` starts with `'/'`.
        #
-       # Note: you may want to use `simplify_path` on the result
+       # This method ensures that the join is valid.
        #
-       # Note: I you want to join a great number of path, you can write
+       #     assert "hello".join_path("world")   == "hello/world"
+       #     assert "hel/lo".join_path("wor/ld") == "hel/lo/wor/ld"
+       #     assert "".join_path("world")        == "world"
+       #     assert "hello".join_path("/world")  == "/world"
+       #     assert "hello/".join_path("world")  == "hello/world"
+       #     assert "hello/".join_path("/world") == "/world"
        #
-       #     [p1, p2, p3, p4].join("/")
+       # Note: You may want to use `simplify_path` on the result.
+       #
+       # Note: This method works only with POSIX paths.
        fun join_path(path: String): String
        do
                if path.is_empty then return self
                if self.is_empty then return path
                if path.chars[0] == '/' then return path
+               if self.last == '/' then return "{self}{path}"
                return "{self}/{path}"
        end
 
diff --git a/share/man/Makefile b/share/man/Makefile
new file mode 100644 (file)
index 0000000..3eeeb03
--- /dev/null
@@ -0,0 +1,21 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+IN=$(wildcard nit*.md)
+OUT=$(patsubst %.md,man1/%.1,$(IN))
+
+all: $(OUT)
+
+man1/%.1: %.md
+       pandoc $< -t man -s -o $@
diff --git a/share/man/README.md b/share/man/README.md
new file mode 100644 (file)
index 0000000..a167029
--- /dev/null
@@ -0,0 +1,21 @@
+# Manual pages for nit commands
+
+Pages, in markdown, in this directory where initially generated thanks to the `--stub-man` options of the commands.
+
+Transformation to real man pages (troff) are done with `pandoc -t man -s` command.
+See the `Makefile`.
+
+
+Once generated, manpages can then be checked individually with `man -l`
+
+~~~
+man -l man1/nitg.1
+~~~
+
+For global access, one can set the `MANPATH` environment variable to this `man` directory (not the `man1` subdirectory).
+Do not forget to append a trailing column (`:`) to keep existing manpages accessible.
+
+~~~
+export MANPATH=/path/to/nit/share/man:
+man nitg
+~~~
diff --git a/share/man/nit.md b/share/man/nit.md
new file mode 100644 (file)
index 0000000..26b2adb
--- /dev/null
@@ -0,0 +1,99 @@
+% NIT(1)
+
+# NAME
+
+Interprets and debugs Nit programs.
+
+# SYNOPSYS
+
+nit [*options*]...
+
+# OPTIONS
+
+`-W`, `--warn`
+:   Show more warnings
+
+`-w`, `--warning`
+:   Show/hide a specific warning
+
+`-q`, `--quiet`
+:   Do not show warnings
+
+`--stop-on-first-error`
+:   Stop on first error
+
+`--no-color`
+:   Do not use color to display errors and warnings
+
+`--log`
+:   Generate various log files
+
+`--log-dir`
+:   Directory where to generate log files
+
+`-h`, `-?`, `--help`
+:   Show Help (This screen)
+
+`--version`
+:   Show version and exit
+
+`--set-dummy-tool`
+:   Set toolname and version to DUMMY. Useful for testing
+
+`-v`, `--verbose`
+:   Verbose
+
+`--bash-completion`
+:   Generate bash_completion file for this program
+
+`--stub-man`
+:   Generate a stub manpage in pandoc markdown format
+
+`--disable-phase`
+:   DEBUG: Disable a specific phase; use `list` to get the list.
+
+`-I`, `--path`
+:   Set include path for loaders (may be used more than once)
+
+`--only-parse`
+:   Only proceed to parse step of loaders
+
+`--only-metamodel`
+:   Stop after meta-model processing
+
+`--ignore-visibility`
+:   Do not check, and produce errors, on visibility issues.
+
+`--discover-call-trace`
+:   Trace calls of the first invocation of a method
+
+`-d`
+:   Launches the target program with the debugger attached to it
+
+`-c`
+:   Launches the target program with the interpreter, such as when the program fails, the debugging prompt is summoned
+
+`--socket`
+:   Launches the target program with raw output on the network via sockets
+
+`--websocket`
+:   Launches the target program with output on the network via websockets
+
+`--port`
+:   Sets the debug port (Defaults to 22125) - Must be contained between 0 and 65535
+
+`-o`
+:   compatibility (does noting)
+
+`-m`
+:   Additionals module to min-in
+
+`-e`
+:   Specifies the program from command-line
+
+`-n`
+:   Repeatedly run the program for each line in file-name arguments
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
diff --git a/share/man/nitdoc.md b/share/man/nitdoc.md
new file mode 100644 (file)
index 0000000..d39c076
--- /dev/null
@@ -0,0 +1,114 @@
+% NITDOC(1)
+
+# NAME
+
+Generates HTML pages of API documentation from Nit source files.
+
+# SYNOPSYS
+
+nitdoc [*options*]...
+
+# OPTIONS
+
+`-W`, `--warn`
+:   Show more warnings
+
+`-w`, `--warning`
+:   Show/hide a specific warning
+
+`-q`, `--quiet`
+:   Do not show warnings
+
+`--stop-on-first-error`
+:   Stop on first error
+
+`--no-color`
+:   Do not use color to display errors and warnings
+
+`--log`
+:   Generate various log files
+
+`--log-dir`
+:   Directory where to generate log files
+
+`-h`, `-?`, `--help`
+:   Show Help (This screen)
+
+`--version`
+:   Show version and exit
+
+`--set-dummy-tool`
+:   Set toolname and version to DUMMY. Useful for testing
+
+`-v`, `--verbose`
+:   Verbose
+
+`--bash-completion`
+:   Generate bash_completion file for this program
+
+`--stub-man`
+:   Generate a stub manpage in pandoc markdown format
+
+`--disable-phase`
+:   DEBUG: Disable a specific phase; use `list` to get the list.
+
+`-I`, `--path`
+:   Set include path for loaders (may be used more than once)
+
+`--only-parse`
+:   Only proceed to parse step of loaders
+
+`--only-metamodel`
+:   Stop after meta-model processing
+
+`--ignore-visibility`
+:   Do not check, and produce errors, on visibility issues.
+
+`-d`, `--dir`
+:   output directory
+
+`--source`
+:   link for source (%f for filename, %l for first line, %L for last line)
+
+`--sharedir`
+:   directory containing nitdoc assets
+
+`--shareurl`
+:   use shareurl instead of copy shared files
+
+`--no-dot`
+:   do not generate graphes with graphviz
+
+`--private`
+:   also generate private API
+
+`--custom-title`
+:   custom title for homepage
+
+`--custom-footer-text`
+:   custom footer text
+
+`--custom-overview-text`
+:   custom intro text for homepage
+
+`--custom-brand`
+:   custom link to external site
+
+`--github-upstream`
+:   Git branch where edited commits will be pulled into (ex: user:repo:branch)
+
+`--github-base-sha1`
+:   Git sha1 of base commit used to create pull request
+
+`--github-gitdir`
+:   Git working directory used to resolve path name (ex: /home/me/myproject/)
+
+`--piwik-tracker`
+:   Piwik tracker URL (ex: nitlanguage.org/piwik/)
+
+`--piwik-site-id`
+:   Piwik site ID
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
diff --git a/share/man/nitg.md b/share/man/nitg.md
new file mode 100644 (file)
index 0000000..1c45f1d
--- /dev/null
@@ -0,0 +1,177 @@
+% NITG(1)
+
+# NAME
+
+Compiles Nit programs.
+
+# SYNOPSYS
+
+nitg [*options*]...
+
+# OPTIONS
+
+`-W`, `--warn`
+:   Show more warnings
+
+`-w`, `--warning`
+:   Show/hide a specific warning
+
+`-q`, `--quiet`
+:   Do not show warnings
+
+`--stop-on-first-error`
+:   Stop on first error
+
+`--no-color`
+:   Do not use color to display errors and warnings
+
+`--log`
+:   Generate various log files
+
+`--log-dir`
+:   Directory where to generate log files
+
+`-h`, `-?`, `--help`
+:   Show Help (This screen)
+
+`--version`
+:   Show version and exit
+
+`--set-dummy-tool`
+:   Set toolname and version to DUMMY. Useful for testing
+
+`-v`, `--verbose`
+:   Verbose
+
+`--bash-completion`
+:   Generate bash_completion file for this program
+
+`--stub-man`
+:   Generate a stub manpage in pandoc markdown format
+
+`--disable-phase`
+:   DEBUG: Disable a specific phase; use `list` to get the list.
+
+`-I`, `--path`
+:   Set include path for loaders (may be used more than once)
+
+`--only-parse`
+:   Only proceed to parse step of loaders
+
+`--only-metamodel`
+:   Stop after meta-model processing
+
+`--ignore-visibility`
+:   Do not check, and produce errors, on visibility issues.
+
+`-o`, `--output`
+:   Output file
+
+`--dir`
+:   Output directory
+
+`--no-cc`
+:   Do not invoke C compiler
+
+`--no-main`
+:   Do not generate main entry point
+
+`--make-flags`
+:   Additional options to make
+
+`--compile-dir`
+:   Directory used to generate temporary files
+
+`--hardening`
+:   Generate contracts in the C code against bugs in the compiler
+
+`--no-shortcut-range`
+:   Always insantiate a range and its iterator on 'for' loops
+
+`--no-check-covariance`
+:   Disable type tests of covariant parameters (dangerous)
+
+`--no-check-attr-isset`
+:   Disable isset tests before each attribute access (dangerous)
+
+`--no-check-assert`
+:   Disable the evaluation of explicit 'assert' and 'as' (dangerous)
+
+`--no-check-autocast`
+:   Disable implicit casts on unsafe expression usage (dangerous)
+
+`--no-check-null`
+:   Disable tests of null receiver (dangerous)
+
+`--no-check-all`
+:   Disable all tests (dangerous)
+
+`--typing-test-metrics`
+:   Enable static and dynamic count of all type tests
+
+`--invocation-metrics`
+:   Enable static and dynamic count of all method invocations
+
+`--isset-checks-metrics`
+:   Enable static and dynamic count of isset checks before attributes access
+
+`--stacktrace`
+:   Control the generation of stack traces
+
+`--no-gcc-directive`
+:   Disable a advanced gcc directives for optimization
+
+`--release`
+:   Compile in release mode and finalize application
+
+`--global`
+:   Use global compilation
+
+`--separate`
+:   Use separate compilation
+
+`--no-inline-intern`
+:   Do not inline call to intern methods
+
+`--no-union-attribute`
+:   Put primitive attibutes in a box instead of an union
+
+`--no-shortcut-equal`
+:   Always call == in a polymorphic way
+
+`--inline-coloring-numbers`
+:   Inline colors and ids (semi-global)
+
+`--inline-some-methods`
+:   Allow the separate compiler to inline some methods (semi-global)
+
+`--direct-call-monomorph`
+:   Allow the separate compiler to direct call monomorph sites (semi-global)
+
+`--skip-dead-methods`
+:   Do not compile dead methods (semi-global)
+
+`--semi-global`
+:   Enable all semi-global optimizations
+
+`--colo-dead-methods`
+:   Force colorization of dead methods
+
+`--tables-metrics`
+:   Enable static size measuring of tables used for vft, typing and resolution
+
+`--erasure`
+:   Erase generic types
+
+`--no-check-erasure-cast`
+:   Disable implicit casts on unsafe return with erasure-typing policy (dangerous)
+
+`--rta`
+:   Activate RTA (implicit with --global and --separate)
+
+`-m`
+:   Additionals module to min-in
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
diff --git a/share/man/nitlight.md b/share/man/nitlight.md
new file mode 100644 (file)
index 0000000..54b2896
--- /dev/null
@@ -0,0 +1,84 @@
+% NITLIGHT(1)
+
+# NAME
+
+Generates HTML of highlited code from Nit source files.
+
+# SYNOPSYS
+
+nitlight [*options*]...
+
+# OPTIONS
+
+`-W`, `--warn`
+:   Show more warnings
+
+`-w`, `--warning`
+:   Show/hide a specific warning
+
+`-q`, `--quiet`
+:   Do not show warnings
+
+`--stop-on-first-error`
+:   Stop on first error
+
+`--no-color`
+:   Do not use color to display errors and warnings
+
+`--log`
+:   Generate various log files
+
+`--log-dir`
+:   Directory where to generate log files
+
+`-h`, `-?`, `--help`
+:   Show Help (This screen)
+
+`--version`
+:   Show version and exit
+
+`--set-dummy-tool`
+:   Set toolname and version to DUMMY. Useful for testing
+
+`-v`, `--verbose`
+:   Verbose
+
+`--bash-completion`
+:   Generate bash_completion file for this program
+
+`--stub-man`
+:   Generate a stub manpage in pandoc markdown format
+
+`--disable-phase`
+:   DEBUG: Disable a specific phase; use `list` to get the list.
+
+`-I`, `--path`
+:   Set include path for loaders (may be used more than once)
+
+`--only-parse`
+:   Only proceed to parse step of loaders
+
+`--only-metamodel`
+:   Stop after meta-model processing
+
+`--ignore-visibility`
+:   Do not check, and produce errors, on visibility issues.
+
+`-f`, `--fragment`
+:   Omit document header and footer
+
+`--first-line`
+:   Start the source file at this line (default: 1)
+
+`--last-line`
+:   End the source file at this line (default: to the end)
+
+`-d`, `--dir`
+:   Output html files in a specific directory (required if more than one module)
+
+`--full`
+:   Process also imported modules
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
diff --git a/share/man/nitls.md b/share/man/nitls.md
new file mode 100644 (file)
index 0000000..705a099
--- /dev/null
@@ -0,0 +1,93 @@
+% NITLS(1)
+
+# NAME
+
+Lists the projects and/or paths of Nit sources files.
+
+# SYNOPSYS
+
+nitls [*options*]...
+
+# OPTIONS
+
+`-W`, `--warn`
+:   Show more warnings
+
+`-w`, `--warning`
+:   Show/hide a specific warning
+
+`-q`, `--quiet`
+:   Do not show warnings
+
+`--stop-on-first-error`
+:   Stop on first error
+
+`--no-color`
+:   Do not use color to display errors and warnings
+
+`--log`
+:   Generate various log files
+
+`--log-dir`
+:   Directory where to generate log files
+
+`-h`, `-?`, `--help`
+:   Show Help (This screen)
+
+`--version`
+:   Show version and exit
+
+`--set-dummy-tool`
+:   Set toolname and version to DUMMY. Useful for testing
+
+`-v`, `--verbose`
+:   Verbose
+
+`--bash-completion`
+:   Generate bash_completion file for this program
+
+`--stub-man`
+:   Generate a stub manpage in pandoc markdown format
+
+`--disable-phase`
+:   DEBUG: Disable a specific phase; use `list` to get the list.
+
+`-I`, `--path`
+:   Set include path for loaders (may be used more than once)
+
+`--only-parse`
+:   Only proceed to parse step of loaders
+
+`--only-metamodel`
+:   Stop after meta-model processing
+
+`--ignore-visibility`
+:   Do not check, and produce errors, on visibility issues.
+
+`-k`, `--keep`
+:   Ignore errors and files that are not a Nit source file
+
+`-r`, `--recursive`
+:   Process directories recussively
+
+`-t`, `--tree`
+:   List source files in their groups and projects
+
+`-s`, `--source`
+:   List source files
+
+`-P`, `--project`
+:   List projects paths (default)
+
+`-d`, `--depends`
+:   List dependencies of given modules
+
+`-p`, `--path`
+:   List only path (instead of name + path)
+
+`-M`
+:   List dependencies suitable for a rule in a Makefile. Alias for -d, -p and -s
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
diff --git a/share/man/nitmetrics.md b/share/man/nitmetrics.md
new file mode 100644 (file)
index 0000000..5aeb779
--- /dev/null
@@ -0,0 +1,120 @@
+% NITMETRICS(1)
+
+# NAME
+
+Computes various metrics on Nit programs.
+
+# SYNOPSYS
+
+nitmetrics [*options*]...
+
+# OPTIONS
+
+`-W`, `--warn`
+:   Show more warnings
+
+`-w`, `--warning`
+:   Show/hide a specific warning
+
+`-q`, `--quiet`
+:   Do not show warnings
+
+`--stop-on-first-error`
+:   Stop on first error
+
+`--no-color`
+:   Do not use color to display errors and warnings
+
+`--log`
+:   Generate various log files
+
+`--log-dir`
+:   Directory where to generate log files
+
+`-h`, `-?`, `--help`
+:   Show Help (This screen)
+
+`--version`
+:   Show version and exit
+
+`--set-dummy-tool`
+:   Set toolname and version to DUMMY. Useful for testing
+
+`-v`, `--verbose`
+:   Verbose
+
+`--bash-completion`
+:   Generate bash_completion file for this program
+
+`--stub-man`
+:   Generate a stub manpage in pandoc markdown format
+
+`--disable-phase`
+:   DEBUG: Disable a specific phase; use `list` to get the list.
+
+`-I`, `--path`
+:   Set include path for loaders (may be used more than once)
+
+`--only-parse`
+:   Only proceed to parse step of loaders
+
+`--only-metamodel`
+:   Stop after meta-model processing
+
+`--ignore-visibility`
+:   Do not check, and produce errors, on visibility issues.
+
+`--all`
+:   Compute all metrics
+
+`--mmodules`
+:   Compute metrics about mmodules
+
+`--mclasses`
+:   Compute metrics about mclasses
+
+`--mendel`
+:   Compute mendel metrics
+
+`--inheritance`
+:   Compute metrics about inheritance usage
+
+`--refinement`
+:   Compute metrics about refinement usage
+
+`--self`
+:   Compute metrics about the usage of explicit and implicit self
+
+`--ast`
+:   Compute metrics about the usage of nodes and identifiers in the AST
+
+`--nullables`
+:   Compute metrics on nullables send
+
+`--static-types`
+:   Compute explicit static types metrics
+
+`--tables`
+:   Compute tables metrics
+
+`--rta`
+:   Compute RTA metrics
+
+`--csv`
+:   Export metrics in CSV format
+
+`--generate_hyperdoc`
+:   Generate Hyperdoc
+
+`--poset`
+:   Complete metrics on posets
+
+`-d`, `--dir`
+:   Directory where some statistics files are generated
+
+`--no-colors`
+:   Disable colors in console outputs
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
diff --git a/share/man/nitpick.md b/share/man/nitpick.md
new file mode 100644 (file)
index 0000000..f852d27
--- /dev/null
@@ -0,0 +1,69 @@
+% NITPICK(1)
+
+# NAME
+
+Collect potential style and code issues.
+
+# SYNOPSYS
+
+nitpick [*options*]...
+
+# OPTIONS
+
+`-W`, `--warn`
+:   Show more warnings
+
+`-w`, `--warning`
+:   Show/hide a specific warning
+
+`-q`, `--quiet`
+:   Do not show warnings
+
+`--stop-on-first-error`
+:   Stop on first error
+
+`--no-color`
+:   Do not use color to display errors and warnings
+
+`--log`
+:   Generate various log files
+
+`--log-dir`
+:   Directory where to generate log files
+
+`-h`, `-?`, `--help`
+:   Show Help (This screen)
+
+`--version`
+:   Show version and exit
+
+`--set-dummy-tool`
+:   Set toolname and version to DUMMY. Useful for testing
+
+`-v`, `--verbose`
+:   Verbose
+
+`--bash-completion`
+:   Generate bash_completion file for this program
+
+`--stub-man`
+:   Generate a stub manpage in pandoc markdown format
+
+`--disable-phase`
+:   DEBUG: Disable a specific phase; use `list` to get the list.
+
+`-I`, `--path`
+:   Set include path for loaders (may be used more than once)
+
+`--only-parse`
+:   Only proceed to parse step of loaders
+
+`--only-metamodel`
+:   Stop after meta-model processing
+
+`--ignore-visibility`
+:   Do not check, and produce errors, on visibility issues.
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
diff --git a/share/man/nitpretty.md b/share/man/nitpretty.md
new file mode 100644 (file)
index 0000000..3238ced
--- /dev/null
@@ -0,0 +1,84 @@
+% NITPRETTY(1)
+
+# NAME
+
+Pretty print Nit code from Nit source files.
+
+# SYNOPSYS
+
+nitpretty [*options*]...
+
+# OPTIONS
+
+`-W`, `--warn`
+:   Show more warnings
+
+`-w`, `--warning`
+:   Show/hide a specific warning
+
+`-q`, `--quiet`
+:   Do not show warnings
+
+`--stop-on-first-error`
+:   Stop on first error
+
+`--no-color`
+:   Do not use color to display errors and warnings
+
+`--log`
+:   Generate various log files
+
+`--log-dir`
+:   Directory where to generate log files
+
+`-h`, `-?`, `--help`
+:   Show Help (This screen)
+
+`--version`
+:   Show version and exit
+
+`--set-dummy-tool`
+:   Set toolname and version to DUMMY. Useful for testing
+
+`-v`, `--verbose`
+:   Verbose
+
+`--bash-completion`
+:   Generate bash_completion file for this program
+
+`--stub-man`
+:   Generate a stub manpage in pandoc markdown format
+
+`--disable-phase`
+:   DEBUG: Disable a specific phase; use `list` to get the list.
+
+`-I`, `--path`
+:   Set include path for loaders (may be used more than once)
+
+`--only-parse`
+:   Only proceed to parse step of loaders
+
+`--only-metamodel`
+:   Stop after meta-model processing
+
+`--ignore-visibility`
+:   Do not check, and produce errors, on visibility issues.
+
+`--dir`
+:   Working directory (default is '.nitpretty')
+
+`-o`, `--output`
+:   Output name (default is pretty.nit)
+
+`--diff`
+:   Show diff between source and output
+
+`--meld`
+:   Show diff between source and output using meld
+
+`--check`
+:   Check format of Nit source files
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
diff --git a/share/man/nitserial.md b/share/man/nitserial.md
new file mode 100644 (file)
index 0000000..056b692
--- /dev/null
@@ -0,0 +1,75 @@
+% NITSERIAL(1)
+
+# NAME
+
+Generates a serialization support module
+
+# SYNOPSYS
+
+nitserial [*options*]...
+
+# OPTIONS
+
+`-o`, `--output`
+:   Output file (can also be 'stdout')
+
+`--dir`
+:   Output directory
+
+`-W`, `--warn`
+:   Show more warnings
+
+`-w`, `--warning`
+:   Show/hide a specific warning
+
+`-q`, `--quiet`
+:   Do not show warnings
+
+`--stop-on-first-error`
+:   Stop on first error
+
+`--no-color`
+:   Do not use color to display errors and warnings
+
+`--log`
+:   Generate various log files
+
+`--log-dir`
+:   Directory where to generate log files
+
+`-h`, `-?`, `--help`
+:   Show Help (This screen)
+
+`--version`
+:   Show version and exit
+
+`--set-dummy-tool`
+:   Set toolname and version to DUMMY. Useful for testing
+
+`-v`, `--verbose`
+:   Verbose
+
+`--bash-completion`
+:   Generate bash_completion file for this program
+
+`--stub-man`
+:   Generate a stub manpage in pandoc markdown format
+
+`--disable-phase`
+:   DEBUG: Disable a specific phase; use `list` to get the list.
+
+`-I`, `--path`
+:   Set include path for loaders (may be used more than once)
+
+`--only-parse`
+:   Only proceed to parse step of loaders
+
+`--only-metamodel`
+:   Stop after meta-model processing
+
+`--ignore-visibility`
+:   Do not check, and produce errors, on visibility issues.
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
diff --git a/share/man/nitunit.md b/share/man/nitunit.md
new file mode 100644 (file)
index 0000000..24d2e1e
--- /dev/null
@@ -0,0 +1,99 @@
+% NITUNIT(1)
+
+# NAME
+
+Executes the unit tests from Nit source files.
+
+# SYNOPSYS
+
+nitunit [*options*]...
+
+# OPTIONS
+
+`-W`, `--warn`
+:   Show more warnings
+
+`-w`, `--warning`
+:   Show/hide a specific warning
+
+`-q`, `--quiet`
+:   Do not show warnings
+
+`--stop-on-first-error`
+:   Stop on first error
+
+`--no-color`
+:   Do not use color to display errors and warnings
+
+`--log`
+:   Generate various log files
+
+`--log-dir`
+:   Directory where to generate log files
+
+`-h`, `-?`, `--help`
+:   Show Help (This screen)
+
+`--version`
+:   Show version and exit
+
+`--set-dummy-tool`
+:   Set toolname and version to DUMMY. Useful for testing
+
+`-v`, `--verbose`
+:   Verbose
+
+`--bash-completion`
+:   Generate bash_completion file for this program
+
+`--stub-man`
+:   Generate a stub manpage in pandoc markdown format
+
+`--disable-phase`
+:   DEBUG: Disable a specific phase; use `list` to get the list.
+
+`-I`, `--path`
+:   Set include path for loaders (may be used more than once)
+
+`--only-parse`
+:   Only proceed to parse step of loaders
+
+`--only-metamodel`
+:   Stop after meta-model processing
+
+`--ignore-visibility`
+:   Do not check, and produce errors, on visibility issues.
+
+`--full`
+:   Process also imported modules
+
+`-o`, `--output`
+:   Output name (default is 'nitunit.xml')
+
+`--dir`
+:   Working directory (default is '.nitunit')
+
+`--no-act`
+:   Does not compile and run tests
+
+`-p`, `--pattern`
+:   Only run test case with name that match pattern. Examples: 'TestFoo', 'TestFoo*', 'TestFoo::test_foo', 'TestFoo::test_foo*', 'test_foo', 'test_foo*'
+
+`-t`, `--target-file`
+:   Specify test suite location.
+
+`--gen-suite`
+:   Generate test suite skeleton for a module
+
+`-f`, `--force`
+:   Force test generation even if file exists
+
+`--private`
+:   Also generate test case for private methods
+
+`--only-show`
+:   Only display skeleton, do not write file
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
diff --git a/share/man/nitx.md b/share/man/nitx.md
new file mode 100644 (file)
index 0000000..73cee66
--- /dev/null
@@ -0,0 +1,69 @@
+% NITX(1)
+
+# NAME
+
+Displays specific pieces of API information from Nit source files.
+
+# SYNOPSYS
+
+nitx [*options*]...
+
+# OPTIONS
+
+`-W`, `--warn`
+:   Show more warnings
+
+`-w`, `--warning`
+:   Show/hide a specific warning
+
+`-q`, `--quiet`
+:   Do not show warnings
+
+`--stop-on-first-error`
+:   Stop on first error
+
+`--no-color`
+:   Do not use color to display errors and warnings
+
+`--log`
+:   Generate various log files
+
+`--log-dir`
+:   Directory where to generate log files
+
+`-h`, `-?`, `--help`
+:   Show Help (This screen)
+
+`--version`
+:   Show version and exit
+
+`--set-dummy-tool`
+:   Set toolname and version to DUMMY. Useful for testing
+
+`-v`, `--verbose`
+:   Verbose
+
+`--bash-completion`
+:   Generate bash_completion file for this program
+
+`--stub-man`
+:   Generate a stub manpage in pandoc markdown format
+
+`--disable-phase`
+:   DEBUG: Disable a specific phase; use `list` to get the list.
+
+`-I`, `--path`
+:   Set include path for loaders (may be used more than once)
+
+`--only-parse`
+:   Only proceed to parse step of loaders
+
+`--only-metamodel`
+:   Stop after meta-model processing
+
+`--ignore-visibility`
+:   Do not check, and produce errors, on visibility issues.
+
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>
index 8e17b4e..630c1c0 100644 (file)
@@ -53,6 +53,12 @@ class ASTBuilder
                return new ABlockExpr.make
        end
 
+       # Make a new, empty, loop of statements
+       fun make_loop: ALoopExpr
+       do
+               return new ALoopExpr.make
+       end
+
        # Make a new variable read
        fun make_var_read(variable: Variable, mtype: MType): AVarExpr
        do
@@ -84,6 +90,12 @@ class ASTBuilder
                return new ADoExpr.make
        end
 
+       # Make a new break for a given escapemark
+       fun make_break(escapemark: EscapeMark): ABreakExpr
+       do
+               return new ABreakExpr.make(escapemark)
+       end
+
        # Make a new condinionnal
        # `mtype` is the return type of the whole if, in case of a ternary operator.
        fun make_if(condition: AExpr, mtype: nullable MType): AIfExpr
@@ -142,6 +154,7 @@ redef class AExpr
        # Note: this method, aimed to `ABlockExpr` is promoted to `AExpr` because of the limitations of the hierarchies generated by sablecc3
        fun add(expr: AExpr)
        do
+               print "add not implemented in {inspect}"
                abort
        end
 end
@@ -172,29 +185,54 @@ redef class ABlockExpr
        end
 end
 
+redef class ALoopExpr
+       private init make
+       do
+               _n_kwloop = new TKwloop
+               self.is_typed = true
+               n_block = new ABlockExpr
+               n_block.is_typed = true
+       end
+
+       redef fun add(expr: AExpr)
+       do
+               n_block.add expr
+       end
+end
+
 redef class ADoExpr
        private init make
        do
                _n_kwdo = new TKwdo
-               escapemark = new EscapeMark(null, false)
+               self.is_typed = true
+               n_block = new ABlockExpr
+               n_block.is_typed = true
        end
 
        # Make a new break expression of the given do
        fun make_break: ABreakExpr
        do
-               var escapemark = self.escapemark
+               var escapemark = self.break_mark
                if escapemark == null then
-                       escapemark = new EscapeMark(null, false)
-                       self.escapemark = escapemark
+                       escapemark = new EscapeMark(null)
+                       self.break_mark = escapemark
                end
                return new ABreakExpr.make(escapemark)
        end
+
+       redef fun add(expr: AExpr)
+       do
+               n_block.add expr
+       end
 end
 
 redef class ABreakExpr
        private init make(escapemark: EscapeMark)
        do
+               _n_kwbreak = new TKwbreak
                self.escapemark = escapemark
+               escapemark.escapes.add self
+               self.is_typed = true
        end
 end
 
@@ -251,7 +289,6 @@ redef class ACallExpr
                if args != null then
                        self.n_args.n_exprs.add_all(args)
                end
-               var mtype = recv.mtype.as(not null)
                self.callsite = callsite
                self.mtype = callsite.msignature.return_mtype
                self.is_typed = true
index 04e0719..85222a9 100644 (file)
@@ -27,43 +27,41 @@ import mixin
 # Add compiling options
 redef class ToolContext
        # --output
-       var opt_output: OptionString = new OptionString("Output file", "-o", "--output")
+       var opt_output = new OptionString("Output file", "-o", "--output")
        # --dir
-       var opt_dir: OptionString = new OptionString("Output directory", "--dir")
+       var opt_dir = new OptionString("Output directory", "--dir")
        # --no-cc
-       var opt_no_cc: OptionBool = new OptionBool("Do not invoke C compiler", "--no-cc")
+       var opt_no_cc = new OptionBool("Do not invoke C compiler", "--no-cc")
        # --no-main
-       var opt_no_main: OptionBool = new OptionBool("Do not generate main entry point", "--no-main")
+       var opt_no_main = new OptionBool("Do not generate main entry point", "--no-main")
        # --cc-paths
-       var opt_cc_path: OptionArray = new OptionArray("Set include path for C header files (may be used more than once)", "--cc-path")
+       var opt_cc_path = new OptionArray("Set include path for C header files (may be used more than once)", "--cc-path")
        # --make-flags
-       var opt_make_flags: OptionString = new OptionString("Additional options to make", "--make-flags")
+       var opt_make_flags = new OptionString("Additional options to make", "--make-flags")
        # --compile-dir
-       var opt_compile_dir: OptionString = new OptionString("Directory used to generate temporary files", "--compile-dir")
+       var opt_compile_dir = new OptionString("Directory used to generate temporary files", "--compile-dir")
        # --hardening
-       var opt_hardening: OptionBool = new OptionBool("Generate contracts in the C code against bugs in the compiler", "--hardening")
-       # --no-shortcut-range
-       var opt_no_shortcut_range: OptionBool = new OptionBool("Always insantiate a range and its iterator on 'for' loops", "--no-shortcut-range")
+       var opt_hardening = new OptionBool("Generate contracts in the C code against bugs in the compiler", "--hardening")
        # --no-check-covariance
-       var opt_no_check_covariance: OptionBool = new OptionBool("Disable type tests of covariant parameters (dangerous)", "--no-check-covariance")
+       var opt_no_check_covariance = new OptionBool("Disable type tests of covariant parameters (dangerous)", "--no-check-covariance")
        # --no-check-attr-isset
-       var opt_no_check_attr_isset: OptionBool = new OptionBool("Disable isset tests before each attribute access (dangerous)", "--no-check-attr-isset")
+       var opt_no_check_attr_isset = new OptionBool("Disable isset tests before each attribute access (dangerous)", "--no-check-attr-isset")
        # --no-check-assert
-       var opt_no_check_assert: OptionBool = new OptionBool("Disable the evaluation of explicit 'assert' and 'as' (dangerous)", "--no-check-assert")
+       var opt_no_check_assert = new OptionBool("Disable the evaluation of explicit 'assert' and 'as' (dangerous)", "--no-check-assert")
        # --no-check-autocast
-       var opt_no_check_autocast: OptionBool = new OptionBool("Disable implicit casts on unsafe expression usage (dangerous)", "--no-check-autocast")
+       var opt_no_check_autocast = new OptionBool("Disable implicit casts on unsafe expression usage (dangerous)", "--no-check-autocast")
        # --no-check-null
-       var opt_no_check_null: OptionBool = new OptionBool("Disable tests of null receiver (dangerous)", "--no-check-null")
+       var opt_no_check_null = new OptionBool("Disable tests of null receiver (dangerous)", "--no-check-null")
        # --no-check-all
-       var opt_no_check_all: OptionBool = new OptionBool("Disable all tests (dangerous)", "--no-check-all")
+       var opt_no_check_all = new OptionBool("Disable all tests (dangerous)", "--no-check-all")
        # --typing-test-metrics
-       var opt_typing_test_metrics: OptionBool = new OptionBool("Enable static and dynamic count of all type tests", "--typing-test-metrics")
+       var opt_typing_test_metrics = new OptionBool("Enable static and dynamic count of all type tests", "--typing-test-metrics")
        # --invocation-metrics
-       var opt_invocation_metrics: OptionBool = new OptionBool("Enable static and dynamic count of all method invocations", "--invocation-metrics")
+       var opt_invocation_metrics = new OptionBool("Enable static and dynamic count of all method invocations", "--invocation-metrics")
        # --isset-checks-metrics
-       var opt_isset_checks_metrics: OptionBool = new OptionBool("Enable static and dynamic count of isset checks before attributes access", "--isset-checks-metrics")
+       var opt_isset_checks_metrics = new OptionBool("Enable static and dynamic count of isset checks before attributes access", "--isset-checks-metrics")
        # --stacktrace
-       var opt_stacktrace: OptionString = new OptionString("Control the generation of stack traces", "--stacktrace")
+       var opt_stacktrace = new OptionString("Control the generation of stack traces", "--stacktrace")
        # --no-gcc-directives
        var opt_no_gcc_directive = new OptionArray("Disable a advanced gcc directives for optimization", "--no-gcc-directive")
        # --release
@@ -72,7 +70,7 @@ redef class ToolContext
        redef init
        do
                super
-               self.option_context.add_option(self.opt_output, self.opt_dir, self.opt_no_cc, self.opt_no_main, self.opt_make_flags, self.opt_compile_dir, self.opt_hardening, self.opt_no_shortcut_range)
+               self.option_context.add_option(self.opt_output, self.opt_dir, self.opt_no_cc, self.opt_no_main, self.opt_make_flags, self.opt_compile_dir, self.opt_hardening)
                self.option_context.add_option(self.opt_no_check_covariance, self.opt_no_check_attr_isset, self.opt_no_check_assert, self.opt_no_check_autocast, self.opt_no_check_null, self.opt_no_check_all)
                self.option_context.add_option(self.opt_typing_test_metrics, self.opt_invocation_metrics, self.opt_isset_checks_metrics)
                self.option_context.add_option(self.opt_stacktrace)
@@ -182,7 +180,6 @@ class MakefileToolchain
        do
                gather_cc_paths
 
-               var mainmodule = compiler.mainmodule
                var compile_dir = compile_dir
 
                # Generate the .h and .c files
@@ -230,7 +227,6 @@ class MakefileToolchain
                compiler.files_to_copy.add "{cc_paths.first}/gc_chooser.h"
 
                # FFI
-               var m2m = toolcontext.modelbuilder.mmodule2nmodule
                for m in compiler.mainmodule.in_importation.greaters do
                        compiler.finalize_ffi_for_module(m)
                end
@@ -352,7 +348,6 @@ class MakefileToolchain
                end
 
                var linker_options = new HashSet[String]
-               var m2m = toolcontext.modelbuilder.mmodule2nmodule
                for m in mainmodule.in_importation.greaters do
                        var libs = m.collect_linker_libs
                        if libs != null then linker_options.add_all(libs)
@@ -460,7 +455,7 @@ abstract class AbstractCompiler
        # The real main module of the program
        var realmainmodule: MModule
 
-       # The modeulbuilder used to know the model and the AST
+       # The modelbuilder used to know the model and the AST
        var modelbuilder: ModelBuilder is protected writable
 
        # Is hardening asked? (see --hardening)
@@ -484,7 +479,7 @@ abstract class AbstractCompiler
 
        # The list of all associated files
        # Used to generate .c files
-       var files: List[CodeFile] = new List[CodeFile]
+       var files = new List[CodeFile]
 
        # Initialize a visitor specific for a compiler engine
        fun new_visitor: VISITOR is abstract
@@ -551,8 +546,6 @@ abstract class AbstractCompiler
        # Compile C headers
        # This method call compile_header_strucs method that has to be refined
        fun compile_header do
-               var v = self.header
-               var toolctx = modelbuilder.toolcontext
                self.header.add_decl("#include <stdlib.h>")
                self.header.add_decl("#include <stdio.h>")
                self.header.add_decl("#include <string.h>")
@@ -1093,39 +1086,45 @@ abstract class AbstractCompilerVisitor
 
        fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable]) is abstract
 
-       # Transform varargs, in raw arguments, into a single argument of type `Array`
-       # Note: this method modify the given `args`
-       # If there is no vararg, then `args` is not modified.
-       fun varargize(mpropdef: MPropDef, msignature: MSignature, args: Array[RuntimeVariable])
+       # Evaluate `args` as expressions in the call of `mpropdef` on `recv`.
+       # This method is used to manage varargs in signatures and returns the real array
+       # of runtime variables to use in the call.
+       fun varargize(mpropdef: MMethodDef, recv: RuntimeVariable, args: SequenceRead[AExpr]): Array[RuntimeVariable]
        do
-               var recv = args.first
-               var vararg_rank = msignature.vararg_rank
-               if vararg_rank >= 0 then
-                       assert args.length >= msignature.arity + 1 # because of self
-                       var rawargs = args
-                       args = new Array[RuntimeVariable]
-
-                       args.add(rawargs.first) # recv
+               var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null)
+               var res = new Array[RuntimeVariable]
+               res.add(recv)
 
-                       for i in [0..vararg_rank[ do
-                               args.add(rawargs[i+1])
-                       end
-
-                       var vararg_lastrank = vararg_rank + rawargs.length-1-msignature.arity
-                       var vararg = new Array[RuntimeVariable]
-                       for i in [vararg_rank..vararg_lastrank] do
-                               vararg.add(rawargs[i+1])
-                       end
+               if args.is_empty then return res
 
-                       var elttype = msignature.mparameters[vararg_rank].mtype
-                       args.add(self.vararg_instance(mpropdef, recv, vararg, elttype))
+               var vararg_rank = msignature.vararg_rank
+               var vararg_len = args.length - msignature.arity
+               if vararg_len < 0 then vararg_len = 0
 
-                       for i in [vararg_lastrank+1..rawargs.length-1[ do
-                               args.add(rawargs[i+1])
+               for i in [0..msignature.arity[ do
+                       if i == vararg_rank then
+                               var ne = args[i]
+                               if ne isa AVarargExpr then
+                                       var e = self.expr(ne.n_expr, null)
+                                       res.add(e)
+                                       continue
+                               end
+                               var vararg = new Array[RuntimeVariable]
+                               for j in [vararg_rank..vararg_rank+vararg_len] do
+                                       var e = self.expr(args[j], null)
+                                       vararg.add(e)
+                               end
+                               var elttype = msignature.mparameters[vararg_rank].mtype
+                               var arg = self.vararg_instance(mpropdef, recv, vararg, elttype)
+                               res.add(arg)
+                       else
+                               var j = i
+                               if i > vararg_rank then j += vararg_len
+                               var e = self.expr(args[j], null)
+                               res.add(e)
                        end
-                       rawargs.clear
-                       rawargs.add_all(args)
                end
+               return res
        end
 
        # Type handling
@@ -1229,7 +1228,7 @@ abstract class AbstractCompilerVisitor
 
        # Checks
 
-       # Add a check and an abort for a null reciever if needed
+       # Add a check and an abort for a null receiver if needed
        fun check_recv_notnull(recv: RuntimeVariable)
        do
                if self.compiler.modelbuilder.toolcontext.opt_no_check_null.value then return
@@ -1244,7 +1243,7 @@ abstract class AbstractCompilerVisitor
 
        # Names handling
 
-       private var names: HashSet[String] = new HashSet[String]
+       private var names = new HashSet[String]
        private var last: Int = 0
 
        # Return a new name based on `s` and unique in the visitor
@@ -1278,6 +1277,14 @@ abstract class AbstractCompilerVisitor
                return name
        end
 
+       # Insert a C label for associated with an escapemark
+       fun add_escape_label(e: nullable EscapeMark)
+       do
+               if e == null then return
+               if e.escapes.is_empty then return
+               add("BREAK_{escapemark_name(e)}: (void)0;")
+       end
+
        private var escapemark_names = new HashMap[EscapeMark, String]
 
        # Return a "const char*" variable associated to the classname of the dynamic type of an object
@@ -1286,7 +1293,7 @@ abstract class AbstractCompilerVisitor
 
        # Variables handling
 
-       protected var variables: HashMap[Variable, RuntimeVariable] = new HashMap[Variable, RuntimeVariable]
+       protected var variables = new HashMap[Variable, RuntimeVariable]
 
        # Return the local runtime_variable associated to a Nit local variable
        fun variable(variable: Variable): RuntimeVariable
@@ -2396,8 +2403,7 @@ redef class AExpr
        # Do not call this method directly, use `v.stmt` instead
        private fun stmt(v: AbstractCompilerVisitor)
        do
-               var res = expr(v)
-               if res != null then v.add("{res};")
+               expr(v)
        end
 end
 
@@ -2439,12 +2445,6 @@ redef class AVarExpr
 end
 
 redef class AVarAssignExpr
-       redef fun stmt(v)
-       do
-               var variable = self.variable.as(not null)
-               var i = v.expr(self.n_value, variable.declared_type)
-               v.assign(v.variable(variable), i)
-       end
        redef fun expr(v)
        do
                var variable = self.variable.as(not null)
@@ -2470,11 +2470,7 @@ redef class ASelfExpr
        redef fun expr(v) do return v.frame.arguments.first
 end
 
-redef class AContinueExpr
-       redef fun stmt(v) do v.add("goto CONTINUE_{v.escapemark_name(self.escapemark)};")
-end
-
-redef class ABreakExpr
+redef class AEscapeExpr
        redef fun stmt(v) do v.add("goto BREAK_{v.escapemark_name(self.escapemark)};")
 end
 
@@ -2537,10 +2533,7 @@ redef class ADoExpr
        redef fun stmt(v)
        do
                v.stmt(self.n_block)
-               var escapemark = self.escapemark
-               if escapemark != null then
-                       v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
-               end
+               v.add_escape_label(break_mark)
        end
 end
 
@@ -2551,9 +2544,9 @@ redef class AWhileExpr
                var cond = v.expr_bool(self.n_expr)
                v.add("if (!{cond}) break;")
                v.stmt(self.n_block)
-               v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
+               v.add_escape_label(continue_mark)
                v.add("\}")
-               v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
+               v.add_escape_label(break_mark)
        end
 end
 
@@ -2562,47 +2555,15 @@ redef class ALoopExpr
        do
                v.add("for(;;) \{")
                v.stmt(self.n_block)
-               v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
+               v.add_escape_label(continue_mark)
                v.add("\}")
-               v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
+               v.add_escape_label(break_mark)
        end
 end
 
 redef class AForExpr
        redef fun stmt(v)
        do
-               # Shortcut on explicit range
-               # Avoid the instantiation of the range and the iterator
-               var nexpr = self.n_expr
-               if self.variables.length == 1 and nexpr isa ARangeExpr and not v.compiler.modelbuilder.toolcontext.opt_no_shortcut_range.value then
-                       var from = v.expr(nexpr.n_expr, null)
-                       var to = v.expr(nexpr.n_expr2, null)
-                       var variable = v.variable(variables.first)
-                       var one = v.new_expr("1", v.get_class("Int").mclass_type)
-
-                       v.assign(variable, from)
-                       v.add("for(;;) \{ /* shortcut range */")
-
-                       var ok
-                       if nexpr isa AOrangeExpr then
-                               ok = v.send(v.get_property("<", variable.mtype), [variable, to])
-                       else
-                               ok = v.send(v.get_property("<=", variable.mtype), [variable, to])
-                       end
-                       assert ok != null
-                       v.add("if(!{ok}) break;")
-
-                       v.stmt(self.n_block)
-
-                       v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
-                       var succ = v.send(v.get_property("successor", variable.mtype), [variable, one])
-                       assert succ != null
-                       v.assign(variable, succ)
-                       v.add("\}")
-                       v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
-                       return
-               end
-
                var cl = v.expr(self.n_expr, null)
                var it_meth = self.method_iterator
                assert it_meth != null
@@ -2635,12 +2596,12 @@ redef class AForExpr
                        abort
                end
                v.stmt(self.n_block)
-               v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
+               v.add_escape_label(continue_mark)
                var next_meth = self.method_next
                assert next_meth != null
                v.compile_callsite(next_meth, [it])
                v.add("\}")
-               v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
+               v.add_escape_label(break_mark)
 
                var method_finish = self.method_finish
                if method_finish != null then
@@ -2787,7 +2748,7 @@ redef class ACrangeExpr
                var i2 = v.expr(self.n_expr2, null)
                var mtype = self.mtype.as(MClassType)
                var res = v.init_instance(mtype)
-               var it = v.compile_callsite(init_callsite.as(not null), [res, i1, i2])
+               v.compile_callsite(init_callsite.as(not null), [res, i1, i2])
                return res
        end
 end
@@ -2799,7 +2760,7 @@ redef class AOrangeExpr
                var i2 = v.expr(self.n_expr2, null)
                var mtype = self.mtype.as(MClassType)
                var res = v.init_instance(mtype)
-               var it = v.compile_callsite(init_callsite.as(not null), [res, i1, i2])
+               v.compile_callsite(init_callsite.as(not null), [res, i1, i2])
                return res
        end
 end
@@ -2879,11 +2840,9 @@ redef class ASendExpr
        redef fun expr(v)
        do
                var recv = v.expr(self.n_expr, null)
-               var args = [recv]
-               for a in self.raw_arguments do
-                       args.add(v.expr(a, null))
-               end
-               return v.compile_callsite(self.callsite.as(not null), args)
+               var callsite = self.callsite.as(not null)
+               var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments)
+               return v.compile_callsite(callsite, args)
        end
 end
 
@@ -2891,13 +2850,12 @@ redef class ASendReassignFormExpr
        redef fun stmt(v)
        do
                var recv = v.expr(self.n_expr, null)
-               var args = [recv]
-               for a in self.raw_arguments do
-                       args.add(v.expr(a, null))
-               end
+               var callsite = self.callsite.as(not null)
+               var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments)
+
                var value = v.expr(self.n_value, null)
 
-               var left = v.compile_callsite(self.callsite.as(not null), args)
+               var left = v.compile_callsite(callsite, args)
                assert left != null
 
                var res = v.compile_callsite(self.reassign_callsite.as(not null), [left, value])
@@ -2912,14 +2870,12 @@ redef class ASuperExpr
        redef fun expr(v)
        do
                var recv = v.frame.arguments.first
-               var args = [recv]
-               for a in self.n_args.n_exprs do
-                       args.add(v.expr(a, null))
-               end
 
                var callsite = self.callsite
                if callsite != null then
-                       # Add additionnals arguments for the super init call
+                       var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs)
+
+                       # Add additional arguments for the super init call
                        if args.length == 1 then
                                for i in [0..callsite.msignature.arity[ do
                                        args.add(v.frame.arguments[i+1])
@@ -2930,12 +2886,14 @@ redef class ASuperExpr
                        return res
                end
 
+               var mpropdef = self.mpropdef.as(not null)
+               var args = v.varargize(mpropdef, recv, self.n_args.n_exprs)
                if args.length == 1 then
                        args = v.frame.arguments
                end
 
                # stantard call-next-method
-               return v.supercall(mpropdef.as(not null), recv.mtype.as(MClassType), args)
+               return v.supercall(mpropdef, recv.mtype.as(MClassType), args)
        end
 end
 
@@ -2958,11 +2916,10 @@ redef class ANewExpr
                else
                        recv = v.new_expr("({ctype})0/*special!*/", mtype)
                end
-               var args = [recv]
-               for a in self.n_args.n_exprs do
-                       args.add(v.expr(a, null))
-               end
-               var res2 = v.compile_callsite(self.callsite.as(not null), args)
+
+               var callsite = self.callsite.as(not null)
+               var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs)
+               var res2 = v.compile_callsite(callsite, args)
                if res2 != null then
                        #self.debug("got {res2} from {mproperty}. drop {recv}")
                        return res2
@@ -2981,12 +2938,13 @@ redef class AAttrExpr
 end
 
 redef class AAttrAssignExpr
-       redef fun stmt(v)
+       redef fun expr(v)
        do
                var recv = v.expr(self.n_expr, null)
                var i = v.expr(self.n_value, null)
                var mproperty = self.mproperty.as(not null)
                v.write_attribute(mproperty, recv, i)
+               return i
        end
 end
 
index a6fc4e2..cc24d6e 100644 (file)
@@ -125,11 +125,9 @@ redef class AAnnotation
        # 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 annotation_name = n_atid.n_id.text
                var version_fields = new Array[Object]
 
                var args = n_args
-               var platform_name
                if args.length < 1 then
                        modelbuilder.error(self, "Annotation error: \"{name}\" expects at least a single argument.")
                        return ""
index ed9b466..e447080 100644 (file)
@@ -279,8 +279,6 @@ class BucketsColorer[H: Object, E: Object]
        private var colors = new HashMap[E, Int]
        private var conflicts = new HashMap[E, Set[E]]
 
-       init do end
-
        # Start bucket coloring
        fun colorize(buckets: Map[H, Set[E]]): Map[E, Int] do
                compute_conflicts(buckets)
index 37689d8..e9c740a 100644 (file)
@@ -82,7 +82,7 @@ extern void nitni_global_ref_decr(void*);
                return res
        end
 
-       private var compiled_callbacks: Array[NitniCallback] = new Array[NitniCallback]
+       private var compiled_callbacks = new Array[NitniCallback]
 
        # Returns true if callbacks has yet to be generated and register it as being generated
        private fun check_callback_compilation(cb: NitniCallback): Bool
@@ -98,7 +98,6 @@ redef class AMethPropdef
        do
                var mmodule = mpropdef.mclassdef.mmodule
                var mainmodule = v.compiler.mainmodule
-               var amainmodule = v.compiler.modelbuilder.mmodule2nmodule[mainmodule]
                var amodule = v.compiler.modelbuilder.mmodule2nmodule[mmodule]
                var mclass_type = mpropdef.mclassdef.bound_mtype
 
@@ -428,7 +427,6 @@ redef class MExplicitSuper
                var mproperty = from.mproperty
                assert mproperty isa MMethod
                var mclass_type = from.mclassdef.mclass.mclass_type
-               var mmodule = from.mclassdef.mmodule
 
                # In nitni files, declare internal function as extern
                var internal_csignature = mproperty.build_csignature(mclass_type, v.compiler.mainmodule, "___super", long_signature, internal_call_context)
index 2196071..7652368 100644 (file)
@@ -342,7 +342,7 @@ class GlobalCompilerVisitor
 
                var valtype = value.mtype.as(MClassType)
                var res = self.new_var(mtype)
-               if compiler.runtime_type_analysis != null and not compiler.runtime_type_analysis.live_types.has(value.mtype.as(MClassType)) then
+               if not compiler.runtime_type_analysis.live_types.has(value.mtype.as(MClassType)) then
                        self.add("/*no boxing of {value.mtype}: {value.mtype} is not live! */")
                        self.add("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);")
                        return res
@@ -520,45 +520,21 @@ class GlobalCompilerVisitor
                return recvtype
        end
 
-       # Subpart of old call function
-       # Gets the receiver boxed and casted if necessary
-       private fun get_recv(recvtype: MClassType, args: Array[RuntimeVariable]): RuntimeVariable
+       redef fun call(m, recvtype, args)
        do
-               return self.autoadapt(self.autobox(args.first, recvtype), recvtype)
-       end
+               var recv_type = get_recvtype(m, recvtype, args)
+               var recv = self.autoadapt(self.autobox(args.first, recvtype), recvtype)
+               if m.is_extern then recv = unbox_extern(recv, recv_type)
+
+               args = args.to_a
+               args.first = recv
 
-       # Finalizes a call to a method Â´m´ on type Â´recvtype´ with arguments Â´args´
-       private fun finalize_call(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable
-       do
                assert args.length == m.msignature.arity + 1 else debug("Invalid arity for {m}. {args.length} arguments given.")
 
                var rm = new CustomizedRuntimeFunction(m, recvtype)
                return rm.call(self, args)
        end
 
-       redef fun call(m, recvtype, args)
-       do
-               var recv_type = get_recvtype(m, recvtype, args)
-               var recv = get_recv(recv_type, args)
-               if m.is_extern then recv = unbox_extern(recv, recv_type)
-               var new_args = args.to_a
-               self.varargize(m, m.msignature.as(not null), new_args)
-               new_args.first = recv
-               return finalize_call(m, recv_type, new_args)
-       end
-
-       # Does a call without encapsulating varargs into an array
-       # Avoids multiple encapsulation when calling a super in a variadic function
-       fun call_without_varargize(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable
-       do
-               var recv_type = get_recvtype(m, recvtype, args)
-               var recv = get_recv(recv_type, args)
-               if m.is_extern then recv = unbox_extern(recv, recv_type)
-               var new_args = args.to_a
-               new_args.first = recv
-               return finalize_call(m, recv_type, new_args)
-       end
-
        redef fun supercall(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable
        do
                var types = self.collect_types(args.first)
@@ -580,7 +556,7 @@ class GlobalCompilerVisitor
                                return res
                        end
                        var propdef = m.lookup_next_definition(self.compiler.mainmodule, mclasstype)
-                       var res2 = self.call_without_varargize(propdef, mclasstype, args)
+                       var res2 = self.call(propdef, mclasstype, args)
                        if res != null then self.assign(res, res2.as(not null))
                        return res
                end
@@ -602,7 +578,7 @@ class GlobalCompilerVisitor
                        else
                                self.add("case {self.compiler.classid(t)}: /* test {t} */")
                        end
-                       var res2 = self.call_without_varargize(propdef, t, args)
+                       var res2 = self.call(propdef, t, args)
                        if res != null then self.assign(res, res2.as(not null))
                        self.add "break;"
                end
index 8c400f9..3645f54 100644 (file)
@@ -22,19 +22,19 @@ import rapid_type_analysis
 # Add separate compiler specific options
 redef class ToolContext
        # --separate
-       var opt_separate: OptionBool = new OptionBool("Use separate compilation", "--separate")
+       var opt_separate = new OptionBool("Use separate compilation", "--separate")
        # --no-inline-intern
-       var opt_no_inline_intern: OptionBool = new OptionBool("Do not inline call to intern methods", "--no-inline-intern")
+       var opt_no_inline_intern = new OptionBool("Do not inline call to intern methods", "--no-inline-intern")
        # --no-union-attribute
-       var opt_no_union_attribute: OptionBool = new OptionBool("Put primitive attibutes in a box instead of an union", "--no-union-attribute")
+       var opt_no_union_attribute = new OptionBool("Put primitive attibutes in a box instead of an union", "--no-union-attribute")
        # --no-shortcut-equate
-       var opt_no_shortcut_equate: OptionBool = new OptionBool("Always call == in a polymorphic way", "--no-shortcut-equal")
+       var opt_no_shortcut_equate = new OptionBool("Always call == in a polymorphic way", "--no-shortcut-equal")
        # --inline-coloring-numbers
-       var opt_inline_coloring_numbers: OptionBool = new OptionBool("Inline colors and ids (semi-global)", "--inline-coloring-numbers")
+       var opt_inline_coloring_numbers = new OptionBool("Inline colors and ids (semi-global)", "--inline-coloring-numbers")
        # --inline-some-methods
-       var opt_inline_some_methods: OptionBool = new OptionBool("Allow the separate compiler to inline some methods (semi-global)", "--inline-some-methods")
+       var opt_inline_some_methods = new OptionBool("Allow the separate compiler to inline some methods (semi-global)", "--inline-some-methods")
        # --direct-call-monomorph
-       var opt_direct_call_monomorph: OptionBool = new OptionBool("Allow the separate compiler to direct call monomorph sites (semi-global)", "--direct-call-monomorph")
+       var opt_direct_call_monomorph = new OptionBool("Allow the separate compiler to direct call monomorph sites (semi-global)", "--direct-call-monomorph")
        # --skip-dead-methods
        var opt_skip_dead_methods = new OptionBool("Do not compile dead methods (semi-global)", "--skip-dead-methods")
        # --semi-global
@@ -42,7 +42,7 @@ redef class ToolContext
        # --no-colo-dead-methods
        var opt_colo_dead_methods = new OptionBool("Force colorization of dead methods", "--colo-dead-methods")
        # --tables-metrics
-       var opt_tables_metrics: OptionBool = new OptionBool("Enable static size measuring of tables used for vft, typing and resolution", "--tables-metrics")
+       var opt_tables_metrics = new OptionBool("Enable static size measuring of tables used for vft, typing and resolution", "--tables-metrics")
 
        redef init
        do
@@ -963,7 +963,6 @@ class SeparateCompilerVisitor
        redef fun unbox_signature_extern(m, args)
        do
                var msignature = m.msignature.resolve_for(m.mclassdef.bound_mtype, m.mclassdef.bound_mtype, m.mclassdef.mmodule, true)
-               var recv = args.first
                if not m.mproperty.is_init and m.is_extern then
                        args.first = self.unbox_extern(args.first, m.mclassdef.mclass.mclass_type)
                end
@@ -1063,14 +1062,12 @@ class SeparateCompilerVisitor
        redef fun compile_callsite(callsite, args)
        do
                var rta = compiler.runtime_type_analysis
-               var recv = args.first.mtype
                var mmethod = callsite.mproperty
                # TODO: Inlining of new-style constructors
                if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null and not mmethod.is_root_init then
                        var tgs = rta.live_targets(callsite)
                        if tgs.length == 1 then
                                # DIRECT CALL
-                               self.varargize(mmethod.intro, mmethod.intro.msignature.as(not null), args)
                                var res0 = before_send(mmethod, args)
                                var res = call(tgs.first, tgs.first.mclassdef.bound_mtype, args)
                                if res0 != null then
@@ -1086,8 +1083,6 @@ class SeparateCompilerVisitor
        end
        redef fun send(mmethod, arguments)
        do
-               self.varargize(mmethod.intro, mmethod.intro.msignature.as(not null), arguments)
-
                if arguments.first.mcasttype.ctype != "val*" then
                        # In order to shortcut the primitive, we need to find the most specific method
                        # Howverr, because of performance (no flattening), we always work on the realmainmodule
index af3a43c..c23476d 100644 (file)
@@ -20,11 +20,11 @@ intrude import separate_compiler
 # Add separate erased compiler specific options
 redef class ToolContext
        # --erasure
-       var opt_erasure: OptionBool = new OptionBool("Erase generic types", "--erasure")
+       var opt_erasure = new OptionBool("Erase generic types", "--erasure")
        # --rta
        var opt_rta = new OptionBool("Activate RTA (implicit with --global and --separate)", "--rta")
        # --no-check-erasure-cast
-       var opt_no_check_erasure_cast: OptionBool = new OptionBool("Disable implicit casts on unsafe return with erasure-typing policy (dangerous)", "--no-check-erasure-cast")
+       var opt_no_check_erasure_cast = new OptionBool("Disable implicit casts on unsafe return with erasure-typing policy (dangerous)", "--no-check-erasure-cast")
 
        redef init
        do
@@ -549,7 +549,6 @@ class SeparateErasureCompilerVisitor
                end
 
                var class_ptr
-               var type_table
                if value.mtype.ctype == "val*" then
                        class_ptr = "{value}->class->"
                else
index f13d69f..41386d2 100644 (file)
@@ -190,12 +190,8 @@ redef class MGroup
 
        redef fun tpl_namespace do
                var tpl = new Template
-               if mproject != null then
-                       tpl.add mproject.tpl_namespace
-               else if parent != null then
-                       tpl.add parent.tpl_namespace
-               end
-               if mproject != null and mproject.root != self then
+               tpl.add mproject.tpl_namespace
+               if mproject.root != self then
                        tpl.add "::"
                        tpl.add tpl_link
                end
index 7be54ce..49a880b 100644 (file)
@@ -96,7 +96,6 @@ class JavaLanguage
 
                var jni_signature_alt
                var return_type
-               var c_return_type
                var params = new Array[String]
                params.add "nit_ffi_jni_env"
                params.add "java_class"
@@ -105,19 +104,16 @@ class JavaLanguage
                if mproperty.is_init then
                        jni_signature_alt = mclass_type.jni_signature_alt
                        return_type = mclass_type
-                       c_return_type = mclass_type.cname
                else
                        params.add "recv"
                        if signature.return_mtype != null then
                                var ret_mtype = signature.return_mtype
                                ret_mtype = ret_mtype.resolve_for(mclass_type, mclass_type, mmodule, true)
                                return_type = signature.return_mtype
-                               c_return_type = mclass_type.cname
                                jni_signature_alt = return_type.jni_signature_alt
                        else
                                jni_signature_alt = "Void"
                                return_type = null
-                               c_return_type = null
                        end
                end
 
@@ -262,16 +258,15 @@ redef class AMethPropdef
                end
        end
 
-       # Insert additionnal explicit calls to get the current `JNIEnv`
+       # Insert additional explicit calls to get the current `JNIEnv`
        #
        # This forces declaration of callbacks to Nit. The callbacks will be available in Java
        # but will be used mainly by the FFI itself.
        #
-       # The developper can aso customize the JNIEnv used by the FFI by redefing `Sys::jni_env`.
+       # The developer can also customize the JNIEnv used by the FFI by redefining `Sys::jni_env`.
        private fun insert_artificial_callbacks(toolcontext: ToolContext)
        do
                var fcc = foreign_callbacks
-               assert fcc != null
 
                var modelbuilder = toolcontext.modelbuilder
                var mmodule = mpropdef.mclassdef.mmodule
@@ -450,7 +445,7 @@ redef class MType
        # Type name in Java
        #
        # * Primitives common to both languages use their Java primitive type
-       # * Nit extern Java classes are reprensented by their full Java type
+       # * Nit extern Java classes are represented by their full Java type
        # * Other Nit objects are represented by `int` in Java. It holds the
        #       pointer to the underlying C structure.
        #       TODO create static Java types to store and hide the pointer
@@ -502,7 +497,6 @@ redef class MClassType
        do
                var ftype = mclass.ftype
                if ftype isa ForeignJavaType then
-                       var ori_jni_type = jni_type
                        var jni_type = ftype.java_type.
                                replace('.', "/").replace(' ', "").replace('\n', "")
 
index a50b45b..9e3775d 100644 (file)
@@ -117,17 +117,7 @@ redef class AReturnExpr
        end
 end
 
-redef class AContinueExpr
-       redef fun after_simple_misc(v)
-       do
-               var e = n_expr
-               if e != null then
-                       e.warn_parentheses(v)
-               end
-       end
-end
-
-redef class ABreakExpr
+redef class AEscapeExpr
        redef fun after_simple_misc(v)
        do
                var e = n_expr
index 06075b4..fe5375c 100644 (file)
@@ -52,7 +52,6 @@ class HighlightVisitor
        do
                var stack2 = new Array[HTMLTag]
                var stack = new Array[Prod]
-               var closes = new Array[Prod]
                var line = 0
                var c: nullable Token = first_token
                var hv = new HighlightVisitor
@@ -932,4 +931,3 @@ redef class AExpr
                return t.infobox(v)
        end
 end
-
diff --git a/src/interpreter/breakpoint.nit b/src/interpreter/breakpoint.nit
deleted file mode 100644 (file)
index ef04a3b..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2013 Lucas Bajolet <lucas.bajolet@gmail.com>
-#
-# 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.
-
-# Classes and methods relative to the management of Breakpoints for the Debugger
-module breakpoint
-
-# Contains all the informations of a Breakpoint for the Debugger
-class Breakpoint
-
-       # Line to break on
-       var line: Int
-
-       # File concerned by the breakpoint
-       var file: String
-
-       # Maximum times to break on self
-       var max_breaks: Int
-
-       init(line: Int, file: String)
-       do
-               self.line = line
-               self.file = file
-               self.max_breaks = -1
-       end
-
-       fun set_max_breaks(breaks: Int)
-       do
-               self.max_breaks = breaks
-       end
-
-       # When the breakpoint is encountered, the check-in function should be called
-       fun check_in
-       do
-               if self.max_breaks > 0 then self.max_breaks -= 1
-       end
-
-       # Checks if the breakpoint is still valid (that is, if it has a remaining breaks number > 0 or == -1)
-       fun is_valid: Bool
-       do
-               if max_breaks == 0 then
-                       return false
-               else
-                       return true
-               end
-       end
-
-end
index 586c04c..771d4a2 100644 (file)
@@ -17,7 +17,6 @@
 # Debugging of a nit program using the NaiveInterpreter
 module debugger
 
-import breakpoint
 intrude import naive_interpreter
 import nitx
 intrude import semantize::local_var_init
@@ -120,9 +119,9 @@ redef class ToolContext
        end
 
        # -d
-       var opt_debugger_mode: OptionBool = new OptionBool("Launches the target program with the debugger attached to it", "-d")
+       var opt_debugger_mode = new OptionBool("Launches the target program with the debugger attached to it", "-d")
        # -c
-       var opt_debugger_autorun: OptionBool = new OptionBool("Launches the target program with the interpreter, such as when the program fails, the debugging prompt is summoned", "-c")
+       var opt_debugger_autorun = new OptionBool("Launches the target program with the interpreter, such as when the program fails, the debugging prompt is summoned", "-c")
 
        redef init
        do
@@ -167,6 +166,20 @@ redef class ModelBuilder
        end
 end
 
+# Contains all the informations of a Breakpoint for the Debugger
+class Breakpoint
+
+       # Line to break on
+       var line: Int
+
+       # File concerned by the breakpoint
+       var file: String
+
+       redef init do
+               if not file.has_suffix(".nit") then file += ".nit"
+       end
+end
+
 # The class extending `NaiveInterpreter` by adding debugging methods
 class Debugger
        super NaiveInterpreter
@@ -257,19 +270,8 @@ class Debugger
        end
 
        # Same as a regular call but for a runtime injected module
-       #
        fun rt_call(mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
        do
-               args = call_commons(mpropdef, args)
-               return rt_call_without_varargs(mpropdef, args)
-       end
-
-       # Common code to call and this function
-       #
-       # Call only executes the variadic part, this avoids
-       # double encapsulation of variadic parameters into an Array
-       fun rt_call_without_varargs(mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
-       do
                if self.modelbuilder.toolcontext.opt_discover_call_trace.value and not self.discover_call_trace.has(mpropdef) then
                        self.discover_call_trace.add mpropdef
                        self.debug("Discovered {mpropdef}")
@@ -324,7 +326,6 @@ class Debugger
                        var mmod = e.mmodule
                        if mmod != null then
                                self.mainmodule = mmod
-                               var local_classdefs = mmod.mclassdefs
                                var sys_type = mmod.sys_type
                                if sys_type == null then
                                        print "Fatal error, cannot find Class Sys !\nAborting"
@@ -379,14 +380,6 @@ class Debugger
                var breakpoint = find_breakpoint(curr_file, n.location.line_start)
 
                if breakpoints.keys.has(curr_file) and breakpoint != null then
-
-                       breakpoint.check_in
-
-                       if not breakpoint.is_valid
-                       then
-                               remove_breakpoint(curr_file, n.location.line_start)
-                       end
-
                        n.debug("Execute stmt {n.to_s}")
                        while read_cmd do end
                end
@@ -399,7 +392,6 @@ class Debugger
                var identifiers_in_instruction = get_identifiers_in_current_instruction(n.location.text)
 
                for i in identifiers_in_instruction do
-                       var variable = seek_variable(i, frame)
                        for j in self.traces do
                                if j.is_variable_traced_in_frame(i, frame) then
                                        n.debug("Traced variable {i} used")
@@ -465,7 +457,7 @@ class Debugger
        #
        # Returns a boolean value, representing whether or not to
        # continue reading commands from the console input
-       fun process_debug_command(command:String): Bool
+       fun process_debug_command(command: String): Bool
        do
                # Step-out command
                if command == "finish"
@@ -478,10 +470,17 @@ class Debugger
                # Step-over command
                else if command == "n" then
                        return step_over
+               # Shows help
+               else if command == "help" then
+                       help
+                       return true
                # Opens a new NitIndex prompt on current model
                else if command == "nitx" then
                        new NitIndex.with_infos(modelbuilder, self.mainmodule).prompt
                        return true
+               else if command == "bt" or command == "backtrack" then
+                       print stack_trace
+                       return true
                # Continues execution until the end
                else if command == "c" then
                        return continue_exec
@@ -503,41 +502,72 @@ class Debugger
                        print stack_trace
                        exit(0)
                else
-                       var parts_of_command = command.split_with(' ')
+                       var parts = command.split_with(' ')
+                       var cname = parts.first
                        # Shows the value of a variable in the current frame
-                       if parts_of_command[0] == "p" or parts_of_command[0] == "print" then
-                               print_command(parts_of_command)
+                       if cname == "p" or cname == "print" then
+                               print_command(parts)
                        # Places a breakpoint on line x of file y
-                       else if parts_of_command[0] == "break" or parts_of_command[0] == "b"
-                       then
-                               process_place_break_fun(parts_of_command)
-                       # Places a temporary breakpoint on line x of file y
-                       else if parts_of_command[0] == "tbreak" and (parts_of_command.length == 2 or parts_of_command.length == 3)
-                       then
-                               process_place_tbreak_fun(parts_of_command)
+                       else if cname == "break" or cname == "b" then
+                               process_place_break_fun(parts)
                        # Removes a breakpoint on line x of file y
-                       else if parts_of_command[0] == "d" or parts_of_command[0] == "delete" then
-                               process_remove_break_fun(parts_of_command)
+                       else if cname == "d" or cname == "delete" then
+                               process_remove_break_fun(parts)
                        # Sets an alias for a variable
-                       else if parts_of_command.length == 3 and parts_of_command[1] == "as"
-                       then
-                               add_alias(parts_of_command[0], parts_of_command[2])
+                       else if parts.length == 2 and parts[1] == "as" then
+                               process_alias(parts)
                        # Modifies the value of a variable in the current frame
-                       else if parts_of_command.length >= 3 and parts_of_command[1] == "=" then
-                               process_mod_function(parts_of_command)
+                       else if parts.length == 3 and parts[1] == "=" then
+                               process_mod_function(parts)
                        # Traces the modifications on a variable
-                       else if parts_of_command.length >= 2 and parts_of_command[0] == "trace" then
-                               process_trace_command(parts_of_command)
+                       else if cname == "trace" then
+                               process_trace_command(parts)
                        # Untraces the modifications on a variable
-                       else if parts_of_command.length == 2 and parts_of_command[0] == "untrace" then
-                               process_untrace_command(parts_of_command)
+                       else if cname == "untrace" then
+                               process_untrace_command(parts)
                        else
-                               print "Unknown command \"{command}\""
+                               bad_command(command)
                        end
                end
                return true
        end
 
+       # Produces help for the commands of the debugger
+       fun help do
+               print ""
+               print "Help :"
+               print "-----------------------------------"
+               print ""
+               print "Variables"
+               print " * Modification: var_name = value (Warning: var_name must be primitive)"
+               print " * Alias: var_name as alias"
+               print ""
+               print "Printing"
+               print " * Variables: p(rint) var_name (Use * to print all local variables)"
+               print " * Collections: p(rint) var_name '[' start_index (.. end_index) ']'"
+               print ""
+               print "Breakpoints"
+               print " * File/line: b(reak) file_name line_number"
+               print " * Remove: d(elete) id"
+               print ""
+               print "Tracepoints"
+               print " * Variable: trace var_name break/print"
+               print " * Untrace variable: untrace var_name"
+               print ""
+               print "Flow control"
+               print " * Next instruction (same-level): n"
+               print " * Next instruction: s"
+               print " * Finish current method: finish"
+               print " * Continue until next breakpoint or end: c"
+               print ""
+               print "General commands"
+               print " * quit: Quits the debugger"
+               print " * abort: Aborts the interpretation, prints the stack trace before leaving"
+               print " * nitx: Ask questions to the model about its entities (classes, methods, etc.)"
+               print " * nit: Inject dynamic code for interpretation"
+               print ""
+       end
+
        #######################################################################
        ##               Processing specific command functions               ##
        #######################################################################
@@ -580,75 +610,96 @@ class Debugger
                return false
        end
 
+       fun bad_command(cmd: String) do
+               print "Unrecognized command {cmd}. Use 'help' to show help."
+       end
+
        # Prints the demanded variable in the command
        #
        # The name of the variable in in position 1 of the array 'parts_of_command'
-       fun print_command(parts_of_command: Array[String])
+       fun print_command(parts: Array[String])
        do
-               if parts_of_command[1] == "*" then
+               if parts.length != 2 then
+                       bad_command(parts.join(" "))
+                       return
+               end
+               if parts[1] == "*" then
                        var map_of_instances = frame.map
 
-                       var keys = map_of_instances.iterator
-
                        var self_var = seek_variable("self", frame)
                        print "self: {self_var.to_s}"
 
                        for instance in map_of_instances.keys do
                                print "{instance.to_s}: {map_of_instances[instance].to_s}"
                        end
-               else if parts_of_command[1] == "stack" then
-                       print self.stack_trace
-               else if parts_of_command[1].chars.has('[') and parts_of_command[1].chars.has(']') then
-                       process_array_command(parts_of_command)
+               else if parts[1].chars.has('[') and parts[1].chars.has(']') then
+                       process_array_command(parts)
                else
-                       var instance = seek_variable(get_real_variable_name(parts_of_command[1]), frame)
+                       var instance = seek_variable(get_real_variable_name(parts[1]), frame)
 
                        if instance != null
                        then
                                print_instance(instance)
                        else
-                               print "Cannot find variable {parts_of_command[1]}"
+                               print "Cannot find variable {parts[1]}"
                        end
                end
        end
 
+       # Process the input command to set an alias for a variable
+       fun process_alias(parts: Array[String]) do
+               if parts.length != 3 then
+                       bad_command(parts.join(" "))
+                       return
+               end
+               add_alias(parts.first, parts.last)
+       end
+
        # Processes the input string to know where to put a breakpoint
-       fun process_place_break_fun(parts_of_command: Array[String])
+       fun process_place_break_fun(parts: Array[String])
        do
-               var bp = get_breakpoint_from_command(parts_of_command)
+               if parts.length != 3 then
+                       bad_command(parts.join(" "))
+                       return
+               end
+               var bp = get_breakpoint_from_command(parts)
                if bp != null then
                        place_breakpoint(bp)
                end
        end
 
        # Returns a breakpoint containing the informations stored in the command
-       fun get_breakpoint_from_command(parts_of_command: Array[String]): nullable Breakpoint
+       fun get_breakpoint_from_command(parts: Array[String]): nullable Breakpoint
        do
-               if parts_of_command[1].is_numeric then
-                       return new Breakpoint(parts_of_command[1].to_i, curr_file)
-               else if parts_of_command.length >= 3 and parts_of_command[2].is_numeric then
-                       return new Breakpoint(parts_of_command[2].to_i, parts_of_command[1])
+               if parts[1].is_numeric then
+                       return new Breakpoint(parts[1].to_i, curr_file)
+               else if parts.length >= 3 and parts[2].is_numeric then
+                       return new Breakpoint(parts[2].to_i, parts[1])
                else
                        return null
                end
        end
 
        # Processes the command of removing a breakpoint on specified line and file
-       fun process_remove_break_fun(parts_of_command: Array[String])
+       fun process_remove_break_fun(parts: Array[String])
        do
-               if parts_of_command[1].is_numeric then
-                       remove_breakpoint(self.curr_file, parts_of_command[1].to_i)
-               else if parts_of_command.length >= 3 and parts_of_command[2].is_numeric then
-                       remove_breakpoint(parts_of_command[1], parts_of_command[2].to_i)
+               if parts.length != 2 then
+                       bad_command(parts.join(" "))
+                       return
+               end
+               if parts[1].is_numeric then
+                       remove_breakpoint(self.curr_file, parts[1].to_i)
+               else if parts.length >= 3 and parts[2].is_numeric then
+                       remove_breakpoint(parts[1], parts[2].to_i)
                end
        end
 
        # Processes an array print command
-       fun process_array_command(parts_of_command: Array[String])
+       fun process_array_command(parts: Array[String])
        do
-               var index_of_first_brace = parts_of_command[1].chars.index_of('[')
-               var variable_name = get_real_variable_name(parts_of_command[1].substring(0,index_of_first_brace))
-               var braces = parts_of_command[1].substring_from(index_of_first_brace)
+               var index_of_first_brace = parts[1].chars.index_of('[')
+               var variable_name = get_real_variable_name(parts[1].substring(0,index_of_first_brace))
+               var braces = parts[1].substring_from(index_of_first_brace)
 
                var indexes = remove_braces(braces)
 
@@ -676,27 +727,32 @@ class Debugger
        # Processes the modification function to modify a variable dynamically
        #
        # Command of type variable = value
-       fun process_mod_function(parts_of_command: Array[String])
+       fun process_mod_function(parts: Array[String])
        do
-               parts_of_command[0] = get_real_variable_name(parts_of_command[0])
-               var parts_of_variable = parts_of_command[0].split_with(".")
+               if parts.length != 3 then
+                       bad_command(parts.join(" "))
+                       return
+               end
+               var p0 = parts[0]
+               p0 = get_real_variable_name(p0)
+               var parts_of_variable = p0.split_with(".")
 
                if parts_of_variable.length > 1 then
                        var last_part = parts_of_variable.pop
-                       var first_part = parts_of_command[0].substring(0,parts_of_command[0].length - last_part.length - 1)
+                       var first_part = p0.substring(0,p0.length - last_part.length - 1)
                        var papa = seek_variable(first_part, frame)
 
                        if papa != null and papa isa MutableInstance then
                                var attribute = get_attribute_in_mutable_instance(papa, last_part)
 
                                if attribute != null then
-                                       modify_argument_of_complex_type(papa, attribute, parts_of_command[2])
+                                       modify_argument_of_complex_type(papa, attribute, parts[2])
                                end
                        end
                else
                        var target = seek_variable(parts_of_variable[0], frame)
                        if target != null then
-                               modify_in_frame(target, parts_of_command[2])
+                               modify_in_frame(target, parts[2])
                        end
                end
        end
@@ -704,42 +760,46 @@ class Debugger
        # Processes the untrace variable command
        #
        # Command pattern : "untrace variable"
-       fun process_untrace_command(parts_of_command: Array[String])
+       fun process_untrace_command(parts: Array[String])
        do
-               var variable_name = get_real_variable_name(parts_of_command[1])
+               if parts.length != 2 then
+                       bad_command(parts.join(" "))
+                       return
+               end
+               var variable_name = get_real_variable_name(parts[1])
                if untrace_variable(variable_name) then
-                       print "Untraced variable {parts_of_command[1]}"
+                       print "Untraced variable {parts[1]}"
                else
-                       print "{parts_of_command[1]} is not traced"
+                       print "{parts[1]} is not traced"
                end
        end
 
        # Processes the trace variable command
        #
        # Command pattern : "trace variable [break/print]"
-       fun process_trace_command(parts_of_command: Array[String])
+       fun process_trace_command(parts: Array[String])
        do
-               var variable_name = get_real_variable_name(parts_of_command[1])
+               if parts.length != 3 then
+                       bad_command(parts.join(" "))
+                       return
+               end
+               var variable_name = get_real_variable_name(parts[1])
                var breaker:Bool
 
                if seek_variable(variable_name, frame) == null then
-                       print "Cannot find a variable called {parts_of_command[1]}"
+                       print "Cannot find a variable called {parts[1]}"
                        return
                end
 
-               if parts_of_command.length == 3 then
-                       if parts_of_command[2] == "break" then
-                               breaker = true
-                       else
-                               breaker = false
-                       end
+               if parts[2] == "break" then
+                       breaker = true
                else
                        breaker = false
                end
 
                trace_variable(variable_name, breaker)
 
-               print "Successfully tracing {parts_of_command[1]}"
+               print "Successfully tracing {parts[1]}"
        end
 
        #######################################################################
@@ -832,14 +892,12 @@ class Debugger
 
                var trigger_char_escape = false
                var trigger_string_escape = false
-               var trigger_concat_in_string = false
 
                for i in instruction.chars do
                        if trigger_char_escape then
                                if i == '\'' then trigger_char_escape = false
                        else if trigger_string_escape then
                                if i == '{' then
-                                       trigger_concat_in_string = true
                                        trigger_string_escape = false
                                else if i == '\"' then trigger_string_escape = false
                        else
@@ -857,7 +915,6 @@ class Debugger
                                else if i == '\"' then
                                        trigger_string_escape = true
                                else if i == '}' then
-                                       trigger_concat_in_string = false
                                        trigger_string_escape = true
                                else
                                        if instruction_buffer.length > 0 and not instruction_buffer.is_numeric and not (instruction_buffer.chars[0] >= 'A' and instruction_buffer.chars[0] <= 'Z') then result_array.push(instruction_buffer.to_s)
@@ -1084,8 +1141,6 @@ class Debugger
        do
                var collection_length_attribute = get_attribute_in_mutable_instance(collection, "length")
 
-               var real_collection_length: nullable Int = null
-
                if collection_length_attribute != null then
                        var primitive_length_instance = collection.attributes[collection_length_attribute]
                        if primitive_length_instance isa PrimitiveInstance[Int] then
@@ -1215,17 +1270,6 @@ class Debugger
                end
        end
 
-       #Places a breakpoint that will trigger once and be destroyed afterwards
-       fun process_place_tbreak_fun(parts_of_command: Array[String])
-       do
-               var bp = get_breakpoint_from_command(parts_of_command)
-               if bp != null
-               then
-                       bp.set_max_breaks(1)
-                       place_breakpoint(bp)
-               end
-       end
-
        #######################################################################
        ##                  Breakpoint removing functions                    ##
        #######################################################################
index 55c6567..e16f060 100644 (file)
@@ -24,7 +24,7 @@ import mixin
 
 redef class ToolContext
        # --discover-call-trace
-       var opt_discover_call_trace: OptionBool = new OptionBool("Trace calls of the first invocation of a method", "--discover-call-trace")
+       var opt_discover_call_trace = new OptionBool("Trace calls of the first invocation of a method", "--discover-call-trace")
 
        redef init
        do
@@ -58,7 +58,7 @@ class NaiveInterpreter
        # The modelbuilder that know the AST and its associations with the model
        var modelbuilder: ModelBuilder
 
-       # The main moduleof the program (used to lookup methoda
+       # The main module of the program (used to lookup method)
        var mainmodule: MModule
 
        # The command line arguments of the interpreted program
@@ -66,6 +66,7 @@ class NaiveInterpreter
        # arguments[1] is the first argument
        var arguments: Array[String]
 
+       # The main Sys instance
        var mainobj: nullable Instance
 
        init(modelbuilder: ModelBuilder, mainmodule: MModule, arguments: Array[String])
@@ -113,43 +114,26 @@ class NaiveInterpreter
        # Set this mark to skip the evaluation until the end of the specified method frame
        var returnmark: nullable Frame = null
 
-       # Is a break executed?
-       # Set this mark to skip the evaluation until a labeled statement catch it with `is_break`
-       var breakmark: nullable EscapeMark = null
-
-       # Is a continue executed?
-       # Set this mark to skip the evaluation until a labeled statement catch it with `is_continue`
-       var continuemark: nullable EscapeMark = null
+       # Is a break or a continue executed?
+       # Set this mark to skip the evaluation until a labeled statement catch it with `is_escape`
+       var escapemark: nullable EscapeMark = null
 
        # Is a return or a break or a continue executed?
        # Use this function to know if you must skip the evaluation of statements
-       fun is_escaping: Bool do return returnmark != null or breakmark != null or continuemark != null
+       fun is_escaping: Bool do return returnmark != null or escapemark != null
 
        # The value associated with the current return/break/continue, if any.
        # Set the value when you set a escapemark.
        # Read the value when you catch a mark or reach the end of a method
        var escapevalue: nullable Instance = null
 
-       # If there is a break and is associated with `escapemark`, then return true an clear the mark.
-       # If there is no break or if `escapemark` is null then return false.
-       # Use this function to catch a potential break.
-       fun is_break(escapemark: nullable EscapeMark): Bool
-       do
-               if escapemark != null and self.breakmark == escapemark then
-                       self.breakmark = null
-                       return true
-               else
-                       return false
-               end
-       end
-
-       # If there is a continue and is associated with `escapemark`, then return true an clear the mark.
-       # If there is no continue or if `escapemark` is null then return false.
-       # Use this function to catch a potential continue.
-       fun is_continue(escapemark: nullable EscapeMark): Bool
+       # If there is a break/continue and is associated with `escapemark`, then return true and clear the mark.
+       # If there is no break/continue or if `escapemark` is null then return false.
+       # Use this function to catch a potential break/continue.
+       fun is_escape(escapemark: nullable EscapeMark): Bool
        do
-               if escapemark != null and self.continuemark == escapemark then
-                       self.continuemark = null
+               if escapemark != null and self.escapemark == escapemark then
+                       self.escapemark = null
                        return true
                else
                        return false
@@ -226,13 +210,13 @@ class NaiveInterpreter
                return new PrimitiveInstance[Float](ic.mclass_type, val)
        end
 
-       # The unique intance of the `true` value.
+       # The unique instance of the `true` value.
        var true_instance: Instance
 
-       # The unique intance of the `false` value.
+       # The unique instance of the `false` value.
        var false_instance: Instance
 
-       # The unique intance of the `null` value.
+       # The unique instance of the `null` value.
        var null_instance: Instance
 
        # Return a new array made of `values`.
@@ -283,9 +267,9 @@ class NaiveInterpreter
        fun frame: Frame do return frames.first
 
        # The stack of all frames. The first one is the current one.
-       var frames: List[Frame] = new List[Frame]
+       var frames = new List[Frame]
 
-       # Return a stack stace. One line per function
+       # Return a stack trace. One line per function
        fun stack_trace: String
        do
                var b = new FlatBuffer
@@ -332,55 +316,58 @@ class NaiveInterpreter
                f.map[v] = value
        end
 
-       # Store known method, used to trace methods as thez are reached
+       # Store known methods, used to trace methods as they are reached
        var discover_call_trace: Set[MMethodDef] = new HashSet[MMethodDef]
 
-       # Common code for calls to injected methods and normal methods
-       fun call_commons(mpropdef: MMethodDef, args: Array[Instance]): Array[Instance]
+       # Evaluate `args` as expressions in the call of `mpropdef` on `recv`.
+       # This method is used to manage varargs in signatures and returns the real array
+       # of instances to use in the call.
+       # Return `null` if one of the evaluation of the arguments return null.
+       fun varargize(mpropdef: MMethodDef, recv: Instance, args: SequenceRead[AExpr]): nullable Array[Instance]
        do
-               var vararg_rank = mpropdef.msignature.vararg_rank
-               if vararg_rank >= 0 then
-                       assert args.length >= mpropdef.msignature.arity + 1 # because of self
-                       var rawargs = args
-                       args = new Array[Instance]
-
-                       args.add(rawargs.first) # recv
+               var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null)
+               var res = new Array[Instance]
+               res.add(recv)
 
-                       for i in [0..vararg_rank[ do
-                               args.add(rawargs[i+1])
-                       end
+               if args.is_empty then return res
 
-                       var vararg_lastrank = vararg_rank + rawargs.length-1-mpropdef.msignature.arity
-                       var vararg = new Array[Instance]
-                       for i in [vararg_rank..vararg_lastrank] do
-                               vararg.add(rawargs[i+1])
-                       end
-                       # FIXME: its it to late to determine the vararg type, this should have been done during a previous analysis
-                       var elttype = mpropdef.msignature.mparameters[vararg_rank].mtype.anchor_to(self.mainmodule, args.first.mtype.as(MClassType))
-                       args.add(self.array_instance(vararg, elttype))
+               var vararg_rank = msignature.vararg_rank
+               var vararg_len = args.length - msignature.arity
+               if vararg_len < 0 then vararg_len = 0
 
-                       for i in [vararg_lastrank+1..rawargs.length-1[ do
-                               args.add(rawargs[i+1])
+               for i in [0..msignature.arity[ do
+                       if i == vararg_rank then
+                               var ne = args[i]
+                               if ne isa AVarargExpr then
+                                       var e = self.expr(ne.n_expr)
+                                       if e == null then return null
+                                       res.add(e)
+                                       continue
+                               end
+                               var vararg = new Array[Instance]
+                               for j in [vararg_rank..vararg_rank+vararg_len] do
+                                       var e = self.expr(args[j])
+                                       if e == null then return null
+                                       vararg.add(e)
+                               end
+                               var elttype = msignature.mparameters[vararg_rank].mtype.anchor_to(self.mainmodule, recv.mtype.as(MClassType))
+                               res.add(self.array_instance(vararg, elttype))
+                       else
+                               var j = i
+                               if i > vararg_rank then j += vararg_len
+                               var e = self.expr(args[j])
+                               if e == null then return null
+                               res.add(e)
                        end
                end
-               return args
+               return res
        end
 
        # Execute `mpropdef` for a `args` (where `args[0]` is the receiver).
-       # Return a falue if `mpropdef` is a function, or null if it is a procedure.
-       # The call is direct/static. There is no message-seding/late-binding.
+       # Return a value if `mpropdef` is a function, or null if it is a procedure.
+       # The call is direct/static. There is no message-sending/late-binding.
        fun call(mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
        do
-               args = call_commons(mpropdef, args)
-               return call_without_varargs(mpropdef, args)
-       end
-
-       # Common code to call and this function
-       #
-       # Call only executes the variadic part, this avoids
-       # double encapsulation of variadic parameters into an Array
-       fun call_without_varargs(mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
-       do
                if self.modelbuilder.toolcontext.opt_discover_call_trace.value and not self.discover_call_trace.has(mpropdef) then
                        self.discover_call_trace.add mpropdef
                        self.debug("Discovered {mpropdef}")
@@ -444,7 +431,7 @@ class NaiveInterpreter
        end
 
        # Execute a full `callsite` for given `args`
-       # Use this method, instead of `send` to execute and control the aditionnal behavior of the call-sites
+       # Use this method, instead of `send` to execute and control the additional behavior of the call-sites
        fun callsite(callsite: nullable CallSite, arguments: Array[Instance]): nullable Instance
        do
                var initializers = callsite.mpropdef.initializers
@@ -473,8 +460,8 @@ class NaiveInterpreter
        end
 
        # Execute `mproperty` for a `args` (where `args[0]` is the receiver).
-       # Return a falue if `mproperty` is a function, or null if it is a procedure.
-       # The call is polimotphic. There is a message-seding/late-bindng according to te receiver (args[0]).
+       # Return a value if `mproperty` is a function, or null if it is a procedure.
+       # The call is polymorphic. There is a message-sending/late-binding according to the receiver (args[0]).
        fun send(mproperty: MMethod, args: Array[Instance]): nullable Instance
        do
                var recv = args.first
@@ -534,7 +521,7 @@ class NaiveInterpreter
                return res
        end
 
-       var collect_attr_propdef_cache = new HashMap[MType, Array[AAttrPropdef]]
+       private var collect_attr_propdef_cache = new HashMap[MType, Array[AAttrPropdef]]
 
        # Fill the initial values of the newly created instance `recv`.
        # `recv.mtype` is used to know what must be filled.
@@ -721,7 +708,7 @@ redef class AMethPropdef
                if auto_super_call then
                        # standard call-next-method
                        var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
-                       v.call_without_varargs(superpd, arguments)
+                       v.call(superpd, arguments)
                end
 
                if mpropdef.is_intern or mpropdef.is_extern then
@@ -770,14 +757,14 @@ redef class AMethPropdef
                        var txt = recv.mtype.to_s
                        return v.native_string_instance(txt)
                else if pname == "==" then
-                       # == is correclt redefined for instances
+                       # == is correctly redefined for instances
                        return v.bool_instance(args[0] == args[1])
                else if pname == "!=" then
                        return v.bool_instance(args[0] != args[1])
                else if pname == "is_same_type" then
                        return v.bool_instance(args[0].mtype == args[1].mtype)
                else if pname == "is_same_instance" then
-                       return v.bool_instance(args[1] != null and args[0].eq_is(args[1]))
+                       return v.bool_instance(args[0].eq_is(args[1]))
                else if pname == "exit" then
                        exit(args[1].to_i)
                        abort
@@ -1126,7 +1113,7 @@ redef class AClassdef
                        if not mpropdef.is_intro then
                                # standard call-next-method
                                var superpd = mpropdef.lookup_next_definition(v.mainmodule, args.first.mtype)
-                               v.call_without_varargs(superpd, args)
+                               v.call(superpd, args)
                        end
                        return null
                else
@@ -1226,20 +1213,7 @@ redef class ASelfExpr
        end
 end
 
-redef class AContinueExpr
-       redef fun stmt(v)
-       do
-               var ne = self.n_expr
-               if ne != null then
-                       var i = v.expr(ne)
-                       if i == null then return
-                       v.escapevalue = i
-               end
-               v.continuemark = self.escapemark
-       end
-end
-
-redef class ABreakExpr
+redef class AEscapeExpr
        redef fun stmt(v)
        do
                var ne = self.n_expr
@@ -1248,7 +1222,7 @@ redef class ABreakExpr
                        if i == null then return
                        v.escapevalue = i
                end
-               v.breakmark = self.escapemark
+               v.escapemark = self.escapemark
        end
 end
 
@@ -1314,7 +1288,7 @@ redef class ADoExpr
        redef fun stmt(v)
        do
                v.stmt(self.n_block)
-               v.is_break(self.escapemark) # Clear the break (if any)
+               v.is_escape(self.break_mark) # Clear the break (if any)
        end
 end
 
@@ -1326,8 +1300,8 @@ redef class AWhileExpr
                        if cond == null then return
                        if not cond.is_true then return
                        v.stmt(self.n_block)
-                       if v.is_break(self.escapemark) then return
-                       v.is_continue(self.escapemark) # Clear the break
+                       if v.is_escape(self.break_mark) then return
+                       v.is_escape(self.continue_mark) # Clear the break
                        if v.is_escaping then return
                end
        end
@@ -1338,8 +1312,8 @@ redef class ALoopExpr
        do
                loop
                        v.stmt(self.n_block)
-                       if v.is_break(self.escapemark) then return
-                       v.is_continue(self.escapemark) # Clear the break
+                       if v.is_escape(self.break_mark) then return
+                       v.is_escape(self.continue_mark) # Clear the break
                        if v.is_escaping then return
                end
        end
@@ -1371,8 +1345,8 @@ redef class AForExpr
                                abort
                        end
                        v.stmt(self.n_block)
-                       if v.is_break(self.escapemark) then break
-                       v.is_continue(self.escapemark) # Clear the break
+                       if v.is_escape(self.break_mark) then break
+                       v.is_escape(self.continue_mark) # Clear the break
                        if v.is_escaping then break
                        v.callsite(method_next, [iter])
                end
@@ -1591,7 +1565,6 @@ redef class AAsNotnullExpr
        do
                var i = v.expr(self.n_expr)
                if i == null then return null
-               var mtype = v.unanchor_type(self.mtype.as(not null))
                if i.mtype isa MNullType then
                        fatal(v, "Cast failed")
                end
@@ -1625,12 +1598,8 @@ redef class ASendExpr
        do
                var recv = v.expr(self.n_expr)
                if recv == null then return null
-               var args = [recv]
-               for a in self.raw_arguments do
-                       var i = v.expr(a)
-                       if i == null then return null
-                       args.add(i)
-               end
+               var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments)
+               if args == null then return null
 
                var res = v.callsite(callsite, args)
                return res
@@ -1642,12 +1611,8 @@ redef class ASendReassignFormExpr
        do
                var recv = v.expr(self.n_expr)
                if recv == null then return
-               var args = [recv]
-               for a in self.raw_arguments do
-                       var i = v.expr(a)
-                       if i == null then return
-                       args.add(i)
-               end
+               var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments)
+               if args == null then return
                var value = v.expr(self.n_value)
                if value == null then return
 
@@ -1667,16 +1632,12 @@ redef class ASuperExpr
        redef fun expr(v)
        do
                var recv = v.frame.arguments.first
-               var args = [recv]
-               for a in self.n_args.n_exprs do
-                       var i = v.expr(a)
-                       if i == null then return null
-                       args.add(i)
-               end
 
                var callsite = self.callsite
                if callsite != null then
-                       # Add additionnals arguments for the super init call
+                       var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs)
+                       if args == null then return null
+                       # Add additional arguments for the super init call
                        if args.length == 1 then
                                for i in [0..callsite.msignature.arity[ do
                                        args.add(v.frame.arguments[i+1])
@@ -1687,14 +1648,17 @@ redef class ASuperExpr
                        return res
                end
 
+               # standard call-next-method
+               var mpropdef = self.mpropdef
+               mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
+
+               var args = v.varargize(mpropdef, recv, self.n_args.n_exprs)
+               if args == null then return null
+
                if args.length == 1 then
                        args = v.frame.arguments
                end
-
-               # stantard call-next-method
-               var mpropdef = self.mpropdef
-               mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
-               var res = v.call_without_varargs(mpropdef, args)
+               var res = v.call(mpropdef, args)
                return res
        end
 end
@@ -1705,12 +1669,8 @@ redef class ANewExpr
                var mtype = v.unanchor_type(self.mtype.as(not null))
                var recv: Instance = new MutableInstance(mtype)
                v.init_instance(recv)
-               var args = [recv]
-               for a in self.n_args.n_exprs do
-                       var i = v.expr(a)
-                       if i == null then return null
-                       args.add(i)
-               end
+               var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs)
+               if args == null then return null
                var res2 = v.callsite(callsite, args)
                if res2 != null then
                        #self.debug("got {res2} from {mproperty}. drop {recv}")
index 664415a..eac5853 100644 (file)
@@ -35,8 +35,6 @@ end
 # Print class tables metrics for the classes of the program main
 fun compute_tables_metrics(main: MModule)
 do
-       var model = main.model
-
        var nc = 0 # Number of runtime classes
        var nl = 0 # Number of usages of class definitions (a class definition can be used more than once)
        var nhp = 0 # Number of usages of properties (a property can be used more than once)
index f26eb2e..64e82c7 100644 (file)
@@ -1226,7 +1226,6 @@ class MVirtualType
                if is_fixed(mmodule, resolved_reciever) then return res
                # If the resolved type isa intern class, then there is no possible valid redefinition in any potential subclass. self is just fixed. so simply return the resolution
                if res isa MClassType and res.mclass.kind == enum_kind then return res
-               # TODO: Add 'fixed' virtual type in the specification.
                # TODO: What if bound to a MParameterType?
                # Note that Nullable types can always be redefined by the non nullable version, so there is no specific case on it.
 
@@ -1275,7 +1274,6 @@ end
 #
 # Note that parameter types are shared among class refinements.
 # Therefore parameter only have an internal name (see `to_s` for details).
-# TODO: Add a `name_for` to get better messages.
 class MParameterType
        super MType
 
index 3153274..9297793 100644 (file)
@@ -528,7 +528,6 @@ class MEntityNameSorter
        super Comparator
        redef type COMPARED: MEntity
        redef fun compare(a, b) do return a.name <=> b.name
-       init do end
 end
 
 # Sort MConcerns based on the module importation hierarchy ranking
@@ -544,8 +543,6 @@ class MConcernRankSorter
        super Comparator
        redef type COMPARED: MConcern
 
-       init do end
-
        redef fun compare(a, b) do
                if a.concern_rank == b.concern_rank then
                        return a.name <=> b.name
index 2a5e9fb..441a6c2 100644 (file)
@@ -258,7 +258,6 @@ redef class ModelBuilder
        private fun check_supertypes(nmodule: AModule, nclassdef: AClassdef)
        do
                var mmodule = nmodule.mmodule.as(not null)
-               var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
                var mclass = nclassdef.mclass.as(not null)
                var mclassdef = nclassdef.mclassdef.as(not null)
 
@@ -410,7 +409,7 @@ redef class ModelBuilder
 
        # Register the nclassdef associated to each mclassdef
        # FIXME: why not refine the `MClassDef` class with a nullable attribute?
-       var mclassdef2nclassdef: HashMap[MClassDef, AClassdef] = new HashMap[MClassDef, AClassdef]
+       var mclassdef2nclassdef = new HashMap[MClassDef, AClassdef]
 
        # Return the static type associated to the node `ntype`.
        # `mmodule` and `mclassdef` is the context where the call is made (used to understand formal types)
index cbcae54..bb4d2cd 100644 (file)
@@ -38,7 +38,7 @@ end
 redef class ModelBuilder
        # Register the npropdef associated to each mpropdef
        # FIXME: why not refine the `MPropDef` class with a nullable attribute?
-       var mpropdef2npropdef: HashMap[MPropDef, APropdef] = new HashMap[MPropDef, APropdef]
+       var mpropdef2npropdef = new HashMap[MPropDef, APropdef]
 
        # Build the properties of `nclassdef`.
        # REQUIRE: all superclasses are built.
@@ -244,7 +244,7 @@ redef class ModelBuilder
                # Extract visibility information of the main part of `mtype`
                # 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 origial module of the type
+               var mmodule_type: nullable MModule = null # The original module of the type
                mtype = mtype.as_notnullable
                if mtype isa MClassType then
                        vis_type = mtype.mclass.visibility
@@ -291,7 +291,7 @@ redef class MPropDef
 end
 
 redef class AClassdef
-       var build_properties_is_done: Bool = false
+       var build_properties_is_done = false
 
        # The free init (implicitely constructed by the class if required)
        var mfree_init: nullable MMethodDef = null
@@ -474,7 +474,7 @@ redef class ASignature
                var ntype = self.n_type
                if ntype != null then
                        self.ret_type = modelbuilder.resolve_mtype(mmodule, mclassdef, ntype)
-                       if self.ret_type == null then return false # Skip errir
+                       if self.ret_type == null then return false # Skip error
                end
 
                self.is_visited = true
@@ -762,12 +762,12 @@ redef class AAttrPropdef
        # Is the node tagged `noinit`?
        var noinit = false
 
-       # Is the node taggeg lazy?
+       # Is the node tagged lazy?
        var is_lazy = false
 
-       # The guard associated to a lasy attribute.
+       # The guard associated to a lazy attribute.
        # Because some engines does not have a working `isset`,
-       # this additionnal attribute is used to guard the lazy initialization.
+       # this additional attribute is used to guard the lazy initialization.
        # TODO: to remove once isset is correctly implemented
        var mlazypropdef: nullable MAttributeDef
 
@@ -874,7 +874,7 @@ redef class AAttrPropdef
        redef fun build_signature(modelbuilder)
        do
                var mpropdef = self.mpropdef
-               if mpropdef == null then return # Error thus skiped
+               if mpropdef == null then return # Error thus skipped
                var mclassdef = mpropdef.mclassdef
                var mmodule = mclassdef.mmodule
                var mtype: nullable MType = null
@@ -887,10 +887,10 @@ redef class AAttrPropdef
                        if mtype == null then return
                end
 
-               # Inherit the type from the getter (usually an abstact getter)
+               # Inherit the type from the getter (usually an abstract getter)
                if mtype == null and mreadpropdef != null and not mreadpropdef.is_intro then
                        var msignature = mreadpropdef.mproperty.intro.msignature
-                       if msignature == null then return # Error, thus skiped
+                       if msignature == null then return # Error, thus skipped
                        mtype = msignature.return_mtype
                end
 
@@ -962,12 +962,10 @@ redef class AAttrPropdef
        redef fun check_signature(modelbuilder)
        do
                var mpropdef = self.mpropdef
-               if mpropdef == null then return # Error thus skiped
-               var mclassdef = mpropdef.mclassdef
-               var mmodule = mclassdef.mmodule
+               if mpropdef == null then return # Error thus skipped
                var ntype = self.n_type
                var mtype = self.mpropdef.static_mtype
-               if mtype == null then return # Error thus skiped
+               if mtype == null then return # Error thus skipped
 
                # Lookup for signature in the precursor
                # FIXME all precursors should be considered
@@ -1090,7 +1088,7 @@ redef class ATypePropdef
        redef fun build_signature(modelbuilder)
        do
                var mpropdef = self.mpropdef
-               if mpropdef == null then return # Error thus skiped
+               if mpropdef == null then return # Error thus skipped
                var mclassdef = mpropdef.mclassdef
                var mmodule = mclassdef.mmodule
                var mtype: nullable MType = null
@@ -1106,10 +1104,10 @@ redef class ATypePropdef
        redef fun check_signature(modelbuilder)
        do
                var mpropdef = self.mpropdef
-               if mpropdef == null then return # Error thus skiped
+               if mpropdef == null then return # Error thus skipped
 
                var bound = self.mpropdef.bound
-               if bound == null then return # Error thus skiped
+               if bound == null then return # Error thus skipped
 
                modelbuilder.check_visibility(n_type, bound, mpropdef)
 
index b44d034..5e795d9 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Save and load `Model` from/to Neo4j base.
+# Save and load a `Model` to/from a Neo4j graph.
 #
 # Nit models are composed by MEntities.
 # This module creates NeoNode for each MEntity found in a `Model` and save them
 # into Neo4j database.
 #
-# see `Neo4jClient`.
+# SEE: `Neo4jClient`
 #
 # NeoNodes can also be translated back to MEntities to rebuild a Nit `Model`.
 #
-# Structure of the nit `Model` in base:
+# Structure of the nit `Model` in the graph:
 #
 # Note : Any null or empty attribute will not be saved in the database.
 #
 #
 # * labels: `MClass`, `model_name` and `MEntity`.
 # * `full_name`: fully qualified name.
-# * `arity`: number of generic formal parameters. 0 if the class is not generic.
 # * `kind`: kind of the class (`interface`, `abstract class`, etc.)
 # * `visibility`: visibility of the class.
+# * `parameter_names`: JSON array listing the name of each formal generic
+# parameter (in order of declaration).
 # * `(:MClass)-[:CLASSTYPE]->(:MClassType)`: SEE: `MClass.mclass_type`
 #
 # Arguments in the `CLASSTYPE` are named following the `parameter_names`
@@ -82,8 +83,6 @@
 # * labels: `MClassDef`, `model_name` and `MEntity`.
 # * `is_intro`: Does this definition introduce the class?
 # * `location`: origin of the definition. SEE: `Location.to_s`
-# * `parameter_names`: JSON array listing the name of each formal generic
-# parameter (in order of declaration).
 # * `(:MClassDef)-[:BOUNDTYPE]->(:MClassType)`: bounded type associated to the
 # classdef.
 # * `(:MClassDef)-[:MCLASS]->(:MClass)`: associated `MClass`.
 # * `(:MClassType)-[:ARGUMENT]->(:MType)`: type arguments.
 #
 # Arguments are named following the `parameter_names` attribute of the
-# `MClassDef` that introduces the class referred by `CLASS`.
+# `MClass` referred by `CLASS`.
 #
 # Additional relationship for `MVirtualType`:
 #
@@ -446,7 +445,6 @@ class NeoModel
                node.labels.add "MModule"
                node["full_name"] = mmodule.full_name
                node["location"] = mmodule.location.to_s
-               var mgroup = mmodule.mgroup
                for parent in mmodule.in_importation.direct_greaters do
                        node.out_edges.add(new NeoEdge(node, "IMPORTS", to_node(parent)))
                end
index e7a733a..e43ff7f 100644 (file)
@@ -2252,7 +2252,6 @@ end
 
 redef class ASuperstringExpr
        redef fun accept_pretty_printer(v) do
-               var force_inline = self.force_inline
                for n_expr in n_exprs do v.visit n_expr
        end
 
index 5ad0aed..2fd0f82 100644 (file)
@@ -53,7 +53,7 @@ class NitModule
                if header != null then add header
 
                var name = name
-               if name != null then add "module {name}\n\n"
+               add "module {name}\n\n"
 
                for i in imports do add "import {i}\n"
                add "\n"
index 5aba49d..a031c12 100644 (file)
@@ -1344,14 +1344,19 @@ abstract class ALabelable
        var n_label: nullable ALabel = null is writable
 end
 
-# A `break` statement.
-class ABreakExpr
+# A `break` or a `continue`
+abstract class AEscapeExpr
        super AExpr
        super ALabelable
-       var n_kwbreak: TKwbreak is writable, noinit
        var n_expr: nullable AExpr = null is writable
 end
 
+# A `break` statement.
+class ABreakExpr
+       super AEscapeExpr
+       var n_kwbreak: TKwbreak is writable, noinit
+end
+
 # An `abort` statement
 class AAbortExpr
        super AExpr
@@ -1360,10 +1365,8 @@ end
 
 # A `continue` statement
 class AContinueExpr
-       super AExpr
-       super ALabelable
+       super AEscapeExpr
        var n_kwcontinue: nullable TKwcontinue = null is writable
-       var n_expr: nullable AExpr = null is writable
 end
 
 # A `do` statement
index 7daee0f..b60ed2e 100644 (file)
@@ -237,8 +237,6 @@ private class ComputeProdLocationVisitor
                        end
                end
        end
-
-       init do end
 end
 
 # Each reduce action has its own class, this one is the root of the hierarchy.
index 95b2acb..25874e2 100644 (file)
@@ -32,10 +32,6 @@ end
 
 private class AutoSuperInitVisitor
        super Visitor
-       init
-       do
-       end
-
        redef fun visit(n)
        do
                n.accept_auto_super_init(self)
@@ -210,7 +206,6 @@ redef class ASendExpr
        redef fun accept_auto_super_init(v)
        do
                var mproperty = self.callsite.mproperty
-               if mproperty == null then return
                if mproperty.is_init then
                        v.has_explicit_super_init = self
                end
index ccc36b7..733e3d3 100644 (file)
@@ -165,7 +165,7 @@ private class FlowVisitor
        fun merge_continues_to(before_loop: FlowContext, escapemark: nullable EscapeMark)
        do
                if escapemark == null then return
-               for b in escapemark.continues do
+               for b in escapemark.escapes do
                        var before = b.before_flow_context
                        if before == null then continue # Forward error
                        before_loop.add_loop(before)
@@ -175,7 +175,7 @@ private class FlowVisitor
        fun merge_breaks(escapemark: nullable EscapeMark)
        do
                if escapemark == null then return
-               for b in escapemark.breaks do
+               for b in escapemark.escapes do
                        var before = b.before_flow_context
                        if before == null then continue # Forward error
                        self.make_merge_flow(self.current_flow_context, before)
@@ -319,22 +319,7 @@ redef class AReturnExpr
        end
 end
 
-redef class AContinueExpr
-       # The flow just before it become unreachable
-       fun before_flow_context: nullable FlowContext
-       do
-               var after = self.after_flow_context
-               if after == null then return null
-               return after.previous.first
-       end
-       redef fun accept_flow_visitor(v)
-       do
-               super
-               v.make_unreachable_flow
-       end
-end
-
-redef class ABreakExpr
+redef class AEscapeExpr
        # The flow just before it become unreachable
        fun before_flow_context: nullable FlowContext
        do
@@ -361,7 +346,7 @@ redef class ADoExpr
        redef fun accept_flow_visitor(v)
        do
                super
-               v.merge_breaks(self.escapemark)
+               v.merge_breaks(self.break_mark)
        end
 end
 
@@ -411,10 +396,10 @@ redef class AWhileExpr
                var after_block = v.current_flow_context
 
                before_loop.add_loop(after_block)
-               v.merge_continues_to(after_block, self.escapemark)
+               v.merge_continues_to(after_block, self.continue_mark)
 
                v.current_flow_context = after_expr.when_false
-               v.merge_breaks(self.escapemark)
+               v.merge_breaks(self.break_mark)
        end
 end
 
@@ -428,10 +413,10 @@ redef class ALoopExpr
                var after_block = v.current_flow_context
 
                before_loop.add_loop(after_block)
-               v.merge_continues_to(after_block, self.escapemark)
+               v.merge_continues_to(after_block, self.continue_mark)
 
                v.make_unreachable_flow
-               v.merge_breaks(self.escapemark)
+               v.merge_breaks(self.break_mark)
        end
 end
 
@@ -447,10 +432,10 @@ redef class AForExpr
                var after_block = v.current_flow_context
 
                before_loop.add_loop(after_block)
-               v.merge_continues_to(after_block, self.escapemark)
+               v.merge_continues_to(after_block, self.continue_mark)
 
                v.make_merge_flow(v.current_flow_context, before_loop)
-               v.merge_breaks(self.escapemark)
+               v.merge_breaks(self.break_mark)
        end
 end
 
index 3039745..00702d0 100644 (file)
@@ -50,15 +50,12 @@ class EscapeMark
        # The name of the label (unless the mark is an anonymous loop mark)
        var name: nullable String
 
-       # Is the mark attached to a loop (loop, while, for)
-       # Such a mark is a candidate to a labelless 'continue' or 'break'
-       var for_loop: Bool
+       # The associated `continue` mark, if any.
+       # If the mark attached to a loop (loop, while, for), a distinct mark is used.
+       private var continue_mark: nullable EscapeMark = null
 
-       # Each 'continue' attached to the mark
-       var continues = new Array[AContinueExpr]
-
-       # Each 'break' attached to the mark
-       var breaks = new Array[ABreakExpr]
+       # Each break/continue attached to the mark
+       var escapes = new Array[AEscapeExpr]
 end
 
 # Visit a npropdef and:
@@ -81,7 +78,7 @@ private class ScopeVisitor
        end
 
        # All stacked scope. `scopes.first` is the current scope
-       private var scopes = new List[Scope]
+       var scopes = new List[Scope]
 
        # Shift and check the last scope
        fun shift_scope
@@ -176,7 +173,8 @@ private class ScopeVisitor
                else
                        name = null
                end
-               var res = new EscapeMark(name, for_loop)
+               var res = new EscapeMark(name)
+               if for_loop then res.continue_mark = new EscapeMark(name)
                return res
        end
 
@@ -292,43 +290,47 @@ redef class ASelfExpr
        end
 end
 
-redef class AContinueExpr
-       # The escape mark associated with the continue
+redef class AEscapeExpr
+       # The escape mark associated with the break/continue
        var escapemark: nullable EscapeMark
+end
+
+redef class AContinueExpr
        redef fun accept_scope_visitor(v)
        do
                super
                var escapemark = v.get_escapemark(self, self.n_label)
                if escapemark == null then return # Skip error
-               if not escapemark.for_loop then
+               escapemark = escapemark.continue_mark
+               if escapemark == null then
                        v.error(self, "Error: cannot 'continue', only 'break'.")
+                       return
                end
-               escapemark.continues.add(self)
+               escapemark.escapes.add(self)
                self.escapemark = escapemark
        end
 end
 
 redef class ABreakExpr
-       # The escape mark associated with the break
-       var escapemark: nullable EscapeMark
        redef fun accept_scope_visitor(v)
        do
                super
                var escapemark = v.get_escapemark(self, self.n_label)
                if escapemark == null then return # Skip error
-               escapemark.breaks.add(self)
+               escapemark.escapes.add(self)
                self.escapemark = escapemark
        end
 end
 
 
 redef class ADoExpr
-       # The escape mark associated with the 'do' block
-       var escapemark: nullable EscapeMark
+       # The break escape mark associated with the 'do' block
+       var break_mark: nullable EscapeMark
+
        redef fun accept_scope_visitor(v)
        do
-               self.escapemark = v.make_escape_mark(n_label, false)
-               v.enter_visit_block(n_block, self.escapemark)
+               self.break_mark = v.make_escape_mark(n_label, false)
+               v.enter_visit_block(n_block, self.break_mark)
        end
 end
 
@@ -342,24 +344,34 @@ redef class AIfExpr
 end
 
 redef class AWhileExpr
-       # The escape mark associated with the 'while'
-       var escapemark: nullable EscapeMark
+       # The break escape mark associated with the 'while'
+       var break_mark: nullable EscapeMark
+
+       # The continue escape mark associated with the 'while'
+       var continue_mark: nullable EscapeMark
+
        redef fun accept_scope_visitor(v)
        do
                var escapemark = v.make_escape_mark(n_label, true)
-               self.escapemark = escapemark
+               self.break_mark = escapemark
+               self.continue_mark = escapemark.continue_mark
                v.enter_visit(n_expr)
                v.enter_visit_block(n_block, escapemark)
        end
 end
 
 redef class ALoopExpr
-       # The escape mark associated with the 'loop'
-       var escapemark: nullable EscapeMark
+       # The break escape mark associated with the 'loop'
+       var break_mark: nullable EscapeMark
+
+       # The continue escape mark associated with the 'loop'
+       var continue_mark: nullable EscapeMark
+
        redef fun accept_scope_visitor(v)
        do
                var escapemark = v.make_escape_mark(n_label, true)
-               self.escapemark = escapemark
+               self.break_mark = escapemark
+               self.continue_mark = escapemark.continue_mark
                v.enter_visit_block(n_block, escapemark)
        end
 end
@@ -368,8 +380,11 @@ redef class AForExpr
        # The automatic variables in order
        var variables: nullable Array[Variable]
 
-       # The escape mark associated with the 'for'
-       var escapemark: nullable EscapeMark
+       # The break escape mark associated with the 'for'
+       var break_mark: nullable EscapeMark
+
+       # The continue escape mark associated with the 'for'
+       var continue_mark: nullable EscapeMark
 
        redef fun accept_scope_visitor(v)
        do
@@ -388,7 +403,8 @@ redef class AForExpr
                end
 
                var escapemark = v.make_escape_mark(n_label, true)
-               self.escapemark = escapemark
+               self.break_mark = escapemark
+               self.continue_mark = escapemark.continue_mark
                v.enter_visit_block(n_block, escapemark)
 
                v.shift_scope
index cf84e4c..22faa9f 100644 (file)
@@ -47,7 +47,7 @@ private class TypeVisitor
        # The analyzed property
        var mpropdef: nullable MPropDef
 
-       var selfvariable: Variable = new Variable("self")
+       var selfvariable = new Variable("self")
 
        # Is `self` use restricted?
        # * no explicit `self`
@@ -195,6 +195,40 @@ private class TypeVisitor
                return sup
        end
 
+       # Special verification on != and == for null
+       # Return true
+       fun null_test(anode: ABinopExpr)
+       do
+               var mtype = anode.n_expr.mtype
+               var mtype2 = anode.n_expr2.mtype
+
+               if mtype == null or mtype2 == null then return
+
+               if not mtype2 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
+
+               # Check for type adaptation
+               var variable = anode.n_expr.its_variable
+               if variable == null then return
+
+               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)
+               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)
+               else
+                       abort
+               end
+       end
+
        fun try_get_mproperty_by_name2(anode: ANode, mtype: MType, name: String): nullable MProperty
        do
                return self.modelbuilder.try_get_mproperty_by_name2(anode, mmodule, mtype, name)
@@ -343,11 +377,18 @@ private class TypeVisitor
                        self.visit_expr_subtype(args[j], paramtype)
                end
                if vararg_rank >= 0 then
-                       var varargs = new Array[AExpr]
                        var paramtype = msignature.mparameters[vararg_rank].mtype
-                       for j in [vararg_rank..vararg_rank+vararg_decl] do
-                               varargs.add(args[j])
-                               self.visit_expr_subtype(args[j], paramtype)
+                       var first = args[vararg_rank]
+                       if vararg_decl == 0 and first isa AVarargExpr then
+                               var mclass = get_mclass(node, "Array")
+                               if mclass == null then return false # Forward error
+                               var array_mtype = mclass.get_mtype([paramtype])
+                               self.visit_expr_subtype(first.n_expr, array_mtype)
+                               first.mtype  = first.n_expr.mtype
+                       else
+                               for j in [vararg_rank..vararg_rank+vararg_decl] do
+                                       self.visit_expr_subtype(args[j], paramtype)
+                               end
                        end
                end
                return true
@@ -395,7 +436,6 @@ private class TypeVisitor
        fun merge_types(node: ANode, col: Array[nullable MType]): nullable MType
        do
                if col.length == 1 then return col.first
-               var res = new Array[nullable MType]
                for t1 in col do
                        if t1 == null then continue # return null
                        var found = true
@@ -461,8 +501,8 @@ end
 
 redef class FlowContext
        # Store changes of types because of type evolution
-       private var vars: HashMap[Variable, nullable MType] = new HashMap[Variable, nullable MType]
-       private var cache: HashMap[Variable, nullable Array[nullable MType]] = new HashMap[Variable, nullable Array[nullable MType]]
+       private var vars = new HashMap[Variable, nullable MType]
+       private var cache = new HashMap[Variable, nullable Array[nullable MType]]
 
        # Adapt the variable to a static type
        # Warning1: do not modify vars directly.
@@ -747,7 +787,7 @@ redef class AContinueExpr
        do
                var nexpr = self.n_expr
                if nexpr != null then
-                       var mtype = v.visit_expr(nexpr)
+                       v.visit_expr(nexpr)
                end
                self.is_typed = true
        end
@@ -758,7 +798,7 @@ redef class ABreakExpr
        do
                var nexpr = self.n_expr
                if nexpr != null then
-                       var mtype = v.visit_expr(nexpr)
+                       v.visit_expr(nexpr)
                end
                self.is_typed = true
        end
@@ -771,9 +811,9 @@ redef class AReturnExpr
                var ret_type = v.mpropdef.as(MMethodDef).msignature.return_mtype
                if nexpr != null then
                        if ret_type != null then
-                               var mtype = v.visit_expr_subtype(nexpr, ret_type)
+                               v.visit_expr_subtype(nexpr, ret_type)
                        else
-                               var mtype = v.visit_expr(nexpr)
+                               v.visit_expr(nexpr)
                                v.error(self, "Error: Return with value in a procedure.")
                        end
                else if ret_type != null then
@@ -857,6 +897,9 @@ redef class AForExpr
        var method_key: nullable CallSite
        var method_finish: nullable CallSite
 
+       var method_lt: nullable CallSite
+       var method_successor: nullable CallSite
+
        private fun do_type_iterator(v: TypeVisitor, mtype: MType)
        do
                if mtype isa MNullType then
@@ -957,6 +1000,19 @@ redef class AForExpr
                        end
                        self.method_key = keydef
                end
+
+               if self.variables.length == 1 and n_expr isa ARangeExpr then
+                       var variable = variables.first
+                       var vtype = variable.declared_type.as(not null)
+
+                       if n_expr isa AOrangeExpr then
+                               self.method_lt = v.get_method(self, vtype, "<", false)
+                       else
+                               self.method_lt = v.get_method(self, vtype, "<=", false)
+                       end
+
+                       self.method_successor = v.get_method(self, vtype, "successor", false)
+               end
        end
 
        redef fun accept_typing(v)
@@ -1207,9 +1263,9 @@ redef class AIsaExpr
 
                var variable = self.n_expr.its_variable
                if variable != null then
-                       var orig = self.n_expr.mtype
-                       var from = if orig != null then orig.to_s else "invalid"
-                       var to = if mtype != null then mtype.to_s else "invalid"
+                       #var orig = self.n_expr.mtype
+                       #var from = if orig != null then orig.to_s else "invalid"
+                       #var to = if mtype != null then mtype.to_s else "invalid"
                        #debug("adapt {variable}: {from} -> {to}")
                        self.after_flow_context.when_true.set_var(variable, mtype)
                end
@@ -1336,16 +1392,7 @@ redef class AEqExpr
        redef fun accept_typing(v)
        do
                super
-
-               var variable = self.n_expr.its_variable
-               if variable == null then return
-               var mtype = self.n_expr2.mtype
-               if not mtype isa MNullType then return
-               var vartype = v.get_variable(self, variable)
-               if not vartype isa MNullableType then return
-               self.after_flow_context.when_true.set_var(variable, mtype)
-               self.after_flow_context.when_false.set_var(variable, vartype.mtype)
-               #debug("adapt {variable}:{vartype} ; true->{mtype} false->{vartype.mtype}")
+               v.null_test(self)
        end
 end
 redef class ANeExpr
@@ -1353,16 +1400,7 @@ redef class ANeExpr
        redef fun accept_typing(v)
        do
                super
-
-               var variable = self.n_expr.its_variable
-               if variable == null then return
-               var mtype = self.n_expr2.mtype
-               if not mtype isa MNullType then return
-               var vartype = v.get_variable(self, variable)
-               if not vartype isa MNullableType then return
-               self.after_flow_context.when_false.set_var(variable, mtype)
-               self.after_flow_context.when_true.set_var(variable, vartype.mtype)
-               #debug("adapt {variable}:{vartype} ; true->{vartype.mtype} false->{mtype}")
+               v.null_test(self)
        end
 end
 redef class ALtExpr
@@ -1763,6 +1801,16 @@ redef class AIssetAttrExpr
        end
 end
 
+redef class AVarargExpr
+       redef fun accept_typing(v)
+       do
+               # This kind of pseudo-expression can be only processed trough a signature
+               # See `check_signature`
+               # Other cases are a syntax error.
+               v.error(self, "Syntax error: unexpected `...`")
+       end
+end
+
 ###
 
 redef class ADebugTypeExpr
index f543a2b..566e014 100644 (file)
@@ -200,7 +200,6 @@ redef class ModelBuilder
                if not mmodule2nmodule.has_key(mmodule) then return ts
 
                var nmodule = mmodule2nmodule[mmodule]
-               assert nmodule != null
 
                # usualy, only the original module must be imported in the unit test.
                var o = mmodule
index 893a843..e174145 100644 (file)
@@ -267,12 +267,15 @@ class ToolContext
        # Option --bash-completion
        var opt_bash_completion = new OptionBool("Generate bash_completion file for this program", "--bash-completion")
 
+       # Option --stub-man
+       var opt_stub_man = new OptionBool("Generate a stub manpage in pandoc markdown format", "--stub-man")
+
        # Verbose level
        var verbose_level: Int = 0
 
        init
        do
-               option_context.add_option(opt_warn, opt_warning, opt_quiet, opt_stop_on_first_error, opt_no_color, opt_log, opt_log_dir, opt_help, opt_version, opt_set_dummy_tool, opt_verbose, opt_bash_completion)
+               option_context.add_option(opt_warn, opt_warning, opt_quiet, opt_stop_on_first_error, opt_no_color, opt_log, opt_log_dir, opt_help, opt_version, opt_set_dummy_tool, opt_verbose, opt_bash_completion, opt_stub_man)
        end
 
        # Name, usage and synopsis of the tool.
@@ -323,6 +326,37 @@ class ToolContext
                        exit 0
                end
 
+               if opt_stub_man.value then
+                       print """
+% {{{toolname.to_upper}}}(1)
+
+# NAME
+
+{{{tooldescription.split("\n")[1]}}}
+
+# SYNOPSYS
+
+{{{toolname}}} [*options*]...
+
+# OPTIONS
+"""
+                       for o in option_context.options do
+                               var first = true
+                               for n in o.names do
+                                       if first then first = false else printn ", "
+                                       printn "`{n}`"
+                               end
+                               print ""
+                               print ":   {o.helptext}"
+                               print ""
+                       end
+                       print """
+# SEE ALSO
+
+The Nit language documentation and the source code of its tools and libraries may be downloaded from <http://nitlanguage.org>"""
+                       exit 0
+               end
+
                var errors = option_context.get_errors
                if not errors.is_empty then
                        for e in errors do print "Error: {e}"
@@ -438,7 +472,7 @@ class BashCompletion
                addn "  COMPREPLY=()"
                addn "  cur=\"$\{COMP_WORDS[COMP_CWORD]\}\""
                addn "  prev=\"$\{COMP_WORDS[COMP_CWORD-1]\}\""
-               if option_names != null then
+               if not option_names.is_empty then
                        addn "  opts=\"{option_names.join(" ")}\""
                        addn "  if [[ $\{cur\} == -* ]] ; then"
                        addn "          COMPREPLY=( $(compgen -W \"$\{opts\}\" -- $\{cur\}) )"
index 6a209c3..6c8208a 100644 (file)
@@ -19,9 +19,19 @@ module transform
 import astbuilder
 import astvalidation
 import semantize
+intrude import semantize::scope
 
 redef class ToolContext
        var transform_phase: Phase = new TransformPhase(self, [typing_phase, auto_super_init_phase])
+
+       # --no-shortcut-range
+       var opt_no_shortcut_range: OptionBool = new OptionBool("Always insantiate a range and its iterator on 'for' loops", "--no-shortcut-range")
+
+       redef init
+       do
+               super
+               self.option_context.add_option(self.opt_no_shortcut_range)
+       end
 end
 
 private class TransformPhase
@@ -151,14 +161,113 @@ end
 redef class AWhileExpr
        redef fun accept_transform_visitor(v)
        do
-               # TODO
+               var nloop = v.builder.make_loop
+               var nif = v.builder.make_if(n_expr, null)
+               nloop.add nif
+
+               var nblock = n_block
+               if nblock != null then nif.n_then.add nblock
+
+               var escapemark = self.break_mark.as(not null)
+               var nbreak = v.builder.make_break(escapemark)
+               nif.n_else.add nbreak
+
+               nloop.break_mark = self.break_mark
+               nloop.continue_mark = self.continue_mark
+
+               replace_with(nloop)
        end
 end
 
 redef class AForExpr
        redef fun accept_transform_visitor(v)
        do
-               # TODO
+               var escapemark = self.break_mark
+               assert escapemark != null
+
+               var nblock = v.builder.make_block
+
+               var nexpr = n_expr
+
+               # Shortcut on explicit range
+               # Avoid the instantiation of the range and the iterator
+               if self.variables.length == 1 and nexpr isa ARangeExpr and not v.phase.toolcontext.opt_no_shortcut_range.value then
+                       var variable = variables.first
+                       nblock.add v.builder.make_var_assign(variable, nexpr.n_expr)
+                       var to = nexpr.n_expr2
+                       nblock.add to
+
+                       var nloop = v.builder.make_loop
+                       nloop.break_mark = escapemark
+                       nblock.add nloop
+
+                       var is_ok = v.builder.make_call(v.builder.make_var_read(variable, variable.declared_type.as(not null)), method_lt.as(not null), [to.make_var_read])
+
+                       var nif = v.builder.make_if(is_ok, null)
+                       nloop.add nif
+
+                       var nthen = nif.n_then
+                       var ndo = v.builder.make_do
+                       ndo.break_mark = escapemark.continue_mark
+                       nthen.add ndo
+
+                       ndo.add self.n_block.as(not null)
+
+                       var one = v.builder.make_int(1)
+                       var succ = v.builder.make_call(v.builder.make_var_read(variable, variable.declared_type.as(not null)), method_successor.as(not null), [one])
+                       nthen.add v.builder.make_var_assign(variable, succ)
+
+                       var nbreak = v.builder.make_break(escapemark)
+                       nif.n_else.add nbreak
+
+                       replace_with(nblock)
+                       return
+               end
+
+               nblock.add nexpr
+
+               var iter = v.builder.make_call(nexpr.make_var_read, method_iterator.as(not null), null)
+               nblock.add iter
+
+               var nloop = v.builder.make_loop
+               nloop.break_mark = escapemark
+               nblock.add nloop
+
+               var is_ok = v.builder.make_call(iter.make_var_read, method_is_ok.as(not null), null)
+
+               var nif = v.builder.make_if(is_ok, null)
+               nloop.add nif
+
+               var nthen = nif.n_then
+               var ndo = v.builder.make_do
+               ndo.break_mark = escapemark.continue_mark
+               nthen.add ndo
+
+               if self.variables.length == 1 then
+                       var item = v.builder.make_call(iter.make_var_read, method_item.as(not null), null)
+                       ndo.add v.builder.make_var_assign(variables.first, item)
+               else if self.variables.length == 2 then
+                       var key = v.builder.make_call(iter.make_var_read, method_key.as(not null), null)
+                       ndo.add v.builder.make_var_assign(variables[0], key)
+                       var item = v.builder.make_call(iter.make_var_read, method_item.as(not null), null)
+                       ndo.add v.builder.make_var_assign(variables[1], item)
+               else
+                       abort
+               end
+
+               ndo.add self.n_block.as(not null)
+
+               nthen.add v.builder.make_call(iter.make_var_read, method_next.as(not null), null)
+
+               var nbreak = v.builder.make_break(escapemark)
+               nif.n_else.add nbreak
+
+               var method_finish = self.method_finish
+               if method_finish != null then
+                       nblock.add v.builder.make_call(iter.make_var_read, method_finish, null)
+               end
+
+               replace_with(nblock)
        end
 end
 
index 0779a6a..3807ab7 100644 (file)
@@ -106,7 +106,6 @@ class VirtualMachine super NaiveInterpreter
                # Sub can be discovered inside a Generic type during the subtyping test
                if not sub.mclass.loaded then create_class(sub.mclass)
 
-               if anchor == null then anchor = sub
                if sup isa MGenericType then
                        var sub2 = sub.supertype_to(mainmodule, anchor, sup.mclass)
                        assert sub2.mclass == sup.mclass
diff --git a/tests/base_vararg3.nit b/tests/base_vararg3.nit
new file mode 100644 (file)
index 0000000..6918fef
--- /dev/null
@@ -0,0 +1,45 @@
+# 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 array
+
+class A
+       fun foo(a: Int...) do a.first.output
+end
+
+class B
+       super A
+       redef fun foo(a)
+       do
+               'a'.output
+               super
+               'b'.output
+               super(a...)
+               'c'.output
+               super(4,5,6)
+               'd'.output
+               super([5,6,7]...)
+               #alt3#super(a)
+               #alt4#super(1...)
+       end
+end
+
+var a = new A
+a.foo(1,2,3)
+a.foo([2,3,4]...)
+#alt1#a.foo([1,2,3])
+#alt2#a.foo(1...)
+
+var b = new B
+b.foo(3,4,5)
index 41a85bf..b4226bc 100644 (file)
@@ -1,3 +1,5 @@
+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`.
 true
 true
 true
index a556a0a..46069e8 100644 (file)
@@ -1,3 +1,4 @@
+base_var_type_evolution_null3.nit:52,5--13: Warning: expression is not null, since it is a `Object`.
 1
 1
 5
index a556a0a..a10a5e3 100644 (file)
@@ -1,3 +1,4 @@
+alt/base_var_type_evolution_null3_alt1.nit:52,5--13: Warning: expression is not null, since it is a `Object`.
 1
 1
 5
diff --git a/tests/sav/base_vararg3.res b/tests/sav/base_vararg3.res
new file mode 100644 (file)
index 0000000..7d434e8
--- /dev/null
@@ -0,0 +1,6 @@
+1
+2
+a3
+b3
+c4
+d5
diff --git a/tests/sav/base_vararg3_alt1.res b/tests/sav/base_vararg3_alt1.res
new file mode 100644 (file)
index 0000000..1e24ee6
--- /dev/null
@@ -0,0 +1 @@
+alt/base_vararg3_alt1.nit:41,7--13: Type error: expected Int, got Array[Int]
diff --git a/tests/sav/base_vararg3_alt2.res b/tests/sav/base_vararg3_alt2.res
new file mode 100644 (file)
index 0000000..52bce29
--- /dev/null
@@ -0,0 +1 @@
+alt/base_vararg3_alt2.nit:42,7: Type error: expected Array[Int], got Int
diff --git a/tests/sav/base_vararg3_alt3.res b/tests/sav/base_vararg3_alt3.res
new file mode 100644 (file)
index 0000000..e7e44bc
--- /dev/null
@@ -0,0 +1 @@
+alt/base_vararg3_alt3.nit:33,9: Type error: expected Int, got Array[Int]
diff --git a/tests/sav/base_vararg3_alt4.res b/tests/sav/base_vararg3_alt4.res
new file mode 100644 (file)
index 0000000..caca43b
--- /dev/null
@@ -0,0 +1 @@
+alt/base_vararg3_alt4.nit:34,9: Type error: expected Array[Int], got Int
index 5e997e3..800327a 100644 (file)
@@ -5,7 +5,7 @@ _DUMMY_TOOL()
        COMPREPLY=()
        cur="${COMP_WORDS[COMP_CWORD]}"
        prev="${COMP_WORDS[COMP_CWORD-1]}"
-       opts="--warn --warning --quiet --stop-on-first-error --no-color --log --log-dir --help --version --set-dummy-tool --verbose --bash-completion --option-a --option-b"
+       opts="--warn --warning --quiet --stop-on-first-error --no-color --log --log-dir --help --version --set-dummy-tool --verbose --bash-completion --stub-man --option-a --option-b"
        if [[ ${cur} == -* ]] ; then
                COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
                return 0
index 8757721..91fa2fa 100644 (file)
@@ -12,6 +12,7 @@ Test for ToolContext, try --bash-completion.
   --set-dummy-tool        Set toolname and version to DUMMY. Useful for testing
   -v, --verbose           Verbose
   --bash-completion       Generate bash_completion file for this program
+  --stub-man              Generate a stub manpage in pandoc markdown format
   -a, --option-a          option a, do nothing
   -b, --option-b          option b, do nothing
   -c                      option c, do nothing
index b070f63..8b49b8b 100644 (file)
@@ -128,15 +128,10 @@ if test.address_is_null then env.print_error("object test not initialized")
 
 # Retrieve field value with field ids
 var v_bool = env.get_boolean_field(test, f_bool)
-if v_bool == null then env.print_error("vbool not found")
 var v_char = env.get_char_field(test, f_char)
-if v_char == null then env.print_error("vchar not found")
 var v_i = env.get_int_field(test, f_i)
-if v_i == null then env.print_error("vi not found")
 var v_f = env.get_float_field(test, f_f)
-if v_f == null then env.print_error("vf not found")
 var v_test1 = env.get_object_field(test, f_test)
-if v_test1 == null then env.print_error("vtest1 not found")
 
 # Set the new values for the fields
 env.set_boolean_field(test, f_bool, true)
@@ -151,7 +146,6 @@ v_char = env.call_char_method(test, m_char, null)
 v_i = env.call_int_method(test, m_i, null)
 v_f = env.call_float_method(test, m_f, null)
 var v_test2 = env.call_object_method(test, m_test, null)
-if v_test2 == null then env.print_error("vtest2 not found")
 
 # assert the values of the fields
 print v_bool