Merge: Performance improvement in read_all_bytes
authorJean Privat <jean@pryen.org>
Mon, 17 Aug 2015 20:15:27 +0000 (16:15 -0400)
committerJean Privat <jean@pryen.org>
Mon, 17 Aug 2015 20:15:27 +0000 (16:15 -0400)
As @privat notified me of yesterday, a lot of time is wasted in read_all by boxing and unboxing bytes when doing the infamous `_buffer.add` operation in `read_all_bytes`.

This PR removes the boxing operations by bulk-writing a NativeString to a Bytes.
The buffer on files is also tenfold-bigger, which cuts I/O times while still retaining a reasonable size.

# Performances

On the Batmobileā„¢

## Valgrind

Before:
standard___standard__BufferedReader___Reader__read_all_bytes: 90.816 MIr
After:
standard___standard__BufferedReader___Reader__read_all_bytes: 7.596 MIr

## ./ncall-best

Before
user 0m4.316s
After
user 0m4.182s

Close #1298

Pull-Request: #1636
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

23 files changed:
contrib/benitlux/.gitignore
contrib/benitlux/src/benitlux_daily.nit
contrib/benitlux/src/benitlux_model.nit
contrib/benitlux/src/correct.nit [new file with mode: 0644]
contrib/benitlux/src/report.nit
contrib/tinks/src/client/client.nit
lib/standard/fixed_ints.nit [new file with mode: 0644]
lib/standard/standard.nit
lib/standard/text/abstract_text.nit
src/compiler/abstract_compiler.nit
src/compiler/separate_compiler.nit
src/ffi/java.nit
src/interpreter/dynamic_loading_ffi/README.md
src/interpreter/dynamic_loading_ffi/dynamic_loading_ffi.nit
src/interpreter/dynamic_loading_ffi/on_demand_compiler.nit
src/interpreter/naive_interpreter.nit
src/model/model.nit
src/modelize/modelize_property.nit
src/nitni/nitni_base.nit
src/rapid_type_analysis.nit
src/semantize/typing.nit
tests/sav/test_fix_int.res [new file with mode: 0644]
tests/test_fix_int.nit [new file with mode: 0644]

index e4e2a7d..2ccbe7b 100644 (file)
@@ -1,3 +1,4 @@
 src/benitlux_serial.nit
 *.db
 *.email
+benitlux_corrections.txt
index 1c1f4d6..f4a3f25 100644 (file)
@@ -75,21 +75,13 @@ class Benitlux
        var street: String
 
        # The url of this precise Benelux
-       var url: String
+       var url = "www.brasseriebenelux.com/{street}" is lazy
 
        # Path to the database
-       var db_path: String
+       var db_path = "benitlux_{street}.db" is lazy
 
        # Where to save the sample email
-       var sample_email_path: String
-
-       init(street: String)
-       do
-               self.street = street
-               self.url = "www.brasseriebenelux.com/{street}"
-               self.db_path = "benitlux_{street}.db"
-               self.sample_email_path = "benitlux_{street}.email"
-       end
+       var sample_email_path = "benitlux_{street}.email" is lazy
 
        # Execute the main program logic
        fun run(send_emails: Bool)
@@ -171,10 +163,10 @@ class Benitlux
        end
 
        # Content lines of the email
-       var email_content: Array[String]
+       var email_content: Array[String] is noautoinit
 
        # Title of the email
-       var email_title: String
+       var email_title: String is noautoinit
 
        # Generate email and fill the attributes `email_content` and `email_title`
        fun generate_email(beer_events: BeerEvents)
@@ -229,7 +221,7 @@ end
 var ben = new Benitlux("sherbrooke")
 ben.run(opts.send_emails.value)
 
-# The parsing logic for the wellington locaiton is active (to gather data)
+# The parsing logic for the wellington location is active (to gather data)
 # but the web interface do not allow to subscribe to its mailing list.
 #
 # TODO revamp mailing list Web interface
index f4aeae8..d3e440d 100644 (file)
@@ -23,12 +23,6 @@ import serialization
 class Beer
        auto_serializable
 
-       init(name, desc: String)
-       do
-               self.name = name
-               self.desc = desc
-       end
-
        # Name of the beer
        var name: String
 
diff --git a/contrib/benitlux/src/correct.nit b/contrib/benitlux/src/correct.nit
new file mode 100644 (file)
index 0000000..3c2384c
--- /dev/null
@@ -0,0 +1,78 @@
+# 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.
+
+# Correct errors in beer names before using data from the DB
+#
+# Reads corrections from the file at `DB::corrections_path` which must be formatted like so:
+#
+# ~~~raw
+# Wrong name -> Correct name
+# Name with typo -> Clean name
+# ~~~
+module correct
+
+import benitlux_db
+
+redef class DB
+       # Path to file with the corrections
+       private var corrections_path = "benitlux_corrections.txt"
+
+       # Corrections of beer name: wrong name to corrected name
+       private var corrections: Map[String, String] is lazy do
+               var map = new HashMap[String, String]
+
+               # Read from file
+               if corrections_path.file_exists then
+                       var lines = corrections_path.to_path.read_lines
+                       for line in lines do
+                               var parts = line.split("->")
+                               assert parts.length == 2 else print_error "Error: wrong format in '{corrections_path}'"
+                               map[parts[0].trim] = parts[1].trim
+                       end
+               end
+
+               return map
+       end
+
+       redef fun beers
+       do
+               var beers = super
+               if beers == null then return null
+
+               # Skip corrected beers
+               for beer in beers.reverse_iterator do
+                       if corrections.keys.has(beer.name) then
+                               beers.remove beer
+                       end
+               end
+
+               return beers
+       end
+
+       redef fun days(beer)
+       do
+               var days = super(beer)
+               if beer == null or days == null then return days
+
+               # Merge days of `corrections` to `beer`
+               for from, to in corrections do
+                       if to == beer.name then
+                               var missing_days = super(new Beer(from, ""))
+                               if missing_days != null then days.add_all missing_days
+                       end
+               end
+
+               return days
+       end
+end
index 54f22ad..084e935 100644 (file)
@@ -14,6 +14,7 @@
 
 import benitlux_model
 import benitlux_db
+import correct
 
 # Sort beers by their availability
 class BeerComparator
@@ -31,6 +32,20 @@ class BeerComparator
                                          else map1[a] <=> map1[b]
 end
 
+redef class Text
+
+       # Get the background for the date `self` of format `yyyy-mm-dd`
+       private fun date_to_back: String
+       do
+               assert length == 10
+
+               var m = substring(5, 2)
+               var month = m.to_i
+               if [4..9].has(month) then return " "
+               return "-"
+       end
+end
+
 # Use the local DB
 var db_path = "benitlux_sherbrooke.db"
 var db = new DB.open(db_path)
@@ -94,20 +109,53 @@ sorter = new BeerComparator(appearances, availability)
 sorter.sort beers
 
 # Display the batch graph
-print "\nBatches:"
+print "\nAvailability graph:"
 
 # Compute `column_width` days from all the known days
 var column_width = 70
 var days_sample = [for i in column_width.times do all_days[i*all_days.length/column_width]]
 
+# Gather columns headers for each month
+var headers = new Array[nullable String]
+var pre = ""
+for day in days_sample do
+       var new_pre = day.substring(0, 7)
+
+       if not day.has_prefix(pre) then
+               headers.add new_pre
+       else headers.add null
+
+       pre = new_pre
+end
+
+# Draw the headers from top to bottom so they look like:
+#
+# ~~~
+# 2
+# 0
+# 1
+# 5
+# -
+# 0
+# 1
+# ~~~
+for l in 7.times do
+       for header in headers do
+               if header != null then
+                       printn header[l]
+               else printn " "
+       end
+       print ""
+end
+
 for beer in beers do
        var days = beer2days[beer]
 
        # Skip never-available beers, usually name errors
        if days.is_empty then continue
 
-       # Print a line looking like: "  ############ ######         ######## : Beer"
-       for s in days_sample do printn if days.has(s) then "#" else " "
+       # Print a line looking like: "  ############ ######    -----########-: Beer"
+       for s in days_sample do printn if days.has(s) then "#" else s.date_to_back
        print ": {beer.name}"
 end
 
index 32a9852..8dad5eb 100644 (file)
@@ -276,26 +276,7 @@ redef class App
                end
 
                # Events
-               for event in turn.events do
-                       event.client_react(display, turn)
-
-                       if event isa ExplosionEvent then
-                               var pos = event.pos.to_screen(camera)
-                               display.blit_centered(assets.drawing.explosion, pos.x, pos.y)
-                       else if event isa OpenFireEvent then
-                               var tank = event.tank
-                               var screen_pos = tank.pos.to_screen(camera)
-                               display.blit_rotated(assets.drawing.turret_firing, screen_pos.x, screen_pos.y, tank.turret.heading)
-
-                               if tank.pos.dist2(camera.center(display)) < far_dist2 then
-                                       assets.turret_fire.play
-                               end
-                       else if event isa TurretReadyEvent then
-                               if event.tank.pos.dist2(camera.center(display)) < far_dist2 then
-                                       assets.turret_ready.play
-                               end
-                       end
-               end
+               for event in turn.events do event.client_react(display, turn)
 
                # Gather and show some performance stats!
                sys.perfs["draw"].add clock.lapse
diff --git a/lib/standard/fixed_ints.nit b/lib/standard/fixed_ints.nit
new file mode 100644 (file)
index 0000000..6dc6550
--- /dev/null
@@ -0,0 +1,979 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Basic integers of fixed-precision
+#
+# All classes defined here have C-equivalents and the semantics of their
+# operations are the same as C's
+#
+# * Int8 => int8_t
+# * Int16 => int16_t
+# * UInt16 => uint16_t
+# * Int32 => int32_t
+# * UInt32 => uint32_t
+#
+# NOTE: No UInt8 is provided as Byte is the same
+# SEE: kernel::Byte
+#
+# HOW TO USE:
+# All classes can be instanciated via a literal rule.
+# Namely, a suffix to append after the literal integer.
+#
+# * Int8 => i8
+# * Byte => u8
+# * Int16 => i16
+# * UInt16 => u16
+# * Int32 => i32
+# * UInt32 => u32
+module fixed_ints
+
+import text
+
+in "C" `{
+#include <inttypes.h>
+`}
+
+redef class Numeric
+
+       # The Int8 equivalent of `self`
+       #
+       #     assert (-1).to_i8 == 0xFFFFi8
+       #     assert (1.9).to_i8 == 1i8
+       fun to_i8: Int8 do return self.to_i.to_i8
+
+       # The Int16 equivalent of `self`
+       #
+       #     assert (-1).to_i16 == 0xFFFFi16
+       #     assert (1.9).to_i16 == 1i16
+       fun to_i16: Int16 do return self.to_i.to_i16
+
+       # The UInt16 equivalent of `self`
+       #
+       #     assert (-1).to_u16 == 0xFFFFu16
+       #     assert (1.9).to_u16 == 1u16
+       fun to_u16: UInt16 do return self.to_i.to_u16
+
+       # The Int32 equivalent of `self`
+       #
+       #     assert (-1).to_i32 == 0xFFFFFFFFi32
+       #     assert (1.9).to_i32 == 1i32
+       fun to_i32: Int32 do return self.to_i.to_i32
+
+       # The UInt32 equivalent of `self`
+       #
+       #     assert (-1).to_u32 == 0xFFFFFFFFu32
+       #     assert (1.9).to_u32 == 1u32
+       fun to_u32: UInt32 do return self.to_i.to_u32
+
+end
+
+redef class Float
+       redef fun to_i8 is intern
+       redef fun to_i16 is intern
+       redef fun to_u16 is intern
+       redef fun to_i32 is intern
+       redef fun to_u32 is intern
+end
+
+redef class Byte
+       redef fun to_i8 is intern
+       redef fun to_i16 is intern
+       redef fun to_u16 is intern
+       redef fun to_i32 is intern
+       redef fun to_u32 is intern
+end
+
+redef class Int
+       redef fun to_i8 is intern
+       redef fun to_i16 is intern
+       redef fun to_u16 is intern
+       redef fun to_i32 is intern
+       redef fun to_u32 is intern
+end
+
+# Native 8-bit signed integer.
+# Same as a C `int8_t`
+universal Int8
+       super Discrete
+       super Numeric
+
+       redef type OTHER: Int8
+
+       redef fun successor(i) do return self + i.to_i8
+       redef fun predecessor(i) do return self - i.to_i8
+
+       redef fun object_id is intern
+       redef fun hash do return self.to_i
+       redef fun ==(i) is intern
+       redef fun !=(i) is intern
+       redef fun output is intern
+
+       redef fun <=(i) is intern
+       redef fun <(i) is intern
+       redef fun >=(i) is intern
+       redef fun >(i) is intern
+       redef fun +(i) is intern
+
+       #     assert -1i8 == 0xFFi8
+       #     assert -0i8 == 0x00i8
+       redef fun - is intern
+       redef fun -(i) is intern
+       redef fun *(i) is intern
+       redef fun /(i) is intern
+
+       # Modulo of `self` with `i`.
+       #
+       # Returns the remainder of division of `self` by `i`.
+       #
+       #     assert 5i8 % 2i8          == 1i8
+       #     assert 10i8 % 2i8         == 0i8
+       fun %(i: Int8): Int8 is intern
+
+       redef fun zero do return 0.to_i8
+       redef fun value_of(val) do return val.to_i8
+
+       # `i` bits shift to the left
+       #
+       #     assert 5i8 << 1    == 10i8
+       fun <<(i: Int): Int8 is intern
+
+       # `i` bits shift to the right
+       #
+       #     assert 5i8 >> 1    == 2i8
+       fun >>(i: Int): Int8 is intern
+
+       redef fun to_i is intern
+       redef fun to_f is intern
+       redef fun to_b is intern
+       redef fun to_i8 do return self
+       redef fun to_i16 is intern
+       redef fun to_u16 is intern
+       redef fun to_i32 is intern
+       redef fun to_u32 is intern
+
+       redef fun distance(i) do return (self - i).to_i
+
+       redef fun <=>(other)
+       do
+               if self < other then
+                       return -1
+               else if other < self then
+                       return 1
+               else
+                       return 0
+               end
+       end
+
+       redef fun is_between(c, d)
+       do
+               if self < c or d < self then
+                       return false
+               else
+                       return true
+               end
+       end
+
+       redef fun max(other)
+       do
+               if self < other then
+                       return other
+               else
+                       return self
+               end
+       end
+
+       redef fun min(c)
+       do
+               if c < self then
+                       return c
+               else
+                       return self
+               end
+       end
+
+       # Returns the result of a binary AND operation on `self` and `i`
+       #
+       #     assert 0x10i8 & 0x01i8 == 0i8
+       fun &(i: Int8): Int8 is intern
+
+       # Returns the result of a binary OR operation on `self` and `i`
+       #
+       #     assert 0x10i8 | 0x01i8 == 0x11i8
+       fun |(i: Int8): Int8 is intern
+
+       # Returns the result of a binary XOR operation on `self` and `i`
+       #
+       #     assert 0x101i8 ^ 0x110i8 == 0x11i8
+       fun ^(i: Int8): Int8 is intern
+
+       # Returns the 1's complement of `self`
+       #
+       #     assert ~0x2Fi8 == 0xD0i8
+       fun ~: Int8 is intern
+
+       # C function to calculate the length of the `NativeString` to receive `self`
+       private fun to_s_len: Int `{
+               return snprintf(NULL, 0, "%"PRIi8, self);
+       `}
+
+       # C function to convert a nit Int to a NativeString (char*)
+       private fun native_to_s(nstr: NativeString, strlen: Int) `{
+               snprintf(nstr, strlen, "%"PRIi8, self);
+       `}
+
+       # Displayable Int8
+       #
+       #     assert 1i8.to_s       == "1"
+       #     assert (-123i8).to_s  == "-123"
+       redef fun to_s do
+               var nslen = to_s_len
+               var ns = new NativeString(nslen + 1)
+               ns[nslen] = 0u8
+               native_to_s(ns, nslen + 1)
+               return ns.to_s_with_length(nslen)
+       end
+end
+
+# Native 16-bit signed integer.
+# Same as a C `int16_t`
+universal Int16
+       super Discrete
+       super Numeric
+
+       redef type OTHER: Int16
+
+       redef fun successor(i) do return self + i.to_i16
+       redef fun predecessor(i) do return self - i.to_i16
+
+       redef fun object_id is intern
+       redef fun hash do return self.to_i
+       redef fun ==(i) is intern
+       redef fun !=(i) is intern
+       redef fun output is intern
+
+       redef fun <=(i) is intern
+       redef fun <(i) is intern
+       redef fun >=(i) is intern
+       redef fun >(i) is intern
+       redef fun +(i) is intern
+
+       #     assert -1i16 == 0xFFFFi16
+       #     assert -0i16 == 0i16
+       redef fun - is intern
+       redef fun -(i) is intern
+       redef fun *(i) is intern
+       redef fun /(i) is intern
+
+       # Modulo of `self` with `i`.
+       #
+       # Returns the remainder of division of `self` by `i`.
+       #
+       #     assert 5i16 % 2i16        == 1i16
+       #     assert 10i16 % 2i16       == 0i16
+       fun %(i: Int16): Int16 is intern
+
+       redef fun zero do return 0.to_i16
+       redef fun value_of(val) do return val.to_i16
+
+       # `i` bits shift to the left
+       #
+       #     assert 5i16 << 1 == 10i16
+       fun <<(i: Int): Int16 is intern
+
+       # `i` bits shift to the right
+       #
+       #     assert 5i16 >> 1 == 2i16
+       fun >>(i: Int): Int16 is intern
+
+       redef fun to_i is intern
+       redef fun to_f is intern
+       redef fun to_b is intern
+       redef fun to_i8 is intern
+       redef fun to_i16 do return self
+       redef fun to_u16 is intern
+       redef fun to_i32 is intern
+       redef fun to_u32 is intern
+
+       redef fun distance(i) do return (self - i).to_i
+
+       redef fun <=>(other)
+       do
+               if self < other then
+                       return -1
+               else if other < self then
+                       return 1
+               else
+                       return 0
+               end
+       end
+
+       redef fun is_between(c, d)
+       do
+               if self < c or d < self then
+                       return false
+               else
+                       return true
+               end
+       end
+
+       redef fun max(other)
+       do
+               if self < other then
+                       return other
+               else
+                       return self
+               end
+       end
+
+       redef fun min(c)
+       do
+               if c < self then
+                       return c
+               else
+                       return self
+               end
+       end
+
+       # Returns the result of a binary AND operation on `self` and `i`
+       #
+       #     assert 0x10i16 & 0x01i16 == 0i16
+       fun &(i: Int16): Int16 is intern
+
+       # Returns the result of a binary OR operation on `self` and `i`
+       #
+       #     assert 0x10i16 | 0x01i16 == 0x11i16
+       fun |(i: Int16): Int16 is intern
+
+       # Returns the result of a binary XOR operation on `self` and `i`
+       #
+       #     assert 0x101i16 ^ 0x110i16 == 0x11i16
+       fun ^(i: Int16): Int16 is intern
+
+       # Returns the 1's complement of `self`
+       #
+       #     assert ~0x2Fi16 == 0xFFD0i16
+       fun ~: Int16 is intern
+
+       # C function to calculate the length of the `NativeString` to receive `self`
+       private fun to_s_len: Int `{
+               return snprintf(NULL, 0, "%"PRIi16, self);
+       `}
+
+       # C function to convert a nit Int to a NativeString (char*)
+       private fun native_to_s(nstr: NativeString, strlen: Int) `{
+               snprintf(nstr, strlen, "%"PRIi16, self);
+       `}
+
+       # Displayable Int16
+       #
+       #     assert 1i16.to_s       == "1"
+       #     assert (-123i16).to_s  == "-123"
+       redef fun to_s do
+               var nslen = to_s_len
+               var ns = new NativeString(nslen + 1)
+               ns[nslen] = 0u8
+               native_to_s(ns, nslen + 1)
+               return ns.to_s_with_length(nslen)
+       end
+end
+
+# Native 16-bit unsigned integer.
+# Same as a C `uint16_t`
+universal UInt16
+       super Discrete
+       super Numeric
+
+       redef type OTHER: UInt16
+
+       redef fun successor(i) do return self + i.to_u16
+       redef fun predecessor(i) do return self - i.to_u16
+
+       redef fun object_id is intern
+       redef fun hash do return self.to_i
+       redef fun ==(i) is intern
+       redef fun !=(i) is intern
+       redef fun output is intern
+
+       redef fun <=(i) is intern
+       redef fun <(i) is intern
+       redef fun >=(i) is intern
+       redef fun >(i) is intern
+       redef fun +(i) is intern
+
+       #     assert -1u16 == 0xFFFFu16
+       #     assert -0u16 == 0u16
+       redef fun - is intern
+       redef fun -(i) is intern
+       redef fun *(i) is intern
+       redef fun /(i) is intern
+
+       # Modulo of `self` with `i`.
+       #
+       # Returns the remainder of division of `self` by `i`.
+       #
+       #     assert 5u16 % 2u16        == 1u16
+       #     assert 10u16 % 2u16       == 0u16
+       fun %(i: UInt16): UInt16 is intern
+
+       redef fun zero do return 0.to_u16
+       redef fun value_of(val) do return val.to_u16
+
+       # `i` bits shift to the left
+       #
+       #     assert 5u16 << 1    == 10u16
+       fun <<(i: Int): UInt16 is intern
+
+       # `i` bits shift to the right
+       #
+       #     assert 5u16 >> 1    == 2u16
+       fun >>(i: Int): UInt16 is intern
+
+       redef fun to_i is intern
+       redef fun to_f is intern
+       redef fun to_b is intern
+       redef fun to_i8 is intern
+       redef fun to_i16 is intern
+       redef fun to_u16 do return self
+       redef fun to_i32 is intern
+       redef fun to_u32 is intern
+
+       redef fun distance(i) do return (self - i).to_i
+
+       redef fun <=>(other)
+       do
+               if self < other then
+                       return -1
+               else if other < self then
+                       return 1
+               else
+                       return 0
+               end
+       end
+
+       redef fun is_between(c, d)
+       do
+               if self < c or d < self then
+                       return false
+               else
+                       return true
+               end
+       end
+
+       redef fun max(other)
+       do
+               if self < other then
+                       return other
+               else
+                       return self
+               end
+       end
+
+       redef fun min(c)
+       do
+               if c < self then
+                       return c
+               else
+                       return self
+               end
+       end
+
+       # Returns the result of a binary AND operation on `self` and `i`
+       #
+       #     assert 0x10u16 & 0x01u16 == 0u16
+       fun &(i: UInt16): UInt16 is intern
+
+       # Returns the result of a binary OR operation on `self` and `i`
+       #
+       #     assert 0x10u16 | 0x01u16 == 0x11u16
+       fun |(i: UInt16): UInt16 is intern
+
+       # Returns the result of a binary XOR operation on `self` and `i`
+       #
+       #     assert 0x101u16 ^ 0x110u16 == 0x11u16
+       fun ^(i: UInt16): UInt16 is intern
+
+       # Returns the 1's complement of `self`
+       #
+       #     assert ~0x2Fu16 == 0xFFD0u16
+       fun ~: UInt16 is intern
+
+       # C function to calculate the length of the `NativeString` to receive `self`
+       private fun to_s_len: Int `{
+               return snprintf(NULL, 0, "%"PRIu16, self);
+       `}
+
+       # C function to convert a nit Int to a NativeString (char*)
+       private fun native_to_s(nstr: NativeString, strlen: Int) `{
+               snprintf(nstr, strlen, "%"PRIu16, self);
+       `}
+
+       # Displayable UInt16
+       #
+       #     assert 1u16.to_s       == "1"
+       #     assert (-123u16).to_s  == "65413"
+       redef fun to_s do
+               var nslen = to_s_len
+               var ns = new NativeString(nslen + 1)
+               ns[nslen] = 0u8
+               native_to_s(ns, nslen + 1)
+               return ns.to_s_with_length(nslen)
+       end
+end
+
+
+# Native 32-bit signed integer.
+# Same as a C `int32_t`
+universal Int32
+       super Discrete
+       super Numeric
+
+       redef type OTHER: Int32
+
+       redef fun successor(i) do return self + i.to_i32
+       redef fun predecessor(i) do return self - i.to_i32
+
+       redef fun object_id is intern
+       redef fun hash do return self.to_i
+       redef fun ==(i) is intern
+       redef fun !=(i) is intern
+       redef fun output is intern
+
+       redef fun <=(i) is intern
+       redef fun <(i) is intern
+       redef fun >=(i) is intern
+       redef fun >(i) is intern
+       redef fun +(i) is intern
+
+       #     assert -1i32 == 0xFFFFFFFFi32
+       #     assert -0i32 == 0x00i32
+       redef fun - is intern
+       redef fun -(i) is intern
+       redef fun *(i) is intern
+       redef fun /(i) is intern
+
+       # Modulo of `self` with `i`.
+       #
+       # Returns the remainder of division of `self` by `i`.
+       #
+       #     assert 5i32 % 2i32                == 1i32
+       #     assert 10i32 % 2i32               == 0i32
+       fun %(i: Int32): Int32 is intern
+
+       redef fun zero do return 0.to_i32
+       redef fun value_of(val) do return val.to_i32
+
+       # `i` bits shift to the left
+       #
+       #     assert 5i32 << 1    == 10i32
+       fun <<(i: Int): Int32 is intern
+
+       # `i` bits shift to the right
+       #
+       #     assert 5i32 >> 1    == 2i32
+       fun >>(i: Int): Int32 is intern
+
+       redef fun to_i is intern
+       redef fun to_f is intern
+       redef fun to_b is intern
+       redef fun to_i8 is intern
+       redef fun to_i16 is intern
+       redef fun to_u16 is intern
+       redef fun to_i32 do return self
+       redef fun to_u32 is intern
+
+       redef fun distance(i) do return (self - i).to_i
+
+       redef fun <=>(other)
+       do
+               if self < other then
+                       return -1
+               else if other < self then
+                       return 1
+               else
+                       return 0
+               end
+       end
+
+       redef fun is_between(c, d)
+       do
+               if self < c or d < self then
+                       return false
+               else
+                       return true
+               end
+       end
+
+       redef fun max(other)
+       do
+               if self < other then
+                       return other
+               else
+                       return self
+               end
+       end
+
+       redef fun min(c)
+       do
+               if c < self then
+                       return c
+               else
+                       return self
+               end
+       end
+
+       # Returns the result of a binary AND operation on `self` and `i`
+       #
+       #     assert 0x10i32 & 0x01i32 == 0i32
+       fun &(i: Int32): Int32 is intern
+
+       # Returns the result of a binary OR operation on `self` and `i`
+       #
+       #     assert 0x10i32 | 0x01i32 == 0x11i32
+       fun |(i: Int32): Int32 is intern
+
+       # Returns the result of a binary XOR operation on `self` and `i`
+       #
+       #     assert 0x101i32 ^ 0x110i32 == 0x11i32
+       fun ^(i: Int32): Int32 is intern
+
+       # Returns the 1's complement of `self`
+       #
+       #     assert ~0x2Fi32 == 0xFFFFFFD0i32
+       fun ~: Int32 is intern
+
+       # C function to calculate the length of the `NativeString` to receive `self`
+       private fun to_s_len: Int `{
+               return snprintf(NULL, 0, "%"PRIi32, self);
+       `}
+
+       # C function to convert a nit Int to a NativeString (char*)
+       private fun native_to_s(nstr: NativeString, strlen: Int) `{
+               snprintf(nstr, strlen, "%"PRIi32, self);
+       `}
+
+       # Displayable Int32
+       #
+       #     assert 1i32.to_s       == "1"
+       #     assert (-123i32).to_s  == "-123"
+       redef fun to_s do
+               var nslen = to_s_len
+               var ns = new NativeString(nslen + 1)
+               ns[nslen] = 0u8
+               native_to_s(ns, nslen + 1)
+               return ns.to_s_with_length(nslen)
+       end
+end
+
+# Native 32-bit unsigned integer.
+# Same as a C `uint32_t`
+universal UInt32
+       super Discrete
+       super Numeric
+
+       redef type OTHER: UInt32
+
+       redef fun successor(i) do return self + i.to_u32
+       redef fun predecessor(i) do return self - i.to_u32
+
+       redef fun object_id is intern
+       redef fun hash do return self.to_i
+       redef fun ==(i) is intern
+       redef fun !=(i) is intern
+       redef fun output is intern
+
+       redef fun <=(i) is intern
+       redef fun <(i) is intern
+       redef fun >=(i) is intern
+       redef fun >(i) is intern
+       redef fun +(i) is intern
+
+       #     assert -1u32 == 0xFFFFFFFFu32
+       #     assert -0u32 == 0x00u32
+       redef fun - is intern
+       redef fun -(i) is intern
+       redef fun *(i) is intern
+       redef fun /(i) is intern
+
+       # Modulo of `self` with `i`.
+       #
+       # Returns the remainder of division of `self` by `i`.
+       #
+       #     assert 5u32 % 2u32                == 1u32
+       #     assert 10u32 % 2u32               == 0u32
+       fun %(i: UInt32): UInt32 is intern
+
+       redef fun zero do return 0.to_u32
+       redef fun value_of(val) do return val.to_u32
+
+       # `i` bits shift to the left
+       #
+       #     assert 5u32 << 1    == 10u32
+       fun <<(i: Int): UInt32 is intern
+
+       # `i` bits shift to the right
+       #
+       #     assert 5u32 >> 1    == 2u32
+       fun >>(i: Int): UInt32 is intern
+
+       redef fun to_i is intern
+       redef fun to_f is intern
+       redef fun to_b is intern
+       redef fun to_i8 is intern
+       redef fun to_i16 is intern
+       redef fun to_u16 is intern
+       redef fun to_i32 is intern
+       redef fun to_u32 do return self
+
+       redef fun distance(i) do return (self - i).to_i
+
+       redef fun <=>(other)
+       do
+               if self < other then
+                       return -1
+               else if other < self then
+                       return 1
+               else
+                       return 0
+               end
+       end
+
+       redef fun is_between(c, d)
+       do
+               if self < c or d < self then
+                       return false
+               else
+                       return true
+               end
+       end
+
+       redef fun max(other)
+       do
+               if self < other then
+                       return other
+               else
+                       return self
+               end
+       end
+
+       redef fun min(c)
+       do
+               if c < self then
+                       return c
+               else
+                       return self
+               end
+       end
+
+       # Returns the result of a binary AND operation on `self` and `i`
+       #
+       #     assert 0x10u32 & 0x01u32 == 0u32
+       fun &(i: UInt32): UInt32 is intern
+
+       # Returns the result of a binary OR operation on `self` and `i`
+       #
+       #     assert 0x10u32 | 0x01u32 == 0x11u32
+       fun |(i: UInt32): UInt32 is intern
+
+       # Returns the result of a binary XOR operation on `self` and `i`
+       #
+       #     assert 0x101u32 ^ 0x110u32 == 0x11u32
+       fun ^(i: UInt32): UInt32 is intern
+
+       # Returns the 1's complement of `self`
+       #
+       #     assert ~0x2Fu32 == 0xFFFFFFD0u32
+       fun ~: UInt32 is intern
+
+       # C function to calculate the length of the `NativeString` to receive `self`
+       private fun to_s_len: Int `{
+               return snprintf(NULL, 0, "%"PRIu32, self);
+       `}
+
+       # C function to convert a nit Int to a NativeString (char*)
+       private fun native_to_s(nstr: NativeString, strlen: Int) `{
+               snprintf(nstr, strlen, "%"PRIu32, self);
+       `}
+
+       # Displayable UInt32
+       #
+       #     assert 1u32.to_s       == "1"
+       #     assert (-123u32).to_s  == "4294967173"
+       redef fun to_s do
+               var nslen = to_s_len
+               var ns = new NativeString(nslen + 1)
+               ns[nslen] = 0u8
+               native_to_s(ns, nslen + 1)
+               return ns.to_s_with_length(nslen)
+       end
+end
+
+redef class Text
+
+       # Removes the numeric head of `self` if present
+       #
+       #     intrude import standard::fixed_ints
+       #     assert "0xFFEF".strip_numhead  == "FFEF"
+       #     assert "0o7364".strip_numhead  == "7364"
+       #     assert "0b01001".strip_numhead == "01001"
+       #     assert "98".strip_numhead      == "98"
+       private fun strip_numhead: Text do
+               if get_numhead != "" then return substring_from(2)
+               return self
+       end
+
+       # Gets the numeric head of `self` if present
+       # Returns "" otherwise
+       #
+       #     intrude import standard::fixed_ints
+       #     assert "0xFEFF".get_numhead  == "0x"
+       #     assert "0b01001".get_numhead == "0b"
+       #     assert "0o872".get_numhead   == "0o"
+       #     assert "98".get_numhead      == ""
+       private fun get_numhead: Text do
+               if self.length < 2 then return ""
+               var c = self[0]
+               if c != '0' then return ""
+               c = self[1]
+               if c == 'x' or c == 'b' or c == 'o' or
+                  c == 'X' or c == 'B' or c == 'O' then return substring(0, 2)
+               return ""
+       end
+
+       # Removes the numeric extension if present
+       #
+       #     intrude import standard::fixed_ints
+       #     assert "0xFEFFu8".strip_numext  == "0xFEFF"
+       #     assert "0b01001u8".strip_numext == "0b01001"
+       #     assert "0o872u8".strip_numext   == "0o872"
+       #     assert "98".strip_numext        == "98"
+       private fun strip_numext: Text do
+               var ext = get_numext
+               if ext != "" then return substring(0, length - ext.length)
+               return self
+       end
+
+       # Gets the numeric extension (i/u 8/16/32) in `self` is present
+       # Returns "" otherwise
+       #
+       #     intrude import standard::fixed_ints
+       #     assert "0xFEFFu8".get_numext  == "u8"
+       #     assert "0b01001u8".get_numext == "u8"
+       #     assert "0o872u8".get_numext   == "u8"
+       #     assert "98".get_numext        == ""
+       private fun get_numext: Text do
+               var len = self.length
+               var max = if self.length < 3 then self.length else 3
+               for i in [1 .. max] do
+                       var c = self[len - i]
+                       if c == 'i' or c == 'u' then return substring_from(len - i)
+               end
+               return ""
+       end
+
+       # Is `self` a well-formed Integer (i.e. parsable via `to_i`)
+       #
+       #     assert "123".is_int
+       #     assert "0b1011".is_int
+       #     assert not "0x_".is_int
+       #     assert not "0xGE".is_int
+       fun is_int: Bool do
+               var s = remove_all('_')
+               var pos = 0
+               while s[pos] == '-' do
+                       pos += 1
+               end
+               s = s.substring_from(pos)
+               var rets = s.strip_numhead
+               if rets == "" then return false
+               var hd = get_numhead
+               if hd == "0x" or hd == "0X" then return rets.is_hex
+               if hd == "0b" or hd == "0B" then return rets.is_bin
+               if hd == "0o" or hd == "0O" then return rets.is_oct
+               return hd.is_dec
+       end
+
+       redef fun to_i
+       do
+               assert self.is_int
+               var s = remove_all('_')
+               var val = 0
+               var neg = false
+               var pos = 0
+               while s[pos] == '-' do
+                       neg = not neg
+                       pos += 1
+               end
+               s = s.substring_from(pos)
+               if s.length >= 2 then
+                       var s1 = s[1]
+                       if s1 == 'x' or s1 == 'X' then
+                               val = s.substring_from(2).to_hex
+                       else if s1 == 'o' or s1 == 'O' then
+                               val = s.substring_from(2).to_oct
+                       else if s1 == 'b' or s1 == 'B' then
+                               val = s.substring_from(2).to_bin
+                       else if s1.is_numeric then
+                               val = s.to_dec
+                       end
+               else
+                       val = s.to_dec
+               end
+               return if neg then -val else val
+       end
+
+       # Is `self` a valid integer ?
+       #
+       #     assert "0xFE46u8".is_num
+       #     assert "0b0100".is_num
+       #     assert "0o645".is_num
+       #     assert "897u8".is_num
+       fun is_num: Bool do
+               var prefix = get_numhead
+               var s = strip_numhead.strip_numext.remove_all('_')
+               if prefix != "" then
+                       var c = prefix[1]
+                       if c == 'x' or c == 'X' then return s.is_hex
+                       if c == 'o' or c == 'O' then return s.is_oct
+                       if c == 'b' or c == 'B' then return s.is_bin
+               end
+               return s.is_dec
+       end
+
+       # If `self` is a properly formatted integer, returns the corresponding value
+       # Returns `null` otherwise
+       #
+       #     assert "0xFEu8".to_num  == 254u8
+       #     assert "0b10_10".to_num != 10u8
+       fun to_num: nullable Numeric do
+               if not is_num then return null
+               var s = remove_all('_')
+               var ext = s.get_numext
+               var trunk = s.strip_numext
+               if trunk.strip_numhead == "" then return null
+               var trval = trunk.to_i
+               if ext == "u8" then
+                       return trval.to_b
+               else if ext == "i8" then
+                       return trval.to_i8
+               else if ext == "i16" then
+                       return trval.to_i16
+               else if ext == "u16" then
+                       return trval.to_u16
+               else if ext == "i32" then
+                       return trval.to_i32
+               else if ext == "u32" then
+                       return trval.to_u32
+               else if ext == "" then
+                       return trval
+               else
+                       return null
+               end
+       end
+end
index e675600..2251bc3 100644 (file)
@@ -32,3 +32,4 @@ import numeric
 import error
 import re
 import bytes
+import fixed_ints
index d7b915c..8de0af9 100644 (file)
@@ -240,89 +240,6 @@ abstract class Text
                return b.to_s
        end
 
-       # Is `self` a well-formed Integer (i.e. parsable via `to_i`)
-       #
-       #     assert "123".is_int
-       #     assert "0b1011".is_int
-       #     assert not "0x_".is_int
-       #     assert not "0xGE".is_int
-       fun is_int: Bool do
-               var s = remove_all('_')
-               var pos = 0
-               while s[pos] == '-' do
-                       pos += 1
-               end
-               s = s.substring_from(pos)
-               var rets = s.strip_numhead
-               if rets == "" then return false
-               var hd = get_numhead
-               if hd == "0x" or hd == "0X" then return rets.is_hex
-               if hd == "0b" or hd == "0B" then return rets.is_bin
-               if hd == "0o" or hd == "0O" then return rets.is_oct
-               return hd.is_dec
-       end
-
-       # Removes the numeric head of `self` if present
-       #
-       #     intrude import standard::text::abstract_text
-       #     assert "0xFFEF".strip_numhead  == "FFEF"
-       #     assert "0o7364".strip_numhead  == "7364"
-       #     assert "0b01001".strip_numhead == "01001"
-       #     assert "98".strip_numhead      == "98"
-       private fun strip_numhead: Text do
-               if get_numhead != "" then return substring_from(2)
-               return self
-       end
-
-       # Gets the numeric head of `self` if present
-       # Returns "" otherwise
-       #
-       #     intrude import standard::text::abstract_text
-       #     assert "0xFEFF".get_numhead  == "0x"
-       #     assert "0b01001".get_numhead == "0b"
-       #     assert "0o872".get_numhead   == "0o"
-       #     assert "98".get_numhead      == ""
-       private fun get_numhead: Text do
-               if self.length < 2 then return ""
-               var c = self[0]
-               if c != '0' then return ""
-               c = self[1]
-               if c == 'x' or c == 'b' or c == 'o' or
-                  c == 'X' or c == 'B' or c == 'O' then return substring(0, 2)
-               return ""
-       end
-
-       # Removes the numeric extension if present
-       #
-       #     intrude import standard::text::abstract_text
-       #     assert "0xFEFFu8".strip_numext  == "0xFEFF"
-       #     assert "0b01001u8".strip_numext == "0b01001"
-       #     assert "0o872u8".strip_numext   == "0o872"
-       #     assert "98".strip_numext        == "98"
-       private fun strip_numext: Text do
-               var ext = get_numext
-               if ext != "" then return substring(0, length - ext.length)
-               return self
-       end
-
-       # Gets the numeric extension (i/u 8/16/32) in `self` is present
-       # Returns "" otherwise
-       #
-       #     intrude import standard::text::abstract_text
-       #     assert "0xFEFFu8".get_numext  == "u8"
-       #     assert "0b01001u8".get_numext == "u8"
-       #     assert "0o872u8".get_numext   == "u8"
-       #     assert "98".get_numext        == ""
-       private fun get_numext: Text do
-               var len = self.length
-               var max = if self.length < 3 then self.length else 3
-               for i in [1 .. max] do
-                       var c = self[len - i]
-                       if c == 'i' or c == 'u' then return substring_from(len - i)
-               end
-               return ""
-       end
-
        # Returns `self` as the corresponding integer
        #
        #     assert "123".to_i        == 123
@@ -332,72 +249,7 @@ abstract class Text
        #     assert "--12".to_i       == 12
        #
        # REQUIRE: `self`.`is_int`
-       fun to_i: Int
-       do
-               assert self.is_int
-               var s = remove_all('_')
-               var val = 0
-               var neg = false
-               var pos = 0
-               while s[pos] == '-' do
-                       neg = not neg
-                       pos += 1
-               end
-               s = s.substring_from(pos)
-               if s.length >= 2 then
-                       var s1 = s[1]
-                       if s1 == 'x' or s1 == 'X' then
-                               val = s.substring_from(2).to_hex
-                       else if s1 == 'o' or s1 == 'O' then
-                               val = s.substring_from(2).to_oct
-                       else if s1 == 'b' or s1 == 'B' then
-                               val = s.substring_from(2).to_bin
-                       else if s1.is_numeric then
-                               val = s.to_dec
-                       end
-               else
-                       val = s.to_dec
-               end
-               return if neg then -val else val
-       end
-
-       # Is `self` a valid integer ?
-       #
-       #     assert "0xFE46u8".is_num
-       #     assert "0b0100".is_num
-       #     assert "0o645".is_num
-       #     assert "897u8".is_num
-       fun is_num: Bool do
-               var prefix = get_numhead
-               var s = strip_numhead.strip_numext.remove_all('_')
-               if prefix != "" then
-                       var c = prefix[1]
-                       if c == 'x' or c == 'X' then return s.is_hex
-                       if c == 'o' or c == 'O' then return s.is_oct
-                       if c == 'b' or c == 'B' then return s.is_bin
-               end
-               return s.is_dec
-       end
-
-       # Is `self` is a properly formatted integer, returns the corresponding value
-       #
-       #     assert "0xFEu8".to_num  == 254u8
-       #     assert "0b10_10".to_num != 10u8
-       fun to_num: nullable Numeric do
-               if not is_num then return null
-               var s = remove_all('_')
-               var ext = s.get_numext
-               var trunk = s.strip_numext
-               if trunk.strip_numhead == "" then return null
-               var trval = trunk.to_i
-               if ext == "u8" then
-                       return trval.to_b
-               else if ext == "" then
-                       return trval
-               else
-                       return null
-               end
-       end
+       fun to_i: Int is abstract
 
        # If `self` contains a float, return the corresponding float
        #
index 78d2c31..b58d4a3 100644 (file)
@@ -654,6 +654,7 @@ abstract class AbstractCompiler
                self.header.add_decl("#include <sys/types.h>\n")
                self.header.add_decl("#include <unistd.h>\n")
                self.header.add_decl("#include <stdint.h>\n")
+               self.header.add_decl("#include <inttypes.h>\n")
                self.header.add_decl("#include \"gc_chooser.h\"")
                self.header.add_decl("#ifdef ANDROID")
                self.header.add_decl("  #include <android/log.h>")
@@ -1506,6 +1507,46 @@ abstract class AbstractCompilerVisitor
                return res
        end
 
+       # Generate an int8 value
+       fun int8_instance(value: Int8): RuntimeVariable
+       do
+               var t = mmodule.int8_type
+               var res = new RuntimeVariable("((int8_t){value.to_s})", t, t)
+               return res
+       end
+
+       # Generate an int16 value
+       fun int16_instance(value: Int16): RuntimeVariable
+       do
+               var t = mmodule.int16_type
+               var res = new RuntimeVariable("((int16_t){value.to_s})", t, t)
+               return res
+       end
+
+       # Generate a uint16 value
+       fun uint16_instance(value: UInt16): RuntimeVariable
+       do
+               var t = mmodule.uint16_type
+               var res = new RuntimeVariable("((uint16_t){value.to_s})", t, t)
+               return res
+       end
+
+       # Generate an int32 value
+       fun int32_instance(value: Int32): RuntimeVariable
+       do
+               var t = mmodule.int32_type
+               var res = new RuntimeVariable("((int32_t){value.to_s})", t, t)
+               return res
+       end
+
+       # Generate a uint32 value
+       fun uint32_instance(value: UInt32): RuntimeVariable
+       do
+               var t = mmodule.uint32_type
+               var res = new RuntimeVariable("((uint32_t){value.to_s})", t, t)
+               return res
+       end
+
        # Generate a char value
        fun char_instance(value: Char): RuntimeVariable
        do
@@ -1905,8 +1946,18 @@ redef class MClassType
                        return "uint32_t"
                else if mclass.name == "Float" then
                        return "double"
+               else if mclass.name == "Int8" then
+                       return "int8_t"
                else if mclass.name == "Byte" then
                        return "unsigned char"
+               else if mclass.name == "Int16" then
+                       return "int16_t"
+               else if mclass.name == "UInt16" then
+                       return "uint16_t"
+               else if mclass.name == "Int32" then
+                       return "int32_t"
+               else if mclass.name == "UInt32" then
+                       return "uint32_t"
                else if mclass.name == "NativeString" then
                        return "char*"
                else if mclass.name == "NativeArray" then
@@ -1937,8 +1988,18 @@ redef class MClassType
                        return "c"
                else if mclass.name == "Float" then
                        return "d"
+               else if mclass.name == "Int8" then
+                       return "i8"
                else if mclass.name == "Byte" then
                        return "b"
+               else if mclass.name == "Int16" then
+                       return "i16"
+               else if mclass.name == "UInt16" then
+                       return "u16"
+               else if mclass.name == "Int32" then
+                       return "i32"
+               else if mclass.name == "UInt32" then
+                       return "u32"
                else if mclass.name == "NativeString" then
                        return "str"
                else if mclass.name == "NativeArray" then
@@ -2160,6 +2221,21 @@ redef class AMethPropdef
                        else if pname == ">=" then
                                v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
                                return true
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
                        else if pname == "to_f" then
                                v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
                                return true
@@ -2259,6 +2335,21 @@ redef class AMethPropdef
                        else if pname == "to_f" then
                                v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
                                return true
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
                        else if pname == "ascii" then
                                v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
                                return true
@@ -2334,6 +2425,21 @@ redef class AMethPropdef
                        else if pname == "to_b" then
                                v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
                                return true
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
                        end
                else if cname == "NativeString" then
                        if pname == "[]" then
@@ -2358,6 +2464,456 @@ redef class AMethPropdef
                else if cname == "NativeArray" then
                        v.native_array_def(pname, ret, arguments)
                        return true
+               else if cname == "Int8" then
+                       if pname == "output" then
+                               v.add("printf(\"%\"PRIi8 \"\\n\", {arguments.first});")
+                               return true
+                       else if pname == "object_id" then
+                               v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
+                               return true
+                       else if pname == "+" then
+                               v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "-" then
+                               v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary -" then
+                               v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary +" then
+                               v.ret(arguments[0])
+                               return true
+                       else if pname == "*" then
+                               v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "/" then
+                               v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "%" then
+                               v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "<<" then
+                               v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">>" then
+                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "==" then
+                               v.ret(v.equal_test(arguments[0], arguments[1]))
+                               return true
+                       else if pname == "!=" then
+                               var res = v.equal_test(arguments[0], arguments[1])
+                               v.ret(v.new_expr("!{res}", ret.as(not null)))
+                               return true
+                       else if pname == "<" then
+                               v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">" then
+                               v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "<=" then
+                               v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">=" then
+                               v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i" then
+                               v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_b" then
+                               v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_f" then
+                               v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "ascii" then
+                               v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "&" then
+                               v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "|" then
+                               v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "^" then
+                               v.ret(v.new_expr("{arguments[0]} ^ {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary ~" then
+                               v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
+                               return true
+                       end
+               else if cname == "Int16" then
+                       if pname == "output" then
+                               v.add("printf(\"%\"PRIi16 \"\\n\", {arguments.first});")
+                               return true
+                       else if pname == "object_id" then
+                               v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
+                               return true
+                       else if pname == "+" then
+                               v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "-" then
+                               v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary -" then
+                               v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary +" then
+                               v.ret(arguments[0])
+                               return true
+                       else if pname == "*" then
+                               v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "/" then
+                               v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "%" then
+                               v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "<<" then
+                               v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">>" then
+                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "==" then
+                               v.ret(v.equal_test(arguments[0], arguments[1]))
+                               return true
+                       else if pname == "!=" then
+                               var res = v.equal_test(arguments[0], arguments[1])
+                               v.ret(v.new_expr("!{res}", ret.as(not null)))
+                               return true
+                       else if pname == "<" then
+                               v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">" then
+                               v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "<=" then
+                               v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">=" then
+                               v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i" then
+                               v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_b" then
+                               v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_f" then
+                               v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "&" then
+                               v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "|" then
+                               v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "^" then
+                               v.ret(v.new_expr("{arguments[0]} ^ {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary ~" then
+                               v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "ascii" then
+                               v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
+                               return true
+                       end
+               else if cname == "UInt16" then
+                       if pname == "output" then
+                               v.add("printf(\"%\"PRIu16 \"\\n\", {arguments.first});")
+                               return true
+                       else if pname == "object_id" then
+                               v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
+                               return true
+                       else if pname == "+" then
+                               v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "-" then
+                               v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary -" then
+                               v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary +" then
+                               v.ret(arguments[0])
+                               return true
+                       else if pname == "*" then
+                               v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "/" then
+                               v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "%" then
+                               v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "<<" then
+                               v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">>" then
+                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "==" then
+                               v.ret(v.equal_test(arguments[0], arguments[1]))
+                               return true
+                       else if pname == "!=" then
+                               var res = v.equal_test(arguments[0], arguments[1])
+                               v.ret(v.new_expr("!{res}", ret.as(not null)))
+                               return true
+                       else if pname == "<" then
+                               v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">" then
+                               v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "<=" then
+                               v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">=" then
+                               v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i" then
+                               v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_b" then
+                               v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_f" then
+                               v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "&" then
+                               v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "|" then
+                               v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "^" then
+                               v.ret(v.new_expr("{arguments[0]} ^ {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary ~" then
+                               v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "ascii" then
+                               v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
+                               return true
+                       end
+               else if cname == "Int32" then
+                       if pname == "output" then
+                               v.add("printf(\"%\"PRIi32 \"\\n\", {arguments.first});")
+                               return true
+                       else if pname == "object_id" then
+                               v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
+                               return true
+                       else if pname == "+" then
+                               v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "-" then
+                               v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary -" then
+                               v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary +" then
+                               v.ret(arguments[0])
+                               return true
+                       else if pname == "*" then
+                               v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "/" then
+                               v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "%" then
+                               v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "<<" then
+                               v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">>" then
+                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "==" then
+                               v.ret(v.equal_test(arguments[0], arguments[1]))
+                               return true
+                       else if pname == "!=" then
+                               var res = v.equal_test(arguments[0], arguments[1])
+                               v.ret(v.new_expr("!{res}", ret.as(not null)))
+                               return true
+                       else if pname == "<" then
+                               v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">" then
+                               v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "<=" then
+                               v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">=" then
+                               v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i" then
+                               v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_b" then
+                               v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_f" then
+                               v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "&" then
+                               v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "|" then
+                               v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "^" then
+                               v.ret(v.new_expr("{arguments[0]} ^ {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary ~" then
+                               v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "ascii" then
+                               v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
+                               return true
+                       end
+               else if cname == "UInt32" then
+                       if pname == "output" then
+                               v.add("printf(\"%\"PRIu32 \"\\n\", {arguments.first});")
+                               return true
+                       else if pname == "object_id" then
+                               v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
+                               return true
+                       else if pname == "+" then
+                               v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "-" then
+                               v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary -" then
+                               v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary +" then
+                               v.ret(arguments[0])
+                               return true
+                       else if pname == "*" then
+                               v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "/" then
+                               v.ret(v.new_expr("{arguments[0]} / {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "%" then
+                               v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "<<" then
+                               v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">>" then
+                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "==" then
+                               v.ret(v.equal_test(arguments[0], arguments[1]))
+                               return true
+                       else if pname == "!=" then
+                               var res = v.equal_test(arguments[0], arguments[1])
+                               v.ret(v.new_expr("!{res}", ret.as(not null)))
+                               return true
+                       else if pname == "<" then
+                               v.ret(v.new_expr("{arguments[0]} < {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">" then
+                               v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "<=" then
+                               v.ret(v.new_expr("{arguments[0]} <= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">=" then
+                               v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i" then
+                               v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_b" then
+                               v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_f" then
+                               v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "&" then
+                               v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "|" then
+                               v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "^" then
+                               v.ret(v.new_expr("{arguments[0]} ^ {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary ~" then
+                               v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "ascii" then
+                               v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
+                               return true
+                       end
                end
                if pname == "exit" then
                        v.add("exit({arguments[1]});")
@@ -2910,6 +3466,11 @@ redef class AIntegerExpr
        redef fun expr(v) do
                if value isa Int then return v.int_instance(value.as(Int))
                if value isa Byte then return v.byte_instance(value.as(Byte))
+               if value isa Int8 then return v.int8_instance(value.as(Int8))
+               if value isa Int16 then return v.int16_instance(value.as(Int16))
+               if value isa UInt16 then return v.uint16_instance(value.as(UInt16))
+               if value isa Int32 then return v.int32_instance(value.as(Int32))
+               if value isa UInt32 then return v.uint32_instance(value.as(UInt32))
                # Should never happen
                abort
        end
index 9fd1606..ff5f3ba 100644 (file)
@@ -252,7 +252,8 @@ class SeparateCompiler
        do
                # Collect all bas box class
                # FIXME: this is not completely fine with a separate compilation scheme
-               for classname in ["Int", "Bool", "Byte", "Char", "Float", "NativeString", "Pointer"] do
+               for classname in ["Int", "Bool", "Byte", "Char", "Float", "NativeString",
+                                "Pointer", "Int8", "Int16", "UInt16", "Int32", "UInt32"] do
                        var classes = self.mainmodule.model.get_mclasses_by_name(classname)
                        if classes == null then continue
                        assert classes.length == 1 else print classes.join(", ")
index dd32712..eca32ac 100644 (file)
@@ -483,6 +483,11 @@ redef class MClassType
                if mclass.name == "Int" then return "long"
                if mclass.name == "Float" then return "double"
                if mclass.name == "Byte" then return "byte"
+               if mclass.name == "Int8" then return "byte"
+               if mclass.name == "Int16" then return "short"
+               if mclass.name == "UInt16" then return "short"
+               if mclass.name == "Int32" then return "int"
+               if mclass.name == "UInt32" then return "int"
                return super
        end
 
@@ -495,6 +500,11 @@ redef class MClassType
                if mclass.name == "Int" then return "jlong"
                if mclass.name == "Float" then return "jdouble"
                if mclass.name == "Byte" then return "jbyte"
+               if mclass.name == "Int8" then return "jbyte"
+               if mclass.name == "Int16" then return "jshort"
+               if mclass.name == "UInt16" then return "jshort"
+               if mclass.name == "Int32" then return "jint"
+               if mclass.name == "UInt32" then return "jint"
                return super
        end
 
@@ -555,6 +565,11 @@ redef class MClassType
                if mclass.name == "Int" then return "J"
                if mclass.name == "Float" then return "D"
                if mclass.name == "Byte" then return "B"
+               if mclass.name == "Int8" then return "B"
+               if mclass.name == "Int16" then return "S"
+               if mclass.name == "UInt16" then return "S"
+               if mclass.name == "Int32" then return "I"
+               if mclass.name == "UInt32" then return "I"
                return super
        end
 
@@ -568,6 +583,11 @@ redef class MClassType
                if mclass.name == "Int" then return "Long"
                if mclass.name == "Float" then return "Double"
                if mclass.name == "Byte" then return "Byte"
+               if mclass.name == "Int8" then return "Byte"
+               if mclass.name == "Int16" then return "Short"
+               if mclass.name == "UInt16" then return "Short"
+               if mclass.name == "Int32" then return "Int"
+               if mclass.name == "UInt32" then return "Int"
                return super
        end
 end
index 3a07c84..1d66f23 100644 (file)
@@ -41,6 +41,11 @@ This API is compose of 2 main elements:
       int value_Bool;
       uint32_t value_Char;
       uint8_t value_Byte;
+      int8_t value_Int8;
+      int16_t value_Int16;
+      uint16_t value_UInt16;
+      int32_t value_Int32;
+      uint32_t value_UInt32;
       double value_Float;
       void* value_Pointer;
   } nit_call_arg;
index 3f1bf0d..b507c9d 100644 (file)
@@ -32,6 +32,11 @@ in "C Header" `{
                int value_Bool;
                uint32_t value_Char;
                uint8_t value_Byte;
+               int8_t value_Int8;
+               int16_t value_Int16;
+               uint16_t value_UInt16;
+               int32_t value_Int32;
+               uint32_t value_UInt32;
                double value_Float;
                void* value_Pointer;
        } nit_call_arg;
@@ -77,6 +82,36 @@ private extern class CallArg `{ nit_call_arg* `}
        # The `Byte` held by this cell
        fun byte=(value: Byte) `{ self->value_Byte = value; `}
 
+       # The `Int` held by this cell
+       fun int8: Int8 `{ return self->value_Int8; `}
+
+       # The `Int` held by this cell
+       fun int8=(value: Int8) `{ self->value_Int8 = value; `}
+
+       # The `Int` held by this cell
+       fun int16: Int16 `{ return self->value_Int16; `}
+
+       # The `Int` held by this cell
+       fun int16=(value: Int16) `{ self->value_Int16 = value; `}
+
+       # The `Int` held by this cell
+       fun uint16: UInt16 `{ return self->value_UInt16; `}
+
+       # The `Int` held by this cell
+       fun uint16=(value: UInt16) `{ self->value_UInt16 = value; `}
+
+       # The `Int` held by this cell
+       fun int32: Int32 `{ return self->value_Int32; `}
+
+       # The `Int` held by this cell
+       fun int32=(value: Int32) `{ self->value_Int32 = value; `}
+
+       # The `Int` held by this cell
+       fun uint32: UInt32 `{ return self->value_UInt32; `}
+
+       # The `Int` held by this cell
+       fun uint32=(value: UInt32) `{ self->value_UInt32 = value; `}
+
        # The `Float` held by this cell
        fun float: Float `{ return self->value_Float; `}
 
@@ -115,6 +150,21 @@ private extern class CallArg `{ nit_call_arg* `}
                else if static_type.name == "Byte" then
                        assert value isa PrimitiveInstance[Byte]
                        self.byte = value.val
+               else if static_type.name == "Int8" then
+                       assert value isa PrimitiveInstance[Int8]
+                       self.int8 = value.val
+               else if static_type.name == "Int16" then
+                       assert value isa PrimitiveInstance[Int16]
+                       self.int16 = value.val
+               else if static_type.name == "UInt16" then
+                       assert value isa PrimitiveInstance[UInt16]
+                       self.uint16 = value.val
+               else if static_type.name == "Int32" then
+                       assert value isa PrimitiveInstance[Int32]
+                       self.int32 = value.val
+               else if static_type.name == "UInt32" then
+                       assert value isa PrimitiveInstance[UInt32]
+                       self.uint32 = value.val
                else if static_type.name == "Float" then
                        assert value isa PrimitiveInstance[Float]
                        self.float = value.val
@@ -145,6 +195,16 @@ private extern class CallArg `{ nit_call_arg* `}
                        return v.char_instance(self.char)
                else if name == "Byte" then
                        return v.byte_instance(self.byte)
+               else if name == "Int8" then
+                       return v.int8_instance(self.int8)
+               else if name == "Int16" then
+                       return v.int16_instance(self.int16)
+               else if name == "UInt16" then
+                       return v.uint16_instance(self.uint16)
+               else if name == "Int32" then
+                       return v.int32_instance(self.int32)
+               else if name == "UInt32" then
+                       return v.uint32_instance(self.uint32)
                else if name == "Float" then
                        return v.float_instance(self.float)
                else if name == "NativeString" then
index 5953647..eba0678 100644 (file)
@@ -143,6 +143,11 @@ typedef union nit_call_arg {
        int value_Bool;
        uint32_t value_Char;
        uint8_t value_Byte;
+       int8_t value_Int8;
+       int16_t value_Int16;
+       uint16_t value_UInt16;
+       int32_t value_Int32;
+       uint32_t value_UInt32;
        double value_Float;
        void* value_Pointer;
 } nit_call_arg;
index 3d3aa12..1181cf0 100644 (file)
@@ -216,6 +216,51 @@ class NaiveInterpreter
                return instance
        end
 
+       # Return the int8 instance associated with `val`.
+       fun int8_instance(val: Int8): Instance
+       do
+               var t = mainmodule.int8_type
+               var instance = new PrimitiveInstance[Int8](t, val)
+               init_instance_primitive(instance)
+               return instance
+       end
+
+       # Return the int16 instance associated with `val`.
+       fun int16_instance(val: Int16): Instance
+       do
+               var t = mainmodule.int16_type
+               var instance = new PrimitiveInstance[Int16](t, val)
+               init_instance_primitive(instance)
+               return instance
+       end
+
+       # Return the uint16 instance associated with `val`.
+       fun uint16_instance(val: UInt16): Instance
+       do
+               var t = mainmodule.uint16_type
+               var instance = new PrimitiveInstance[UInt16](t, val)
+               init_instance_primitive(instance)
+               return instance
+       end
+
+       # Return the int32 instance associated with `val`.
+       fun int32_instance(val: Int32): Instance
+       do
+               var t = mainmodule.int32_type
+               var instance = new PrimitiveInstance[Int32](t, val)
+               init_instance_primitive(instance)
+               return instance
+       end
+
+       # Return the uint32 instance associated with `val`.
+       fun uint32_instance(val: UInt32): Instance
+       do
+               var t = mainmodule.uint32_type
+               var instance = new PrimitiveInstance[UInt32](t, val)
+               init_instance_primitive(instance)
+               return instance
+       end
+
        # Return the char instance associated with `val`.
        fun char_instance(val: Char): Instance
        do
@@ -656,6 +701,26 @@ abstract class Instance
        # else aborts
        fun to_b: Byte do abort
 
+       # Return the integer value if the instance is a int8.
+       # else aborts
+       fun to_i8: Int8 do abort
+
+       # Return the integer value if the instance is a int16.
+       # else aborts
+       fun to_i16: Int16 do abort
+
+       # Return the integer value if the instance is a uint16.
+       # else aborts
+       fun to_u16: UInt16 do abort
+
+       # Return the integer value if the instance is a int32.
+       # else aborts
+       fun to_i32: Int32 do abort
+
+       # Return the integer value if the instance is a uint32.
+       # else aborts
+       fun to_u32: UInt32 do abort
+
        # The real value encapsulated if the instance is primitive.
        # Else aborts.
        fun val: nullable Object do abort
@@ -703,6 +768,16 @@ class PrimitiveInstance[E]
        redef fun to_f do return val.as(Float)
 
        redef fun to_b do return val.as(Byte)
+
+       redef fun to_i8 do return val.as(Int8)
+
+       redef fun to_i16 do return val.as(Int16)
+
+       redef fun to_u16 do return val.as(UInt16)
+
+       redef fun to_i32 do return val.as(Int32)
+
+       redef fun to_u32 do return val.as(UInt32)
 end
 
 # Information about local variables in a running method
@@ -907,6 +982,16 @@ redef class AMethPropdef
                                return v.int_instance(recvval << args[1].to_i)
                        else if pname == ">>" then
                                return v.int_instance(recvval >> args[1].to_i)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recvval.to_i8)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recvval.to_i16)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recvval.to_u16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recvval.to_i32)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recvval.to_u32)
                        else if pname == "rand" then
                                var res = recvval.rand
                                return v.int_instance(res)
@@ -945,6 +1030,16 @@ redef class AMethPropdef
                                return v.byte_instance(recvval << args[1].to_i)
                        else if pname == ">>" then
                                return v.byte_instance(recvval >> args[1].to_i)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recvval.to_i8)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recvval.to_i16)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recvval.to_u16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recvval.to_i32)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recvval.to_u32)
                        else if pname == "byte_to_s_len" then
                                return v.int_instance(recvval.to_s.length)
                        end
@@ -993,6 +1088,16 @@ redef class AMethPropdef
                                return v.int_instance(recv.to_i)
                        else if pname == "to_b" then
                                return v.byte_instance(recv.to_b)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recv.to_i8)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recv.to_i16)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recv.to_u16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recv.to_i32)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recv.to_u32)
                        else if pname == "cos" then
                                return v.float_instance(args[0].to_f.cos)
                        else if pname == "sin" then
@@ -1073,6 +1178,271 @@ redef class AMethPropdef
                                recvval.copy_to(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
                                return null
                        end
+               else if cname == "Int8" then
+                       var recvval = args[0].to_i8
+                       if pname == "unary -" then
+                               return v.int8_instance(-recvval)
+                       else if pname == "unary +" then
+                               return args[0]
+                       else if pname == "+" then
+                               return v.int8_instance(recvval + args[1].to_i8)
+                       else if pname == "-" then
+                               return v.int8_instance(recvval - args[1].to_i8)
+                       else if pname == "*" then
+                               return v.int8_instance(recvval * args[1].to_i8)
+                       else if pname == "%" then
+                               return v.int8_instance(recvval % args[1].to_i8)
+                       else if pname == "/" then
+                               return v.int8_instance(recvval / args[1].to_i8)
+                       else if pname == "<" then
+                               return v.bool_instance(recvval < args[1].to_i8)
+                       else if pname == ">" then
+                               return v.bool_instance(recvval > args[1].to_i8)
+                       else if pname == "<=" then
+                               return v.bool_instance(recvval <= args[1].to_i8)
+                       else if pname == ">=" then
+                               return v.bool_instance(recvval >= args[1].to_i8)
+                       else if pname == "<=>" then
+                               return v.int_instance(recvval <=> args[1].to_i8)
+                       else if pname == "to_f" then
+                               return v.float_instance(recvval.to_f)
+                       else if pname == "to_i" then
+                               return v.int_instance(recvval.to_i)
+                       else if pname == "to_b" then
+                               return v.byte_instance(recvval.to_b)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recvval.to_i16)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recvval.to_u16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recvval.to_i32)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recvval.to_u32)
+                       else if pname == "<<" then
+                               return v.int8_instance(recvval << (args[1].to_i))
+                       else if pname == ">>" then
+                               return v.int8_instance(recvval >> (args[1].to_i))
+                       else if pname == "&" then
+                               return v.int8_instance(recvval & args[1].to_i8)
+                       else if pname == "|" then
+                               return v.int8_instance(recvval | args[1].to_i8)
+                       else if pname == "^" then
+                               return v.int8_instance(recvval ^ args[1].to_i8)
+                       else if pname == "unary ~" then
+                               return v.int8_instance(~recvval)
+                       end
+               else if cname == "Int16" then
+                       var recvval = args[0].to_i16
+                       if pname == "unary -" then
+                               return v.int16_instance(-recvval)
+                       else if pname == "unary +" then
+                               return args[0]
+                       else if pname == "+" then
+                               return v.int16_instance(recvval + args[1].to_i16)
+                       else if pname == "-" then
+                               return v.int16_instance(recvval - args[1].to_i16)
+                       else if pname == "*" then
+                               return v.int16_instance(recvval * args[1].to_i16)
+                       else if pname == "%" then
+                               return v.int16_instance(recvval % args[1].to_i16)
+                       else if pname == "/" then
+                               return v.int16_instance(recvval / args[1].to_i16)
+                       else if pname == "<" then
+                               return v.bool_instance(recvval < args[1].to_i16)
+                       else if pname == ">" then
+                               return v.bool_instance(recvval > args[1].to_i16)
+                       else if pname == "<=" then
+                               return v.bool_instance(recvval <= args[1].to_i16)
+                       else if pname == ">=" then
+                               return v.bool_instance(recvval >= args[1].to_i16)
+                       else if pname == "<=>" then
+                               return v.int_instance(recvval <=> args[1].to_i16)
+                       else if pname == "to_f" then
+                               return v.float_instance(recvval.to_f)
+                       else if pname == "to_i" then
+                               return v.int_instance(recvval.to_i)
+                       else if pname == "to_b" then
+                               return v.byte_instance(recvval.to_b)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recvval.to_i8)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recvval.to_u16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recvval.to_i32)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recvval.to_u32)
+                       else if pname == "<<" then
+                               return v.int16_instance(recvval << (args[1].to_i))
+                       else if pname == ">>" then
+                               return v.int16_instance(recvval >> (args[1].to_i))
+                       else if pname == "&" then
+                               return v.int16_instance(recvval & args[1].to_i16)
+                       else if pname == "|" then
+                               return v.int16_instance(recvval | args[1].to_i16)
+                       else if pname == "^" then
+                               return v.int16_instance(recvval ^ args[1].to_i16)
+                       else if pname == "unary ~" then
+                               return v.int16_instance(~recvval)
+                       end
+               else if cname == "UInt16" then
+                       var recvval = args[0].to_u16
+                       if pname == "unary -" then
+                               return v.uint16_instance(-recvval)
+                       else if pname == "unary +" then
+                               return args[0]
+                       else if pname == "+" then
+                               return v.uint16_instance(recvval + args[1].to_u16)
+                       else if pname == "-" then
+                               return v.uint16_instance(recvval - args[1].to_u16)
+                       else if pname == "*" then
+                               return v.uint16_instance(recvval * args[1].to_u16)
+                       else if pname == "%" then
+                               return v.uint16_instance(recvval % args[1].to_u16)
+                       else if pname == "/" then
+                               return v.uint16_instance(recvval / args[1].to_u16)
+                       else if pname == "<" then
+                               return v.bool_instance(recvval < args[1].to_u16)
+                       else if pname == ">" then
+                               return v.bool_instance(recvval > args[1].to_u16)
+                       else if pname == "<=" then
+                               return v.bool_instance(recvval <= args[1].to_u16)
+                       else if pname == ">=" then
+                               return v.bool_instance(recvval >= args[1].to_u16)
+                       else if pname == "<=>" then
+                               return v.int_instance(recvval <=> args[1].to_u16)
+                       else if pname == "to_f" then
+                               return v.float_instance(recvval.to_f)
+                       else if pname == "to_i" then
+                               return v.int_instance(recvval.to_i)
+                       else if pname == "to_b" then
+                               return v.byte_instance(recvval.to_b)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recvval.to_i8)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recvval.to_i16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recvval.to_i32)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recvval.to_u32)
+                       else if pname == "<<" then
+                               return v.uint16_instance(recvval << (args[1].to_i))
+                       else if pname == ">>" then
+                               return v.uint16_instance(recvval >> (args[1].to_i))
+                       else if pname == "&" then
+                               return v.uint16_instance(recvval & args[1].to_u16)
+                       else if pname == "|" then
+                               return v.uint16_instance(recvval | args[1].to_u16)
+                       else if pname == "^" then
+                               return v.uint16_instance(recvval ^ args[1].to_u16)
+                       else if pname == "unary ~" then
+                               return v.uint16_instance(~recvval)
+                       end
+               else if cname == "Int32" then
+                       var recvval = args[0].to_i32
+                       if pname == "unary -" then
+                               return v.int32_instance(-recvval)
+                       else if pname == "unary +" then
+                               return args[0]
+                       else if pname == "+" then
+                               return v.int32_instance(recvval + args[1].to_i32)
+                       else if pname == "-" then
+                               return v.int32_instance(recvval - args[1].to_i32)
+                       else if pname == "*" then
+                               return v.int32_instance(recvval * args[1].to_i32)
+                       else if pname == "%" then
+                               return v.int32_instance(recvval % args[1].to_i32)
+                       else if pname == "/" then
+                               return v.int32_instance(recvval / args[1].to_i32)
+                       else if pname == "<" then
+                               return v.bool_instance(recvval < args[1].to_i32)
+                       else if pname == ">" then
+                               return v.bool_instance(recvval > args[1].to_i32)
+                       else if pname == "<=" then
+                               return v.bool_instance(recvval <= args[1].to_i32)
+                       else if pname == ">=" then
+                               return v.bool_instance(recvval >= args[1].to_i32)
+                       else if pname == "<=>" then
+                               return v.int_instance(recvval <=> args[1].to_i32)
+                       else if pname == "to_f" then
+                               return v.float_instance(recvval.to_f)
+                       else if pname == "to_i" then
+                               return v.int_instance(recvval.to_i)
+                       else if pname == "to_b" then
+                               return v.byte_instance(recvval.to_b)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recvval.to_i8)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recvval.to_i16)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recvval.to_u16)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recvval.to_u32)
+                       else if pname == "<<" then
+                               return v.int32_instance(recvval << (args[1].to_i))
+                       else if pname == ">>" then
+                               return v.int32_instance(recvval >> (args[1].to_i))
+                       else if pname == "&" then
+                               return v.int32_instance(recvval & args[1].to_i32)
+                       else if pname == "|" then
+                               return v.int32_instance(recvval | args[1].to_i32)
+                       else if pname == "^" then
+                               return v.int32_instance(recvval ^ args[1].to_i32)
+                       else if pname == "unary ~" then
+                               return v.int32_instance(~recvval)
+                       end
+               else if cname == "UInt32" then
+                       var recvval = args[0].to_u32
+                       if pname == "unary -" then
+                               return v.uint32_instance(-recvval)
+                       else if pname == "unary +" then
+                               return args[0]
+                       else if pname == "+" then
+                               return v.uint32_instance(recvval + args[1].to_u32)
+                       else if pname == "-" then
+                               return v.uint32_instance(recvval - args[1].to_u32)
+                       else if pname == "*" then
+                               return v.uint32_instance(recvval * args[1].to_u32)
+                       else if pname == "%" then
+                               return v.uint32_instance(recvval % args[1].to_u32)
+                       else if pname == "/" then
+                               return v.uint32_instance(recvval / args[1].to_u32)
+                       else if pname == "<" then
+                               return v.bool_instance(recvval < args[1].to_u32)
+                       else if pname == ">" then
+                               return v.bool_instance(recvval > args[1].to_u32)
+                       else if pname == "<=" then
+                               return v.bool_instance(recvval <= args[1].to_u32)
+                       else if pname == ">=" then
+                               return v.bool_instance(recvval >= args[1].to_u32)
+                       else if pname == "<=>" then
+                               return v.int_instance(recvval <=> args[1].to_u32)
+                       else if pname == "to_f" then
+                               return v.float_instance(recvval.to_f)
+                       else if pname == "to_i" then
+                               return v.int_instance(recvval.to_i)
+                       else if pname == "to_b" then
+                               return v.byte_instance(recvval.to_b)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recvval.to_i8)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recvval.to_i16)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recvval.to_u16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recvval.to_i32)
+                       else if pname == "<<" then
+                               return v.uint32_instance(recvval << (args[1].to_i))
+                       else if pname == ">>" then
+                               return v.uint32_instance(recvval >> (args[1].to_i))
+                       else if pname == "&" then
+                               return v.uint32_instance(recvval & args[1].to_u32)
+                       else if pname == "|" then
+                               return v.uint32_instance(recvval | args[1].to_u32)
+                       else if pname == "^" then
+                               return v.uint32_instance(recvval ^ args[1].to_u32)
+                       else if pname == "unary ~" then
+                               return v.uint32_instance(~recvval)
+                       end
                else if pname == "native_argc" then
                        return v.int_instance(v.arguments.length)
                else if pname == "native_argv" then
@@ -1512,6 +1882,11 @@ redef class AIntegerExpr
        do
                if value isa Int then return v.int_instance(value.as(Int))
                if value isa Byte then return v.byte_instance(value.as(Byte))
+               if value isa Int8 then return v.int8_instance(value.as(Int8))
+               if value isa Int16 then return v.int16_instance(value.as(Int16))
+               if value isa UInt16 then return v.uint16_instance(value.as(UInt16))
+               if value isa Int32 then return v.int32_instance(value.as(Int32))
+               if value isa UInt32 then return v.uint32_instance(value.as(UInt32))
                return null
        end
 end
index 70c635e..7812cb2 100644 (file)
@@ -209,6 +209,21 @@ redef class MModule
        # The primitive type `Byte`
        var byte_type: MClassType = self.get_primitive_class("Byte").mclass_type is lazy
 
+       # The primitive type `Int8`
+       var int8_type: MClassType = self.get_primitive_class("Int8").mclass_type is lazy
+
+       # The primitive type `Int16`
+       var int16_type: MClassType = self.get_primitive_class("Int16").mclass_type is lazy
+
+       # The primitive type `UInt16`
+       var uint16_type: MClassType = self.get_primitive_class("UInt16").mclass_type is lazy
+
+       # The primitive type `Int32`
+       var int32_type: MClassType = self.get_primitive_class("Int32").mclass_type is lazy
+
+       # The primitive type `UInt32`
+       var uint32_type: MClassType = self.get_primitive_class("UInt32").mclass_type is lazy
+
        # The primitive type `Char`
        var char_type: MClassType = self.get_primitive_class("Char").mclass_type is lazy
 
index af3ae39..97312f2 100644 (file)
@@ -1341,6 +1341,16 @@ redef class AAttrPropdef
                                                cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
                                        else if nexpr.value isa Byte then
                                                cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Byte")
+                                       else if nexpr.value isa Int8 then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int8")
+                                       else if nexpr.value isa Int16 then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int16")
+                                       else if nexpr.value isa UInt16 then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "UInt16")
+                                       else if nexpr.value isa Int32 then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int32")
+                                       else if nexpr.value isa UInt32 then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "UInt32")
                                        else
                                                # Should not happen, and should be updated as new types are added
                                                abort
index a64c3df..a43e1d7 100644 (file)
@@ -94,6 +94,11 @@ redef class MClassType
                if name == "Float" then return "double"
                if name == "Int" then return "long"
                if name == "Byte" then return "unsigned char"
+               if name == "Int8" then return "int8_t"
+               if name == "Int16" then return "int16_t"
+               if name == "UInt16" then return "uint16_t"
+               if name == "Int32" then return "int32_t"
+               if name == "UInt32" then return "uint32_t"
                if name == "NativeString" then return "char*"
                if mclass.kind == extern_kind then
                        var ctype = mclass.ctype
@@ -110,6 +115,11 @@ redef class MClassType
                if name == "Float" then return "double"
                if name == "Int" then return "long"
                if name == "Byte" then return "unsigned char"
+               if name == "Int8" then return "int8_t"
+               if name == "Int16" then return "int16_t"
+               if name == "UInt16" then return "uint16_t"
+               if name == "Int32" then return "int32_t"
+               if name == "UInt32" then return "uint32_t"
                if name == "NativeString" then return "char*"
                if mclass.kind == extern_kind then return "void*"
                return super
@@ -121,7 +131,8 @@ 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", "Byte"]).has(mclass.name)
+                       (once ["Bool", "Char", "Float", "Int", "NativeString",
+                              "Byte", "Int8", "Int16", "UInt16", "Int32", "UInt32"]).has(mclass.name)
 end
 
 redef class MNullableType
index 87e808c..9ef5320 100644 (file)
@@ -213,11 +213,16 @@ class RapidTypeAnalysis
 
                # Force primitive types
                force_alive("Bool")
-               force_alive("Int")
                force_alive("Float")
                force_alive("Char")
                force_alive("Pointer")
                force_alive("Byte")
+               force_alive("Int")
+               force_alive("Int8")
+               force_alive("Int16")
+               force_alive("UInt16")
+               force_alive("Int32")
+               force_alive("UInt32")
 
                while not todo.is_empty do
                        var mmethoddef = todo.shift
index b5f5d0c..935e1fc 100644 (file)
@@ -1389,6 +1389,16 @@ redef class AIntegerExpr
                        mclass = v.get_mclass(self, "Byte")
                else if value isa Int then
                        mclass = v.get_mclass(self, "Int")
+               else if value isa Int8 then
+                       mclass = v.get_mclass(self, "Int8")
+               else if value isa Int16 then
+                       mclass = v.get_mclass(self, "Int16")
+               else if value isa UInt16 then
+                       mclass = v.get_mclass(self, "UInt16")
+               else if value isa Int32 then
+                       mclass = v.get_mclass(self, "Int32")
+               else if value isa UInt32 then
+                       mclass = v.get_mclass(self, "UInt32")
                end
                if mclass == null then return # Forward error
                self.mtype = mclass.mclass_type
diff --git a/tests/sav/test_fix_int.res b/tests/sav/test_fix_int.res
new file mode 100644 (file)
index 0000000..e35445d
--- /dev/null
@@ -0,0 +1,84 @@
+
+-128
+-128
+0x80
+127
+127
+0x7f
+127
+127
+127
+127
+
+
+-32768
+-32768
+0x00
+32767
+32767
+0xff
+-1
+32767
+32767
+32767
+
+
+0
+0
+0x00
+65535
+65535
+0xff
+-1
+-1
+65535
+65535
+
+
+-2147483648
+-2147483648
+0x00
+2147483647
+2147483647
+0xff
+-1
+-1
+65535
+2147483647
+
+
+0
+0
+0x00
+4294967295
+4294967295
+0xff
+-1
+-1
+65535
+-1
+
+
+0x00
+0
+0x00
+0xff
+255
+0xff
+-1
+255
+255
+255
+
+
+256
+256
+0x00
+255
+255
+0xff
+-1
+255
+255
+255
+
diff --git a/tests/test_fix_int.nit b/tests/test_fix_int.nit
new file mode 100644 (file)
index 0000000..f7ecfa7
--- /dev/null
@@ -0,0 +1,79 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT.  This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
+# PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You  are  allowed  to  redistribute it and sell it, alone or is a part of
+# another product.
+
+# Tests for the fixed-length integers variant of standard
+module test_fix_int
+
+private fun test_int(i, j, l: Numeric) do
+       print ""
+       var k = i + j
+
+       print k
+       print k.to_i
+       print k.to_b
+
+       k = l + j
+
+       print k
+       print k.to_i
+       print k.to_b
+
+       print k.to_i8
+       print k.to_i16
+       print k.to_u16
+       print k.to_i32
+       print ""
+end
+
+var i: Numeric
+var j: Numeric
+var l: Numeric
+
+j = 126i8
+i = 2i8
+l = 1i8
+
+test_int(i, j, l)
+
+j = 32766i16
+i = 2i16
+l = 1i16
+
+test_int(i, j, l)
+
+j = 65534u16
+i = 2u16
+l = 1u16
+
+test_int(i, j, l)
+
+j = 2147483646i32
+i = 2i32
+l = 1i32
+
+test_int(i, j, l)
+
+j = 4294967294u32
+i = 2u32
+l = 1u32
+
+test_int(i, j, l)
+
+j = 254u8
+i = 2u8
+l = 1u8
+
+test_int(i, j, l)
+
+j = 254
+i = 2
+l = 1
+
+test_int(i, j, l)