From: Jean Privat Date: Wed, 10 Jun 2015 01:46:42 +0000 (-0400) Subject: Merge: Attribute and autoinit annotations X-Git-Tag: v0.7.6~54 X-Git-Url: http://nitlanguage.org?hp=6a7295a0258019dbddb80f059307b83fb263d9a8 Merge: Attribute and autoinit annotations A big set of loosely coupled but related changed on the annotations on attributes and methods. Here is a summary of the changes on the user-side: * No more special case for the kind of classes, so you can use `autoinit` in interfaces. * Explicit annotation `autoinit` is understood on attributes and is the default on value-less concrete attribute. * Abstract attributes are `noautoinit` by default, if `autoinit` is given, it is applied on the setter. This way abstract attributes are basically just a couple of getter-setter. close #1311 This way there is less special cases and behaviors. Still more work is required to finish #1322. Pull-Request: #1433 Reviewed-by: Lucas Bajolet Reviewed-by: Romain Chanoir Reviewed-by: Alexandre Terrasa --- diff --git a/contrib/opportunity/src/templates/meetup.nit b/contrib/opportunity/src/templates/meetup.nit index 6eca566..07a5f66 100644 --- a/contrib/opportunity/src/templates/meetup.nit +++ b/contrib/opportunity/src/templates/meetup.nit @@ -356,7 +356,7 @@ redef class Meetup end t.add """ - Total + Total ({{{participants(db).length}}}) """ for i in answers(db) do t.add """
{{{i.count(db)}}}""" diff --git a/examples/rosettacode/24_game.nit b/examples/rosettacode/24_game.nit new file mode 100644 index 0000000..e6fa12d --- /dev/null +++ b/examples/rosettacode/24_game.nit @@ -0,0 +1,157 @@ +#!/usr/bin/env nit +# +# This file is part of NIT ( http://www.nitlanguage.org ). +# This program is public domain + +# Task: 24 game +# SEE: + +redef class Char + fun is_op: Bool do return "-+/*".has(self) +end + +# Get `numbers` and `operands` from string `operation` collect with `gets` in `main` function +# Fill `numbers` and `operands` array with previous extraction +fun exportation(operation: String, numbers: Array[Int], operands: Array[Char]) do + var previous_char: nullable Char = null + var number: nullable Int = null + var negative = false + + for i in operation.length.times do + var current_char = operation[i] + var current_int = current_char.to_i + + if (previous_char == null or previous_char.is_op) and current_char == '-' then + negative = true + continue + end + + if current_char.is_digit then + if number == null then + number = current_int + else + number = number * 10 + current_int + end + end + + if negative and (current_char.is_op or i == operation.length - 1) then + number = number - number * 2 + negative = false + end + + if (current_char.is_op or i == operation.length - 1) and number != null then + numbers.add(number) + number = null + end + + if not negative and current_char.is_op then + operands.add(current_char) + end + previous_char = current_char + end + # Update `numbers` and `operands` array in main function with pointer +end + +# Create random numbers between 1 to 9 +fun random: Array[Int] do + return [for i in 4.times do 1 + 9.rand] +end + +# Make mathematical operation with `numbers` and `operands` and add the operation result into `random_numbers` +fun calculation(random_numbers, numbers: Array[Int], operands: Array[Char]) do + var number = 0 + var temp_numbers = numbers.clone + + while temp_numbers.length > 1 do + var operand = operands.shift + var a = temp_numbers.shift + var b = temp_numbers.shift + + if operand == '+' then number = a + b + if operand == '-' then number = a - b + if operand == '*' then number = a * b + if operand == '/' then number = a / b + + temp_numbers.unshift(number) + end + if number != 0 then random_numbers.add(number) +end + +# Check if used `numbers` exist in the `random_numbers` created +fun numbers_exists(random_numbers, numbers: Array[Int]): Bool do + for number in numbers do + if not random_numbers.count(number) >= numbers.count(number) then return false + end + return true +end + +# Remove `numbers` when they are used +fun remove_numbers(random_numbers, numbers: Array[Int]) do + for number in numbers do random_numbers.remove(number) +end + +# Check if the mathematical `operation` is valid +fun check(operation: String): Bool do + var previous_char: nullable Char = null + var next_char: nullable Char = null + var next_1_char: nullable Char = null + + for i in operation.length.times do + var current_char = operation[i] + + if i + 1 < operation.length then + next_char = operation[i + 1] + if i + 2 < operation.length then + next_1_char = operation[i + 2] + else + next_1_char = null + end + else + next_char = null + end + + if not current_char.is_op and not current_char.is_digit then return false + if next_char == null and current_char.is_op then return false + + if previous_char == null then + if next_char == null or next_1_char == null then return false + if current_char == '-' and not next_char.is_digit then return false + if current_char != '-' and not current_char.is_digit then return false + else + if next_char != null then + if previous_char.is_digit and current_char.is_op and + not (next_char == '-' and next_1_char != null and + next_1_char.is_digit or next_char.is_digit) then + return false + end + end + end + previous_char = current_char + end + return true +end + +var random_numbers = new Array[Int] +var operation = "" + +random_numbers = random +while not random_numbers.has(24) and random_numbers.length > 1 do + var numbers = new Array[Int] + var operands = new Array[Char] + + print "numbers: " + random_numbers.join(", ") + operation = gets + if check(operation) then + exportation(operation, numbers, operands) + if numbers_exists(random_numbers, numbers) then + calculation(random_numbers, numbers, operands) + remove_numbers(random_numbers, numbers) + else + print "NUMBERS ERROR!" + end + else + print "STRING ERROR!" + end +end + +if random_numbers.has(24) then print "CONGRATULATIONS" else print "YOU LOSE" diff --git a/lib/android/bundle/bundle.nit b/lib/android/bundle/bundle.nit index edb0c88..76babb4 100644 --- a/lib/android/bundle/bundle.nit +++ b/lib/android/bundle/bundle.nit @@ -63,7 +63,7 @@ extern class NativeBundle in "Java" `{ android.os.Bundle `} `} # FIXME: Java's `char` are encoded on 16-bits whereas Nit's are on 8-bits. fun put_char(key: JavaString, value: Char) in "Java" `{ - self.putChar(key, value); + self.putChar(key, (char)value); `} fun put_short(key: JavaString, value: Int) in "Java" `{ self.putShort(key, (short) value); @@ -148,7 +148,7 @@ extern class NativeBundle in "Java" `{ android.os.Bundle `} char[] java_array = new char[(int)Array_of_Char_length(value)]; for(int i=0; i < java_array.length; ++i) - java_array[i] = Array_of_Char__index(value, i); + java_array[i] = (char)Array_of_Char__index(value, i); self.putCharArray(key, java_array); `} @@ -218,10 +218,10 @@ extern class NativeBundle in "Java" `{ android.os.Bundle `} return self.getByte(key, (byte) def_value); `} # FIXME: Java's `char` are encoded on 16-bits whereas Nit's are on 8-bits. - fun get_char(key: JavaString): Char in "Java" `{ return self.getChar(key); `} + fun get_char(key: JavaString): Char in "Java" `{ return (int)self.getChar(key); `} # FIXME: Java's `char` are encoded on 16-bits whereas Nit's are on 8-bits. fun get_char_with_def_value(key: JavaString, def_value: Char): Char in "Java" `{ - return self.getChar(key, def_value); + return (int)self.getChar(key, (char)def_value); `} fun get_short(key: JavaString): Int in "Java" `{ return (short) self.getShort(key); `} fun get_short_with_def_value(key: JavaString, def_value: Int): Int in "Java" `{ @@ -335,7 +335,7 @@ extern class NativeBundle in "Java" `{ android.os.Bundle `} if (java_array == null) return nit_array; for(int i=0; i < java_array.length; ++i) - Array_of_Char_add(nit_array, java_array[i]); + Array_of_Char_add(nit_array, (int)java_array[i]); return nit_array; `} diff --git a/lib/android/intent/intent_api10.nit b/lib/android/intent/intent_api10.nit index 2d536fd..8c6a928 100644 --- a/lib/android/intent/intent_api10.nit +++ b/lib/android/intent/intent_api10.nit @@ -81,7 +81,7 @@ extern class NativeIntent in "Java" `{ android.content.Intent `} `} # FIXME: Java's `char` are encoded on 16-bits whereas Nit's are on 8-bits. fun char_extra(name: JavaString, def_value: Char): Char in "Java" `{ - return self.getCharExtra(name, def_value); + return (int)self.getCharExtra(name, (char)def_value); `} fun char_sequence_array_extra(name: JavaString): Array[String] import StringCopyArray, StringCopyArray.add, StringCopyArray.collection in "Java" `{ @@ -244,7 +244,7 @@ extern class NativeIntent in "Java" `{ android.content.Intent `} char[] java_array = new char[(int)Array_of_Char_length(value)]; for (int i=0; i < java_array.length; ++i) - java_array[i] = Array_of_Char__index(value, i); + java_array[i] = (char)Array_of_Char__index(value, i); return self.putExtra(name, java_array); `} diff --git a/lib/binary/binary.nit b/lib/binary/binary.nit index 59ec88d..f4be1eb 100644 --- a/lib/binary/binary.nit +++ b/lib/binary/binary.nit @@ -45,10 +45,13 @@ in "C" `{ #include // Android compatibility + #ifndef be32toh + #define be32toh(val) betoh32(val) + #define le32toh(val) letoh32(val) + #endif + #ifndef be64toh #define be64toh(val) betoh64(val) - #endif - #ifndef le64toh #define le64toh(val) letoh64(val) #endif `} @@ -148,11 +151,15 @@ redef abstract class Reader super BinaryStream # Read a single byte and return `true` if its value is different than 0 + # + # Returns `false` when an error is pending (`last_error != null`). fun read_bool: Bool do return read_byte != 0 # Get an `Array` of 8 `Bool` by reading a single byte # # To be used with `BinaryWriter::write_bits`. + # + # Returns an array of `false` when an error is pending (`last_error != null`). fun read_bits: Array[Bool] do var int = read_byte @@ -163,12 +170,14 @@ redef abstract class Reader # Read a null terminated string # # To be used with `Writer::write_string`. + # + # Returns a truncated string when an error is pending (`last_error != null`). fun read_string: String do var buf = new FlatBuffer loop var byte = read_byte - if byte == 0x00 then return buf.to_s + if byte == null or byte == 0x00 then return buf.to_s buf.chars.add byte.ascii end end @@ -176,6 +185,8 @@ redef abstract class Reader # Read the length as a 64 bits integer, then the content of the block # # To be used with `Writer::write_block`. + # + # Returns a truncated string when an error is pending (`last_error != null`). fun read_block: String do var length = read_int64 @@ -187,6 +198,8 @@ redef abstract class Reader # # Using this format may result in a loss of precision as it uses less bits # than Nit `Float`. + # + # Returns `0.0` when an error is pending (`last_error != null`). fun read_float: Float do if last_error != null then return 0.0 @@ -223,6 +236,8 @@ redef abstract class Reader `} # Read a floating point on 64 bits and return it as a `Float` + # + # Returns `0.0` when an error is pending (`last_error != null`). fun read_double: Float do if last_error != null then return 0.0 @@ -271,6 +286,8 @@ redef abstract class Reader # # Using this format may result in a loss of precision as the length of a # Nit `Int` may be less than 64 bits on some platforms. + # + # Returns `0` when an error is pending (`last_error != null`). fun read_int64: Int do if last_error != null then return 0 diff --git a/lib/cpp.nit b/lib/cpp.nit index a2896d3..c64ae33 100644 --- a/lib/cpp.nit +++ b/lib/cpp.nit @@ -31,6 +31,6 @@ end redef class NativeString # Get `self` as a `CppString` fun to_cpp_string(length: Int): CppString in "C++" `{ - return new std::string(self, length); + return new std::string(reinterpret_cast(self), length); `} end diff --git a/lib/date.nit b/lib/date.nit new file mode 100755 index 0000000..19e8ceb --- /dev/null +++ b/lib/date.nit @@ -0,0 +1,180 @@ +# 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. + +# Services to manipulate `Date`, `Time` and `DateTime` +# +# The services are split in 2 classes: +# +# * `Date` handles the year, month and day parts of the date. +# * `Time` handles the time in hours, minutes and seconds. +# +# These are united in `DateTime` for a precise time in a precise day. +# +# ~~~ +# var now = new Time.now +# var midnight = new Time(0, 0, 0) +# assert now > midnight +# +# var nine_thirty = new Time(9, 30, 0) +# var eleven_twenty = new Time(11, 20, 0) +# assert eleven_twenty > nine_thirty +# +# var pi_day = new Date(2015, 03, 14) +# var may_the_fourth = new Date(2015, 5, 4) +# assert pi_day < may_the_fourth +# +# var now_t = new DateTime.now +# var epoch = new DateTime(1970, 1, 1, 0, 0, 0) +# assert now_t > epoch +# ~~~ +# +module date + +# A time of the day, composed of an `hour`, a `minute` and a `second` count +class Time + super Comparable + redef type OTHER: Time + + # The hour part of this time, between 0 and 23 + var hour: Int + + # The minute within the hour, between 0 and 59 + var minute: Int + + # The second within the minute, between 0 and 59 + var second: Int + + # Get the current time of the day + init now do + var tm = new Tm.localtime + hour = tm.hour + minute = tm.min + second = tm.sec + end + + # Get the difference between two times in second + fun diff_time(other: Time): Int do + return (hour * 3600 + minute * 60 + second) - + (other.hour * 3600 + other.minute * 60 + other.second) + end + + redef fun ==(d) do return d isa Time and time_eq(d) + + redef fun <(d) do return self.diff_time(d) < 0 + + redef fun hash do return hour * 1024 + minute * 64 + second + + private fun time_eq(other: Time): Bool + do + return hour * 3600 + minute * 60 + second == + other.hour * 3600 + other.minute * 60 + other.second + end +end + +# A date, composed by a `year`, a `month` and a `day` +class Date + super Comparable + redef type OTHER: Date + + # Year, ex: 1989 + var year: Int + + # Month as an integer, `1` for January, `2` for February, etc. + var month: Int + + # Day of the month + var day: Int + + # UTC time zone + # + # FIXME this value is not yet applied + var time_zone = "Z" + + # The date of this day + init today do + var tm = new Tm.localtime + year = 1900 + tm.year + month = tm.mon + 1 + day = tm.mday + end + + # `self` formatted according to ISO 8601 + redef fun to_s do return "{year}-{month}-{day}" + + # Difference in days between `self` and `other` + fun diff_days(other: Date): Int + do + var y_out = year - other.year + y_out = y_out * 365 + var m_out = month - other.month + m_out = m_out * 30 # FIXME + return day - other.day + m_out + y_out + end + + # Difference in months between `self` and `other` + fun diff_months(other: Date): Int + do + var y_out = year - other.year + y_out = y_out * 12 + return month - other.month + y_out + end + + # Difference in years between `self` and `other` + fun diff_years(other: Date): Int do return year - other.year + + redef fun ==(d) do return d isa Date and self.diff_days(d) == 0 + + redef fun hash do return year + month * 1024 + day * 2048 + + redef fun <(d) do return self.diff_days(d) < 0 + + # Is `self` is between the years of `a` and `b`? + private fun is_between_years(a, b: Date): Bool + do + return (a.year > year and b.year < year) or (b.year > year and a.year < year) or (a.year == year or b.year == year) + end + + # Is `self` is between the months of `a` and `b`? + private fun is_between_months(a, b: Date) : Bool + do + if not self.is_between_years(a,b) then return false + return (a.month > month and b.month < month) or (b.month > month and a.month < month) or (a.month == month or b.month == month) + end + + # Is `self` between `a` and `b`? + redef fun is_between(a, b) + do + if not self.is_between_months(a, b) then return false + return (a.day > day and b.day < day) or (b.day > day and a.day < day) or (a.day == day or b.day == day) + end +end + +# A `Time` in a `Date` +class DateTime + super Date + super Time + redef type OTHER: DateTime + autoinit year, month, day, hour, minute, second + + # Get the current `DateTime` + init now + do + super + today + end + + redef fun ==(other) do return other isa DateTime and diff_days(other) == 0 and time_eq(other) + + redef fun to_s do return "{super} {hour}:{minute}:{second}{time_zone}" +end diff --git a/lib/mnit_android/android_assets.nit b/lib/mnit_android/android_assets.nit index 51e1ec8..6531035 100644 --- a/lib/mnit_android/android_assets.nit +++ b/lib/mnit_android/android_assets.nit @@ -231,7 +231,7 @@ redef universal Int # The first power of `exp` greater or equal to `self` private fun next_pow(exp: Int): Int do - var p = 0 + var p = 1 while p < self do p = p*exp return p end diff --git a/lib/socket/socket.nit b/lib/socket/socket.nit index 4885805..a40cc5d 100644 --- a/lib/socket/socket.nit +++ b/lib/socket/socket.nit @@ -71,14 +71,29 @@ class TCPStream closed = true return end - var hostname = socket.gethostbyname(host) - addrin = new NativeSocketAddrIn.with_hostent(hostname, port) + var hostname = sys.gethostbyname(host.to_cstring) + if hostname.address_is_null then + # Error in name lookup + var err = sys.h_errno + last_error = new IOError(err.to_s) + + closed = true + end_reached = true + + return + end + + addrin = new NativeSocketAddrIn.with_hostent(hostname, port) address = addrin.address init(addrin.port, hostname.h_name) closed = not internal_connect end_reached = closed + if closed then + # Connection failed + last_error = new IOError(errno.strerror) + end end # Creates a client socket, this is meant to be used by accept only diff --git a/lib/socket/socket_c.nit b/lib/socket/socket_c.nit index d9056d6..94eecd7 100644 --- a/lib/socket/socket_c.nit +++ b/lib/socket/socket_c.nit @@ -121,8 +121,6 @@ extern class NativeSocket `{ int* `} fun descriptor: Int `{ return *self; `} - fun gethostbyname(n: String): NativeSocketHostent import String.to_cstring `{ return gethostbyname(String_to_cstring(n)); `} - fun connect(addrIn: NativeSocketAddrIn): Int `{ return connect(*self, (struct sockaddr*)addrIn, sizeof(*addrIn)); `} @@ -482,3 +480,52 @@ extern class NativeSocketPollValues `{ int `} return self | other; `} end + +redef class Sys + # Get network host entry + fun gethostbyname(name: NativeString): NativeSocketHostent `{ + return gethostbyname(name); + `} + + # Last error raised by `gethostbyname` + fun h_errno: HErrno `{ return h_errno; `} +end + +# Error code of `Sys::h_errno` +extern class HErrno `{ int `} + # The specified host is unknown + fun host_not_found: Bool `{ return self == HOST_NOT_FOUND; `} + + # The requested name is valid but does not have an IP address + # + # Same as `no_data`. + fun no_address: Bool `{ return self == NO_ADDRESS; `} + + # The requested name is valid byt does not have an IP address + # + # Same as `no_address`. + fun no_data: Bool `{ return self == NO_DATA; `} + + # A nonrecoverable name server error occurred + fun no_recovery: Bool `{ return self == NO_RECOVERY; `} + + # A temporary error occurred on an authoritative name server, try again later + fun try_again: Bool `{ return self == TRY_AGAIN; `} + + redef fun to_s + do + if host_not_found then + return "The specified host is unknown" + else if no_address then + return "The requested name is valid but does not have an IP address" + else if no_recovery then + return "A nonrecoverable name server error occurred" + else if try_again then + return "A temporary error occurred on an authoritative name server, try again later" + else + # This may happen if another call was made to `gethostbyname` + # before we fetch the error code. + return "Unknown error on `gethostbyname`" + end + end +end diff --git a/lib/standard/file.nit b/lib/standard/file.nit index 46c52ec..9687b0c 100644 --- a/lib/standard/file.nit +++ b/lib/standard/file.nit @@ -767,11 +767,12 @@ redef class String return res end - # Simplify a file path by remove useless ".", removing "//", and resolving ".." + # Simplify a file path by remove useless `.`, removing `//`, and resolving `..` # - # * ".." are not resolved if they start the path - # * starting "/" is not removed - # * trailing "/" is removed + # * `..` are not resolved if they start the path + # * starting `.` is simplified unless the path is empty + # * starting `/` is not removed + # * trailing `/` is removed # # Note that the method only work on the string: # @@ -785,17 +786,29 @@ redef class String # assert "dir/..".simplify_path == "." # assert "//absolute//path/".simplify_path == "/absolute/path" # assert "//absolute//../".simplify_path == "/" + # assert "/".simplify_path == "/" + # assert "../".simplify_path == ".." + # assert "./".simplify_path == "." + # assert "././././././".simplify_path == "." + # assert "./../dir".simplify_path == "../dir" + # assert "./dir".simplify_path == "dir" # ~~~ fun simplify_path: String do var a = self.split_with("/") var a2 = new Array[String] for x in a do - if x == "." then continue - if x == "" and not a2.is_empty then continue + if x == "." and not a2.is_empty then continue # skip `././` + if x == "" and not a2.is_empty then continue # skip `//` if x == ".." and not a2.is_empty and a2.last != ".." then - a2.pop - continue + if a2.last == "." then # do not skip `./../` + a2.pop # reduce `./../` in `../` + else # reduce `dir/../` in `/` + a2.pop + continue + end + else if not a2.is_empty and a2.last == "." then + a2.pop # reduce `./dir` in `dir` end a2.push(x) end diff --git a/share/man/nitc.md b/share/man/nitc.md index 91e8d8c..9e0fbf5 100644 --- a/share/man/nitc.md +++ b/share/man/nitc.md @@ -404,8 +404,18 @@ They are useless for a normal user. `--no-main` : Do not generate main entry point. -`--stacktrace` -: Control the generation of stack traces. +`--no-stacktrace` +: The compiled program will not display stack traces on runtime errors. + + Because stack traces rely on libunwind, this option might be useful in order to generate more portable binaries + since libunwind might be non available on the runtime system (or available with an ABI incompatible version). + + The generated C is API-portable and can be reused, distributed and compiled on any supported system. + If the option `--no-stacktrace` is not used but the development files of the library `libunwind` are not available, then a warning will be displayed + and stack trace will be disabled. + + Note that the `--no-stacktrace` option (or this absence) can be toggled manually in the generated Makefile (search `NO_STACKTRACE` in the Makefile). + Moreover, the environment variable `NIT_NO_STACK` (see bellow) can also be used at runtime to disable stack traces. `--max-c-lines` : Maximum number of lines in generated C files. Use 0 for unlimited. @@ -481,6 +491,20 @@ This option is used to test the robustness of the tools by allowing phases to pr * large: disable the GC and just allocate a large memory area to use for all instantiation. * help: show the list of available options. +`NIT_NO_STACK` +: Runtime control of stack traces. + + By default, stack traces are printed when a runtime errors occurs during the execution of a compiled program. + When setting this environment variable to a non empty value, such stack traces are disabled. + + The environment variable is used when programs are executed, not when they are compiled. + Thus, you do not need to recompile programs in order to disable generated stack traces. + + Note that stack traces require that, during the compilation, development files of the library `libunwind` are available. + If they are not available, then programs are compiled without any stack trace support. + + To completely disable stack traces, see the option `--no-stacktrace`. + # SEE ALSO The Nit language documentation and the source code of its tools and libraries may be downloaded from diff --git a/src/c_tools.nit b/src/c_tools.nit index df2ddd8..0b80817 100644 --- a/src/c_tools.nit +++ b/src/c_tools.nit @@ -47,7 +47,7 @@ class CCompilationUnit # files to compile TODO check is appropriate var files = new Array[String] - # Add `c_function` as a `static` function local to this unit + # Add a `static` `c_function` to be strictly local to this unit fun add_local_function(c_function: CFunction) do body_decl.add "static {c_function.signature};\n" @@ -55,10 +55,10 @@ class CCompilationUnit body_impl.add c_function.to_writer end - # Add `c_function` as a public function to this unit + # Add a public `c_function` accessible from outside this compilation unit fun add_exported_function(c_function: CFunction) do - header_decl.add "{c_function.signature};\n" + body_decl.add "{c_function.signature};\n" body_impl.add "\n" body_impl.add c_function.to_writer end diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index 61b59a9..c48aab9 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -63,8 +63,8 @@ redef class ToolContext 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 = new OptionBool("Enable static and dynamic count of isset checks before attributes access", "--isset-checks-metrics") - # --stacktrace - var opt_stacktrace = new OptionString("Control the generation of stack traces", "--stacktrace") + # --no-stacktrace + var opt_no_stacktrace = new OptionBool("Disable the generation of stack traces", "--no-stacktrace") # --no-gcc-directives var opt_no_gcc_directive = new OptionArray("Disable a advanced gcc directives for optimization", "--no-gcc-directive") # --release @@ -76,7 +76,7 @@ redef class ToolContext 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) + self.option_context.add_option(self.opt_no_stacktrace) self.option_context.add_option(self.opt_no_gcc_directive) self.option_context.add_option(self.opt_release) self.option_context.add_option(self.opt_max_c_lines, self.opt_group_c_files) @@ -88,17 +88,6 @@ redef class ToolContext do super - var st = opt_stacktrace.value - if st == "none" or st == "libunwind" or st == "nitstack" then - # Fine, do nothing - else if st == "auto" or st == null then - # Default is nitstack - opt_stacktrace.value = "nitstack" - else - print "Option Error: unknown value `{st}` for --stacktrace. Use `none`, `libunwind`, `nitstack` or `auto`." - exit(1) - end - if opt_output.value != null and opt_dir.value != null then print "Option Error: cannot use both --dir and --output" exit(1) @@ -212,7 +201,7 @@ class MakefileToolchain fun write_files(compile_dir: String, cfiles: Array[String]) do var platform = compiler.target_platform - if self.toolcontext.opt_stacktrace.value == "nitstack" and platform.supports_libunwind then compiler.build_c_to_nit_bindings + if platform.supports_libunwind then compiler.build_c_to_nit_bindings var cc_opt_with_libgc = "-DWITH_LIBGC" if not platform.supports_libgc then cc_opt_with_libgc = "" @@ -355,25 +344,50 @@ class MakefileToolchain makefile.write("CC = ccache cc\nCXX = ccache c++\nCFLAGS = -g -O2 -Wno-unused-value -Wno-switch -Wno-attributes\nCINCL =\nLDFLAGS ?= \nLDLIBS ?= -lm {linker_options.join(" ")}\n\n") - var ost = toolcontext.opt_stacktrace.value - if (ost == "libunwind" or ost == "nitstack") and platform.supports_libunwind then makefile.write("NEED_LIBUNWIND := YesPlease\n") + makefile.write "\n# SPECIAL CONFIGURATION FLAGS\n" + if platform.supports_libunwind then + if toolcontext.opt_no_stacktrace.value then + makefile.write "NO_STACKTRACE=True" + else + makefile.write "NO_STACKTRACE= # Set to `True` to enable" + end + end # Dynamic adaptations # While `platform` enable complex toolchains, they are statically applied # For a dynamic adaptsation of the compilation, the generated Makefile should check and adapt things itself + makefile.write "\n\n" # Check and adapt the targeted system makefile.write("uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')\n") - makefile.write("ifeq ($(uname_S),Darwin)\n") - # remove -lunwind since it is already included on macosx - makefile.write("\tNEED_LIBUNWIND :=\n") - makefile.write("endif\n\n") # Check and adapt for the compiler used # clang need an additionnal `-Qunused-arguments` makefile.write("clang_check := $(shell sh -c '$(CC) -v 2>&1 | grep -q clang; echo $$?')\nifeq ($(clang_check), 0)\n\tCFLAGS += -Qunused-arguments\nendif\n") - makefile.write("ifdef NEED_LIBUNWIND\n\tLDLIBS += -lunwind\nendif\n") + if platform.supports_libunwind then + makefile.write """ +ifneq ($(NO_STACKTRACE), True) + # Check and include lib-unwind in a portable way + ifneq ($(uname_S),Darwin) + # already included on macosx, but need to get the correct flags in other supported platforms. + ifeq ($(shell pkg-config --exists 'libunwind'; echo $$?), 0) + LDLIBS += `pkg-config --libs libunwind` + CFLAGS += `pkg-config --cflags libunwind` + else + $(warning "[_] stack-traces disabled. Please install libunwind-dev.") + CFLAGS += -D NO_STACKTRACE + endif + endif +else + # Stacktraces disabled + CFLAGS += -D NO_STACKTRACE +endif + +""" + else + makefile.write("CFLAGS += -D NO_STACKTRACE\n\n") + end makefile.write("all: {outpath}\n") if outpath != real_outpath then @@ -623,6 +637,7 @@ abstract class AbstractCompiler self.header.add_decl("#include ") self.header.add_decl("#include \n") self.header.add_decl("#include \n") + self.header.add_decl("#include \n") self.header.add_decl("#include \"gc_chooser.h\"") self.header.add_decl("#ifdef ANDROID") self.header.add_decl(" #include ") @@ -730,19 +745,16 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref ); do var v = self.new_visitor v.add_decl("#include ") - var ost = modelbuilder.toolcontext.opt_stacktrace.value var platform = target_platform - if not platform.supports_libunwind then ost = "none" - var no_main = platform.no_main or modelbuilder.toolcontext.opt_no_main.value - if ost == "nitstack" or ost == "libunwind" then + if platform.supports_libunwind then + v.add_decl("#ifndef NO_STACKTRACE") v.add_decl("#define UNW_LOCAL_ONLY") v.add_decl("#include ") - if ost == "nitstack" then - v.add_decl("#include \"c_functions_hash.h\"") - end + v.add_decl("#include \"c_functions_hash.h\"") + v.add_decl("#endif") end v.add_decl("int glob_argc;") v.add_decl("char **glob_argv;") @@ -776,7 +788,8 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref ); end v.add_decl("static void show_backtrace(void) \{") - if ost == "nitstack" or ost == "libunwind" then + if platform.supports_libunwind then + v.add_decl("#ifndef NO_STACKTRACE") v.add_decl("char* opt = getenv(\"NIT_NO_STACK\");") v.add_decl("unw_cursor_t cursor;") v.add_decl("if(opt==NULL)\{") @@ -790,20 +803,17 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref ); v.add_decl("PRINT_ERROR(\"-------------------------------------------------\\n\");") v.add_decl("while (unw_step(&cursor) > 0) \{") v.add_decl(" unw_get_proc_name(&cursor, procname, 100, &ip);") - if ost == "nitstack" then v.add_decl(" const char* recv = get_nit_name(procname, strlen(procname));") v.add_decl(" if (recv != NULL)\{") v.add_decl(" PRINT_ERROR(\"` %s\\n\", recv);") v.add_decl(" \}else\{") v.add_decl(" PRINT_ERROR(\"` %s\\n\", procname);") v.add_decl(" \}") - else - v.add_decl(" PRINT_ERROR(\"` %s \\n\",procname);") - end v.add_decl("\}") v.add_decl("PRINT_ERROR(\"-------------------------------------------------\\n\");") v.add_decl("free(procname);") v.add_decl("\}") + v.add_decl("#endif /* NO_STACKTRACE */") end v.add_decl("\}") @@ -1662,8 +1672,9 @@ abstract class AbstractCompilerVisitor if nexpr == null then return if nexpr.mtype == null and not nexpr.is_typed then # Untyped expression. - # Might mean dead code - # So just return + # Might mean dead code or invalid code + # so aborts + add_abort("FATAL: bad statement executed.") return end @@ -1687,8 +1698,10 @@ abstract class AbstractCompilerVisitor do if nexpr.mtype == null then # Untyped expression. - # Might mean dead code - # so return a placebo result + # Might mean dead code or invalid code. + # so aborts + add_abort("FATAL: bad expression executed.") + # and return a placebo result to please the C compiler if mtype == null then mtype = compiler.mainmodule.object_type return new_var(mtype) end @@ -1860,13 +1873,13 @@ redef class MClassType else if mclass.name == "Bool" then return "short int" else if mclass.name == "Char" then - return "char" + return "uint32_t" else if mclass.name == "Float" then return "double" else if mclass.name == "Byte" then return "unsigned char" else if mclass.name == "NativeString" then - return "char*" + return "unsigned char*" else if mclass.name == "NativeArray" then return "val*" else @@ -2131,12 +2144,12 @@ redef class AMethPropdef v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null))) return true else if pname == "ascii" then - v.ret(v.new_expr("{arguments[0]}", ret.as(not null))) + v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null))) return true end else if cname == "Char" then if pname == "output" then - v.add("printf(\"%c\", {arguments.first});") + v.add("printf(\"%c\", ((unsigned char){arguments.first}));") return true else if pname == "object_id" then v.ret(v.new_expr("(long){arguments.first}", ret.as(not null))) @@ -2170,7 +2183,7 @@ redef class AMethPropdef v.ret(v.new_expr("{arguments[0]}-'0'", ret.as(not null))) return true else if pname == "ascii" then - v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null))) + v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null))) return true end else if cname == "Byte" then @@ -2310,10 +2323,10 @@ redef class AMethPropdef end else if cname == "NativeString" then if pname == "[]" then - v.ret(v.new_expr("{arguments[0]}[{arguments[1]}]", ret.as(not null))) + v.ret(v.new_expr("(uint32_t){arguments[0]}[{arguments[1]}]", ret.as(not null))) return true else if pname == "[]=" then - v.add("{arguments[0]}[{arguments[1]}]={arguments[2]};") + v.add("{arguments[0]}[{arguments[1]}]=(unsigned char){arguments[2]};") return true else if pname == "copy_to" then v.add("memmove({arguments[1]}+{arguments[4]},{arguments[0]}+{arguments[3]},{arguments[2]});") @@ -2325,7 +2338,7 @@ redef class AMethPropdef v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null))) return true else if pname == "new" then - v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null))) + v.ret(v.new_expr("(unsigned char*)nit_alloc({arguments[1]})", ret.as(not null))) return true end else if cname == "NativeArray" then @@ -2339,7 +2352,7 @@ redef class AMethPropdef v.ret(v.new_expr("glob_sys", ret.as(not null))) return true else if pname == "calloc_string" then - v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null))) + v.ret(v.new_expr("(unsigned char*)nit_alloc({arguments[1]})", ret.as(not null))) return true else if pname == "calloc_array" then v.calloc_array(ret.as(not null), arguments) diff --git a/src/compiler/compiler_ffi/light.nit b/src/compiler/compiler_ffi/light.nit index 01579b0..1f59771 100644 --- a/src/compiler/compiler_ffi/light.nit +++ b/src/compiler/compiler_ffi/light.nit @@ -43,6 +43,7 @@ redef class MModule ensure_compile_nitni_base(v) nitni_ccu.header_c_types.add("#include \"{c_name}._ffi.h\"\n") + nitni_ccu.header_c_types.add("#include \n") nitni_ccu.header_c_types.add """ extern void nitni_global_ref_incr(void*); extern void nitni_global_ref_decr(void*); diff --git a/src/compiler/separate_compiler.nit b/src/compiler/separate_compiler.nit index 31a4f20..e07f125 100644 --- a/src/compiler/separate_compiler.nit +++ b/src/compiler/separate_compiler.nit @@ -625,6 +625,7 @@ class SeparateCompiler for cd in mmodule.mclassdefs do for pd in cd.mpropdefs do if not pd isa MMethodDef then continue + if pd.msignature == null then continue # Skip broken method var rta = runtime_type_analysis if modelbuilder.toolcontext.opt_skip_dead_methods.value and rta != null and not rta.live_methoddefs.has(pd) then continue #print "compile {pd} @ {cd} @ {mmodule}" @@ -1193,7 +1194,7 @@ class SeparateCompilerVisitor if mtype.name == "Int" then return self.new_expr("(long)({value})>>2", mtype) else if mtype.name == "Char" then - return self.new_expr("(char)((long)({value})>>2)", mtype) + return self.new_expr("(uint32_t)((long)({value})>>2)", mtype) else if mtype.name == "Bool" then return self.new_expr("(short int)((long)({value})>>2)", mtype) else diff --git a/src/ffi/java.nit b/src/ffi/java.nit index 3f2a21e..c26fea2 100644 --- a/src/ffi/java.nit +++ b/src/ffi/java.nit @@ -243,7 +243,6 @@ redef class MModule private fun insert_compiler_options do cflags.add_one("", "-I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux/") - ldflags.add_one("", "-L $(JNI_LIB_PATH) -ljvm") end # Name of the generated Java class where to store all implementation methods of this module @@ -480,7 +479,7 @@ redef class MClassType if ftype isa ForeignJavaType then return ftype.java_type. replace('/', ".").replace('$', ".").replace(' ', "").replace('\n',"") if mclass.name == "Bool" then return "boolean" - if mclass.name == "Char" then return "char" + if mclass.name == "Char" then return "int" if mclass.name == "Int" then return "long" if mclass.name == "Float" then return "double" if mclass.name == "Byte" then return "byte" @@ -492,7 +491,7 @@ redef class MClassType var ftype = mclass.ftype if ftype isa ForeignJavaType then return "jobject" if mclass.name == "Bool" then return "jboolean" - if mclass.name == "Char" then return "jchar" + if mclass.name == "Char" then return "jint" if mclass.name == "Int" then return "jlong" if mclass.name == "Float" then return "jdouble" if mclass.name == "Byte" then return "jbyte" @@ -552,7 +551,7 @@ redef class MClassType return "L{jni_type};" end if mclass.name == "Bool" then return "Z" - if mclass.name == "Char" then return "C" + if mclass.name == "Char" then return "I" if mclass.name == "Int" then return "J" if mclass.name == "Float" then return "D" if mclass.name == "Byte" then return "B" @@ -565,7 +564,7 @@ redef class MClassType if ftype isa ForeignJavaType then return "Object" if mclass.name == "Bool" then return "Boolean" - if mclass.name == "Char" then return "Char" + if mclass.name == "Char" then return "Int" if mclass.name == "Int" then return "Long" if mclass.name == "Float" then return "Double" if mclass.name == "Byte" then return "Byte" diff --git a/src/ffi/light_ffi_base.nit b/src/ffi/light_ffi_base.nit index 6791e5c..3385301 100644 --- a/src/ffi/light_ffi_base.nit +++ b/src/ffi/light_ffi_base.nit @@ -161,10 +161,10 @@ redef class CCompilationUnit var h_file = "{base_name}.h" var guard = "{mmodule.c_name.to_upper}_NIT_H" - write_header_to_file(mmodule, "{compdir}/{h_file}", new Array[String], guard) + write_header_to_file(mmodule, "{compdir}/{h_file}", [""], guard) var c_file = "{base_name}.c" - write_body_to_file(mmodule, "{compdir}/{c_file}", ["", "", "\"{h_file}\""]) + write_body_to_file(mmodule, "{compdir}/{c_file}", ["", "", "", "\"{h_file}\""]) files.add( "{compdir}/{c_file}" ) end diff --git a/src/frontend/simple_misc_analysis.nit b/src/frontend/simple_misc_analysis.nit index 885d794..f61b10a 100644 --- a/src/frontend/simple_misc_analysis.nit +++ b/src/frontend/simple_misc_analysis.nit @@ -65,6 +65,14 @@ private class SimpleMiscVisitor do toolcontext.warning(node.hot_location, tag, msg) end + + # Issue a warning if `sub` is a standalone `do` block. + fun check_do_expr(sub: nullable AExpr) + do + if sub isa ADoExpr then + warning(sub, "useless-do", "Warning: superfluous `do` block.") + end + end end @@ -143,6 +151,21 @@ redef class AWhileExpr else n_expr.warn_parentheses(v) end + v.check_do_expr(n_block) + end +end + +redef class ADoExpr + redef fun after_simple_misc(v) + do + v.check_do_expr(n_block) + end +end + +redef class ALoopExpr + redef fun after_simple_misc(v) + do + v.check_do_expr(n_block) end end @@ -150,6 +173,14 @@ redef class AForExpr redef fun after_simple_misc(v) do n_expr.warn_parentheses(v) + v.check_do_expr(n_block) + end +end + +redef class AWithExpr + redef fun after_simple_misc(v) + do + v.check_do_expr(n_block) end end diff --git a/src/loader.nit b/src/loader.nit index 0e6878b..d78ac71 100644 --- a/src/loader.nit +++ b/src/loader.nit @@ -50,7 +50,9 @@ redef class ModelBuilder end var nit_dir = toolcontext.nit_dir - var libname = "{nit_dir}/lib" + var libname = nit_dir/"lib" + if libname.file_exists then paths.add(libname) + libname = nit_dir/"contrib" if libname.file_exists then paths.add(libname) end @@ -222,6 +224,14 @@ redef class ModelBuilder return res end + # Fourth, try if the requested module is itself a group with a src + try_file = dirname + "/" + name + "/src/" + name + ".nit" + if try_file.file_exists then + var res = self.identify_file(try_file.simplify_path) + assert res != null + return res + end + c = c.parent end @@ -301,6 +311,19 @@ redef class ModelBuilder end end end + try_file = (dirname + "/" + name + "/src/" + name + ".nit").simplify_path + if try_file.file_exists then + if candidate == null then + candidate = try_file + else if candidate != try_file then + # try to disambiguate conflicting modules + var abs_candidate = module_absolute_path(candidate) + var abs_try_file = module_absolute_path(try_file) + if abs_candidate != abs_try_file then + toolcontext.error(location, "Error: conflicting module file for `{name}`: `{candidate}` `{try_file}`") + end + end + end end if candidate == null then return null return identify_file(candidate) diff --git a/src/mkcsrc b/src/mkcsrc index e1f43cc..de71f37 100755 --- a/src/mkcsrc +++ b/src/mkcsrc @@ -3,7 +3,7 @@ # Regeneration of c_src from the current nitc rm -r ../c_src -./nitc nith.nit --stacktrace none --semi-global --compile-dir ../c_src --output ../c_src/nitg --no-cc +./nitc nith.nit --semi-global --compile-dir ../c_src --output ../c_src/nitg --no-cc # Remove old compilation flags sed -i -e 's/OLDNITCOPT=.*/OLDNITCOPT=/' Makefile diff --git a/src/nitni/nitni_base.nit b/src/nitni/nitni_base.nit index 7cf6bbc..f5cccc0 100644 --- a/src/nitni/nitni_base.nit +++ b/src/nitni/nitni_base.nit @@ -71,14 +71,15 @@ redef class MType # Representation of this type in C for the internal of the system # Hides extern types. - fun cname_blind: String is abstract + fun cname_blind: String do return "struct nitni_instance *" # Representation of this type in mangled C # Object -> Object # Pointer -> Pointer fun mangled_cname: String is abstract - # Does this types has a primitive reprensentation + # Does this type have a primitive representation? + # # type Object is_primitive? false # type Pointer is_primitive? true fun is_cprimitive: Bool is abstract @@ -89,11 +90,11 @@ redef class MClassType do var name = mclass.name if name == "Bool" then return "int" - if name == "Char" then return "char" + if name == "Char" then return "uint32_t" if name == "Float" then return "double" if name == "Int" then return "long" if name == "Byte" then return "unsigned char" - if name == "NativeString" then return "char*" + if name == "NativeString" then return "unsigned char*" if mclass.kind == extern_kind then var ctype = mclass.ctype assert ctype != null @@ -105,13 +106,13 @@ redef class MClassType redef fun cname_blind do var name = mclass.name if name == "Bool" then return "int" - if name == "Char" then return "char" + if name == "Char" then return "uint32_t" if name == "Float" then return "double" if name == "Int" then return "long" if name == "Byte" then return "unsigned char" - if name == "NativeString" then return "char*" + if name == "NativeString" then return "unsigned char*" if mclass.kind == extern_kind then return "void*" - return "struct nitni_instance *" + return super end # Name of this type in C for normal classes (not extern and not primitive) @@ -120,18 +121,17 @@ redef class MClassType redef fun mangled_cname do return mclass.name redef fun is_cprimitive do return mclass.kind == extern_kind or - (once ["Bool", "Char", "Float", "Int", "NativeString"]).has(mclass.name) + (once ["Bool", "Char", "Float", "Int", "NativeString", "Byte"]).has(mclass.name) end redef class MNullableType redef fun cname do return mangled_cname - redef fun cname_blind do return "struct nitni_instance *" redef fun mangled_cname do return "nullable_{mtype.mangled_cname}" redef fun is_cprimitive do return false end redef class MVirtualType - redef fun mangled_cname: String do return to_s + redef fun mangled_cname do return to_s end redef class MGenericType diff --git a/src/parser/nit.sablecc3xx b/src/parser/nit.sablecc3xx index 769f05b..592cc42 100644 --- a/src/parser/nit.sablecc3xx +++ b/src/parser/nit.sablecc3xx @@ -207,7 +207,7 @@ bytenum = digit+ 'u8'; hex_bytenum = ('0x' | '0X') hexdigit+ 'u8'; bin_bytenum = ('0b' | '0B') bindigit+ 'u8'; oct_bytenum = ('0o' | '0O') octdigit+ 'u8'; -float = digit* '.' digit+; +float = digit* '.' digit+ | (digit+ | digit* '.' digit+) ('E'|'e') ('+'|'-'|) digit+; string = '"' str_body '"' | '"' '"' '"' long_str_body lsend1 | ''' ''' ''' long_sstr_body ''' ''' '''; start_string = '"' str_body '{' | '"' '"' '"' long_str_body lsend2; mid_string = '}' str_body '{' | '}' '}' '}' long_str_body lsend2; diff --git a/src/parser/parser_nodes.nit b/src/parser/parser_nodes.nit index 6ec146f..9131c3e 100644 --- a/src/parser/parser_nodes.nit +++ b/src/parser/parser_nodes.nit @@ -311,6 +311,35 @@ abstract class Token # May have disappeared in the AST var next_token: nullable Token = null + # Is `self` a token discarded from the AST? + # + # Loose tokens are not present in the AST. + # It means they were identified by the lexer but were discarded by the parser. + # It also means that they are not visited or manipulated by AST-related functions. + # + # Each loose token is attached to the non-loose token that precedes or follows it. + # The rules are the following: + # + # * tokens that follow a non-loose token on a same line are attached to it. + # See `next_looses`. + # * other tokens, thus that precede a non-loose token on the same line or the next one, + # are attached to this one. See `prev_looses`. + # + # Loose tokens are mostly end of lines (`TEol`) and comments (`TComment`). + # Whitespace are ignored by the lexer, so they are not even considered as loose tokens. + # See `blank_before` to get the whitespace that separate tokens. + var is_loose = false + + # Loose tokens that precede `self`. + # + # These tokens start the line or belong to a line with only loose tokens. + var prev_looses = new Array[Token] is lazy + + # Loose tokens that follow `self` + # + # These tokens are on the same line than `self`. + var next_looses = new Array[Token] is lazy + # The verbatim blank text between `prev_token` and `self` fun blank_before: String do diff --git a/src/parser/parser_work.nit b/src/parser/parser_work.nit index c2eff11..a344fc7 100644 --- a/src/parser/parser_work.nit +++ b/src/parser/parser_work.nit @@ -141,7 +141,8 @@ class Parser var node1 = pop assert node1 isa AModule var node = new Start(node1, node2) - (new ComputeProdLocationVisitor).enter_visit(node) + node2.parent = node + (new ComputeProdLocationVisitor(lexer.file.first_token)).enter_visit(node) return node else if action_type == 3 then # ERROR # skip injected tokens @@ -176,21 +177,55 @@ end # Uses existing token locations to infer location of productions. private class ComputeProdLocationVisitor super Visitor + + # The current (or starting) cursor on the token sequence used to collect loose tokens + var token: nullable Token + # Currently visited productions that need a first token var need_first_prods = new Array[Prod] # Already visited epsilon productions that waits something after them var need_after_epsilons = new Array[Prod] - # Location of the last visited token in the current production - var last_location: nullable Location = null + # The last visited token in the current production + var last_token: nullable Token = null redef fun visit(n: ANode) do if n isa Token then + # Skip injected tokens if not isset n._location then return + + # Collect loose tokens (not in the AST) and attach them to token in the AST + var cursor = token + if n != cursor then + var lt = last_token + # In order, we have the tokens: + # * `lt` the previous visited token in the AST (if any) + # * then `cursor` the loose tokens to attach + # * then `n` the current visited token in the AST + + # In the following, we advance `cursor` to add them to `lt.next_looses` or to `n.prev_looses`. + if lt != null then + var ltl = lt.location.line_end + # floating tokens on the same line of a AST-token follows it + while cursor != null and cursor != n and ltl == cursor.location.line_start do + cursor.is_loose = true + lt.next_looses.add cursor + cursor = cursor.next_token + end + end + # other loose tokens precede the next AST-token + while cursor != null and cursor != n do + cursor.is_loose = true + n.prev_looses.add cursor + cursor = cursor.next_token + end + end + token = n.next_token + var loc = n._location - _last_location = loc + _last_token = n # Add a first token to productions that need one if not _need_first_prods.is_empty then @@ -217,8 +252,7 @@ private class ComputeProdLocationVisitor var startl = n._first_location if startl != null then # Non-epsilon production - var endl = _last_location - assert endl != null + var endl = _last_token.location if startl == endl then n.location = startl diff --git a/src/parser/tables_nit.c b/src/parser/tables_nit.c index ce36ccc..4fd03ae 100644 --- a/src/parser/tables_nit.c +++ b/src/parser/tables_nit.c @@ -140,254 +140,258 @@ static const int lexer_goto_row19[] = { 61, 61, 75 }; static const int lexer_goto_row20[] = { - 9, + 11, 46, 46, 76, 48, 57, 20, 66, 66, 77, - 79, 79, 78, - 88, 88, 79, - 98, 98, 80, - 111, 111, 81, - 117, 117, 82, - 120, 120, 83 + 69, 69, 78, + 79, 79, 79, + 88, 88, 80, + 98, 98, 81, + 101, 101, 82, + 111, 111, 83, + 117, 117, 84, + 120, 120, 85 }; static const int lexer_goto_row21[] = { - 2, + 4, 46, 57, -21, - 117, 117, 82 + 69, 69, 78, + 101, 101, 82, + 117, 117, 84 }; static const int lexer_goto_row22[] = { 1, - 58, 58, 84 + 58, 58, 86 }; static const int lexer_goto_row24[] = { 2, - 60, 60, 85, - 61, 61, 86 + 60, 60, 87, + 61, 61, 88 }; static const int lexer_goto_row25[] = { 1, - 61, 61, 87 + 61, 61, 89 }; static const int lexer_goto_row26[] = { 2, - 61, 61, 88, - 62, 62, 89 + 61, 61, 90, + 62, 62, 91 }; static const int lexer_goto_row28[] = { 4, - 48, 57, 90, - 65, 90, 91, - 95, 95, 92, - 97, 122, 93 + 48, 57, 92, + 65, 90, 93, + 95, 95, 94, + 97, 122, 95 }; static const int lexer_goto_row31[] = { 1, - 61, 61, 94 + 61, 61, 96 }; static const int lexer_goto_row32[] = { 2, - 95, 95, 95, - 97, 122, 96 + 95, 95, 97, + 97, 122, 98 }; static const int lexer_goto_row33[] = { 1, - 123, 123, 97 + 123, 123, 99 }; static const int lexer_goto_row34[] = { 10, - 48, 57, 98, - 65, 90, 99, - 95, 95, 100, - 97, 97, 101, - 98, 98, 102, - 99, 109, 101, - 110, 110, 103, - 111, 114, 101, - 115, 115, 104, - 116, 122, 101 + 48, 57, 100, + 65, 90, 101, + 95, 95, 102, + 97, 97, 103, + 98, 98, 104, + 99, 109, 103, + 110, 110, 105, + 111, 114, 103, + 115, 115, 106, + 116, 122, 103 }; static const int lexer_goto_row35[] = { 4, 48, 95, -35, - 97, 113, 101, - 114, 114, 105, - 115, 122, 101 + 97, 113, 103, + 114, 114, 107, + 115, 122, 103 }; static const int lexer_goto_row36[] = { 6, 48, 95, -35, - 97, 107, 101, - 108, 108, 106, - 109, 110, 101, - 111, 111, 107, - 112, 122, 101 + 97, 107, 103, + 108, 108, 108, + 109, 110, 103, + 111, 111, 109, + 112, 122, 103 }; static const int lexer_goto_row37[] = { 4, 48, 95, -35, - 97, 110, 101, - 111, 111, 108, - 112, 122, 101 + 97, 110, 103, + 111, 111, 110, + 112, 122, 103 }; static const int lexer_goto_row38[] = { 7, 48, 107, -37, - 108, 108, 109, - 109, 109, 101, - 110, 110, 110, - 111, 119, 101, - 120, 120, 111, - 121, 122, 101 + 108, 108, 111, + 109, 109, 103, + 110, 110, 112, + 111, 119, 103, + 120, 120, 113, + 121, 122, 103 }; static const int lexer_goto_row39[] = { 7, 48, 95, -35, - 97, 97, 112, - 98, 110, 101, - 111, 111, 113, - 112, 116, 101, - 117, 117, 114, - 118, 122, 101 + 97, 97, 114, + 98, 110, 103, + 111, 111, 115, + 112, 116, 103, + 117, 117, 116, + 118, 122, 103 }; static const int lexer_goto_row40[] = { 2, 48, 95, -35, - 97, 122, 101 + 97, 122, 103 }; static const int lexer_goto_row41[] = { 9, 48, 95, -35, - 97, 101, 101, - 102, 102, 115, - 103, 108, 101, - 109, 109, 116, - 110, 110, 117, - 111, 114, 101, - 115, 115, 118, - 116, 122, 101 + 97, 101, 103, + 102, 102, 117, + 103, 108, 103, + 109, 109, 118, + 110, 110, 119, + 111, 114, 103, + 115, 115, 120, + 116, 122, 103 }; static const int lexer_goto_row42[] = { 5, 48, 95, -35, - 97, 97, 119, - 98, 110, 101, - 111, 111, 120, - 112, 122, 101 + 97, 97, 121, + 98, 110, 103, + 111, 111, 122, + 112, 122, 103 }; static const int lexer_goto_row43[] = { 3, 48, 110, -38, - 111, 111, 121, - 112, 122, 101 + 111, 111, 123, + 112, 122, 103 }; static const int lexer_goto_row44[] = { 8, 48, 95, -35, - 97, 100, 101, - 101, 101, 122, - 102, 110, 101, - 111, 111, 123, - 112, 116, 101, - 117, 117, 124, - 118, 122, 101 + 97, 100, 103, + 101, 101, 124, + 102, 110, 103, + 111, 111, 125, + 112, 116, 103, + 117, 117, 126, + 118, 122, 103 }; static const int lexer_goto_row45[] = { 6, 48, 95, -35, - 97, 109, 101, - 110, 110, 125, - 111, 113, 101, - 114, 114, 126, - 115, 122, 101 + 97, 109, 103, + 110, 110, 127, + 111, 113, 103, + 114, 114, 128, + 115, 122, 103 }; static const int lexer_goto_row46[] = { 7, 48, 95, -35, - 97, 97, 127, - 98, 113, 101, - 114, 114, 128, - 115, 116, 101, - 117, 117, 129, - 118, 122, 101 + 97, 97, 129, + 98, 113, 103, + 114, 114, 130, + 115, 116, 103, + 117, 117, 131, + 118, 122, 103 }; static const int lexer_goto_row47[] = { 3, 48, 100, -45, - 101, 101, 130, - 102, 122, 101 + 101, 101, 132, + 102, 122, 103 }; static const int lexer_goto_row48[] = { 5, 48, 100, -45, - 101, 101, 131, - 102, 116, 101, - 117, 117, 132, - 118, 122, 101 + 101, 101, 133, + 102, 116, 103, + 117, 117, 134, + 118, 122, 103 }; static const int lexer_goto_row49[] = { 8, 48, 95, -35, - 97, 103, 101, - 104, 104, 133, - 105, 113, 101, - 114, 114, 134, - 115, 120, 101, - 121, 121, 135, - 122, 122, 101 + 97, 103, 103, + 104, 104, 135, + 105, 113, 103, + 114, 114, 136, + 115, 120, 103, + 121, 121, 137, + 122, 122, 103 }; static const int lexer_goto_row50[] = { 3, 48, 109, -46, - 110, 110, 136, - 111, 122, 101 + 110, 110, 138, + 111, 122, 103 }; static const int lexer_goto_row51[] = { 3, 48, 95, -35, - 97, 97, 137, - 98, 122, 101 + 97, 97, 139, + 98, 122, 103 }; static const int lexer_goto_row52[] = { 4, 48, 103, -50, - 104, 104, 138, - 105, 105, 139, - 106, 122, 101 + 104, 104, 140, + 105, 105, 141, + 106, 122, 103 }; static const int lexer_goto_row53[] = { 1, - 61, 61, 140 + 61, 61, 142 }; static const int lexer_goto_row54[] = { 11, - 0, 9, 141, - 11, 12, 141, - 14, 33, 141, - 34, 34, 142, - 35, 91, 141, - 92, 92, 143, - 93, 122, 141, - 123, 123, 144, - 124, 124, 141, - 125, 125, 145, - 126, 255, 141 + 0, 9, 143, + 11, 12, 143, + 14, 33, 143, + 34, 34, 144, + 35, 91, 143, + 92, 92, 145, + 93, 122, 143, + 123, 123, 146, + 124, 124, 143, + 125, 125, 147, + 126, 255, 143 }; static const int lexer_goto_row58[] = { 3, 0, 33, -8, - 34, 34, 146, + 34, 34, 148, 35, 255, -8 }; static const int lexer_goto_row59[] = { 1, - 34, 34, 147 + 34, 34, 149 }; static const int lexer_goto_row60[] = { 3, - 0, 9, 148, - 11, 12, 148, - 14, 255, 148 + 0, 9, 150, + 11, 12, 150, + 14, 255, 150 }; static const int lexer_goto_row62[] = { 1, @@ -395,33 +399,34 @@ static const int lexer_goto_row62[] = { }; static const int lexer_goto_row64[] = { 1, - 10, 10, 149 + 10, 10, 151 }; static const int lexer_goto_row67[] = { 1, - 39, 39, 150 + 39, 39, 152 }; static const int lexer_goto_row68[] = { 1, - 39, 39, 151 + 39, 39, 153 }; static const int lexer_goto_row69[] = { 3, - 0, 9, 152, - 11, 12, 152, - 14, 255, 152 + 0, 9, 154, + 11, 12, 154, + 14, 255, 154 }; static const int lexer_goto_row70[] = { 1, - 61, 61, 153 + 61, 61, 155 }; static const int lexer_goto_row74[] = { 1, - 46, 46, 154 + 46, 46, 156 }; static const int lexer_goto_row75[] = { - 1, - 48, 57, 74 + 2, + 48, 57, 74, + 69, 101, -22 }; static const int lexer_goto_row77[] = { 1, @@ -429,57 +434,59 @@ static const int lexer_goto_row77[] = { }; static const int lexer_goto_row78[] = { 3, - 48, 48, 155, - 49, 49, 156, - 95, 95, 157 + 48, 48, 157, + 49, 49, 158, + 95, 95, 159 }; static const int lexer_goto_row79[] = { - 2, - 48, 55, 158, - 95, 95, 159 + 3, + 43, 43, 160, + 45, 45, 161, + 48, 57, 162 }; static const int lexer_goto_row80[] = { - 4, - 48, 57, 160, - 65, 70, 161, - 95, 95, 162, - 97, 102, 163 + 2, + 48, 55, 163, + 95, 95, 164 }; static const int lexer_goto_row81[] = { - 1, - 48, 95, -79 + 4, + 48, 57, 165, + 65, 70, 166, + 95, 95, 167, + 97, 102, 168 }; static const int lexer_goto_row82[] = { 1, - 48, 95, -80 + 48, 95, -79 }; static const int lexer_goto_row83[] = { 1, - 56, 56, 164 + 43, 57, -80 }; static const int lexer_goto_row84[] = { 1, - 48, 102, -81 + 48, 95, -81 }; -static const int lexer_goto_row86[] = { +static const int lexer_goto_row85[] = { 1, - 61, 61, 165 + 56, 56, 169 }; -static const int lexer_goto_row87[] = { +static const int lexer_goto_row86[] = { 1, - 62, 62, 166 + 48, 102, -82 }; -static const int lexer_goto_row90[] = { +static const int lexer_goto_row88[] = { 1, - 61, 61, 167 + 61, 61, 170 }; -static const int lexer_goto_row91[] = { +static const int lexer_goto_row89[] = { 1, - 48, 122, -29 + 62, 62, 171 }; static const int lexer_goto_row92[] = { 1, - 48, 122, -29 + 61, 61, 172 }; static const int lexer_goto_row93[] = { 1, @@ -489,817 +496,809 @@ static const int lexer_goto_row94[] = { 1, 48, 122, -29 }; +static const int lexer_goto_row95[] = { + 1, + 48, 122, -29 +}; static const int lexer_goto_row96[] = { 1, - 100, 100, 168 + 48, 122, -29 +}; +static const int lexer_goto_row98[] = { + 1, + 100, 100, 173 }; -static const int lexer_goto_row97[] = { +static const int lexer_goto_row99[] = { 4, - 48, 57, 169, - 65, 90, 170, - 95, 95, 171, - 97, 122, 172 + 48, 57, 174, + 65, 90, 175, + 95, 95, 176, + 97, 122, 177 }; -static const int lexer_goto_row98[] = { +static const int lexer_goto_row100[] = { 5, - 0, 91, 173, - 92, 92, 174, - 93, 95, 173, - 96, 96, 175, - 97, 255, 173 + 0, 91, 178, + 92, 92, 179, + 93, 95, 178, + 96, 96, 180, + 97, 255, 178 }; -static const int lexer_goto_row99[] = { +static const int lexer_goto_row101[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row100[] = { +static const int lexer_goto_row102[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row101[] = { +static const int lexer_goto_row103[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row102[] = { +static const int lexer_goto_row104[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row103[] = { +static const int lexer_goto_row105[] = { 5, 48, 110, -38, - 111, 111, 176, - 112, 114, 101, - 115, 115, 177, - 116, 122, 101 + 111, 111, 181, + 112, 114, 103, + 115, 115, 182, + 116, 122, 103 }; -static const int lexer_goto_row104[] = { +static const int lexer_goto_row106[] = { 4, 48, 95, -35, - 97, 99, 101, - 100, 100, 178, - 101, 122, 101 + 97, 99, 103, + 100, 100, 183, + 101, 122, 103 }; -static const int lexer_goto_row105[] = { +static const int lexer_goto_row107[] = { 4, 48, 95, -35, - 97, 114, 101, - 115, 115, 179, - 116, 122, 101 + 97, 114, 103, + 115, 115, 184, + 116, 122, 103 }; -static const int lexer_goto_row106[] = { +static const int lexer_goto_row108[] = { 3, 48, 100, -45, - 101, 101, 180, - 102, 122, 101 + 101, 101, 185, + 102, 122, 103 }; -static const int lexer_goto_row107[] = { +static const int lexer_goto_row109[] = { 3, 48, 95, -35, - 97, 97, 181, - 98, 122, 101 + 97, 97, 186, + 98, 122, 103 }; -static const int lexer_goto_row108[] = { +static const int lexer_goto_row110[] = { 3, 48, 109, -46, - 110, 110, 182, - 111, 122, 101 + 110, 110, 187, + 111, 122, 103 }; -static const int lexer_goto_row109[] = { +static const int lexer_goto_row111[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row110[] = { +static const int lexer_goto_row112[] = { 3, - 48, 114, -106, - 115, 115, 183, - 116, 122, 101 + 48, 114, -108, + 115, 115, 188, + 116, 122, 103 }; -static const int lexer_goto_row111[] = { +static const int lexer_goto_row113[] = { 5, - 48, 99, -105, - 100, 100, 184, - 101, 116, 101, - 117, 117, 185, - 118, 122, 101 + 48, 99, -107, + 100, 100, 189, + 101, 116, 103, + 117, 117, 190, + 118, 122, 103 }; -static const int lexer_goto_row112[] = { +static const int lexer_goto_row114[] = { 4, 48, 95, -35, - 97, 115, 101, - 116, 116, 186, - 117, 122, 101 + 97, 115, 103, + 116, 116, 191, + 117, 122, 103 }; -static const int lexer_goto_row113[] = { +static const int lexer_goto_row115[] = { 3, 48, 107, -37, - 108, 108, 187, - 109, 122, 101 + 108, 108, 192, + 109, 122, 103 }; -static const int lexer_goto_row114[] = { +static const int lexer_goto_row116[] = { 3, 48, 113, -36, - 114, 114, 188, - 115, 122, 101 + 114, 114, 193, + 115, 122, 103 }; -static const int lexer_goto_row115[] = { +static const int lexer_goto_row117[] = { 3, 48, 109, -46, - 110, 110, 189, - 111, 122, 101 + 110, 110, 194, + 111, 122, 103 }; -static const int lexer_goto_row116[] = { +static const int lexer_goto_row118[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row117[] = { +static const int lexer_goto_row119[] = { 4, 48, 95, -35, - 97, 111, 101, - 112, 112, 190, - 113, 122, 101 + 97, 111, 103, + 112, 112, 195, + 113, 122, 103 }; -static const int lexer_goto_row118[] = { +static const int lexer_goto_row120[] = { 6, 48, 95, -35, - 97, 104, 101, - 105, 105, 191, - 106, 115, 101, - 116, 116, 192, - 117, 122, 101 + 97, 104, 103, + 105, 105, 196, + 106, 115, 103, + 116, 116, 197, + 117, 122, 103 }; -static const int lexer_goto_row119[] = { +static const int lexer_goto_row121[] = { 5, 48, 95, -35, - 97, 97, 193, - 98, 114, 101, - 115, 115, 194, - 116, 122, 101 + 97, 97, 198, + 98, 114, 103, + 115, 115, 199, + 116, 122, 103 }; -static const int lexer_goto_row120[] = { +static const int lexer_goto_row122[] = { 3, 48, 97, -35, - 98, 98, 195, - 99, 122, 101 + 98, 98, 200, + 99, 122, 103 }; -static const int lexer_goto_row121[] = { +static const int lexer_goto_row123[] = { 3, 48, 110, -38, - 111, 111, 196, - 112, 122, 101 + 111, 111, 201, + 112, 122, 103 }; -static const int lexer_goto_row122[] = { +static const int lexer_goto_row124[] = { 3, - 48, 99, -105, - 100, 100, 197, - 101, 122, 101 + 48, 99, -107, + 100, 100, 202, + 101, 122, 103 }; -static const int lexer_goto_row123[] = { +static const int lexer_goto_row125[] = { 4, 48, 95, -35, - 97, 118, 101, - 119, 119, 198, - 120, 122, 101 + 97, 118, 103, + 119, 119, 203, + 120, 122, 103 }; -static const int lexer_goto_row124[] = { +static const int lexer_goto_row126[] = { 3, - 48, 115, -113, - 116, 116, 199, - 117, 122, 101 + 48, 115, -115, + 116, 116, 204, + 117, 122, 103 }; -static const int lexer_goto_row125[] = { +static const int lexer_goto_row127[] = { 3, 48, 107, -37, - 108, 108, 200, - 109, 122, 101 + 108, 108, 205, + 109, 122, 103 }; -static const int lexer_goto_row126[] = { +static const int lexer_goto_row128[] = { 4, 48, 95, -35, - 97, 98, 101, - 99, 99, 201, - 100, 122, 101 + 97, 98, 103, + 99, 99, 206, + 100, 122, 103 }; -static const int lexer_goto_row127[] = { +static const int lexer_goto_row129[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row128[] = { - 3, - 48, 98, -127, - 99, 99, 202, - 100, 122, 101 -}; -static const int lexer_goto_row129[] = { - 5, - 48, 104, -119, - 105, 105, 203, - 106, 110, 101, - 111, 111, 204, - 112, 122, 101 -}; static const int lexer_goto_row130[] = { 3, - 48, 97, -35, - 98, 98, 205, - 99, 122, 101 + 48, 98, -129, + 99, 99, 207, + 100, 122, 103 }; static const int lexer_goto_row131[] = { 5, - 48, 99, -105, - 100, 100, 206, - 101, 115, 101, - 116, 116, 207, - 117, 122, 101 + 48, 104, -121, + 105, 105, 208, + 106, 110, 103, + 111, 111, 209, + 112, 122, 103 }; static const int lexer_goto_row132[] = { 3, - 48, 107, -37, - 108, 108, 208, - 109, 122, 101 + 48, 97, -35, + 98, 98, 210, + 99, 122, 103 }; static const int lexer_goto_row133[] = { - 3, - 48, 111, -118, - 112, 112, 209, - 113, 122, 101 + 5, + 48, 99, -107, + 100, 100, 211, + 101, 115, 103, + 116, 116, 212, + 117, 122, 103 }; static const int lexer_goto_row134[] = { 3, - 48, 100, -45, - 101, 101, 210, - 102, 122, 101 + 48, 107, -37, + 108, 108, 213, + 109, 122, 103 }; static const int lexer_goto_row135[] = { - 4, - 48, 95, -35, - 97, 116, 101, - 117, 117, 211, - 118, 122, 101 + 3, + 48, 111, -120, + 112, 112, 214, + 113, 122, 103 }; static const int lexer_goto_row136[] = { 3, - 48, 111, -118, - 112, 112, 212, - 113, 122, 101 + 48, 100, -45, + 101, 101, 215, + 102, 122, 103 }; static const int lexer_goto_row137[] = { - 3, - 48, 104, -119, - 105, 105, 213, - 106, 122, 101 + 4, + 48, 95, -35, + 97, 116, 103, + 117, 117, 216, + 118, 122, 103 }; static const int lexer_goto_row138[] = { 3, - 48, 113, -36, - 114, 114, 214, - 115, 122, 101 + 48, 111, -120, + 112, 112, 217, + 113, 122, 103 }; static const int lexer_goto_row139[] = { 3, - 48, 104, -119, - 105, 105, 215, - 106, 122, 101 + 48, 104, -121, + 105, 105, 218, + 106, 122, 103 }; static const int lexer_goto_row140[] = { 3, - 48, 115, -113, - 116, 116, 216, - 117, 122, 101 + 48, 113, -36, + 114, 114, 219, + 115, 122, 103 +}; +static const int lexer_goto_row141[] = { + 3, + 48, 104, -121, + 105, 105, 220, + 106, 122, 103 }; static const int lexer_goto_row142[] = { + 3, + 48, 115, -115, + 116, 116, 221, + 117, 122, 103 +}; +static const int lexer_goto_row144[] = { 2, 0, 123, -55, - 124, 255, 141 + 124, 255, 143 }; -static const int lexer_goto_row144[] = { +static const int lexer_goto_row146[] = { 3, - 0, 9, 217, - 11, 12, 217, - 14, 255, 217 + 0, 9, 222, + 11, 12, 222, + 14, 255, 222 }; -static const int lexer_goto_row146[] = { +static const int lexer_goto_row148[] = { 3, 0, 124, -55, - 125, 125, 218, - 126, 255, 141 + 125, 125, 223, + 126, 255, 143 }; -static const int lexer_goto_row148[] = { +static const int lexer_goto_row150[] = { 11, - 0, 9, 219, - 10, 10, 220, - 11, 12, 219, - 13, 13, 221, - 14, 33, 219, - 34, 34, 222, - 35, 91, 219, - 92, 92, 223, - 93, 122, 219, - 123, 123, 224, - 124, 255, 219 -}; -static const int lexer_goto_row149[] = { + 0, 9, 224, + 10, 10, 225, + 11, 12, 224, + 13, 13, 226, + 14, 33, 224, + 34, 34, 227, + 35, 91, 224, + 92, 92, 228, + 93, 122, 224, + 123, 123, 229, + 124, 255, 224 +}; +static const int lexer_goto_row151[] = { 1, 0, 255, -59 }; -static const int lexer_goto_row152[] = { +static const int lexer_goto_row154[] = { 9, - 0, 9, 225, - 10, 10, 226, - 11, 12, 225, - 13, 13, 227, - 14, 38, 225, - 39, 39, 228, - 40, 91, 225, - 92, 92, 229, - 93, 255, 225 + 0, 9, 230, + 10, 10, 231, + 11, 12, 230, + 13, 13, 232, + 14, 38, 230, + 39, 39, 233, + 40, 91, 230, + 92, 92, 234, + 93, 255, 230 }; -static const int lexer_goto_row153[] = { +static const int lexer_goto_row155[] = { 1, - 39, 39, 230 + 39, 39, 235 }; -static const int lexer_goto_row156[] = { +static const int lexer_goto_row158[] = { 2, 48, 95, -79, - 117, 117, 231 -}; -static const int lexer_goto_row157[] = { - 1, - 48, 117, -157 -}; -static const int lexer_goto_row158[] = { - 1, - 48, 117, -157 + 117, 117, 236 }; static const int lexer_goto_row159[] = { - 2, - 48, 95, -80, - 117, 117, 232 + 1, + 48, 117, -159 }; static const int lexer_goto_row160[] = { 1, - 48, 117, -160 + 48, 117, -159 }; static const int lexer_goto_row161[] = { - 2, - 48, 102, -81, - 117, 117, 233 + 1, + 48, 57, 162 }; static const int lexer_goto_row162[] = { 1, - 48, 117, -162 + 48, 57, 162 }; static const int lexer_goto_row163[] = { 1, - 48, 117, -162 + 48, 57, 162 }; static const int lexer_goto_row164[] = { - 1, - 48, 117, -162 + 2, + 48, 95, -81, + 117, 117, 237 }; -static const int lexer_goto_row169[] = { +static const int lexer_goto_row165[] = { 1, - 101, 101, 234 + 48, 117, -165 }; -static const int lexer_goto_row170[] = { - 1, - 48, 122, -98 +static const int lexer_goto_row166[] = { + 2, + 48, 102, -82, + 117, 117, 238 }; -static const int lexer_goto_row171[] = { +static const int lexer_goto_row167[] = { 1, - 48, 122, -98 + 48, 117, -167 }; -static const int lexer_goto_row172[] = { +static const int lexer_goto_row168[] = { 1, - 48, 122, -98 + 48, 117, -167 }; -static const int lexer_goto_row173[] = { +static const int lexer_goto_row169[] = { 1, - 48, 122, -98 + 48, 117, -167 }; static const int lexer_goto_row174[] = { 1, - 0, 255, -99 + 101, 101, 239 }; static const int lexer_goto_row175[] = { 1, - 0, 255, 235 + 48, 122, -100 }; static const int lexer_goto_row176[] = { - 3, - 0, 124, 236, - 125, 125, 237, - 126, 255, 236 + 1, + 48, 122, -100 }; static const int lexer_goto_row177[] = { - 3, - 48, 113, -36, - 114, 114, 238, - 115, 122, 101 + 1, + 48, 122, -100 }; static const int lexer_goto_row178[] = { - 3, - 48, 115, -113, - 116, 116, 239, - 117, 122, 101 + 1, + 48, 122, -100 }; static const int lexer_goto_row179[] = { 1, - 48, 122, -41 + 0, 255, -101 }; static const int lexer_goto_row180[] = { - 3, - 48, 100, -45, - 101, 101, 240, - 102, 122, 101 + 1, + 0, 255, 240 }; static const int lexer_goto_row181[] = { 3, - 48, 95, -35, - 97, 97, 241, - 98, 122, 101 + 0, 124, 241, + 125, 125, 242, + 126, 255, 241 }; static const int lexer_goto_row182[] = { 3, - 48, 114, -106, - 115, 115, 242, - 116, 122, 101 + 48, 113, -36, + 114, 114, 243, + 115, 122, 103 }; static const int lexer_goto_row183[] = { 3, - 48, 115, -113, - 116, 116, 243, - 117, 122, 101 + 48, 115, -115, + 116, 116, 244, + 117, 122, 103 }; static const int lexer_goto_row184[] = { - 3, - 48, 100, -45, - 101, 101, 244, - 102, 122, 101 -}; -static const int lexer_goto_row185[] = { 1, 48, 122, -41 }; +static const int lexer_goto_row185[] = { + 3, + 48, 100, -45, + 101, 101, 245, + 102, 122, 103 +}; static const int lexer_goto_row186[] = { - 4, + 3, 48, 95, -35, - 97, 108, 101, - 109, 109, 245, - 110, 122, 101 + 97, 97, 246, + 98, 122, 103 }; static const int lexer_goto_row187[] = { 3, - 48, 100, -45, - 101, 101, 246, - 102, 122, 101 + 48, 114, -108, + 115, 115, 247, + 116, 122, 103 }; static const int lexer_goto_row188[] = { 3, - 48, 114, -106, - 115, 115, 247, - 116, 122, 101 + 48, 115, -115, + 116, 116, 248, + 117, 122, 103 }; static const int lexer_goto_row189[] = { - 1, - 48, 122, -41 + 3, + 48, 100, -45, + 101, 101, 249, + 102, 122, 103 }; static const int lexer_goto_row190[] = { 1, 48, 122, -41 }; static const int lexer_goto_row191[] = { - 5, - 48, 107, -37, - 108, 108, 248, - 109, 110, 101, - 111, 111, 249, - 112, 122, 101 + 4, + 48, 95, -35, + 97, 108, 103, + 109, 109, 250, + 110, 122, 103 }; static const int lexer_goto_row192[] = { 3, - 48, 115, -113, - 116, 116, 250, - 117, 122, 101 -}; -static const int lexer_goto_row193[] = { - 5, 48, 100, -45, 101, 101, 251, - 102, 113, 101, - 114, 114, 252, - 115, 122, 101 + 102, 122, 103 +}; +static const int lexer_goto_row193[] = { + 3, + 48, 114, -108, + 115, 115, 252, + 116, 122, 103 }; static const int lexer_goto_row194[] = { 1, 48, 122, -41 }; static const int lexer_goto_row195[] = { - 3, - 48, 100, -45, - 101, 101, 253, - 102, 122, 101 + 1, + 48, 122, -41 }; static const int lexer_goto_row196[] = { - 3, - 48, 100, -45, - 101, 101, 254, - 102, 122, 101 + 5, + 48, 107, -37, + 108, 108, 253, + 109, 110, 103, + 111, 111, 254, + 112, 122, 103 }; static const int lexer_goto_row197[] = { 3, - 48, 111, -118, - 112, 112, 255, - 113, 122, 101 + 48, 115, -115, + 116, 116, 255, + 117, 122, 103 }; static const int lexer_goto_row198[] = { - 3, - 48, 116, -136, - 117, 117, 256, - 118, 122, 101 + 5, + 48, 100, -45, + 101, 101, 256, + 102, 113, 103, + 114, 114, 257, + 115, 122, 103 }; static const int lexer_goto_row199[] = { 1, 48, 122, -41 }; static const int lexer_goto_row200[] = { - 1, - 48, 122, -41 + 3, + 48, 100, -45, + 101, 101, 258, + 102, 122, 103 }; static const int lexer_goto_row201[] = { 3, - 48, 107, -37, - 108, 108, 257, - 109, 122, 101 + 48, 100, -45, + 101, 101, 259, + 102, 122, 103 }; static const int lexer_goto_row202[] = { 3, - 48, 100, -45, - 101, 101, 258, - 102, 122, 101 + 48, 111, -120, + 112, 112, 260, + 113, 122, 103 }; static const int lexer_goto_row203[] = { - 4, - 48, 95, -35, - 97, 106, 101, - 107, 107, 259, - 108, 122, 101 + 3, + 48, 116, -138, + 117, 117, 261, + 118, 122, 103 }; static const int lexer_goto_row204[] = { - 4, - 48, 95, -35, - 97, 117, 101, - 118, 118, 260, - 119, 122, 101 + 1, + 48, 122, -41 }; static const int lexer_goto_row205[] = { - 3, - 48, 115, -113, - 116, 116, 261, - 117, 122, 101 + 1, + 48, 122, -41 }; static const int lexer_goto_row206[] = { 3, 48, 107, -37, 108, 108, 262, - 109, 122, 101 + 109, 122, 103 }; static const int lexer_goto_row207[] = { 3, 48, 100, -45, 101, 101, 263, - 102, 122, 101 + 102, 122, 103 }; static const int lexer_goto_row208[] = { - 3, - 48, 116, -136, - 117, 117, 264, - 118, 122, 101 + 4, + 48, 95, -35, + 97, 106, 103, + 107, 107, 264, + 108, 122, 103 }; static const int lexer_goto_row209[] = { - 3, - 48, 101, -42, - 102, 102, 265, - 103, 122, 101 + 4, + 48, 95, -35, + 97, 117, 103, + 118, 118, 265, + 119, 122, 103 }; static const int lexer_goto_row210[] = { 3, - 48, 100, -45, - 101, 101, 266, - 102, 122, 101 + 48, 115, -115, + 116, 116, 266, + 117, 122, 103 }; static const int lexer_goto_row211[] = { 3, - 48, 109, -46, - 110, 110, 267, - 111, 122, 101 + 48, 107, -37, + 108, 108, 267, + 109, 122, 103 }; static const int lexer_goto_row212[] = { 3, 48, 100, -45, 101, 101, 268, - 102, 122, 101 + 102, 122, 103 }; static const int lexer_goto_row213[] = { 3, - 48, 100, -45, - 101, 101, 269, - 102, 122, 101 + 48, 116, -138, + 117, 117, 269, + 118, 122, 103 }; static const int lexer_goto_row214[] = { 3, - 48, 117, -205, - 118, 118, 270, - 119, 122, 101 + 48, 101, -42, + 102, 102, 270, + 103, 122, 103 }; static const int lexer_goto_row215[] = { - 1, - 48, 122, -41 + 3, + 48, 100, -45, + 101, 101, 271, + 102, 122, 103 }; static const int lexer_goto_row216[] = { 3, - 48, 107, -37, - 108, 108, 271, - 109, 122, 101 + 48, 109, -46, + 110, 110, 272, + 111, 122, 103 }; static const int lexer_goto_row217[] = { 3, - 48, 103, -50, - 104, 104, 272, - 105, 122, 101 + 48, 100, -45, + 101, 101, 273, + 102, 122, 103 }; static const int lexer_goto_row218[] = { - 1, - 0, 255, -143 + 3, + 48, 100, -45, + 101, 101, 274, + 102, 122, 103 }; static const int lexer_goto_row219[] = { - 11, - 0, 9, 273, - 10, 10, 274, - 11, 12, 273, - 13, 13, 275, - 14, 33, 273, - 34, 34, 276, - 35, 91, 273, - 92, 92, 277, - 93, 122, 273, - 123, 123, 278, - 124, 255, 273 + 3, + 48, 117, -210, + 118, 118, 275, + 119, 122, 103 }; static const int lexer_goto_row220[] = { 1, - 0, 255, -149 + 48, 122, -41 }; static const int lexer_goto_row221[] = { - 1, - 0, 255, -149 + 3, + 48, 107, -37, + 108, 108, 276, + 109, 122, 103 }; static const int lexer_goto_row222[] = { - 1, - 0, 255, -149 + 3, + 48, 103, -50, + 104, 104, 277, + 105, 122, 103 }; static const int lexer_goto_row223[] = { - 5, - 0, 33, -149, - 34, 34, 279, - 35, 122, -149, - 123, 123, 280, - 124, 255, 219 + 1, + 0, 255, -145 }; static const int lexer_goto_row224[] = { - 3, - 0, 9, 281, - 11, 12, 281, - 14, 255, 281 + 11, + 0, 9, 278, + 10, 10, 279, + 11, 12, 278, + 13, 13, 280, + 14, 33, 278, + 34, 34, 281, + 35, 91, 278, + 92, 92, 282, + 93, 122, 278, + 123, 123, 283, + 124, 255, 278 }; static const int lexer_goto_row225[] = { - 5, - 0, 33, -149, - 34, 34, 282, - 35, 122, -149, - 123, 123, 283, - 124, 255, 219 + 1, + 0, 255, -151 }; static const int lexer_goto_row226[] = { 1, - 0, 255, -153 + 0, 255, -151 }; static const int lexer_goto_row227[] = { 1, - 0, 255, -153 + 0, 255, -151 }; static const int lexer_goto_row228[] = { - 1, - 0, 255, -153 + 5, + 0, 33, -151, + 34, 34, 284, + 35, 122, -151, + 123, 123, 285, + 124, 255, 224 }; static const int lexer_goto_row229[] = { - 9, - 0, 9, 284, - 10, 10, 285, - 11, 12, 284, - 13, 13, 286, - 14, 38, 284, - 39, 39, 287, - 40, 91, 284, - 92, 92, 288, - 93, 255, 284 + 3, + 0, 9, 286, + 11, 12, 286, + 14, 255, 286 }; static const int lexer_goto_row230[] = { - 3, - 0, 9, 289, - 11, 12, 289, - 14, 255, 289 + 5, + 0, 33, -151, + 34, 34, 287, + 35, 122, -151, + 123, 123, 288, + 124, 255, 224 +}; +static const int lexer_goto_row231[] = { + 1, + 0, 255, -155 }; static const int lexer_goto_row232[] = { 1, - 56, 56, 290 + 0, 255, -155 }; static const int lexer_goto_row233[] = { 1, - 56, 56, 291 + 0, 255, -155 }; static const int lexer_goto_row234[] = { - 1, - 56, 56, 292 + 9, + 0, 9, 289, + 10, 10, 290, + 11, 12, 289, + 13, 13, 291, + 14, 38, 289, + 39, 39, 292, + 40, 91, 289, + 92, 92, 293, + 93, 255, 289 }; static const int lexer_goto_row235[] = { - 1, - 98, 98, 293 + 3, + 0, 9, 294, + 11, 12, 294, + 14, 255, 294 }; -static const int lexer_goto_row236[] = { +static const int lexer_goto_row237[] = { 1, - 0, 255, -99 + 56, 56, 295 }; -static const int lexer_goto_row237[] = { +static const int lexer_goto_row238[] = { 1, - 0, 255, -99 + 56, 56, 296 }; static const int lexer_goto_row239[] = { - 3, - 48, 115, -113, - 116, 116, 294, - 117, 122, 101 + 1, + 56, 56, 297 }; static const int lexer_goto_row240[] = { - 3, - 48, 113, -36, - 114, 114, 295, - 115, 122, 101 + 1, + 98, 98, 298 }; static const int lexer_goto_row241[] = { - 3, - 48, 113, -36, - 114, 114, 296, - 115, 122, 101 + 1, + 0, 255, -101 }; static const int lexer_goto_row242[] = { - 3, - 48, 106, -204, - 107, 107, 297, - 108, 122, 101 -}; -static const int lexer_goto_row243[] = { - 3, - 48, 114, -106, - 115, 115, 298, - 116, 122, 101 + 1, + 0, 255, -101 }; static const int lexer_goto_row244[] = { 3, - 48, 104, -119, - 105, 105, 299, - 106, 122, 101 + 48, 115, -115, + 116, 116, 299, + 117, 122, 103 }; static const int lexer_goto_row245[] = { - 1, - 48, 122, -41 + 3, + 48, 113, -36, + 114, 114, 300, + 115, 122, 103 }; static const int lexer_goto_row246[] = { - 1, - 48, 122, -41 + 3, + 48, 113, -36, + 114, 114, 301, + 115, 122, 103 }; static const int lexer_goto_row247[] = { 3, - 48, 113, -36, - 114, 114, 300, - 115, 122, 101 + 48, 106, -209, + 107, 107, 302, + 108, 122, 103 }; static const int lexer_goto_row248[] = { 3, - 48, 100, -45, - 101, 101, 301, - 102, 122, 101 + 48, 114, -108, + 115, 115, 303, + 116, 122, 103 }; static const int lexer_goto_row249[] = { 3, - 48, 104, -119, - 105, 105, 302, - 106, 122, 101 + 48, 104, -121, + 105, 105, 304, + 106, 122, 103 }; static const int lexer_goto_row250[] = { - 3, - 48, 113, -36, - 114, 114, 303, - 115, 122, 101 + 1, + 48, 122, -41 }; static const int lexer_goto_row251[] = { 1, @@ -1308,26 +1307,26 @@ static const int lexer_goto_row251[] = { static const int lexer_goto_row252[] = { 3, 48, 113, -36, - 114, 114, 304, - 115, 122, 101 + 114, 114, 305, + 115, 122, 103 }; static const int lexer_goto_row253[] = { 3, - 48, 116, -136, - 117, 117, 305, - 118, 122, 101 + 48, 100, -45, + 101, 101, 306, + 102, 122, 103 }; static const int lexer_goto_row254[] = { 3, - 48, 115, -113, - 116, 116, 306, - 117, 122, 101 + 48, 104, -121, + 105, 105, 307, + 106, 122, 103 }; static const int lexer_goto_row255[] = { 3, - 48, 107, -37, - 108, 108, 307, - 109, 122, 101 + 48, 113, -36, + 114, 114, 308, + 115, 122, 103 }; static const int lexer_goto_row256[] = { 1, @@ -1335,466 +1334,468 @@ static const int lexer_goto_row256[] = { }; static const int lexer_goto_row257[] = { 3, - 48, 107, -37, - 108, 108, 308, - 109, 122, 101 + 48, 113, -36, + 114, 114, 309, + 115, 122, 103 }; static const int lexer_goto_row258[] = { 3, - 48, 95, -35, - 97, 97, 309, - 98, 122, 101 + 48, 116, -138, + 117, 117, 310, + 118, 122, 103 }; static const int lexer_goto_row259[] = { + 3, + 48, 115, -115, + 116, 116, 311, + 117, 122, 103 +}; +static const int lexer_goto_row260[] = { + 3, + 48, 107, -37, + 108, 108, 312, + 109, 122, 103 +}; +static const int lexer_goto_row261[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row260[] = { +static const int lexer_goto_row262[] = { + 3, + 48, 107, -37, + 108, 108, 313, + 109, 122, 103 +}; +static const int lexer_goto_row263[] = { 3, 48, 95, -35, - 97, 97, 310, - 98, 122, 101 + 97, 97, 314, + 98, 122, 103 }; -static const int lexer_goto_row261[] = { +static const int lexer_goto_row264[] = { + 1, + 48, 122, -41 +}; +static const int lexer_goto_row265[] = { 3, 48, 95, -35, - 97, 97, 311, - 98, 122, 101 + 97, 97, 315, + 98, 122, 103 }; -static const int lexer_goto_row262[] = { +static const int lexer_goto_row266[] = { + 3, + 48, 95, -35, + 97, 97, 316, + 98, 122, 103 +}; +static const int lexer_goto_row267[] = { 3, 48, 100, -45, - 101, 101, 312, - 102, 122, 101 + 101, 101, 317, + 102, 122, 103 }; -static const int lexer_goto_row263[] = { +static const int lexer_goto_row268[] = { 3, - 48, 104, -119, - 105, 105, 313, - 106, 122, 101 + 48, 104, -121, + 105, 105, 318, + 106, 122, 103 }; -static const int lexer_goto_row264[] = { +static const int lexer_goto_row269[] = { 3, 48, 101, -42, - 102, 102, 314, - 103, 122, 101 + 102, 102, 319, + 103, 122, 103 }; -static const int lexer_goto_row265[] = { +static const int lexer_goto_row270[] = { 3, 48, 113, -36, - 114, 114, 315, - 115, 122, 101 + 114, 114, 320, + 115, 122, 103 }; -static const int lexer_goto_row266[] = { +static const int lexer_goto_row271[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row267[] = { +static const int lexer_goto_row272[] = { 3, 48, 113, -36, - 114, 114, 316, - 115, 122, 101 + 114, 114, 321, + 115, 122, 103 }; -static const int lexer_goto_row268[] = { +static const int lexer_goto_row273[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row269[] = { +static const int lexer_goto_row274[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row270[] = { +static const int lexer_goto_row275[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row271[] = { +static const int lexer_goto_row276[] = { 3, 48, 100, -45, - 101, 101, 317, - 102, 122, 101 + 101, 101, 322, + 102, 122, 103 }; -static const int lexer_goto_row272[] = { +static const int lexer_goto_row277[] = { 3, 48, 100, -45, - 101, 101, 318, - 102, 122, 101 + 101, 101, 323, + 102, 122, 103 }; -static const int lexer_goto_row273[] = { +static const int lexer_goto_row278[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row274[] = { +static const int lexer_goto_row279[] = { 1, - 0, 255, -220 + 0, 255, -225 }; -static const int lexer_goto_row275[] = { +static const int lexer_goto_row280[] = { 11, - 0, 9, 319, - 10, 10, 274, - 11, 12, 319, - 13, 13, 275, - 14, 33, 319, - 34, 34, 320, - 35, 91, 319, - 92, 92, 321, - 93, 122, 319, - 123, 123, 322, - 124, 255, 319 + 0, 9, 324, + 10, 10, 279, + 11, 12, 324, + 13, 13, 280, + 14, 33, 324, + 34, 34, 325, + 35, 91, 324, + 92, 92, 326, + 93, 122, 324, + 123, 123, 327, + 124, 255, 324 }; -static const int lexer_goto_row276[] = { +static const int lexer_goto_row281[] = { 1, - 0, 255, -276 + 0, 255, -281 }; -static const int lexer_goto_row277[] = { +static const int lexer_goto_row282[] = { 5, - 0, 33, -276, - 34, 34, 323, - 35, 122, -276, - 123, 123, 324, - 124, 255, 319 + 0, 33, -281, + 34, 34, 328, + 35, 122, -281, + 123, 123, 329, + 124, 255, 324 }; -static const int lexer_goto_row278[] = { +static const int lexer_goto_row283[] = { 3, - 0, 9, 325, - 11, 12, 325, - 14, 255, 325 + 0, 9, 330, + 11, 12, 330, + 14, 255, 330 }; -static const int lexer_goto_row279[] = { +static const int lexer_goto_row284[] = { 5, - 0, 33, -276, - 34, 34, 326, - 35, 122, -276, - 123, 123, 327, - 124, 255, 319 + 0, 33, -281, + 34, 34, 331, + 35, 122, -281, + 123, 123, 332, + 124, 255, 324 }; -static const int lexer_goto_row280[] = { +static const int lexer_goto_row285[] = { 3, - 0, 33, -149, - 34, 34, 328, - 35, 255, -224 + 0, 33, -151, + 34, 34, 333, + 35, 255, -229 }; -static const int lexer_goto_row281[] = { +static const int lexer_goto_row286[] = { 3, - 0, 122, -226, - 123, 123, 329, - 124, 255, 219 + 0, 122, -231, + 123, 123, 334, + 124, 255, 224 }; -static const int lexer_goto_row282[] = { +static const int lexer_goto_row287[] = { 1, - 0, 255, -149 + 0, 255, -151 }; -static const int lexer_goto_row283[] = { +static const int lexer_goto_row288[] = { 3, - 0, 33, -149, - 34, 34, 330, - 35, 255, -224 + 0, 33, -151, + 34, 34, 335, + 35, 255, -229 }; -static const int lexer_goto_row284[] = { +static const int lexer_goto_row289[] = { 3, - 0, 122, -226, - 123, 123, 331, - 124, 255, 219 + 0, 122, -231, + 123, 123, 336, + 124, 255, 224 }; -static const int lexer_goto_row285[] = { +static const int lexer_goto_row290[] = { 1, - 0, 255, -153 + 0, 255, -155 }; -static const int lexer_goto_row286[] = { +static const int lexer_goto_row291[] = { 1, - 0, 255, -153 + 0, 255, -155 }; -static const int lexer_goto_row287[] = { +static const int lexer_goto_row292[] = { 1, - 0, 255, -153 + 0, 255, -155 }; -static const int lexer_goto_row288[] = { +static const int lexer_goto_row293[] = { 9, - 0, 9, 332, - 10, 10, 333, - 11, 12, 332, - 13, 13, 334, - 14, 38, 332, - 39, 39, 335, - 40, 91, 332, - 92, 92, 336, - 93, 255, 332 -}; -static const int lexer_goto_row289[] = { - 3, 0, 9, 337, + 10, 10, 338, 11, 12, 337, - 14, 255, 337 + 13, 13, 339, + 14, 38, 337, + 39, 39, 340, + 40, 91, 337, + 92, 92, 341, + 93, 255, 337 }; -static const int lexer_goto_row290[] = { +static const int lexer_goto_row294[] = { + 3, + 0, 9, 342, + 11, 12, 342, + 14, 255, 342 +}; +static const int lexer_goto_row295[] = { 1, - 0, 255, -153 + 0, 255, -155 }; -static const int lexer_goto_row294[] = { +static const int lexer_goto_row299[] = { 1, - 117, 117, 338 + 117, 117, 343 }; -static const int lexer_goto_row295[] = { +static const int lexer_goto_row300[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row296[] = { +static const int lexer_goto_row301[] = { 3, 48, 95, -35, - 97, 97, 339, - 98, 122, 101 + 97, 97, 344, + 98, 122, 103 }; -static const int lexer_goto_row297[] = { +static const int lexer_goto_row302[] = { 3, - 48, 115, -113, - 116, 116, 340, - 117, 122, 101 + 48, 115, -115, + 116, 116, 345, + 117, 122, 103 }; -static const int lexer_goto_row298[] = { +static const int lexer_goto_row303[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row299[] = { +static const int lexer_goto_row304[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row300[] = { +static const int lexer_goto_row305[] = { 3, 48, 109, -46, - 110, 110, 341, - 111, 122, 101 + 110, 110, 346, + 111, 122, 103 }; -static const int lexer_goto_row301[] = { +static const int lexer_goto_row306[] = { 3, 48, 109, -46, - 110, 110, 342, - 111, 122, 101 + 110, 110, 347, + 111, 122, 103 }; -static const int lexer_goto_row302[] = { +static const int lexer_goto_row307[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row303[] = { +static const int lexer_goto_row308[] = { 3, 48, 100, -45, - 101, 101, 343, - 102, 122, 101 + 101, 101, 348, + 102, 122, 103 }; -static const int lexer_goto_row304[] = { +static const int lexer_goto_row309[] = { 3, - 48, 115, -113, - 116, 116, 344, - 117, 122, 101 + 48, 115, -115, + 116, 116, 349, + 117, 122, 103 }; -static const int lexer_goto_row305[] = { +static const int lexer_goto_row310[] = { 3, 48, 101, -42, - 102, 102, 345, - 103, 122, 101 + 102, 102, 350, + 103, 122, 103 }; -static const int lexer_goto_row306[] = { +static const int lexer_goto_row311[] = { 3, - 48, 99, -105, - 100, 100, 346, - 101, 122, 101 + 48, 99, -107, + 100, 100, 351, + 101, 122, 103 }; -static const int lexer_goto_row307[] = { +static const int lexer_goto_row312[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row308[] = { +static const int lexer_goto_row313[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row309[] = { +static const int lexer_goto_row314[] = { 3, 48, 100, -45, - 101, 101, 347, - 102, 122, 101 + 101, 101, 352, + 102, 122, 103 }; -static const int lexer_goto_row310[] = { +static const int lexer_goto_row315[] = { 3, 48, 97, -35, - 98, 98, 348, - 99, 122, 101 + 98, 98, 353, + 99, 122, 103 }; -static const int lexer_goto_row311[] = { +static const int lexer_goto_row316[] = { 4, 48, 95, -35, - 97, 102, 101, - 103, 103, 349, - 104, 122, 101 + 97, 102, 103, + 103, 103, 354, + 104, 122, 103 }; -static const int lexer_goto_row312[] = { +static const int lexer_goto_row317[] = { 3, - 48, 115, -113, - 116, 116, 350, - 117, 122, 101 + 48, 115, -115, + 116, 116, 355, + 117, 122, 103 }; -static const int lexer_goto_row313[] = { +static const int lexer_goto_row318[] = { 3, - 48, 98, -127, - 99, 99, 351, - 100, 122, 101 + 48, 98, -129, + 99, 99, 356, + 100, 122, 103 }; -static const int lexer_goto_row314[] = { +static const int lexer_goto_row319[] = { 3, - 48, 98, -127, - 99, 99, 352, - 100, 122, 101 + 48, 98, -129, + 99, 99, 357, + 100, 122, 103 }; -static const int lexer_goto_row315[] = { +static const int lexer_goto_row320[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row316[] = { +static const int lexer_goto_row321[] = { 3, 48, 109, -46, - 110, 110, 353, - 111, 122, 101 + 110, 110, 358, + 111, 122, 103 }; -static const int lexer_goto_row317[] = { +static const int lexer_goto_row322[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row318[] = { +static const int lexer_goto_row323[] = { 3, 48, 113, -36, - 114, 114, 354, - 115, 122, 101 + 114, 114, 359, + 115, 122, 103 }; -static const int lexer_goto_row319[] = { +static const int lexer_goto_row324[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row320[] = { - 1, - 0, 255, -276 -}; -static const int lexer_goto_row321[] = { - 1, - 0, 255, -278 -}; -static const int lexer_goto_row322[] = { - 3, - 0, 9, 355, - 11, 12, 355, - 14, 255, 355 -}; -static const int lexer_goto_row323[] = { - 1, - 0, 255, -280 -}; -static const int lexer_goto_row324[] = { - 3, - 0, 33, -276, - 34, 34, 356, - 35, 255, -278 -}; static const int lexer_goto_row325[] = { - 3, - 0, 122, -280, - 123, 123, 357, - 124, 255, 319 + 1, + 0, 255, -281 }; static const int lexer_goto_row326[] = { 1, - 0, 255, -220 + 0, 255, -283 }; static const int lexer_goto_row327[] = { 3, - 0, 33, -276, - 34, 34, 358, - 35, 255, -278 + 0, 9, 360, + 11, 12, 360, + 14, 255, 360 }; static const int lexer_goto_row328[] = { - 3, - 0, 122, -280, - 123, 123, 359, - 124, 255, 319 + 1, + 0, 255, -285 }; static const int lexer_goto_row329[] = { - 1, - 34, 34, 360 + 3, + 0, 33, -281, + 34, 34, 361, + 35, 255, -283 }; static const int lexer_goto_row330[] = { - 1, - 0, 255, -285 + 3, + 0, 122, -285, + 123, 123, 362, + 124, 255, 324 }; static const int lexer_goto_row331[] = { 1, - 0, 255, -281 + 0, 255, -225 }; static const int lexer_goto_row332[] = { - 1, - 123, 123, 361 + 3, + 0, 33, -281, + 34, 34, 363, + 35, 255, -283 }; static const int lexer_goto_row333[] = { - 1, - 0, 255, -153 + 3, + 0, 122, -285, + 123, 123, 364, + 124, 255, 324 }; static const int lexer_goto_row334[] = { 1, - 0, 255, -153 + 34, 34, 365 }; static const int lexer_goto_row335[] = { 1, - 0, 255, -153 + 0, 255, -290 +}; +static const int lexer_goto_row336[] = { + 1, + 0, 255, -286 }; static const int lexer_goto_row337[] = { - 3, - 0, 9, 362, - 11, 12, 362, - 14, 255, 362 + 1, + 123, 123, 366 }; static const int lexer_goto_row338[] = { 1, - 0, 255, -153 + 0, 255, -155 }; static const int lexer_goto_row339[] = { 1, - 103, 103, 363 + 0, 255, -155 }; static const int lexer_goto_row340[] = { - 3, - 48, 98, -127, - 99, 99, 364, - 100, 122, 101 -}; -static const int lexer_goto_row341[] = { 1, - 48, 122, -41 + 0, 255, -155 }; static const int lexer_goto_row342[] = { 3, - 48, 116, -136, - 117, 117, 365, - 118, 122, 101 + 0, 9, 367, + 11, 12, 367, + 14, 255, 367 }; static const int lexer_goto_row343[] = { 1, - 48, 122, -41 + 0, 255, -155 }; static const int lexer_goto_row344[] = { - 3, - 48, 114, -106, - 115, 115, 366, - 116, 122, 101 + 1, + 103, 103, 368 }; static const int lexer_goto_row345[] = { - 1, - 48, 122, -41 + 3, + 48, 98, -129, + 99, 99, 369, + 100, 122, 103 }; static const int lexer_goto_row346[] = { - 3, - 48, 95, -35, - 97, 97, 367, - 98, 122, 101 + 1, + 48, 122, -41 }; static const int lexer_goto_row347[] = { 3, - 48, 100, -45, - 101, 101, 368, - 102, 122, 101 + 48, 116, -138, + 117, 117, 370, + 118, 122, 103 }; static const int lexer_goto_row348[] = { 1, @@ -1802,113 +1803,115 @@ static const int lexer_goto_row348[] = { }; static const int lexer_goto_row349[] = { 3, - 48, 107, -37, - 108, 108, 369, - 109, 122, 101 + 48, 114, -108, + 115, 115, 371, + 116, 122, 103 }; static const int lexer_goto_row350[] = { - 3, - 48, 100, -45, - 101, 101, 370, - 102, 122, 101 + 1, + 48, 122, -41 }; static const int lexer_goto_row351[] = { 3, - 48, 100, -45, - 101, 101, 371, - 102, 122, 101 + 48, 95, -35, + 97, 97, 372, + 98, 122, 103 }; static const int lexer_goto_row352[] = { 3, - 48, 115, -113, - 116, 116, 372, - 117, 122, 101 + 48, 100, -45, + 101, 101, 373, + 102, 122, 103 }; static const int lexer_goto_row353[] = { 1, 48, 122, -41 }; static const int lexer_goto_row354[] = { - 1, - 48, 122, -41 + 3, + 48, 107, -37, + 108, 108, 374, + 109, 122, 103 }; static const int lexer_goto_row355[] = { 3, - 48, 114, -106, - 115, 115, 373, - 116, 122, 101 + 48, 100, -45, + 101, 101, 375, + 102, 122, 103 }; static const int lexer_goto_row356[] = { - 1, - 0, 255, -276 + 3, + 48, 100, -45, + 101, 101, 376, + 102, 122, 103 }; static const int lexer_goto_row357[] = { - 1, - 34, 34, 374 + 3, + 48, 115, -115, + 116, 116, 377, + 117, 122, 103 }; static const int lexer_goto_row358[] = { 1, - 0, 255, -329 + 48, 122, -41 }; static const int lexer_goto_row359[] = { 1, - 0, 255, -325 + 48, 122, -41 }; static const int lexer_goto_row360[] = { - 1, - 123, 123, 375 + 3, + 48, 114, -108, + 115, 115, 378, + 116, 122, 103 }; static const int lexer_goto_row361[] = { 1, - 34, 34, 360 + 0, 255, -281 }; static const int lexer_goto_row362[] = { 1, - 123, 123, 361 + 34, 34, 379 }; static const int lexer_goto_row363[] = { 1, - 0, 255, -153 + 0, 255, -334 }; static const int lexer_goto_row364[] = { 1, - 95, 95, 376 + 0, 255, -330 }; static const int lexer_goto_row365[] = { - 3, - 48, 115, -113, - 116, 116, 377, - 117, 122, 101 + 1, + 123, 123, 380 }; static const int lexer_goto_row366[] = { - 3, - 48, 100, -45, - 101, 101, 378, - 102, 122, 101 + 1, + 34, 34, 365 }; static const int lexer_goto_row367[] = { 1, - 48, 122, -41 + 123, 123, 366 }; static const int lexer_goto_row368[] = { - 3, - 48, 98, -127, - 99, 99, 379, - 100, 122, 101 + 1, + 0, 255, -155 }; static const int lexer_goto_row369[] = { 1, - 48, 122, -41 + 95, 95, 381 }; static const int lexer_goto_row370[] = { 3, - 48, 100, -45, - 101, 101, 380, - 102, 122, 101 + 48, 115, -115, + 116, 116, 382, + 117, 122, 103 }; static const int lexer_goto_row371[] = { - 1, - 48, 122, -41 + 3, + 48, 100, -45, + 101, 101, 383, + 102, 122, 103 }; static const int lexer_goto_row372[] = { 1, @@ -1916,67 +1919,91 @@ static const int lexer_goto_row372[] = { }; static const int lexer_goto_row373[] = { 3, - 48, 100, -45, - 101, 101, 381, - 102, 122, 101 + 48, 98, -129, + 99, 99, 384, + 100, 122, 103 }; static const int lexer_goto_row374[] = { - 3, - 48, 95, -35, - 97, 97, 382, - 98, 122, 101 + 1, + 48, 122, -41 }; static const int lexer_goto_row375[] = { - 1, - 34, 34, 374 + 3, + 48, 100, -45, + 101, 101, 385, + 102, 122, 103 }; static const int lexer_goto_row376[] = { 1, - 123, 123, 375 + 48, 122, -41 }; static const int lexer_goto_row377[] = { 1, - 95, 95, 383 + 48, 122, -41 }; static const int lexer_goto_row378[] = { + 3, + 48, 100, -45, + 101, 101, 386, + 102, 122, 103 +}; +static const int lexer_goto_row379[] = { + 3, + 48, 95, -35, + 97, 97, 387, + 98, 122, 103 +}; +static const int lexer_goto_row380[] = { + 1, + 34, 34, 379 +}; +static const int lexer_goto_row381[] = { + 1, + 123, 123, 380 +}; +static const int lexer_goto_row382[] = { + 1, + 95, 95, 388 +}; +static const int lexer_goto_row383[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row379[] = { +static const int lexer_goto_row384[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row380[] = { +static const int lexer_goto_row385[] = { 3, 48, 100, -45, - 101, 101, 384, - 102, 122, 101 + 101, 101, 389, + 102, 122, 103 }; -static const int lexer_goto_row381[] = { +static const int lexer_goto_row386[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row382[] = { +static const int lexer_goto_row387[] = { 3, - 48, 99, -105, - 100, 100, 385, - 101, 122, 101 + 48, 99, -107, + 100, 100, 390, + 101, 122, 103 }; -static const int lexer_goto_row383[] = { +static const int lexer_goto_row388[] = { 3, 48, 107, -37, - 108, 108, 386, - 109, 122, 101 + 108, 108, 391, + 109, 122, 103 }; -static const int lexer_goto_row385[] = { +static const int lexer_goto_row390[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row386[] = { +static const int lexer_goto_row391[] = { 1, 48, 122, -41 }; -static const int lexer_goto_row387[] = { +static const int lexer_goto_row392[] = { 1, 48, 122, -41 }; @@ -2066,19 +2093,19 @@ const int* const lexer_goto_table[] = { lexer_goto_row82, lexer_goto_row83, lexer_goto_row84, - lexer_goto_row_null, + lexer_goto_row85, lexer_goto_row86, - lexer_goto_row87, + lexer_goto_row_null, + lexer_goto_row88, + lexer_goto_row89, lexer_goto_row_null, lexer_goto_row_null, - lexer_goto_row90, - lexer_goto_row91, lexer_goto_row92, lexer_goto_row93, lexer_goto_row94, - lexer_goto_row_null, + lexer_goto_row95, lexer_goto_row96, - lexer_goto_row97, + lexer_goto_row_null, lexer_goto_row98, lexer_goto_row99, lexer_goto_row100, @@ -2122,7 +2149,7 @@ const int* const lexer_goto_table[] = { lexer_goto_row138, lexer_goto_row139, lexer_goto_row140, - lexer_goto_row_null, + lexer_goto_row141, lexer_goto_row142, lexer_goto_row_null, lexer_goto_row144, @@ -2130,15 +2157,15 @@ const int* const lexer_goto_table[] = { lexer_goto_row146, lexer_goto_row_null, lexer_goto_row148, - lexer_goto_row149, + lexer_goto_row_null, + lexer_goto_row150, + lexer_goto_row151, lexer_goto_row_null, lexer_goto_row_null, - lexer_goto_row152, - lexer_goto_row153, + lexer_goto_row154, + lexer_goto_row155, lexer_goto_row_null, lexer_goto_row_null, - lexer_goto_row156, - lexer_goto_row157, lexer_goto_row158, lexer_goto_row159, lexer_goto_row160, @@ -2146,15 +2173,15 @@ const int* const lexer_goto_table[] = { lexer_goto_row162, lexer_goto_row163, lexer_goto_row164, + lexer_goto_row165, + lexer_goto_row166, + lexer_goto_row167, + lexer_goto_row168, + lexer_goto_row169, lexer_goto_row_null, lexer_goto_row_null, lexer_goto_row_null, lexer_goto_row_null, - lexer_goto_row169, - lexer_goto_row170, - lexer_goto_row171, - lexer_goto_row172, - lexer_goto_row173, lexer_goto_row174, lexer_goto_row175, lexer_goto_row176, @@ -2212,19 +2239,19 @@ const int* const lexer_goto_table[] = { lexer_goto_row228, lexer_goto_row229, lexer_goto_row230, - lexer_goto_row_null, + lexer_goto_row231, lexer_goto_row232, lexer_goto_row233, lexer_goto_row234, lexer_goto_row235, - lexer_goto_row236, - lexer_goto_row237, lexer_goto_row_null, + lexer_goto_row237, + lexer_goto_row238, lexer_goto_row239, lexer_goto_row240, lexer_goto_row241, lexer_goto_row242, - lexer_goto_row243, + lexer_goto_row_null, lexer_goto_row244, lexer_goto_row245, lexer_goto_row246, @@ -2272,14 +2299,14 @@ const int* const lexer_goto_table[] = { lexer_goto_row288, lexer_goto_row289, lexer_goto_row290, + lexer_goto_row291, + lexer_goto_row292, + lexer_goto_row293, + lexer_goto_row294, + lexer_goto_row295, lexer_goto_row_null, lexer_goto_row_null, lexer_goto_row_null, - lexer_goto_row294, - lexer_goto_row295, - lexer_goto_row296, - lexer_goto_row297, - lexer_goto_row298, lexer_goto_row299, lexer_goto_row300, lexer_goto_row301, @@ -2317,12 +2344,12 @@ const int* const lexer_goto_table[] = { lexer_goto_row333, lexer_goto_row334, lexer_goto_row335, - lexer_goto_row_null, + lexer_goto_row336, lexer_goto_row337, lexer_goto_row338, lexer_goto_row339, lexer_goto_row340, - lexer_goto_row341, + lexer_goto_row_null, lexer_goto_row342, lexer_goto_row343, lexer_goto_row344, @@ -2365,14 +2392,19 @@ const int* const lexer_goto_table[] = { lexer_goto_row381, lexer_goto_row382, lexer_goto_row383, - lexer_goto_row_null, + lexer_goto_row384, lexer_goto_row385, lexer_goto_row386, - lexer_goto_row387 + lexer_goto_row387, + lexer_goto_row388, + lexer_goto_row_null, + lexer_goto_row390, + lexer_goto_row391, + lexer_goto_row392 }; const int lexer_accept_table[] = { - -1,0,1,1,0,94,114,2,80,83,-1,53,54,77,75,57,76,74,79,100,100,58,96,87,60,90,95,97,55,56,82,-1,-1,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,81,114,84,1,86,114,109,-1,110,2,2,2,65,69,115,115,115,78,63,61,62,73,108,64,-1,-1,-1,-1,-1,-1,-1,-1,59,89,88,85,91,92,97,97,97,97,68,-1,99,-1,98,98,98,98,98,98,47,98,98,98,16,98,98,98,98,98,98,23,98,29,15,98,98,98,98,98,98,98,31,98,98,98,98,98,98,98,98,98,98,98,98,98,67,114,112,-1,111,114,109,114,114,2,113,114,115,66,72,102,102,102,103,103,101,101,101,101,104,70,93,71,-1,99,99,99,99,-1,-1,-1,98,98,30,98,98,98,98,98,10,98,98,98,28,11,98,98,98,40,98,98,98,98,39,32,98,98,98,98,98,98,98,98,98,98,98,98,98,98,17,98,98,114,114,114,114,114,-1,-1,-1,114,114,114,-1,-1,113,-1,-1,-1,-1,-1,-1,116,98,98,98,98,98,98,25,9,98,98,98,98,13,98,98,98,98,27,98,46,41,98,98,98,98,98,98,43,98,24,44,12,98,98,51,114,-1,-1,112,-1,111,-1,-1,114,-1,-1,114,114,114,-1,-1,114,106,107,105,-1,37,98,98,36,6,98,98,45,98,98,98,98,49,50,98,98,98,98,98,98,14,98,42,98,26,-1,-1,-1,-1,-1,-1,114,-1,-1,109,-1,-1,110,114,114,114,109,-1,114,-1,98,38,98,18,98,5,98,98,4,98,98,98,98,19,34,98,-1,112,-1,-1,111,109,110,114,-1,98,98,33,98,22,98,3,21,98,98,112,111,-1,7,35,98,48,98,98,52,8,20,9 + -1,0,1,1,0,94,114,2,80,83,-1,53,54,77,75,57,76,74,79,100,100,58,96,87,60,90,95,97,55,56,82,-1,-1,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,81,114,84,1,86,114,109,-1,110,2,2,2,65,69,115,115,115,78,63,61,62,73,108,64,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,59,89,88,85,91,92,97,97,97,97,68,-1,99,-1,98,98,98,98,98,98,47,98,98,98,16,98,98,98,98,98,98,23,98,29,15,98,98,98,98,98,98,98,31,98,98,98,98,98,98,98,98,98,98,98,98,98,67,114,112,-1,111,114,109,114,114,2,113,114,115,66,72,102,102,102,-1,-1,108,103,103,101,101,101,101,104,70,93,71,-1,99,99,99,99,-1,-1,-1,98,98,30,98,98,98,98,98,10,98,98,98,28,11,98,98,98,40,98,98,98,98,39,32,98,98,98,98,98,98,98,98,98,98,98,98,98,98,17,98,98,114,114,114,114,114,-1,-1,-1,114,114,114,-1,-1,113,-1,-1,-1,-1,-1,-1,116,98,98,98,98,98,98,25,9,98,98,98,98,13,98,98,98,98,27,98,46,41,98,98,98,98,98,98,43,98,24,44,12,98,98,51,114,-1,-1,112,-1,111,-1,-1,114,-1,-1,114,114,114,-1,-1,114,106,107,105,-1,37,98,98,36,6,98,98,45,98,98,98,98,49,50,98,98,98,98,98,98,14,98,42,98,26,-1,-1,-1,-1,-1,-1,114,-1,-1,109,-1,-1,110,114,114,114,109,-1,114,-1,98,38,98,18,98,5,98,98,4,98,98,98,98,19,34,98,-1,112,-1,-1,111,109,110,114,-1,98,98,33,98,22,98,3,21,98,98,112,111,-1,7,35,98,48,98,98,52,8,20,9 }; static int parser_action_row1[] = { diff --git a/src/phase.nit b/src/phase.nit index 5f0faf1..682d23e 100644 --- a/src/phase.nit +++ b/src/phase.nit @@ -115,7 +115,6 @@ redef class ToolContext phase.process_nmodule(nmodule) if errcount != self.error_count then self.check_errors - break end errcount = self.error_count for nclassdef in nmodule.n_classdefs do @@ -128,7 +127,6 @@ redef class ToolContext end if errcount != self.error_count then self.check_errors - break end for na in vannot.annotations do var p = na.parent @@ -138,7 +136,6 @@ redef class ToolContext end if errcount != self.error_count then self.check_errors - break end end self.check_errors diff --git a/src/rapid_type_analysis.nit b/src/rapid_type_analysis.nit index a87bc94..9010dde 100644 --- a/src/rapid_type_analysis.nit +++ b/src/rapid_type_analysis.nit @@ -218,13 +218,16 @@ class RapidTypeAnalysis while not todo.is_empty do var mmethoddef = todo.shift var mmeth = mmethoddef.mproperty + var msignature = mmethoddef.msignature + if msignature == null then continue # Skip broken method + #print "# visit {mmethoddef}" var v = new RapidTypeVisitor(self, mmethoddef.mclassdef.bound_mtype, mmethoddef) - var vararg_rank = mmethoddef.msignature.vararg_rank + var vararg_rank = msignature.vararg_rank if vararg_rank > -1 then var node = self.modelbuilder.mpropdef2node(mmethoddef) - var elttype = mmethoddef.msignature.mparameters[vararg_rank].mtype + var elttype = msignature.mparameters[vararg_rank].mtype #elttype = elttype.anchor_to(self.mainmodule, v.receiver) var vararg = self.mainmodule.array_type(elttype) v.add_type(vararg) @@ -234,7 +237,7 @@ class RapidTypeAnalysis end # TODO? new_msignature - var sig = mmethoddef.msignature.as(not null) + var sig = msignature var osig = mmeth.intro.msignature.as(not null) for i in [0..sig.arity[ do var origtype = osig.mparameters[i].mtype @@ -255,7 +258,7 @@ class RapidTypeAnalysis continue else if mmethoddef.constant_value != null then # Make the return type live - v.add_type(mmethoddef.msignature.return_mtype.as(MClassType)) + v.add_type(msignature.return_mtype.as(MClassType)) continue else if npropdef == null then abort @@ -275,7 +278,7 @@ class RapidTypeAnalysis if mmethoddef.is_intern or mmethoddef.is_extern then # UGLY: We force the "instantation" of the concrete return type if any - var ret = mmethoddef.msignature.return_mtype + var ret = msignature.return_mtype if ret != null and ret isa MClassType and ret.mclass.kind != abstract_kind and ret.mclass.kind != interface_kind then v.add_type(ret) end @@ -297,10 +300,10 @@ class RapidTypeAnalysis if not ot.can_resolve_for(t, t, mainmodule) then continue var rt = ot.anchor_to(mainmodule, t) if live_types.has(rt) then continue + if not check_depth(rt) then continue #print "{ot}/{t} -> {rt}" live_types.add(rt) todo_types.add(rt) - check_depth(rt) end end #print "MType {live_types.length}: {live_types.join(", ")}" @@ -318,12 +321,14 @@ class RapidTypeAnalysis #print "cast MType {live_cast_types.length}: {live_cast_types.join(", ")}" end - private fun check_depth(mtype: MClassType) + private fun check_depth(mtype: MClassType): Bool do var d = mtype.length if d > 255 then self.modelbuilder.toolcontext.fatal_error(null, "Fatal Error: limitation in the rapidtype analysis engine: a type depth of {d} is too important, the problematic type is `{mtype}`.") + return false end + return true end fun add_new(recv: MClassType, mtype: MClassType) @@ -450,10 +455,14 @@ class RapidTypeVisitor redef fun visit(n) do - n.accept_rapid_type_visitor(self) if n isa AExpr then - var implicit_cast_to = n.implicit_cast_to - if implicit_cast_to != null then self.add_cast_type(implicit_cast_to) + if n.mtype != null or n.is_typed then + n.accept_rapid_type_visitor(self) + var implicit_cast_to = n.implicit_cast_to + if implicit_cast_to != null then self.add_cast_type(implicit_cast_to) + end + else + n.accept_rapid_type_visitor(self) end # RTA does not enter in AAnnotations diff --git a/src/semantize/scope.nit b/src/semantize/scope.nit index a69c57a..4106660 100644 --- a/src/semantize/scope.nit +++ b/src/semantize/scope.nit @@ -33,13 +33,13 @@ end # A local variable (including parameters, automatic variables and self) class Variable # The name of the variable (as used in the program) - var name: String + var name: String is writable # Alias of `name` redef fun to_s do return self.name # The declaration of the variable, if any - var location: nullable Location = null + var location: nullable Location = null is writable # Is the local variable not read and need a warning? var warn_unread = false is writable @@ -439,7 +439,7 @@ end redef class AVarFormExpr # The associated variable - var variable: nullable Variable + var variable: nullable Variable is writable end redef class ACallFormExpr diff --git a/src/semantize/typing.nit b/src/semantize/typing.nit index 9676168..b37e4a4 100644 --- a/src/semantize/typing.nit +++ b/src/semantize/typing.nit @@ -648,7 +648,7 @@ end redef class Variable # The declared type of the variable - var declared_type: nullable MType + var declared_type: nullable MType is writable # Was the variable type-adapted? # This is used to speedup type retrieval while it remains `false` @@ -960,7 +960,7 @@ redef class AVarReassignExpr v.set_variable(self, variable, rettype) - self.is_typed = true + self.is_typed = rettype != null end end @@ -1006,9 +1006,11 @@ redef class AReturnExpr else v.visit_expr(nexpr) v.error(nexpr, "Error: `return` with value in a procedure.") + return end else if ret_type != null then v.error(self, "Error: `return` without value in a function.") + return end self.is_typed = true end @@ -2061,7 +2063,7 @@ redef class AAttrAssignExpr var mtype = self.attr_type v.visit_expr_subtype(self.n_value, mtype) - self.is_typed = true + self.is_typed = mtype != null end end @@ -2072,9 +2074,9 @@ redef class AAttrReassignExpr var mtype = self.attr_type if mtype == null then return # Skip error - self.resolve_reassignment(v, mtype, mtype) + var rettype = self.resolve_reassignment(v, mtype, mtype) - self.is_typed = true + self.is_typed = rettype != null end end diff --git a/src/ssa.nit b/src/ssa.nit new file mode 100644 index 0000000..634dfa3 --- /dev/null +++ b/src/ssa.nit @@ -0,0 +1,1138 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2015 Julien Pagès +# +# 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. + +# Single-Static Assignment algorithm from an AST +module ssa + +import semantize +import astbuilder + +# Represent a sequence of the program +# A basic block is composed of several instructions without a jump +class BasicBlock + # First instruction of the basic block + var first: ANode is noinit + + # Last instruction of the basic block + var last: ANode is noinit + + # Direct successors + var successors = new Array[BasicBlock] + + # Direct predecessors + var predecessors = new Array[BasicBlock] + + # Parts of AST that contain a read to a variable + var read_sites = new Array[AVarFormExpr] + + # Parts of AST that contain a write to a variable + var write_sites = new Array[AVarFormExpr] + + # Parts of AST that contain a variable access (read or write) + var variables_sites = new Array[AExpr] + + # The iterated dominance frontier of this block + # i.e. the set of blocks this block dominate directly or indirectly + var dominance_frontier: Array[BasicBlock] = new Array[BasicBlock] is lazy + + # Self is the old block to link to the new, + # The two blocks are not linked if the current ends with a `AReturnExpr` or `ABreakExpr` + # i.e. self is the predecessor of `successor` + # `successor` The successor block + fun link(successor: BasicBlock) + do + # Do not link the two blocks if the current block end with a return, break or continue + if last isa AReturnExpr or last isa ABreakExpr or last isa AContinueExpr then return + + successors.add(successor) + successor.predecessors.add(self) + end + + # Self is the old block to link to the new + # i.e. self is the predecessor of `successor` + # `successor` The successor block + fun link_special(successor: BasicBlock) + do + # Link the two blocks even if the current block ends with a return or a break + successors.add(successor) + successor.predecessors.add(self) + end + + # Add the `block` to the dominance frontier of this block + fun add_df(block: BasicBlock) + do + dominance_frontier.add(block) + + # Add this block recursively in super-blocks to compute the iterated + # dominance frontier + for successor in block.successors do + # If this successor has not already been add to the dominance frontier + if not dominance_frontier.has(successor) then + add_df(successor) + end + end + end + + # Compute recursively the dominance frontier of self block and its successors + private fun compute_df + do + # Treat each block only one time + df_computed = true + + for s in successors do + add_df(s) + + if not s.df_computed then s.compute_df + end + end + + # Used to handle recursions by treating only one time each block + var treated: Bool = false + + # Used to dump the BasicBlock to dot + var treated_debug: Bool = false + + # If true, the iterated dominance frontier of this block has been computed + var df_computed: Bool = false + + # Indicate the BasicBlock is newly created and needs to be updated + var need_update: Bool = false + + # Indicate if the variables renaming step has been made for this block + var is_renaming: Bool = false + + # The variables that are accessed in this block + var variables = new Array[Variable] is lazy + + # The PhiFunction this block contains at the beginning + var phi_functions = new Array[PhiFunction] is lazy +end + +# Contain the currently analyzed propdef +class SSA + # The currently analyzed APropdef + var propdef: APropdef + + # The PhiFunction `current_propdef` contains + var phi_functions = new Array[PhiFunction] + + # Recursively generate the basic blocks for this propdef + fun generate_basic_blocks + do + propdef.generate_basic_blocks(self) + end +end + +redef class Variable + # The expressions of AST of this variable depends + var dep_exprs = new Array[AExpr] + + # The blocks in which this variable is assigned + var assignment_blocks: Array[BasicBlock] = new Array[BasicBlock] is lazy + + # Part of the program where this variable is read + var read_blocks: Array[BasicBlock] = new Array[BasicBlock] is lazy + + # The stack of this variable, used for SSA renaming + var stack = new Array[Variable] is lazy + + # The original Variable in case of renaming + var original_variable: nullable Variable = self + + # If true, this variable is a parameter of a method + var parameter: Bool = false +end + +# A PhiFunction is a kind of Variable used in SSA-construction, +# it is placed at the beginning of a BasicBlock with many incoming blocks +class PhiFunction + super Variable + + # The dependences of this variable for SSA-Algorithm + var dependences = new Array[Couple[Variable, BasicBlock]] + + # The position in the AST of the phi-function + var block: BasicBlock + + # Set the dependences for the phi-function + # *`block` BasicBlock in which we go through the dominance-frontier + # *`v` The variable to looking for + fun add_dependences(block: BasicBlock, v: Variable) + do + # Look in which blocks of DF(block) `v` has been assigned + for b in block.predecessors do + if v.assignment_blocks.has(b) then + var dep = new Couple[Variable, BasicBlock](v, b) + dependences.add(dep) + end + end + end + + # Print the PhiFunction with all its dependences + redef fun to_s: String + do + var s = "" + s += " dependences = [ " + for d in dependences do + s += d.first.to_s + " " + end + s += "]" + + return s + end +end + +redef class APropdef + # The variables contained in the body on this propdef + var variables: HashSet[Variable] = new HashSet[Variable] is lazy + + # The first basic block of the code + var basic_block: nullable BasicBlock + + # If true, the basic blocks where generated + var is_generated: Bool = false + + # Generate all basic blocks for this code + fun generate_basic_blocks(ssa: SSA) is abstract + + # Contain all AST-parts related to object mechanisms the propdef has: + # instantiation, method dispatch, attribute access, subtyping-test + var object_sites: Array[AExpr] = new Array[AExpr] + + # Compute the three steps of SSA-algorithm + # `ssa` A new instance of SSA class initialized with `self` + fun compute_ssa(ssa: SSA) + do + if is_generated then return + + # The first step is to generate the basic blocks + generate_basic_blocks(ssa) + + # The propdef has no body (abstract) + if not is_generated then return + + # Once basic blocks were generated, compute SSA algorithm + compute_phi(ssa) + rename_variables(ssa) + ssa_destruction(ssa) + end + + # Compute the first phase of SSA algorithm: placing phi-functions + fun compute_phi(ssa: SSA) + do + var root_block = basic_block.as(not null) + + # Compute the iterated dominance frontier of the graph of basic blocks + root_block.compute_df + + # Places where a phi-function is added per variable + var phi_blocks = new HashMap[Variable, Array[BasicBlock]] + + # For each variables in the propdef + for v in variables do + var phi_variables = new Array[BasicBlock] + + var read_blocks = new Array[BasicBlock] + read_blocks.add_all(v.read_blocks) + read_blocks.add_all(v.assignment_blocks) + + # While we have not treated each part accessing `v` + while not read_blocks.is_empty do + # Remove a block from the array + var block = read_blocks.shift + + # For each block in the dominance frontier of `block` + for df in block.dominance_frontier do + # If we have not yet put a phi-function at the beginning of this block + if not phi_variables.has(df) then + phi_variables.add(df) + + # Create a new phi-function and set its dependences + var phi = new PhiFunction("phi", df) + phi.add_dependences(df, v) + phi.block = df + phi.original_variable = phi + phi.declared_type = v.declared_type + + # Indicate this phi-function is assigned in this block + phi.assignment_blocks.add(block) + ssa.phi_functions.add(phi) + + # Add a phi-function at the beginning of df for variable v + df.phi_functions.add(phi) + + if not v.read_blocks.has(df) or not v.assignment_blocks.has(df) then read_blocks.add(df) + end + end + end + + # Add `phi-variables` to the global map + phi_blocks[v] = phi_variables + end + end + + # Compute the second phase of SSA algorithm: renaming variables + # NOTE: `compute_phi` must has been called before + fun rename_variables(ssa: SSA) + do + # A counter for each variable + # The key is the variable, the value the number of assignment into the variable + var counter = new HashMap[Variable, Int] + + for v in variables do + counter[v] = 0 + v.stack.push(v) + end + + for phi in ssa.phi_functions do counter[phi] = 0 + + # Launch the recursive renaming from the root block + rename(basic_block.as(not null), counter, ssa) + end + + # Recursively rename each variable from `block` + # *`block` The starting basic block + # *`counter` The key is the variable, the value the number of assignment into the variable + fun rename(block: BasicBlock, counter: HashMap[Variable, Int], ssa: SSA) + do + if block.is_renaming then return + + block.is_renaming = true + + # For each phi-function of this block + for phi in block.phi_functions do + generate_name(phi, counter, block.first, ssa) + + # Replace the phi into the block + block.phi_functions[block.phi_functions.index_of(phi)] = phi.original_variable.stack.last.as(PhiFunction) + end + + # For each variable read in `block` + for vread in block.read_sites do + # Replace the old variable in AST + vread.variable = vread.variable.original_variable.stack.last + end + + # For each variable write + for vwrite in block.write_sites do + generate_name(vwrite.variable.as(not null), counter, vwrite, ssa) + + var new_version = vwrite.variable.original_variable.stack.last + + # Set dependence of the new variable + if vwrite isa AVarReassignExpr then + new_version.dep_exprs.add(vwrite.n_value) + else if vwrite isa AVarAssignExpr then + new_version.dep_exprs.add(vwrite.n_value) + end + + # Replace the old variable by the last created + vwrite.variable = new_version + end + + # Rename occurrence of old names in phi-function + for successor in block.dominance_frontier do + for sphi in successor.phi_functions do + # Go over the couples in the phi dependences to rename variables + for couple in sphi.dependences do + if couple.second == block then + # Rename this variable + couple.first = couple.first.original_variable.stack.last + end + end + end + end + + # Recurse in successor blocks + for successor in block.successors do + rename(successor, counter, ssa) + end + + # Pop old names off the stack for each phi-function + for phi in block.phi_functions do + if not phi.stack.is_empty then phi.stack.pop + end + end + + # Generate a new version of the variable `v` and return it + # *`v` The variable for which we generate a name + # *`counter` The key is the variable, the value the number of assignment into the variable + # *`expr` The AST node in which the assignment of v is made + # *`ssa` The instance of SSA + fun generate_name(v: Variable, counter: HashMap[Variable, Int], expr: ANode, ssa: SSA): Variable + do + var original_variable = v.original_variable.as(not null) + + var i = counter[original_variable] + + var new_version: Variable + + # Create a new version of Variable + if original_variable isa PhiFunction then + var block = original_variable.block + new_version = new PhiFunction(original_variable.name + i.to_s, block) + new_version.dependences.add_all(original_variable.dependences) + ssa.phi_functions.add(new_version) + else + new_version = new Variable(original_variable.name + i.to_s) + new_version.declared_type = expr.as(AVarFormExpr).variable.declared_type + variables.add(new_version) + end + + # Recopy the fields into the new version + new_version.location = expr.location + new_version.original_variable = original_variable + + # Push a new version on the stack + original_variable.stack.add(new_version) + counter[v] = i + 1 + + return new_version + end + + # Transform SSA-representation into an executable code (delete phi-functions) + # `ssa` Current instance of SSA + fun ssa_destruction(ssa: SSA) + do + var builder = new ASTBuilder(mpropdef.mclassdef.mmodule, mpropdef.mclassdef.bound_mtype) + + # Iterate over all phi-functions + for phi in ssa.phi_functions do + for dep in phi.dependences do + # dep.second is the block where we need to create a varassign + var var_read = builder.make_var_read(dep.first, dep.first.declared_type.as(not null)) + var nvar = builder.make_var_assign(dep.first, var_read) + + var block = dep.second.last.parent + + # This variable read must be add to a ABlockExpr + if block isa ABlockExpr then + block.add(nvar) + end + + propagate_dependences(phi, phi.block) + ssa.propdef.variables.add(dep.first) + end + end + end + + # Propagate the dependences of the phi-functions into following variables + # `phi` The PhiFunction + # `block` Current block where we propagate dependences + fun propagate_dependences(phi: PhiFunction, block: BasicBlock) + do + # Treat each block once + if block.treated then return + + # For each variable access site in the block + for site in block.variables_sites do + if site isa AVarExpr then + # Propagate the dependences of the phi-function in variables after the phi + for dep in phi.dependences do + for expr in dep.first.dep_exprs do + if site.variable.dep_exprs.has(expr) then break + + if dep.first.original_variable == site.variable.original_variable then + site.variable.dep_exprs.add(expr) + end + end + end + else + # The site is a variable write, we stop the propagation + return + end + end + + block.treated = true + + # If we do not meet a variable write, continue the propagation + for b in block.successors do propagate_dependences(phi, b) + end +end + +redef class AAttrPropdef + redef fun generate_basic_blocks(ssa: SSA) + do + basic_block = new BasicBlock + basic_block.first = self + basic_block.last = self + + # Add the self variable + if self.selfvariable != null then variables.add(selfvariable.as(not null)) + + # Recursively goes into the nodes + if n_block != null then + n_block.generate_basic_blocks(ssa, basic_block.as(not null)) + is_generated = true + end + end +end + +redef class AMethPropdef + + # The return variable of the propdef + # Create an empty variable for the return of the method + # and treat returns like variable assignments + var returnvar: Variable = new Variable("returnvar") + + redef fun generate_basic_blocks(ssa: SSA) + do + basic_block = new BasicBlock + basic_block.first = self + basic_block.last = self + + # If the method has a signature + if n_signature != null then + for p in n_signature.n_params do + # Add parameters to the local variables + variables.add(p.variable.as(not null)) + p.variable.parameter = true + end + end + + # Add the return variable + variables.add(returnvar) + + # Add the self variable + if self.selfvariable != null then variables.add(selfvariable.as(not null)) + + # Recursively goes into the nodes + if n_block != null then + n_block.generate_basic_blocks(ssa, basic_block.as(not null)) + is_generated = true + end + end +end + +# Utility class for dump basic block and SSA output to dot files +class BlockDebug + # The output file + var file: FileWriter + + # Dump all the hierarchy of BasicBlock from `block` to the leaves + fun dump(block: BasicBlock) + do + # Write the basic blocks hierarchy in output file + file.write("digraph basic_blocks\n\{\n") + var i = 0 + file.write(print_block(block, i)) + file.write("\n\}") + + file.close + end + + # Print all the block recursively from `block` to the leaves + # *`block` The root BasicBlock + # *`i` Used for the recursion + private fun print_block(block: BasicBlock, i: Int): String + do + # Precise the type and location of the begin and end of current block + var s = "block{block.hash.to_s} [shape=record, label="+"\"\{" + s += "block" + block.to_s.escape_to_dot + s += "|\{" + block.first.location.file.filename.to_s + block.first.location.line_start.to_s + s += " | " + block.first.to_s.escape_to_dot + + # Print phi-functions if any + for phi in block.phi_functions do + s += " | " + phi.to_s.escape_to_dot + " " + end + + s += "}|\{" + block.last.location.file.filename.to_s + block.last.location.line_start.to_s + s += " | " + block.last.to_s.escape_to_dot + "}}\"];"+ "\n" + + i += 1 + block.treated_debug = true + + for b in block.successors do + # Print edges to successors + s += "block{block.hash.to_s} -> " + " block{b.hash.to_s};\n" + + # Recursively print child blocks + if not b.treated_debug then s += print_block(b, i) + end + + return s + end +end + +redef class AExpr + # Generate recursively basic block for this expression + # *`ssa` An instance of the SSA class initialized with the enclosing `APropdef` + # *`old_block` A basic block not completely filled + # Return the last created block (the last block can be nested) + fun generate_basic_blocks(ssa: SSA, old_block: BasicBlock): BasicBlock + do + return old_block + end +end + +redef class AVarFormExpr + # The original variable + var original_variable: nullable Variable = variable +end + +redef class AVarExpr + redef fun generate_basic_blocks(ssa, old_block) + do + self.variable.as(not null).read_blocks.add(old_block) + old_block.variables.add(self.variable.as(not null)) + + self.variable.as(not null).original_variable = self.variable.as(not null) + # Save this read site in the block + old_block.read_sites.add(self) + old_block.variables_sites.add(self) + + return old_block + end +end + +redef class AVardeclExpr + redef fun generate_basic_blocks(ssa, old_block) + do + var decl = self.variable.as(not null) + + # Add the corresponding variable to the enclosing mpropdef + ssa.propdef.variables.add(decl) + + decl.original_variable = decl + decl.assignment_blocks.add(old_block) + old_block.variables.add(decl) + + if self.n_expr != null then + self.variable.dep_exprs.add(self.n_expr.as(not null)) + old_block = self.n_expr.generate_basic_blocks(ssa, old_block) + end + + return old_block + end +end + +redef class AVarAssignExpr + redef fun generate_basic_blocks(ssa, old_block) + do + self.variable.as(not null).assignment_blocks.add(old_block) + old_block.variables.add(self.variable.as(not null)) + self.variable.as(not null).original_variable = self.variable.as(not null) + + # Save this write site in the block + old_block.write_sites.add(self) + old_block.variables_sites.add(self) + + ssa.propdef.variables.add(self.variable.as(not null)) + + return self.n_value.generate_basic_blocks(ssa, old_block) + end +end + +redef class AVarReassignExpr + redef fun generate_basic_blocks(ssa, old_block) + do + self.variable.as(not null).assignment_blocks.add(old_block) + old_block.variables.add(self.variable.as(not null)) + self.variable.as(not null).original_variable = self.variable.as(not null) + + # Save this write site in the block + old_block.write_sites.add(self) + old_block.variables_sites.add(self) + + ssa.propdef.variables.add(self.variable.as(not null)) + return self.n_value.generate_basic_blocks(ssa, old_block) + end +end + +redef class ABreakExpr + redef fun generate_basic_blocks(ssa, old_block) + do + # Finish the old block + old_block.last = self + + return old_block + end +end + +redef class AContinueExpr + redef fun generate_basic_blocks(ssa, old_block) + do + return old_block + end +end + +redef class AReturnExpr + redef fun generate_basic_blocks(ssa, old_block) + do + # The return just set the current block and stop the recursion + if self.n_expr != null then + old_block = self.n_expr.generate_basic_blocks(ssa, old_block) + + # Store the return expression in the dependences of the dedicated returnvar + if ssa.propdef isa AMethPropdef then + ssa.propdef.as(AMethPropdef).returnvar.dep_exprs.add(n_expr.as(not null)) + end + end + + old_block.last = self + + return old_block + end +end + +redef class AAssertExpr + redef fun generate_basic_blocks(ssa, old_block) + do + self.n_expr.generate_basic_blocks(ssa, old_block) + + # The condition of the assert is the last expression of the previous block + old_block.last = self.n_expr + + # The block if the assert fail + var block_false = new BasicBlock + + if self.n_else != null then + block_false.first = self.n_else.as(not null) + block_false.last = self.n_else.as(not null) + self.n_else.generate_basic_blocks(ssa, block_false) + else + block_false.first = self + block_false.first = self + end + + old_block.link(block_false) + + # The block if the assert is true: the execution continue + var block_true = new BasicBlock + block_true.first = self + block_true.last = self + + old_block.link(block_true) + + return block_true + end +end + +redef class AOrExpr + redef fun generate_basic_blocks(ssa, old_block) + do + self.n_expr.generate_basic_blocks(ssa, old_block) + return self.n_expr2.generate_basic_blocks(ssa, old_block) + end +end + +redef class AImpliesExpr + redef fun generate_basic_blocks(ssa, old_block) + do + self.n_expr.generate_basic_blocks(ssa, old_block) + return self.n_expr2.generate_basic_blocks(ssa, old_block) + end +end + +redef class AAndExpr + redef fun generate_basic_blocks(ssa, old_block) + do + self.n_expr.generate_basic_blocks(ssa, old_block) + return self.n_expr2.generate_basic_blocks(ssa, old_block) + end +end + +redef class ANotExpr + redef fun generate_basic_blocks(ssa, old_block) + do + return self.n_expr.generate_basic_blocks(ssa, old_block) + end +end + +redef class AOrElseExpr + redef fun generate_basic_blocks(ssa, old_block) + do + self.n_expr.generate_basic_blocks(ssa, old_block) + return self.n_expr2.generate_basic_blocks(ssa, old_block) + end +end + +redef class AArrayExpr + redef fun generate_basic_blocks(ssa, old_block) + do + for nexpr in self.n_exprs do + old_block = nexpr.generate_basic_blocks(ssa, old_block) + end + + return old_block + end +end + +redef class ASuperstringExpr + redef fun generate_basic_blocks(ssa, old_block) + do + for nexpr in self.n_exprs do old_block = nexpr.generate_basic_blocks(ssa, old_block) + + return old_block + end +end + +redef class ACrangeExpr + redef fun generate_basic_blocks(ssa, old_block) + do + self.n_expr.generate_basic_blocks(ssa, old_block) + return self.n_expr2.generate_basic_blocks(ssa, old_block) + end +end + +redef class AOrangeExpr + redef fun generate_basic_blocks(ssa, old_block) + do + self.n_expr.generate_basic_blocks(ssa, old_block) + return self.n_expr2.generate_basic_blocks(ssa, old_block) + end +end + +redef class AIsaExpr + redef fun generate_basic_blocks(ssa, old_block) + do + ssa.propdef.object_sites.add(self) + + return self.n_expr.generate_basic_blocks(ssa, old_block) + end +end + +redef class AAsCastExpr + redef fun generate_basic_blocks(ssa, old_block) + do + ssa.propdef.object_sites.add(self) + + return self.n_expr.generate_basic_blocks(ssa, old_block) + end +end + +redef class AAsNotnullExpr + redef fun generate_basic_blocks(ssa, old_block) + do + return self.n_expr.generate_basic_blocks(ssa, old_block) + end +end + +redef class AParExpr + redef fun generate_basic_blocks(ssa, old_block) + do + return self.n_expr.generate_basic_blocks(ssa, old_block) + end +end + +redef class AOnceExpr + redef fun generate_basic_blocks(ssa, old_block) + do + return self.n_expr.generate_basic_blocks(ssa, old_block) + end +end + +redef class ASendExpr + redef fun generate_basic_blocks(ssa, old_block) + do + # A call does not finish the current block, + # because we create intra-procedural basic blocks here + + ssa.propdef.object_sites.add(self) + + # Recursively goes into arguments to find variables if any + for e in self.raw_arguments do e.generate_basic_blocks(ssa, old_block) + + return self.n_expr.generate_basic_blocks(ssa, old_block) + end +end + +redef class ASendReassignFormExpr + redef fun generate_basic_blocks(ssa, old_block) + do + self.n_expr.generate_basic_blocks(ssa, old_block) + + ssa.propdef.object_sites.add(self) + + # Recursively goes into arguments to find variables if any + for e in self.raw_arguments do e.generate_basic_blocks(ssa, old_block) + + return self.n_value.generate_basic_blocks(ssa, old_block) + end +end + +redef class ASuperExpr + redef fun generate_basic_blocks(ssa, old_block) + do + # Recursively goes into arguments to find variables if any + for arg in self.n_args.n_exprs do arg.generate_basic_blocks(ssa, old_block) + + return old_block + end +end + +redef class ANewExpr + redef fun generate_basic_blocks(ssa, old_block) + do + for e in self.n_args.n_exprs do e.generate_basic_blocks(ssa, old_block) + + ssa.propdef.object_sites.add(self) + + return old_block + end +end + +redef class AAttrExpr + redef fun generate_basic_blocks(ssa, old_block) + do + ssa.propdef.object_sites.add(self) + + return self.n_expr.generate_basic_blocks(ssa, old_block) + end +end + +redef class AAttrAssignExpr + redef fun generate_basic_blocks(ssa, old_block) + do + ssa.propdef.object_sites.add(self) + + return self.n_expr.generate_basic_blocks(ssa, old_block) + end +end + +redef class AAttrReassignExpr + redef fun generate_basic_blocks(ssa, old_block) + do + ssa.propdef.object_sites.add(self) + + return self.n_expr.generate_basic_blocks(ssa, old_block) + end +end + +redef class AIssetAttrExpr + redef fun generate_basic_blocks(ssa, old_block) + do + return self.n_expr.generate_basic_blocks(ssa, old_block) + end +end + +redef class ABlockExpr + # The block needs to know if a new block is created + redef fun generate_basic_blocks(ssa, old_block) + do + var last_block = old_block + var current_block: BasicBlock + + # Recursively continue in the body of the block + for i in [0..self.n_expr.length[ do + current_block = self.n_expr[i].generate_basic_blocks(ssa, last_block) + + if current_block.need_update then + if i < (self.n_expr.length-1) then + # Current_block must be filled + current_block.first = self.n_expr[i+1] + current_block.last = self.n_expr[i+1] + current_block.need_update = false + else + # Put the current block at the end of the block + current_block.first = last_block.last + current_block.last = last_block.last + end + end + + if not current_block.last isa AEscapeExpr or current_block.last isa AReturnExpr then + # Re-affected the last block + current_block.last = self.n_expr[i] + end + + last_block = current_block + end + + return last_block + end +end + +redef class AIfExpr + redef fun generate_basic_blocks(ssa, old_block) + do + # Terminate the previous block + old_block.last = self + + # We start two new blocks if the if has two branches + var block_then = new BasicBlock + + # Visit the test of the if + self.n_expr.generate_basic_blocks(ssa, old_block) + + # Launch the recursion in two successors if they exist + if self.n_then != null then + old_block.link(block_then) + + block_then.first = self.n_then.as(not null) + block_then.last = self.n_then.as(not null) + self.n_then.generate_basic_blocks(ssa, block_then) + end + + var block_else = new BasicBlock + + if self.n_else != null then + old_block.link(block_else) + + block_else.first = self.n_else.as(not null) + block_else.last = self.n_else.as(not null) + self.n_else.generate_basic_blocks(ssa, block_else) + end + + # Create a new BasicBlock to represent the two successor + # branches of the if + var new_block = new BasicBlock + new_block.first = self + new_block.last = self + + if self.n_then != null then block_then.link(new_block) + + # The new block needs to be filled by the caller + new_block.need_update = true + + if block_else.predecessors.length != 0 then block_else.link(new_block) + + return new_block + end +end + +redef class AIfexprExpr + redef fun generate_basic_blocks(ssa, old_block) + do + # Terminate the previous block + old_block.last = self + + # We start two new blocks if the if has two branches + var block_then = new BasicBlock + + # Visit the test of the if + self.n_expr.generate_basic_blocks(ssa, old_block) + + # Launch the recursion in two successors if they exist + old_block.link(block_then) + + block_then.first = self.n_then + block_then.last = self.n_then + self.n_then.generate_basic_blocks(ssa, block_then) + + var block_else = new BasicBlock + + old_block.link(block_else) + + block_else.first = self.n_else + block_else.last = self.n_else + self.n_else.generate_basic_blocks(ssa, block_else) + + # Create a new BasicBlock to represent the two successor + # branches of the if + var new_block = new BasicBlock + new_block.first = self + new_block.last = self + + block_then.link(new_block) + + # The new block needs to be filled by the caller + new_block.need_update = true + + block_else.link(new_block) + + return new_block + end +end + +redef class ADoExpr + redef fun generate_basic_blocks(ssa, old_block) + do + old_block.last = self + + # The beginning of the block is the first instruction + var block = new BasicBlock + block.first = self.n_block.as(not null) + block.last = self.n_block.as(not null) + + old_block.link(block) + return self.n_block.generate_basic_blocks(ssa, block) + end +end + +redef class AWhileExpr + redef fun generate_basic_blocks(ssa, old_block) + do + old_block.last = self + + # The beginning of the block is the test of the while + var block = new BasicBlock + block.first = self.n_expr + block.last = self.n_block.as(not null) + + old_block.link(block) + + self.n_expr.generate_basic_blocks(ssa, old_block) + var inside_block = self.n_block.generate_basic_blocks(ssa, block) + + # Link the inside of the block to the previous block + block.link_special(old_block) + + # Create a new Block after the while + var new_block = new BasicBlock + new_block.need_update = true + + old_block.link_special(new_block) + + return new_block + end +end + +redef class ALoopExpr + redef fun generate_basic_blocks(ssa, old_block) + do + old_block.last = self + + # The beginning of the block is the first instruction + var block = new BasicBlock + block.first = self.n_block.as(not null) + block.last = self.n_block.as(not null) + + old_block.link(block) + self.n_block.generate_basic_blocks(ssa, block) + + return block + end +end + +redef class AForExpr + redef fun generate_basic_blocks(ssa, old_block) + do + old_block.last = self + + # The beginning of the block is the first instruction + var block = new BasicBlock + block.first = self.n_expr + block.last = self.n_block.as(not null) + + # Visit the test of the if + self.n_expr.generate_basic_blocks(ssa, block) + + # Collect the variables declared in the for + for v in variables do + ssa.propdef.variables.add(v) + end + + old_block.link(block) + + block.link(old_block) + + var new_block = new BasicBlock + new_block.need_update = true + + return new_block + end +end diff --git a/src/transform.nit b/src/transform.nit index ebe2c73..838b9bc 100644 --- a/src/transform.nit +++ b/src/transform.nit @@ -104,7 +104,12 @@ redef class AExpr var nadd = v.builder.make_call(recv, na.push_callsite.as(not null), [self]) place.replace_with(nadd) end - super + + visit_all(v) + + if mtype == null and not is_typed then return # Skip broken + + accept_transform_visitor(v) end redef fun replace_with(other) diff --git a/src/vm/compilation.nit b/src/vm/compilation.nit new file mode 100644 index 0000000..5dca966 --- /dev/null +++ b/src/vm/compilation.nit @@ -0,0 +1,60 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2015 Julien Pagès +# +# 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. + +# The compilation module of the VirtualMachine +module compilation + +import variables_numbering +import ssa + +redef class VirtualMachine + + # The currently analyzed APropdef + var current_propdef: APropdef + + redef fun new_frame(node, mpropdef, args) + do + # Save the current propdef + if node isa APropdef then self.current_propdef = node + + return super + end +end + +redef class APropdef + + redef fun compile(vm) + do + super + + # A new instance of SSA to analyze the self propdef + var ssa = new SSA(self) + + # Generate basic_blocks and compute SSA-algorithm for this propdef + compute_ssa(ssa) + end + + # Redef to add the same position to a new version of a Variable than the original variable + redef fun generate_name(v, counter, expr, ssa) + do + var new_version = super + + # All versions of a variable have the same position in the environment + new_version.position = v.original_variable.position + + return new_version + end +end diff --git a/src/vm/variables_numbering.nit b/src/vm/variables_numbering.nit index 4de0eb4..d01b390 100644 --- a/src/vm/variables_numbering.nit +++ b/src/vm/variables_numbering.nit @@ -39,19 +39,10 @@ redef class VirtualMachine do var f = new VmFrame(node, mpropdef, args) - # If this Frame is for a method then number variables into the body of the method - if node isa AMethPropdef then - # Number the variables - if not node.is_numbering then node.numbering_variables(self, mpropdef.as(MMethodDef)) - - # Create an empty environment - f.variables = new Array[Instance].filled_with(initialization_value, node.environment_size) - end - - # If this Frame is for an attribute with a block then number the block - if node isa AAttrPropdef then - # Number the variables - if not node.is_numbering then node.numbering_variables(self) + # If this Frame is for a method or an attribute block then number variables into the body of the method + if node isa APropdef then + # Compile the code (number its local variables) + if not node.is_compiled then node.compile(self) # Create an empty environment f.variables = new Array[Instance].filled_with(initialization_value, node.environment_size) @@ -77,7 +68,7 @@ end redef class Variable # The position in the environment - var position: Int + var position: Int is writable end # Implementation of a Frame with numbered variables @@ -102,18 +93,33 @@ redef class AExpr end redef class APropdef + # Indicite if this propdef was compile + var is_compiled: Bool = false + # Indicate if the variables numbering has been done private var is_numbering: Bool = false # The size of the environment to create to call this method private var environment_size: Int = 0 + + # Compile this propdef + # *`vm` The running instance of `VirtualMachine` + fun compile(vm: VirtualMachine) + do + # Number the variables + if not is_numbering then numbering_variables(vm) + + is_compiled = true + end + + # Numbering the variable inside the propdef + fun numbering_variables(vm: VirtualMachine) is abstract end redef class AMethPropdef - # Assign a position in the environment to each local variable of `mpropdef` - # *`v` The current VirtualMachine - # *`mpropdef` The method to number - private fun numbering_variables(v: VirtualMachine, mpropdef: MMethodDef) + # Assign a position in the environment to each local variable + # *`vm` The current VirtualMachine + redef fun numbering_variables(vm: VirtualMachine) do # The position in the environment var position = 0 @@ -133,7 +139,7 @@ redef class AMethPropdef # Recursively go into the AST nodes to number all local variables if n_block != null then - position = v.numbering(self.n_block, position) + position = vm.numbering(self.n_block, position) end is_numbering = true @@ -144,9 +150,9 @@ redef class AMethPropdef end redef class AAttrPropdef - # Assign a position in the environment to each local variable of `mpropdef` - # *`v` The current VirtualMachine - private fun numbering_variables(v: VirtualMachine) + # Assign a position in the environment to each local variable + # *`vm` The current VirtualMachine + redef fun numbering_variables(vm: VirtualMachine) do # The position in the environment var position = 0 @@ -159,7 +165,7 @@ redef class AAttrPropdef # Recursively go into the AST nodes to number all local variables if n_block != null then - position = v.numbering(self.n_block, position) + position = vm.numbering(self.n_block, position) end is_numbering = true diff --git a/src/vm/vm.nit b/src/vm/vm.nit index 4027a15..e98d2da 100644 --- a/src/vm/vm.nit +++ b/src/vm/vm.nit @@ -20,3 +20,4 @@ module vm import virtual_machine import vm_optimizations import variables_numbering +import compilation diff --git a/tests/24_game.inputs b/tests/24_game.inputs new file mode 100644 index 0000000..7b80b80 --- /dev/null +++ b/tests/24_game.inputs @@ -0,0 +1,3 @@ +8/4 +8*2 +16+8 diff --git a/tests/base_adaptive_loop3.nit b/tests/base_adaptive_loop3.nit index 33f4c8d..42e331a 100644 --- a/tests/base_adaptive_loop3.nit +++ b/tests/base_adaptive_loop3.nit @@ -27,4 +27,5 @@ while t2 != null do t2 = t2.next #alt2# t2 = null end #alt3#t2 = t2.next + #alt3#exit(0) end diff --git a/tests/base_adaptive_loop_null.nit b/tests/base_adaptive_loop_null.nit index cfbb80f..e342e07 100644 --- a/tests/base_adaptive_loop_null.nit +++ b/tests/base_adaptive_loop_null.nit @@ -48,6 +48,6 @@ loop if i != null then bar(i) else - break #alt4# + break #alt4# exit(0) end end diff --git a/tests/base_do_block.nit b/tests/base_do_block.nit new file mode 100644 index 0000000..b9fdad4 --- /dev/null +++ b/tests/base_do_block.nit @@ -0,0 +1,41 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +class Foo + fun start do end + fun finish do end +end +fun foo: Foo do return new Foo + +do do + 1.output +end +while false do do + 2.output +end +if true then do + 3.output +end else do + 4.output +end +for i in [0..1] do do + 5.output +end +with foo do do + 6.output +end +loop do + 7.output + return +end diff --git a/tests/sav/24_game.res b/tests/sav/24_game.res new file mode 100644 index 0000000..bcbdec9 --- /dev/null +++ b/tests/sav/24_game.res @@ -0,0 +1,4 @@ +numbers: 8, 4, 8, 8 +numbers: 8, 8, 2 +numbers: 8, 16 +CONGRATULATIONS diff --git a/tests/sav/base_do_block.res b/tests/sav/base_do_block.res new file mode 100644 index 0000000..f99d451 --- /dev/null +++ b/tests/sav/base_do_block.res @@ -0,0 +1,11 @@ +base_do_block.nit:21,4--23,3: Warning: superfluous `do` block. +base_do_block.nit:24,16--26,3: Warning: superfluous `do` block. +base_do_block.nit:32,20--34,3: Warning: superfluous `do` block. +base_do_block.nit:35,13--37,3: Warning: superfluous `do` block. +base_do_block.nit:38,6--41,3: Warning: superfluous `do` block. +1 +3 +5 +5 +6 +7 diff --git a/tests/sav/base_import_alt3.res b/tests/sav/base_import_alt3.res index 4fcab0a..debc62f 100644 --- a/tests/sav/base_import_alt3.res +++ b/tests/sav/base_import_alt3.res @@ -1 +1 @@ -alt/base_import_alt3.nit:1,8--21: Error: cannot find module `fail` from `project1`. Tried: ., ../lib/standard, ../lib/standard/collection, alt, ../lib. +alt/base_import_alt3.nit:1,8--21: Error: cannot find module `fail` from `project1`. Tried: ., ../lib/standard, ../lib/standard/collection, alt, ../lib, ../contrib. diff --git a/tests/sav/error_mod_unk.res b/tests/sav/error_mod_unk.res index 20bc8ca..29ce68b 100644 --- a/tests/sav/error_mod_unk.res +++ b/tests/sav/error_mod_unk.res @@ -1 +1 @@ -error_mod_unk.nit:17,8--11: Error: cannot find module `dfgd` from `error_mod_unk`. Tried: ., ../lib/standard, ../lib/standard/collection, alt, ../lib. +error_mod_unk.nit:17,8--11: Error: cannot find module `dfgd` from `error_mod_unk`. Tried: ., ../lib/standard, ../lib/standard/collection, alt, ../lib, ../contrib. diff --git a/tests/sav/neo_doxygen_dump_args4.res b/tests/sav/neo_doxygen_dump_args4.res index 0d6a211..a732359 100644 --- a/tests/sav/neo_doxygen_dump_args4.res +++ b/tests/sav/neo_doxygen_dump_args4.res @@ -1457,7 +1457,7 @@ Edge 8:MPropDef 13:MAttributeDef =properties=JsonObject(5): -{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["\u000e2\u00080\u0009cAnswer to the Ultimate Question of Life, the Universe, and Everything.","\u000e2\u00080\u0009c"],"is_intro":true} +{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["“Answer to the Ultimate Question of Life, the Universe, and Everything.","“"],"is_intro":true} ---- =to=Entity#0: =labels=Array(4): @@ -1481,7 +1481,7 @@ Edge 8:MPropDef 13:MAttributeDef =properties=JsonObject(5): -{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["\u000e2\u00080\u0009cAnswer to the Ultimate Question of Life, the Universe, and Everything.","\u000e2\u00080\u0009c"],"is_intro":true} +{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["“Answer to the Ultimate Question of Life, the Universe, and Everything.","“"],"is_intro":true} ---- =to=Entity#0: =labels=Array(4): @@ -1722,7 +1722,7 @@ Edge 8:MPropDef 13:MAttributeDef =properties=JsonObject(5): -{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["\u000e2\u00080\u0009cAnswer to the Ultimate Question of Life, the Universe, and Everything.","\u000e2\u00080\u0009c"],"is_intro":true} +{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["“Answer to the Ultimate Question of Life, the Universe, and Everything.","“"],"is_intro":true} Edge diff --git a/tests/sav/neo_doxygen_dump_args5.res b/tests/sav/neo_doxygen_dump_args5.res index 70cda4d..5e63fb7 100644 --- a/tests/sav/neo_doxygen_dump_args5.res +++ b/tests/sav/neo_doxygen_dump_args5.res @@ -1457,7 +1457,7 @@ Edge 8:MPropDef 13:MAttributeDef =properties=JsonObject(5): -{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["\u000e2\u00080\u0009cAnswer to the Ultimate Question of Life, the Universe, and Everything.","\u000e2\u00080\u0009c"],"is_intro":true} +{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["“Answer to the Ultimate Question of Life, the Universe, and Everything.","“"],"is_intro":true} ---- =to=Entity#0: =labels=Array(4): @@ -1481,7 +1481,7 @@ Edge 8:MPropDef 13:MAttributeDef =properties=JsonObject(5): -{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["\u000e2\u00080\u0009cAnswer to the Ultimate Question of Life, the Universe, and Everything.","\u000e2\u00080\u0009c"],"is_intro":true} +{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["“Answer to the Ultimate Question of Life, the Universe, and Everything.","“"],"is_intro":true} ---- =to=Entity#0: =labels=Array(4): @@ -1722,7 +1722,7 @@ Edge 8:MPropDef 13:MAttributeDef =properties=JsonObject(5): -{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["\u000e2\u00080\u0009cAnswer to the Ultimate Question of Life, the Universe, and Everything.","\u000e2\u00080\u0009c"],"is_intro":true} +{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["“Answer to the Ultimate Question of Life, the Universe, and Everything.","“"],"is_intro":true} Edge diff --git a/tests/sav/test_ffi_c_primitives.res b/tests/sav/test_ffi_c_primitives.res index c68bddc..1a3828f 100644 --- a/tests/sav/test_ffi_c_primitives.res +++ b/tests/sav/test_ffi_c_primitives.res @@ -3,4 +3,5 @@ true k 2234 12345.0 +0x12 hello world diff --git a/tests/sav/test_float.res b/tests/sav/test_float.res index cd932ee..feaed3f 100644 --- a/tests/sav/test_float.res +++ b/tests/sav/test_float.res @@ -5,3 +5,9 @@ 12.346 12.3 12 +0.5 +0.000 +0.000003125 +3410.0 +400.0 +10.0 diff --git a/tests/sav/test_keep_going.res b/tests/sav/test_keep_going.res new file mode 100644 index 0000000..346b309 --- /dev/null +++ b/tests/sav/test_keep_going.res @@ -0,0 +1 @@ +test_keep_going.nit:15,11--14: Error: class `Fail` not found in module `test_keep_going`. diff --git a/tests/sav/xymus_net.res b/tests/sav/xymus_net.res index 112bdb0..64d374b 100644 --- a/tests/sav/xymus_net.res +++ b/tests/sav/xymus_net.res @@ -1,3 +1,2 @@ -../examples/nitcorn/src/xymus_net.nit:24,8--14: Error: cannot find module `tnitter` from `nitcorn`. Tried: alt, ../lib, ../examples/nitcorn. -../examples/nitcorn/src/xymus_net.nit:25,8--26: Error: cannot find module `benitlux_controller` from `nitcorn`. Tried: alt, ../lib, ../examples/nitcorn. -../examples/nitcorn/src/xymus_net.nit:26,8--29: Error: cannot find module `opportunity_controller` from `nitcorn`. Tried: alt, ../lib, ../examples/nitcorn. +../examples/nitcorn/src/xymus_net.nit:25,8--26: Error: cannot find module `benitlux_controller` from `nitcorn`. Tried: alt, ../lib, ../contrib, ../examples/nitcorn. +../examples/nitcorn/src/xymus_net.nit:26,8--29: Error: cannot find module `opportunity_controller` from `nitcorn`. Tried: alt, ../lib, ../contrib, ../examples/nitcorn. diff --git a/tests/test_ffi_c_primitives.nit b/tests/test_ffi_c_primitives.nit index ffac1cd..2295927 100644 --- a/tests/test_ffi_c_primitives.nit +++ b/tests/test_ffi_c_primitives.nit @@ -1,7 +1,5 @@ # This file is part of NIT ( http://www.nitlanguage.org ). # -# Copyright 2011-2013 Alexis Laferrière -# # 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 @@ -14,29 +12,39 @@ # See the License for the specific language governing permissions and # limitations under the License. -fun opposite( v : Bool ) : Bool `{ +fun opposite(v: Bool): Bool `{ return v == 0; `} -fun plus_10( v : Char ) : Char `{ + +fun plus_10(v: Char): Char `{ return v + 10; `} -fun plus_1000( v : Int ) : Int `{ + +fun plus_1000(v: Int): Int `{ return v + 1000; `} -fun multiply_by_100( v : Float ) : Float `{ + +fun multiply_by_100(v: Float): Float `{ return v * 100; `} -fun print_ns( s : NativeString ) `{ - printf( "%s\n", s ); + +fun plus_0x10(v: Byte): Byte `{ + return v + 0x10; +`} + +fun print_ns(s: NativeString) `{ + printf("%s\n", s); `} -print opposite( true ) -print opposite( false ) +print opposite(true) +print opposite(false) + +print plus_10('a') -print plus_10( 'a' ) +print plus_1000(1234) -print plus_1000( 1234 ) +print multiply_by_100(123.45) -print multiply_by_100( 123.45 ) +print plus_0x10(0x2u8) -print_ns( "hello world".to_cstring ) +print_ns("hello world".to_cstring) diff --git a/tests/test_ffi_cpp_duplicated_callback_a.nit b/tests/test_ffi_cpp_duplicated_callback_a.nit index 76c1172..16375e3 100644 --- a/tests/test_ffi_cpp_duplicated_callback_a.nit +++ b/tests/test_ffi_cpp_duplicated_callback_a.nit @@ -17,7 +17,7 @@ in "C++ Header" `{ `} fun print_a(str: String) import String.to_cstring in "C++" `{ - puts(String_to_cstring(str)); + puts(reinterpret_cast(String_to_cstring(str))); `} print_a "Hello from `a`." diff --git a/tests/test_ffi_cpp_duplicated_callback_b.nit b/tests/test_ffi_cpp_duplicated_callback_b.nit index 01eb25c..e4631dc 100644 --- a/tests/test_ffi_cpp_duplicated_callback_b.nit +++ b/tests/test_ffi_cpp_duplicated_callback_b.nit @@ -19,7 +19,7 @@ in "C++ header" `{ `} fun print_b(str: String) import String.to_cstring in "C++" `{ - puts(String_to_cstring(str)); + puts(reinterpret_cast(String_to_cstring(str))); `} print_a "Hello from `a`." diff --git a/tests/test_float.nit b/tests/test_float.nit index 387c312..a997f01 100644 --- a/tests/test_float.nit +++ b/tests/test_float.nit @@ -23,3 +23,14 @@ print(f.to_s) print(f.to_precision(3)) print(f.to_precision(1)) print(f.to_precision(0)) +f = 5.0e-1 +print(f) +f = 3.125e-6 +print(f.to_precision(3)) +print(f.to_precision(9)) +f = 3.41e3 +print f +f = 4e2 +print f +f = .1e2 +print f diff --git a/tests/test_keep_going.nit b/tests/test_keep_going.nit new file mode 100755 index 0000000..b3bedaa --- /dev/null +++ b/tests/test_keep_going.nit @@ -0,0 +1,47 @@ +# 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. + +fun plop: Fail +do + print 1 +end + +1.output +if false then + plop +end +2.output +if false then + fail +end +3.output +if false then + var x = new Fail + x.output +end +4.output +if false then + if 1 then abort +end +5.output +if false then + abort + 999.output +end +6.output +if false then + var a = new Sys.fail + a.output +end +7.output