From: Jean Privat Date: Wed, 23 Sep 2015 18:20:19 +0000 (-0400) Subject: Merge: Geometry X-Git-Tag: v0.7.8~10 X-Git-Url: http://nitlanguage.org?hp=841a459826488508493791ca14c37402d80325cf Merge: Geometry Adds a README for the geometry package. Also adds an abstraction for polygons and an algorithm to triangulate them Pull-Request: #1731 Reviewed-by: Jean Privat Reviewed-by: Lucas Bajolet --- diff --git a/contrib/brainfuck/brainfuck.nit b/contrib/brainfuck/brainfuck.nit index f7de908..4216952 100644 --- a/contrib/brainfuck/brainfuck.nit +++ b/contrib/brainfuck/brainfuck.nit @@ -18,29 +18,24 @@ module brainfuck # Interpreter for Brainfuck source code. class BFInterpreter # Data cells - var dr = new Array[Char] + var dr = new Array[Byte] # Data pointer var dp = 0 # Instruction pointer var ip = 0 # The program being interpreted - var program: String - - # Contains the set of valid instructions, used in next - var valid_instr: Set[Char] is noinit + var program: Bytes # Create an interpreter for `program`. init do - valid_instr = new HashSet[Char] - valid_instr.add_all "><[].,+-".chars - dr.add 0.ascii + dr.add 0u8 end # Create an interpreter for the file located at `path`. init from_file(path: String) do var ifs = new FileReader.open(path) - init(ifs.read_all) + init(ifs.read_all_bytes) end # Starts the interpretation of the loaded program @@ -48,50 +43,43 @@ class BFInterpreter loop if ip >= program.length then break eval - next - end - end - - # Go to the next executable instruction - fun next do - ip += 1 - while ip < program.length and not valid_instr.has(program[ip]) do ip += 1 end end + # Evaluates the current instruction fun eval do var instr = program[ip] - if instr == '.' then printn dr[dp] - if instr == '[' then - if dr[dp] == 0.ascii then + if instr == '.'.ascii then printn dr[dp].ascii + if instr == '['.ascii then + if dr[dp] == 0u8 then ip = find_matching_rbra return end end - if instr == ']' then - if dr[dp] != 0.ascii then + if instr == ']'.ascii then + if dr[dp] != 0u8 then ip = find_matching_lbra return end end - if instr == '>' then + if instr == '>'.ascii then dp += 1 - if dp >= dr.length then dr.add(0.ascii) + if dp >= dr.length then dr.add(0u8) end - if instr == '<' then + if instr == '<'.ascii then dp -= 1 if dp < 0 then abort end - if instr == '+' then - dr[dp] = (dr[dp].ascii + 1).ascii + if instr == '+'.ascii then + dr[dp] = dr[dp] + 1u8 end - if instr == '-' then - dr[dp] = (dr[dp].ascii - 1).ascii + if instr == '-'.ascii then + dr[dp] = dr[dp] - 1u8 end - if instr == ',' then - dr[dp] = getc + if instr == ','.ascii then + dr[dp] = getc.ascii end end @@ -101,14 +89,14 @@ class BFInterpreter var lbracnt = 0 loop if pos > program.length then abort - if program[pos] == ']' then + if program[pos] == ']'.ascii then if lbracnt > 0 then lbracnt -= 1 else break end end - if program[pos] == '[' then lbracnt += 1 + if program[pos] == '['.ascii then lbracnt += 1 pos += 1 end return pos @@ -120,14 +108,14 @@ class BFInterpreter var rbracnt = 0 loop if pos < 0 then abort - if program[pos] == '[' then + if program[pos] == '['.ascii then if rbracnt > 0 then rbracnt -= 1 else break end end - if program[pos] == ']' then rbracnt += 1 + if program[pos] == ']'.ascii then rbracnt += 1 pos -= 1 end return pos diff --git a/contrib/friendz/src/grid.nit b/contrib/friendz/src/grid.nit index 3a141f6..6f1c883 100644 --- a/contrib/friendz/src/grid.nit +++ b/contrib/friendz/src/grid.nit @@ -249,13 +249,13 @@ class Grid else if c >= 'A' and c <= 'I' then var t = self.get(x,y) assert t != null - t.update(c.ascii-'A'.ascii+1) + t.update(c.code_point-'A'.code_point+1) t.fixed = true x += 1 else if c >= 'a' and c <= 'i' then var t = self.get(x,y) assert t != null - t.update(c.ascii-'a'.ascii+1) + t.update(c.code_point-'a'.code_point+1) x += 1 else if c >= '1' and c <= '9' then rle = c.to_i @@ -289,16 +289,16 @@ class Grid if k == 0 then if t.fixed then c = '#' else - b.add(0x1b.ascii) + b.add(0x1b.code_point) b.add('[') b.append ansicols[k] - c = (k + 'a'.ascii - 1).ascii + c = (k + 'a'.code_point - 1).code_point if t.fixed then c = c.to_upper b.append("m") end b.add(c) if k != 0 then - b.add(0x1b.ascii) + b.add(0x1b.code_point) b.append("[0m") end diff --git a/contrib/memory/.gitignore b/contrib/memory/.gitignore new file mode 100644 index 0000000..c4781eb --- /dev/null +++ b/contrib/memory/.gitignore @@ -0,0 +1,3 @@ +assets/images/ +res/ +src/drawing.nit diff --git a/contrib/memory/Makefile b/contrib/memory/Makefile new file mode 100644 index 0000000..8e39e1d --- /dev/null +++ b/contrib/memory/Makefile @@ -0,0 +1,36 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +all: bin/memory + +bin/memory: assets/images/drawing.png src/*.nit + mkdir -p bin + ../../bin/nitc -o bin/memory src/memory.nit -m ../../lib/mnit/linux/linux.nit + +assets/images/drawing.png: art/drawing.svg + mkdir -p assets/images/ + ../inkscape_tools/bin/svg_to_png_and_nit art/drawing.svg -a assets/ -s src/ -x 4 + +res/drawable-ldpi/icon.png: art/icon.svg + mkdir -p res/ + ../inkscape_tools/bin/svg_to_icons art/icon.svg --android --out res/ + +android: bin/memory.apk +bin/memory.apk: assets/images/drawing.png src/*.nit res/drawable-ldpi/icon.png + mkdir -p bin + ../../bin/nitc -o bin/memory.apk src/memory.nit -m ../../lib/mnit/android/android.nit -m ../../lib/android/landscape.nit + +android-release: assets/images/drawing.png src/*.nit res/drawable-ldpi/icon.png + mkdir -p bin + ../../bin/nitc -o bin/memory.apk src/memory.nit -m ../../lib/mnit/android/android.nit -m ../../lib/android/ landscape.nit --release diff --git a/contrib/memory/README.md b/contrib/memory/README.md new file mode 100644 index 0000000..ffbcdae --- /dev/null +++ b/contrib/memory/README.md @@ -0,0 +1,31 @@ +# Memorize Shapes and Colors + +A memory-based game where figures are cliqued in sequence by the computer and should be replayed by the player in the same order. +As the player progresses, more figures are added and the sequences to remember become longer. + +The player can make up to 2 errors to solve a single level. +At the 3rd error, the level has to be replayed. + +The game use a very simple user interface and features big figures with bright colors and simple distinguishable shapes; that makes it suitable for young children. + +The game offers three modes (difficulty level) + +Easy (for young children): + +* Start with 2 figures, 1 to remember +* Figures are easily distinguishable +* Figures remain on place +* After 3 errors, the same level is replayed + +Medium (for normal player): + +* Like easy but: +* Start with 3 figures, 3 to remember +* Figures are moved after the sequence played by the computer +* After 3 errors, a new level is produced + +Hard (for hypermnesic players) + +* Like medium but: +* Figures use overlapping combinations of colors and shapes +* Figures are shuffled completely diff --git a/contrib/memory/art/drawing.svg b/contrib/memory/art/drawing.svg new file mode 100644 index 0000000..7a4cd1c --- /dev/null +++ b/contrib/memory/art/drawing.svg @@ -0,0 +1,368 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ✘ + + + + + + + + + + + ↻ + + diff --git a/contrib/memory/art/icon.svg b/contrib/memory/art/icon.svg new file mode 100644 index 0000000..8a5990d --- /dev/null +++ b/contrib/memory/art/icon.svg @@ -0,0 +1,98 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/contrib/memory/assets/bing.wav b/contrib/memory/assets/bing.wav new file mode 100644 index 0000000..c7cae5b Binary files /dev/null and b/contrib/memory/assets/bing.wav differ diff --git a/contrib/memory/assets/boing.wav b/contrib/memory/assets/boing.wav new file mode 100644 index 0000000..70c529f Binary files /dev/null and b/contrib/memory/assets/boing.wav differ diff --git a/contrib/memory/assets/click.wav b/contrib/memory/assets/click.wav new file mode 100644 index 0000000..3d07b83 Binary files /dev/null and b/contrib/memory/assets/click.wav differ diff --git a/contrib/memory/assets/cymbal.wav b/contrib/memory/assets/cymbal.wav new file mode 100644 index 0000000..b55bac4 Binary files /dev/null and b/contrib/memory/assets/cymbal.wav differ diff --git a/contrib/memory/assets/dart.wav b/contrib/memory/assets/dart.wav new file mode 100644 index 0000000..422e2c2 Binary files /dev/null and b/contrib/memory/assets/dart.wav differ diff --git a/contrib/memory/assets/duh.wav b/contrib/memory/assets/duh.wav new file mode 100644 index 0000000..054e1fe Binary files /dev/null and b/contrib/memory/assets/duh.wav differ diff --git a/contrib/memory/assets/grunt.wav b/contrib/memory/assets/grunt.wav new file mode 100644 index 0000000..f0d8350 Binary files /dev/null and b/contrib/memory/assets/grunt.wav differ diff --git a/contrib/memory/assets/honkhonk.wav b/contrib/memory/assets/honkhonk.wav new file mode 100644 index 0000000..b107329 Binary files /dev/null and b/contrib/memory/assets/honkhonk.wav differ diff --git a/contrib/memory/assets/level.wav b/contrib/memory/assets/level.wav new file mode 100644 index 0000000..2d30b6e Binary files /dev/null and b/contrib/memory/assets/level.wav differ diff --git a/contrib/memory/assets/line_end.wav b/contrib/memory/assets/line_end.wav new file mode 100644 index 0000000..aead13e Binary files /dev/null and b/contrib/memory/assets/line_end.wav differ diff --git a/contrib/memory/assets/penalty.wav b/contrib/memory/assets/penalty.wav new file mode 100644 index 0000000..2ad3af0 Binary files /dev/null and b/contrib/memory/assets/penalty.wav differ diff --git a/contrib/memory/assets/squishy-hit.wav b/contrib/memory/assets/squishy-hit.wav new file mode 100644 index 0000000..dbd958b Binary files /dev/null and b/contrib/memory/assets/squishy-hit.wav differ diff --git a/contrib/memory/assets/whip.wav b/contrib/memory/assets/whip.wav new file mode 100644 index 0000000..b907832 Binary files /dev/null and b/contrib/memory/assets/whip.wav differ diff --git a/contrib/memory/assets/woodthunk.wav b/contrib/memory/assets/woodthunk.wav new file mode 100644 index 0000000..2001e38 Binary files /dev/null and b/contrib/memory/assets/woodthunk.wav differ diff --git a/contrib/memory/org.nitlanguage.memory.txt b/contrib/memory/org.nitlanguage.memory.txt new file mode 100644 index 0000000..1bef17b --- /dev/null +++ b/contrib/memory/org.nitlanguage.memory.txt @@ -0,0 +1,16 @@ +Categories:Nit,Games +License:Apache2 +Web Site:http://nitlanguage.org +Source Code:http://nitlanguage.org/nit.git/tree/HEAD:/contrib/memory +Issue Tracker:https://github.com/nitlang/nit/issues + +Summary: memory-based game using shapes and colors +Description: +A memory-based game where figures are cliqued in sequence by the computer and should be replayed by the player in the same order. +As the player progresses, more figures are added and the sequences to remember become longer. + +The player can make up to 2 errors to solve a single level. +At the 3rd error, the level has to be replayed. + +The game use a very simple user interface and features big figures with bright colors and simple distinguishable shapes; that makes it suitable for young children. +. diff --git a/contrib/memory/package.ini b/contrib/memory/package.ini new file mode 100644 index 0000000..d271a73 --- /dev/null +++ b/contrib/memory/package.ini @@ -0,0 +1,11 @@ +[package] +name=memory +tags=game +maintainer=Jean Privat +license=Apache-2.0 +[upstream] +browse=https://github.com/nitlang/nit/tree/master/contrib/memory/ +git=https://github.com/nitlang/nit.git +git.directory=contrib/memory/ +homepage=http://nitlanguage.org +issues=https://github.com/nitlang/nit/issues diff --git a/contrib/memory/src/memory.nit b/contrib/memory/src/memory.nit new file mode 100644 index 0000000..3e9877d --- /dev/null +++ b/contrib/memory/src/memory.nit @@ -0,0 +1,1000 @@ +# 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. + +# A game of memory using shapes and colors +# +# # Features and TODO +# +# * [X] Various shapes, colors and sounds +# * [X] 3 difficulty modes +# * [X] Saved high scores +# * [ ] Level selection +# +# The remaining issues are +# +# * Crappy event system +# * Crappy UI element placement +module memory is + app_name("Memorize Shapes and Colors") + app_version(0, 1, git_revision) +end + +import mnit +import app::audio +import mnit::opengles1 +import app::data_store + +import drawing + +# A figure to click on +class Button + # The place, starting from 0. + # Will be used to derive the display place. + var place: Int + + # The color of the figure + var color: Color + + # The shape of the figure + var shape: Image + + # The sound of the figure + var sound: Sound + + # x-coordinate on the display + var x: Float = 0.0 + # y-coordinate on the display + var y: Float = 0.0 + # width on the display + var w: Float = 0.0 + # height the display + var h: Float = 0.0 + + # Event time to live (from 1.0 downto 0.0) + var ttl: Float = 0.0 + + # Is there a big error on the button? + var error = false + + # The initial position (according to shuffle) + var from: Pos is noinit + + # The current path if shuffling + var path: nullable BPath = null + + # The second path if hard shuffling + var path2: nullable BPath = null + + # Is there an hard shuffling? + var hard = false + + # The optional text on the button (in the menu) + var text: nullable Image = null + + # The color of the text + var text_color: nullable Color = null + + # The high score on the menu button + var text_max: Int = 0 + + # Draw on the display + fun blit_on(display: Display) + do + if ttl > 0.0 then + ttl -= 0.1 + if ttl <= 0.0 then + ttl = 0.0 + path = path2 + path2 = null + if path != null then ttl = path.duration + error = false + end + end + + var x = self.x + var y = self.y + var p = 0.0 + if ttl > 0.0 then + if path != null then + var pos = to_pos + path.update(pos, ttl) + x = pos.x + y = pos.y + if hard then + p = ttl/5.0 + if path2 != null then + p = 1.0 - p + end + end + else if error then + # nothing + else + y -= ttl * h / 10.0 + end + end + + if not app.player then + p = 0.2.lerp(p, 1.0) + end + + color.set(display, p) + display.blit_centered(shape, x, y) + var text = self.text + if text != null then + text.scale = shape.scale + text_color.set(display, p) + display.blit_centered(text, x, y - h/8.0) + if text_max > 0 then + app.blit_number(text_max, app.scale, x, y + h/8.0) + end + end + if display isa Opengles1Display then + display.reset_color + end + if error then + app.drawing.error.scale = app.scale + display.blit_centered(app.drawing.error, x, y) + end + end + + redef fun to_s do + return "{place},{color},{shape},{sound}" + end + + # Check collision + fun has(x,y: Float): Bool + do + return (self.x - x).abs*2.0 <= w and (self.y - y).abs*2.0 <= h + end + + # Return a new pos centered on the button + fun to_pos: Pos do return new Pos(x, y) +end + +# A rbg color +class Color + # red (from 0.0 to 1.0) + var r: Float + # green (from 0.0 to 1.0) + var g: Float + # blue (from 0.0 to 1.0) + var b: Float + + # Globally change the color of the display. + # The color will be used for the next blit operations. + # The color of the display has to be reseted manually (see `Opengles1Display::reset_color`). + fun set(display: Display, p: Float) + do + if display isa Opengles1Display then + display.color(p.lerp(r,1.0),p.lerp(g,1.0),p.lerp(b,1.0),p.lerp(1.0,0.0)) + end + end +end + +# A point in the display coordinates +class Pos + # x coordinate + var x: Float + # y coordinate + var y: Float + redef fun to_s do return "({x},{y})" +end + +# A cubic Bézier path between two points with two handles. +class BPath + # The origin point + var from: Pos + # The handle of the origin point + var from_handle: Pos + # The handle of the destination point + var to_handle: Pos + # The destination point + var to: Pos + # The duration on the path + var duration: Float + + # Update the coordinates of `cursor` for an absolute time to destination `ttd` + fun update(cursor: Pos, ttd: Float) + do + var p = 1.0 - ttd / duration + if p <= 0.0 then + cursor.x = from.x + cursor.y = from.y + return + end + if p >= 1.1 then + cursor.x = to.x + cursor.y = to.y + end + var bx = p.cerp(from.x, from_handle.x, to_handle.x, to.x) + var by = p.cerp(from.y, from_handle.y, to_handle.y, to.y) + cursor.x = bx + cursor.y = by + end +end + +redef class App + + # # Assets and resources + + # All the images assets + var drawing = new DrawingImages + + # Array of all available colors for the figures + var colors = new Array[Color] + + # Array of all available shapes for the figures + var shapes = new Array[Image] + + # Array of all available sounds for the figures + var sounds = new Array[Sound] + + # The sound to play on error (error) + var snd_penalty: Sound is noautoinit + + # The sound of other ui element + var snd_click: Sound is noautoinit + + redef fun on_create + do + colors.clear + colors.add new Color(0.9, 0.6, 0.0) + colors.add new Color(0.6, 0.0, 0.9) + colors.add new Color(0.6, 0.5, 0.4) + colors.add new Color(1.0, 0.0, 0.0) + colors.add new Color(1.0, 1.0, 0.0) + colors.add new Color(1.0, 0.0, 1.0) + colors.add new Color(0.0, 1.0, 0.0) + colors.add new Color(0.0, 1.0, 1.0) + colors.add new Color(0.0, 0.0, 1.0) + + drawing.load_all(self) + shapes.clear + shapes.add drawing.circle + shapes.add drawing.rect + shapes.add drawing.cross + shapes.add drawing.penta + shapes.add drawing.star + shapes.add drawing.triangle + shapes.add drawing.heart + shapes.add drawing.diamond + shapes.add drawing.moon + shapes.add drawing.spiral + + number_images = new NumberImages(drawing.n) + + sounds.clear + sounds.add new Sound("bing.wav") + sounds.add new Sound("boing.wav") + sounds.add new Sound("cymbal.wav") + sounds.add new Sound("dart.wav") + sounds.add new Sound("duh.wav") + sounds.add new Sound("grunt.wav") + sounds.add new Sound("honkhonk.wav") + sounds.add new Sound("line_end.wav") + sounds.add new Sound("squishy-hit.wav") + sounds.add new Sound("woodthunk.wav") + sounds.add new Sound("whip.wav") + + snd_penalty = new Sound("penalty.wav") + snd_click = new Sound("click.wav") + + # Force load the sounds. Required because bug #1728 + for s in sounds do s.load + snd_penalty.load + + is_menu = data_store["game"] != true + mode = data_int("mode") or else 0 + current_level = data_int("level") or else 0 + + max_levels[0] = data_int("max_0") or else 0 + max_levels[1] = data_int("max_1") or else 0 + max_levels[2] = data_int("max_2") or else 0 + + print "max_levels: {max_levels}" + + reload = new Button(-1, new Color(1.0,1.0,1.0), drawing.reload, snd_click) + + if is_menu then + new_menu + else + new_game + end + end + + # Get a positive numeric value from the store + fun data_int(name: String): nullable Int + do + var x = data_store[name] + if x isa Int then return x else return null + end + + # # Level information + + # Number of buttons for the next game + var size = 5 + + # Length of the memory sequence for the next game + var length = 5 + + # Do a hard deal? + var hard_deal = false + + # No shuffle (0), easy shuffle (1), or hard shuffle (2)? + var shuffling = 0 + + # Is a new deal make on replay? + # If true, a new set of figures and a new sequence is produced + # If false, the same is reused. + var deal_on_replay = true + + # Current buttons in the game + var buttons = new Array[Button] + + # The sequence of the buttons to memorize + var level = new Array[Button] + + # The number of errors (crosses) in the current level. (in [0..3]) + var error = 0 + + # Is the player playing? + # If false it means that the game is showing the sequence to memorize + var player = false + + # Next button on the level (to show or guess according to `player`) + var cpt = 0 + + # Time to live before the next event + var ttl = 0.0 + + # Are we in the menu? + var is_menu = true + + # In the end of game, is this a win of a lose? + var is_win = false + + # Reset everything and create a menu + fun new_menu + do + is_menu = true + size = 3 + length = 0 + shuffling = 0 + + data_store["game"] = false + + colors.shuffle + shapes.shuffle + sounds.shuffle + + buttons.clear + for i in [0..size[ do + var b = new Button(i, colors[i], shapes[i], sounds[i]) + buttons.add b + b.text = drawing.hard[i] + b.text_color = colors[3+i] + b.text_max = max_levels[i] + end + + # Start the scene + start_scene + end + + # The current mode: easy (0), medium (1), hard (2) + var mode = 0 + + # The current level (from 0) + var current_level = 0 + + # Hight scores of each mode + var max_levels: Array[Int] = [0, 0, 0] + + # Reset everything and create a new game using `mode` and `level` + fun new_game + do + print "Next game: mode={mode} level={current_level}" + data_store["game"] = true + data_store["mode"] = mode + data_store["level"] = current_level + if max_levels[mode] < current_level then + max_levels[mode] = current_level + data_store["max_{mode}"] = current_level + end + + if mode == 0 then + hard_deal = false + shuffling = 0 + deal_on_replay = false + size = 2 + length = 1 + else if mode == 1 then + hard_deal = false + shuffling = 1 + deal_on_replay = true + size = 3 + length = 3 + else + hard_deal = true + shuffling = 2 + deal_on_replay = true + size = 3 + length = 3 + end + for i in [0..current_level[ do + length += 1 + if length > size + 2 then + size += 1 + length -= 1 + end + if size > 16 then size = 16 + end + + deal_game + end + + # Reset the buttons and deal a new game using `size` and `length` + fun deal_game + do + is_menu = false + + # Randomize the deal + colors.shuffle + shapes.shuffle + sounds.shuffle + + # Setup the figure + buttons.clear + if not hard_deal then + # With the easy deal, each button is easily distinguishable + for i in [0..size[ do + var b = new Button(i, colors[i%colors.length], shapes[i%shapes.length], sounds[i%sounds.length]) + buttons.add b + end + else + # With the hard deal, use overlapping combinations of colors and shapes + var sqrt = size.to_f.sqrt + var ncol = sqrt.floor.to_i + var nsha = sqrt.ceil.to_i + while ncol*nsha < size do ncol += 1 + + # Randomly swap the numbers of colors/shapes + if 2.rand == 0 then + var t = ncol + ncol = nsha + nsha = t + end + + # Deal combinations (up to `size`) + for i in [0..ncol[ do + for j in [0..nsha[ do + if buttons.length >= size then break + var b = new Button(buttons.length, colors[i], shapes[j], sounds.rand) + buttons.add b + end + end + + # A last shuffle to break the colors/shapes grid + buttons.shuffle + end + + # Deal the level (i.e. sequence to memorize) + # To increase distribution, determinate a maximum number of repetition + # of a single button + var rep = (length.to_f / size.to_f).ceil.to_i + var pool = buttons * rep + pool.shuffle + + level.clear + for i in [0..length[ do + level.add pool[i] + end + + print "newgame size={size} length={length}" + + # Start the scene + start_scene + end + + # Cause a replay on the same level + # On easy mode, the same level is replayed exactly + # On other modes, a new deal is made + fun replay_game + do + if deal_on_replay then + deal_game + else + start_scene + end + end + + # Reset the state of the scene and start with `fly_in` + fun start_scene + do + player = false + cpt = -1 + path = null + error = 0 + + # Ask for a redraw + first_frame = true + end + + # # Placement and moves + + # Locations used to place buttons on the screen + private var locations: Array[Array[Float]] = [ + [0.0, 1.0], + [0.0, 1.0, 0.5], + [0.0, 1.0, 0.0, 1.0], + [0.0, 1.0, 2.0, 0.5, 1.5], + [0.0, 1.0, 2.0, 0.0, 1.0, 2.0], + [0.5, 1.5, 0.0, 1.0, 2.0, 0.5, 1.5], + [0.0, 1.0, 2.0, 0.0, 2.0, 0.0, 1.0, 2.0], + [0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0], + [0.5, 1.5, 2.5, 0.0, 1.0, 2.0, 3.0, 0.5, 1.5, 2.5], + [0.0, 1.0, 2.0, 3.0, 0.0, 1.5, 3.0, 0.0, 1.0, 2.0, 3.0], + [0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0], + [0.5, 1.5, 2.5, 0.0, 1.5, 3.0, 0.0, 1.0, 2.0, 3.0, 0.5, 1.5, 2.5], + [0.5, 1.5, 2.5, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.5, 1.5, 2.5], + [0.5, 1.5, 2.5, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0], + [0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0]] + + + # The scale of the figures. + # According to the screen dimensions and the number of figures + var scale = 0.0 + + # The scale of the UI + # According to the screen dimensions + var ui_scale = 0.0 + + # Compute then location on the display for each button + # + # The method can be called when there is a change in the buttons (or the display). + fun locate(display: Display) + do + # The locations depend of the number of buttons (from 2 to 9) + var n = buttons.length + var locs = locations[n-2] + var columns = if n <= 4 then 2 else if n <= 9 then 3 else 4 + var rows = if n <= 2 then 1 else if n <= 6 then 2 else if n <= 12 then 3 else 4 + + # Compute basic dimensions according to the screen + var slotw = display.width / columns + var sloth = display.height / rows + var subw = slotw - slotw/5 + var subh = sloth - sloth/5 + + # Compute the figure scale + var img = drawing.circle + var xs = subw.to_f / img.width.to_f + var ys = subh.to_f / img.height.to_f + scale = xs.min(ys) + + # Compute the UI scale + xs = display.width.to_f / img.width.to_f + ys = display.height.to_f / img.height.to_f + ui_scale = xs.min(ys) / 4.0 + + var last = -1.0 + var row = 0.0 + var cpt = 0 + for b in buttons do + b.place = cpt + var col = locs[cpt] + if col <= last then + row += 1.0 + end + last = col + + b.x = (col + 0.5) * slotw.to_f + b.y = (row + 0.5) * sloth.to_f + img = b.shape + img.scale = scale + b.w = (img.width.to_f * scale) + b.h = (img.height.to_f * scale) + + cpt += 1 + end + + left.x = -150.0 * scale + left.y = (display.height / 2).to_f + right.x = display.width.to_f + 150.0 * scale + right.y = left.y + + # Other UI elements + + if not is_menu then + var reload = self.reload + drawing.reload.scale = ui_scale + reload.x = display.width.to_f - (drawing.reload.width.to_f / 2.0 * 1.2 ) * ui_scale + reload.y = drawing.reload.height.to_f / 2.0 * 1.2 * ui_scale + reload.w = drawing.reload.width.to_f * ui_scale + reload.h = drawing.reload.height.to_f * ui_scale + end + end + + # The origin point of the cursor on the left + var left = new Pos(0.0, 0.0) + + # The destination point of the cursor on the right + var right = new Pos(0.0, 0.0) + + # The current cursor position + var cursor = new Pos(0.0, 0.0) + + # The current cursor path + var path: nullable BPath = null + + # The reload button + var reload: Button is noautoinit + + # Safe point for a cursor on the i-th button of the level + fun path_pos(i: Int): Pos + do + if i < 0 then return left + if i >= level.length then return right + return level[i].to_pos + end + + # A random point outside of the screen + fun far_away(display: Display): Pos + do + var a = (2.0*pi).rand + var w = display.width.to_f / 2.0 + var h = display.height.to_f / 2.0 + var x = w + a.cos * w * 1.8 + var y = h + a.sin * h * 1.8 + return new Pos(x, y) + end + + # Create a BPath between two point with some nice handle values + fun new_path(from, to: Pos, ttl: Float): BPath + do + var a = atan2(to.y-from.y, to.x-from.x) + a += pi * (2.0.rand - 1.0) + var radius = 300.0 * scale + var fh = new Pos(from.x + a.cos*radius, from.y + a.sin*radius) + #var th = new Pos(to.x - a.cos*radius, to.y - a.sin*radius) + var path = new BPath(from, fh, to, to, ttl) + return path + end + + # Initial placement of buttons + fun fly_in(display: Display) + do + for b in buttons do + var from = far_away(display) + var to = b.to_pos + var path = new_path(from, to, 5.0) + b.path = path + b.ttl = 5.0 + end + ttl = 6.0 + end + + # Final leaving of buttons + fun fly_out(display: Display) + do + for b in buttons do + var from = b.to_pos + var to = far_away(display) + b.x = to.x + b.y = to.y + var path = new_path(from, to, 5.0) + b.path = path + b.ttl = 5.0 + b.hard = false + end + ttl = 6.0 + end + + # Randomly permute the content of `buttons` such that no element appears in its original position. + fun derangement + do + # The simplest algorithm is to shuffle until no buttons is at the same place + # This is also quite efficient and converges extremely quickly + var redo = true + while redo do + redo = false + buttons.shuffle + for i in [0..size[ do + if i == buttons[i].place then + redo = true + break + end + end + end + end + + # Shuffling the place of each button on the screen + fun shuffle(display: Display) + do + for b in buttons do + b.from = b.to_pos + end + + derangement + + locate(display) + for b in buttons do + var from = b.from + var to = b.to_pos + #print "shuffle move {b.place}: {from} -> {to}" + b.path = new_path(from, to, 5.0) + b.ttl = 5.0 + end + ttl = 5.0 + end + + # Shuffle the place of each button in a hard way + fun hard_shuffle(display: Display) + do + for b in buttons do + b.from = b.to_pos + b.hard = true + end + + derangement + + locate(display) + for b in buttons do + var from = b.from + var to = b.to_pos + var midx = display.width.to_f / 2.0 + var midy = display.height.to_f / 2.0 + var mid = new Pos(midx, midy) + #print "shuffle move {b.place}: {from} -> {to}" + b.path = new_path(from, mid, 5.0) + b.path2 = new_path(mid, to, 5.0) + b.ttl = 5.0 + end + ttl = 5.0 + end + + # Setup the next cursor path + fun setpath + do + if is_menu then return + var from = path_pos(cpt-1) + var to = path_pos(cpt) + #print "cursor {cpt-1}->{cpt}: {from} -> {to}" + path = new_path(from, to, 4.0) + cursor.x = from.x + cursor.y = from.y + ttl = 5.0 + end + + # Main loop, drawing and inputs + + # Flag used to ask for a (re-)computation of the display layout + private var first_frame = true + + redef fun frame_core(display) + do + if first_frame then + locate(display) + if cpt == -1 then + fly_in(display) + end + first_frame = false + end + + # Clear the screen + display.clear(1.0, 1.0, 1.0) + + # Manage events + # This is a crappy ad hoc organic implementation + if not player then + ttl -= 0.1 + if path != null then path.update(cursor, ttl) + if ttl <= 0.0 then + ttl = 0.0 + if is_menu then + # Menu animation is over + player = true + else if cpt < 0 then + # Level place animation is over + cpt += 1 + setpath + else if cpt < level.length then + # The cursor is playing + var b = level[cpt] + b.ttl = 1.0 + b.sound.play + cpt += 1 + setpath + else if cpt == level.length then + # The cursor is out, run the shuffle + path = null + if shuffling == 1 then + shuffle(display) + else if shuffling > 1 then + hard_shuffle(display) + end + cpt += 1 + else + # The shuffling is over, start playing + player = true + cpt = 0 + end + end + else if ttl > 0.0 then + ttl -= 0.1 + if ttl <= 0.0 then + ttl = 0.0 + if cpt == level.length then + fly_out(display) + cpt += 1 + else + if is_menu then + new_game + else if is_win then + current_level += 1 + new_game + else + replay_game + end + end + end + end + + # Display each button + for b in buttons do + b.blit_on(display) + end + + # Display the cursor + if path != null then + drawing.cursor.scale = scale + display.blit(drawing.cursor, cursor.x, cursor.y) + end + + if not is_menu then + blit_number(current_level, ui_scale, 10.0 * scale, 10.0 * scale) + reload.blit_on(display) + end + end + + # Blit a number somewhere + fun blit_number(number: Int, scale: Float, x, y: Float) + do + for img in number_images.imgs do img.scale = scale + display.blit_number(number_images, number, x.to_i, y.to_i) + end + + # Images with the numbers + private var number_images: NumberImages is noautoinit + + # A player click on a button + fun action(b: Button) + do + if is_menu then + b.sound.play + mode = b.place + current_level = 0 + ttl = 0.1 + cpt = level.length + is_win = true + return + end + if cpt >= level.length then return + if b == level[cpt] then + b.sound.play + b.ttl = 1.0 + + cpt += 1 + if cpt >= level.length then + is_win = true + print "Won!" + ttl = 2.0 + end + else + error += 1 + print "Err {error}" + b.error = true + b.ttl = 3.0 + snd_penalty.play + if error > 2 then + is_win = false + print "Lose!" + for b2 in buttons do + b2.error = true + b2.ttl = 3.0 + end + ttl = 3.0 + cpt = level.length + end + end + end + + redef fun input(ie) + do + # Quit? + if ie isa QuitEvent then + quit = true + return true + end + + # On click (or tap) + if ie isa PointerEvent and ie.depressed then + if player then + for b in buttons do + if b.has(ie.x, ie.y) then + action(b) + return true + end + end + end + + if not is_menu then + if reload.has(ie.x, ie.y) then + reload.sound.play + reload.ttl = 1.0 + replay_game + return true + end + end + end + + # Special commands + if ie isa KeyEvent and ie.is_down then + var c = ie.name + + if c == "4" or c == "escape" then + # 4 is *back* on android + if is_menu then + # quit = true # broken + new_menu + else + new_menu + end + return true + end + + if is_menu then + return false + end + + if c == "[+]" or c == "=" then + # [+] is keypad `+` + size += 1 + deal_game + return true + else if c == "[-]" or c == "-" then + size -= 1 + deal_game + return true + else if c == "[*]" or c == "]" then + length += 1 + deal_game + return true + else if c == "[/]" or c == "[" then + length -= 1 + deal_game + return true + else if c == "space" or c == "82" then + # 82 is *menu* on android + reload.sound.play + reload.ttl = 1.0 + replay_game + return true + end + + print "got keydown: `{c}`" + end + + return false + end +end diff --git a/contrib/nitcc/src/autom.nit b/contrib/nitcc/src/autom.nit index 19e113c..946b420 100644 --- a/contrib/nitcc/src/autom.nit +++ b/contrib/nitcc/src/autom.nit @@ -714,7 +714,7 @@ private class DFAGenerator else add("\tredef fun trans(char) do\n") - add("\t\tvar c = char.ascii\n") + add("\t\tvar c = char.code_point\n") var haslast = false var last = -1 for sym, next in trans do @@ -791,14 +791,14 @@ class TSymbol if f <= 32 then res = "#{f}" else - res = f.ascii.to_s + res = f.code_point.to_s end var l = last if f == l then return res res += " .. " if l == null then return res if l <= 32 or l >= 127 then return res + "#{l}" - return res + l.ascii.to_s + return res + l.code_point.to_s end end diff --git a/contrib/nitcc/src/nitcc_semantic.nit b/contrib/nitcc/src/nitcc_semantic.nit index af417d4..795cee0 100644 --- a/contrib/nitcc/src/nitcc_semantic.nit +++ b/contrib/nitcc/src/nitcc_semantic.nit @@ -588,7 +588,7 @@ redef class Token if text != null then var nfa = new Automaton.epsilon for c in text.chars do - nfa.concat(new Automaton.atom(c.ascii)) + nfa.concat(new Automaton.atom(c.code_point)) end return nfa end diff --git a/contrib/nitcc/src/re2nfa.nit b/contrib/nitcc/src/re2nfa.nit index d0d90ac..886eaea 100644 --- a/contrib/nitcc/src/re2nfa.nit +++ b/contrib/nitcc/src/re2nfa.nit @@ -38,7 +38,7 @@ redef class Nstr do var a = new Automaton.epsilon for c in self.value.chars do - var b = new Automaton.atom(c.ascii) + var b = new Automaton.atom(c.code_point) a.concat(b) end return a @@ -46,19 +46,19 @@ redef class Nstr end redef class Nch_dec - redef fun value: String do return text.substring_from(1).to_i.ascii.to_s + redef fun value: String do return text.substring_from(1).to_i.code_point.to_s redef fun make_rfa: Automaton do - var a = new Automaton.atom(self.value.chars.first.ascii) + var a = new Automaton.atom(self.value.chars.first.code_point) return a end end redef class Nch_hex - redef fun value: String do return text.substring_from(2).to_hex.ascii.to_s + redef fun value: String do return text.substring_from(2).to_hex.code_point.to_s redef fun make_rfa: Automaton do - var a = new Automaton.atom(self.value.chars.first.ascii) + var a = new Automaton.atom(self.value.chars.first.code_point) return a end end @@ -227,7 +227,7 @@ redef class Nre_class exit(1) abort end - var a = new Automaton.cla(c1.chars.first.ascii, c2.chars.first.ascii) + var a = new Automaton.cla(c1.chars.first.code_point, c2.chars.first.code_point) return a end end diff --git a/contrib/pep8analysis/src/location.nit b/contrib/pep8analysis/src/location.nit index 6fd9edf..634b695 100644 --- a/contrib/pep8analysis/src/location.nit +++ b/contrib/pep8analysis/src/location.nit @@ -165,7 +165,7 @@ class Location # * `"0;32"` for green fun colored_line(color: String): String do - var esc = 27.ascii + var esc = 27.code_point var def = "{esc}[0m" var col = "{esc}[{color}m" diff --git a/contrib/pep8analysis/src/model/operands.nit b/contrib/pep8analysis/src/model/operands.nit index 592e1af..d74d1f1 100644 --- a/contrib/pep8analysis/src/model/operands.nit +++ b/contrib/pep8analysis/src/model/operands.nit @@ -24,12 +24,12 @@ redef class ANumberValue end redef class ACharValue - redef fun to_i do return n_char.content.first.ascii + redef fun to_i do return n_char.content.first.code_point end redef class AStringValue # legal but no not recommended - redef fun to_i do return n_string.content.first.ascii + redef fun to_i do return n_string.content.first.code_point end redef class AHexValue diff --git a/contrib/pep8analysis/src/parser/lexer.nit b/contrib/pep8analysis/src/parser/lexer.nit index 912336c..718ee98 100644 --- a/contrib/pep8analysis/src/parser/lexer.nit +++ b/contrib/pep8analysis/src/parser/lexer.nit @@ -337,7 +337,7 @@ class Lexer if sp >= string_len then dfa_state = -1 else - var c = string[sp].ascii + var c = string[sp].code_point if c >= 255 then c = 255 sp += 1 diff --git a/examples/rosettacode/vignere_cipher.nit b/examples/rosettacode/vignere_cipher.nit index 73a3f41..565c19e 100644 --- a/examples/rosettacode/vignere_cipher.nit +++ b/examples/rosettacode/vignere_cipher.nit @@ -19,7 +19,7 @@ fun encrypt(src, key: String): String do continue end - out.add(((c.ascii + key[j].ascii - 2 * 'A'.ascii) % 26 + 'A'.ascii).ascii) + out.add(((c.ascii + key[j].ascii - 2u8 * 'A'.ascii) % 26u8 + 'A'.ascii).ascii) j = (j + 1) % key.length end @@ -39,7 +39,7 @@ fun decrypt(src, key: String): String do continue end - out.add(((c.ascii - key[j].ascii + 26) % 26 + 'A'.ascii).ascii) + out.add(((c.ascii - key[j].ascii + 26u8) % 26u8 + 'A'.ascii).ascii) j = (j + 1) % key.length end diff --git a/lib/base64.nit b/lib/base64.nit index 4eae395..cb73b3b 100644 --- a/lib/base64.nit +++ b/lib/base64.nit @@ -42,7 +42,7 @@ redef class NativeString # assert "string".encode_base64 == "c3RyaW5n" private fun encode_base64(length: Int, padding: nullable Byte): Bytes do var base64_bytes = once base64_chars - if padding == null then padding = '='.ascii.to_b + if padding == null then padding = '='.ascii var steps = length / 3 var bytes_in_last_step = length % 3 var result_length = steps * 4 @@ -81,7 +81,7 @@ redef class NativeString # # REQUIRE: `length % 4 == 0` private fun decode_base64(length: Int, padding: nullable Byte): Bytes do - if padding == null then padding = '='.ascii.to_b + if padding == null then padding = '='.ascii var inv = once inverted_base64_chars if length == 0 then return new Bytes.empty assert length % 4 == 0 else print "base64::decode_base64 only supports strings of length multiple of 4" diff --git a/lib/bcm2835/bcm2835.nit b/lib/bcm2835/bcm2835.nit index dad9899..48f0ed2 100644 --- a/lib/bcm2835/bcm2835.nit +++ b/lib/bcm2835/bcm2835.nit @@ -442,10 +442,10 @@ class HD44780 #write(true, "C0".to_hex) # instead we use the following which may not be portable - for s in [count..40[ do write(false, ' '.ascii) + for s in [count..40[ do write(false, ' '.code_point) count = 0 else - write(false, c.ascii) + write(false, c.code_point) count += 1 end end diff --git a/lib/binary/binary.nit b/lib/binary/binary.nit index b6909cd..c15cb52 100644 --- a/lib/binary/binary.nit +++ b/lib/binary/binary.nit @@ -107,7 +107,7 @@ redef abstract class Writer # Compared to `write_string`, this method supports null bytes in `text`. fun write_block(text: Text) do - write_int64 text.length + write_int64 text.bytelen write text end @@ -197,7 +197,7 @@ redef abstract class Reader do var length = read_int64 if length == 0 then return "" - return read(length) + return read_bytes(length).to_s end # Read a floating point on 32 bits and return it as a `Float` diff --git a/lib/binary/serialization.nit b/lib/binary/serialization.nit index d36f9c0..e069304 100644 --- a/lib/binary/serialization.nit +++ b/lib/binary/serialization.nit @@ -17,16 +17,16 @@ # The serialized data format uses a dictionary structure similar to BSON: # # ~~~raw -# object = 0x01 # null -# | 0x02 id attributes # New object -# | 0x03 id # Ref to object -# | 0x04 int64 # Int -# | 0x05 int8 # Bool (int8 != 0) -# | 0x06 int8 # Char -# | 0x07 double(64 bits) # Float -# | 0x08 block # String -# | 0x09 block # NativeString -# | 0x0A flat_array; # Array[nullable Object] +# object = 0x01 # null +# | 0x02 id attributes # New object +# | 0x03 id # Ref to object +# | 0x04 int64 # Int +# | 0x05 int8 # Bool (int8 != 0) +# | 0x06 utf8 byte sequence # Char +# | 0x07 double(64 bits) # Float +# | 0x08 block # String +# | 0x09 block # NativeString +# | 0x0A flat_array; # Array[nullable Object] # # block = int64 int8*; # cstring = int8* 0x00; @@ -128,6 +128,9 @@ class BinaryDeserializer # Tree of attributes, deserialized but not yet claimed private var unclaimed_attributes = new UnrolledList[HashMap[String, nullable Object]] + # Buffer for one char + private var char_buf: NativeString is lazy do return new NativeString(4) + # Read and deserialize the next attribute name and value # # A `peeked_char` can suffix the next attribute name. @@ -217,9 +220,17 @@ class BinaryDeserializer if kind == kind_bool then return stream.read_bool if kind == kind_float then return stream.read_double if kind == kind_char then + var bf = char_buf var b = stream.read_byte - if b == null then return 0 - return b.to_i.ascii + if b == null then return '�' + var ln = b.u8len + bf[0] = b + for i in [1 .. ln[ do + b = stream.read_byte + if b == null then return '�' + bf[i] = b + end + return bf.to_s_with_length(ln)[0] end if kind == kind_string then return stream.read_block if kind == kind_native_string then return stream.read_block.to_cstring @@ -382,8 +393,7 @@ redef class Char redef fun serialize_to_binary(v) do v.stream.write_byte kind_char - # Fix when UTF-8 - v.stream.write_byte self.ascii.to_b + for i in bytes do v.stream.write_byte i end end diff --git a/lib/bitmap/bitmap.nit b/lib/bitmap/bitmap.nit index e408402..0aceff5 100644 --- a/lib/bitmap/bitmap.nit +++ b/lib/bitmap/bitmap.nit @@ -211,11 +211,11 @@ class Bitmap var fw = new FileWriter.open(path) # Write bitmap header for x in [0..self.bitmap_header.length[ do - fw.write(self.bitmap_header[x].ascii.to_s) + fw.write(self.bitmap_header[x].code_point.to_s) end # Write dib header for x in [0..self.dib_header.length[ do - fw.write(self.dib_header[x].ascii.to_s) + fw.write(self.dib_header[x].code_point.to_s) end # Write color table (if any) # Write data (no padding for now) @@ -226,9 +226,9 @@ class Bitmap var red = pixel >> 16 var green = (pixel & 0x00FF00) >> 8 var blue = pixel & 0x000000FF - fw.write(red.ascii.to_s) - fw.write(green.ascii.to_s) - fw.write(blue.ascii.to_s) + fw.write(red.code_point.to_s) + fw.write(green.code_point.to_s) + fw.write(blue.code_point.to_s) end end fw.close diff --git a/lib/buffered_ropes.nit b/lib/buffered_ropes.nit index 8ed1f6b..fcc90c7 100644 --- a/lib/buffered_ropes.nit +++ b/lib/buffered_ropes.nit @@ -109,7 +109,7 @@ private class Leaf redef fun substrings do return new LeafSubstrings(self) - redef fun [](i) do return buf[i].to_i.ascii + redef fun [](i) do return buf[i].to_i.code_point init do bns = buf.ns diff --git a/lib/console.nit b/lib/console.nit index c0a8772..0020b7a 100644 --- a/lib/console.nit +++ b/lib/console.nit @@ -18,7 +18,7 @@ module console # A ANSI/VT100 escape sequence. abstract class TermEscape # The US-ASCII ESC character. - protected fun esc: Char do return 27.ascii + protected fun esc: Char do return 27.code_point # The Control Sequence Introducer (CSI). protected fun csi: String do return "{esc}[" diff --git a/lib/core/bytes.nit b/lib/core/bytes.nit index 356f386..227759a 100644 --- a/lib/core/bytes.nit +++ b/lib/core/bytes.nit @@ -32,18 +32,18 @@ redef class Byte # # ~~~nit # intrude import core::bytes - # assert not '/'.ascii.to_b.is_valid_hexdigit - # assert '0'.ascii.to_b.is_valid_hexdigit - # assert '9'.ascii.to_b.is_valid_hexdigit - # assert not ':'.ascii.to_b.is_valid_hexdigit - # assert not '@'.ascii.to_b.is_valid_hexdigit - # assert 'A'.ascii.to_b.is_valid_hexdigit - # assert 'F'.ascii.to_b.is_valid_hexdigit - # assert not 'G'.ascii.to_b.is_valid_hexdigit - # assert not '`'.ascii.to_b.is_valid_hexdigit - # assert 'a'.ascii.to_b.is_valid_hexdigit - # assert 'f'.ascii.to_b.is_valid_hexdigit - # assert not 'g'.ascii.to_b.is_valid_hexdigit + # assert not '/'.ascii.is_valid_hexdigit + # assert '0'.ascii.is_valid_hexdigit + # assert '9'.ascii.is_valid_hexdigit + # assert not ':'.ascii.is_valid_hexdigit + # assert not '@'.ascii.is_valid_hexdigit + # assert 'A'.ascii.is_valid_hexdigit + # assert 'F'.ascii.is_valid_hexdigit + # assert not 'G'.ascii.is_valid_hexdigit + # assert not '`'.ascii.is_valid_hexdigit + # assert 'a'.ascii.is_valid_hexdigit + # assert 'f'.ascii.is_valid_hexdigit + # assert not 'g'.ascii.is_valid_hexdigit # ~~~ private fun is_valid_hexdigit: Bool do return (self >= 0x30u8 and self <= 0x39u8) or diff --git a/lib/core/fixed_ints.nit b/lib/core/fixed_ints.nit index 17ef576..36f21a3 100644 --- a/lib/core/fixed_ints.nit +++ b/lib/core/fixed_ints.nit @@ -158,6 +158,9 @@ universal Int8 redef fun to_i32 is intern redef fun to_u32 is intern + # Returns `self` as a Char according to its ASCII value. + fun ascii: Char `{ return (uint32_t)self; `} + redef fun distance(i) do return (self - i).to_i redef fun <=>(other) @@ -271,6 +274,9 @@ universal Int16 redef fun *(i) is intern redef fun /(i) is intern + # Returns `self` as a Char according to its ASCII value. + fun ascii: Char `{ return (uint32_t)self; `} + # Modulo of `self` with `i`. # # Returns the remainder of division of `self` by `i`. @@ -425,6 +431,9 @@ universal UInt16 redef fun zero do return 0.to_u16 redef fun value_of(val) do return val.to_u16 + # Returns `self` as a Char according to its ASCII value. + fun ascii: Char `{ return (uint32_t)self; `} + # `i` bits shift to the left # # assert 5u16 << 1 == 10u16 @@ -558,6 +567,9 @@ universal Int32 redef fun *(i) is intern redef fun /(i) is intern + # Returns `self` as a Char according to its ASCII value. + fun ascii: Char `{ return (uint32_t)self; `} + # Modulo of `self` with `i`. # # Returns the remainder of division of `self` by `i`. @@ -701,6 +713,9 @@ universal UInt32 redef fun *(i) is intern redef fun /(i) is intern + # Returns `self` as a Char according to its ASCII value. + fun ascii: Char `{ return (uint32_t)self; `} + # Modulo of `self` with `i`. # # Returns the remainder of division of `self` by `i`. diff --git a/lib/core/kernel.nit b/lib/core/kernel.nit index b2ac524..650360a 100644 --- a/lib/core/kernel.nit +++ b/lib/core/kernel.nit @@ -651,6 +651,11 @@ universal Byte # assert 5u8 >> 1 == 2u8 fun >>(i: Int): Byte `{ return self >> i; `} + # Returns the character equivalent of `self` + # + # REQUIRE: `self <= 127u8` + fun ascii: Char `{ return (uint32_t)self; `} + redef fun to_i is intern redef fun to_f is intern redef fun to_b do return self @@ -797,11 +802,12 @@ universal Int end end - # The character whose ASCII value is `self`. + # The character which code point (unicode-wise) is `self` # - # assert 65.ascii == 'A' - # assert 10.ascii == '\n' - fun ascii: Char is intern + # assert 65.code_point == 'A' + # assert 10.code_point == '\n' + # assert 0x220B.code_point == '∋' + fun code_point: Char `{ return (uint32_t)self; `} # Number of digits of an integer in base `b` (plus one if negative) # @@ -861,9 +867,9 @@ universal Int do assert self >= 0 and self <= 36 # TODO plan for this if self < 10 then - return (self + '0'.ascii).ascii + return (self + '0'.code_point).code_point else - return (self + ('a'.ascii - 10)).ascii + return (self - 10 + 'a'.code_point).code_point end end @@ -905,7 +911,7 @@ universal Char printf("%c", self); } `} - redef fun hash do return ascii + redef fun hash do return code_point redef fun ==(o) is intern redef fun !=(o) is intern @@ -919,7 +925,7 @@ universal Char redef fun distance(c) do - var d = self.ascii - c.ascii + var d = self.code_point - c.code_point if d >= 0 then return d else @@ -936,17 +942,32 @@ universal Char if self == '-' then return -1 else if is_digit then - return self.ascii - '0'.ascii + return self.code_point - '0'.code_point else - return self.to_lower.ascii - 'a'.ascii + 10 + return self.to_lower.code_point - 'a'.code_point + 10 end end - # the ascii value of self + # The ascii value of `self` + # + # assert 'a'.ascii == 97u8 + # assert '\n'.ascii == 10u8 + # + # REQUIRE: `is_ascii` + fun ascii: Byte do return code_point.to_b + + # The unicode code point value of `self` + # + # assert 'A'.code_point == 65 + # assert '\n'.code_point == 10 + # assert '∋'.code_point == 0x220B + fun code_point: Int `{ return (long)self; `} + + # Is `self` an ASCII character ? # - # assert 'a'.ascii == 97 - # assert '\n'.ascii == 10 - fun ascii: Int is intern + # assert 'x'.is_ascii + # assert not 'ま'.is_ascii + fun is_ascii: Bool do return code_point <= 127 # Return the lower case version of self. # If self is not a letter, then return self @@ -957,7 +978,7 @@ universal Char fun to_lower: Char do if is_upper then - return (ascii + ('a'.distance('A'))).ascii + return (code_point + ('a'.distance('A'))).code_point else return self end @@ -972,7 +993,7 @@ universal Char fun to_upper: Char do if is_lower then - return (ascii - ('a'.distance('A'))).ascii + return (code_point - ('a'.distance('A'))).code_point else return self end @@ -1033,7 +1054,7 @@ universal Char # assert '\t'.is_whitespace == true fun is_whitespace: Bool do - var i = ascii + var i = code_point return i <= 0x20 or i == 0x7F end end diff --git a/lib/core/math.nit b/lib/core/math.nit index 50b36e9..c08c735 100644 --- a/lib/core/math.nit +++ b/lib/core/math.nit @@ -333,6 +333,45 @@ redef class Float # assert -0.5.lerp(0.0, 128.0) == -64.0 # ~~~ fun lerp(a, b: Float): Float do return (1.0 - self) * a + self * b + + # Quadratic Bézier interpolation between `a` and `b` with an `handle` using `self` as weight + # + # ~~~ + # assert 0.00.qerp(0.0, 32.0, 128.0) == 0.0 + # assert 0.25.qerp(0.0, 32.0, 128.0) == 20.0 + # assert 0.50.qerp(0.0, 32.0, 128.0) == 48.0 + # assert 0.75.qerp(0.0, 32.0, 128.0) == 84.0 + # assert 1.00.qerp(0.0, 32.0, 128.0) == 128.0 + # ~~~ + fun qerp(a, handle, b: Float): Float do + var p = self + var i = 1.0 - p + var r = i*i * a + + 2.0*i*p * handle + + p*p * b + return r + end + + # Cubic Bézier interpolation between `a` and `b` with two handles using `self` as weight + # + # The Cubic Bézier interpolation is the most common one and use two control points. + # + # ~~~ + # assert 0.00.cerp(0.0, 32.0, 128.0, 64.0) == 0.0 + # assert 0.25.cerp(0.0, 32.0, 128.0, 64.0) == 32.5 + # assert 0.50.cerp(0.0, 32.0, 128.0, 64.0) == 68.0 + # assert 0.75.cerp(0.0, 32.0, 128.0, 64.0) == 85.5 + # assert 1.00.cerp(0.0, 32.0, 128.0, 64.0) == 64.0 + # ~~~ + fun cerp(a, a_handle, b_handle, b: Float): Float do + var p = self + var i = 1.0 - p + var r = i*i*i * a + + 3.0*i*i*p * a_handle + + 3.0*i*p*p * b_handle + + p*p*p * b + return r + end end # Positive float infinite (IEEE 754) diff --git a/lib/core/stream.nit b/lib/core/stream.nit index 4b1e826..b4a0e2b 100644 --- a/lib/core/stream.nit +++ b/lib/core/stream.nit @@ -275,7 +275,7 @@ abstract class Reader # ~~~ # var w = new StringReader(" Hello, \n\t World!") # assert w.read_word == "Hello," - # assert w.read_char == '\n'.ascii + # assert w.read_char == '\n' # assert w.read_word == "World!" # assert w.read_word == "" # ~~~ @@ -441,7 +441,7 @@ abstract class BufferedReader return null end # TODO: Fix when supporting UTF-8 - var c = _buffer[_buffer_pos].to_i.ascii + var c = _buffer[_buffer_pos].to_i.code_point _buffer_pos += 1 return c end diff --git a/lib/core/text/abstract_text.nit b/lib/core/text/abstract_text.nit index b1e6a04..63fb920 100644 --- a/lib/core/text/abstract_text.nit +++ b/lib/core/text/abstract_text.nit @@ -543,7 +543,7 @@ abstract class Text if c >= '0' and c <= '9' then res.add('_') - res.append(c.ascii.to_s) + res.append(c.code_point.to_s) res.add('d') start = 1 end @@ -555,7 +555,7 @@ abstract class Text continue end if underscore then - res.append('_'.ascii.to_s) + res.append('_'.code_point.to_s) res.add('d') end if c >= '0' and c <= '9' then @@ -566,13 +566,13 @@ abstract class Text underscore = true else res.add('_') - res.append(c.ascii.to_s) + res.append(c.code_point.to_s) res.add('d') underscore = false end end if underscore then - res.append('_'.ascii.to_s) + res.append('_'.code_point.to_s) res.add('d') end return res.to_s @@ -587,7 +587,7 @@ abstract class Text # Three digits are always used to avoid following digits to be interpreted as an element # of the octal sequence. # - # assert "{0.ascii}{1.ascii}{8.ascii}{31.ascii}{32.ascii}".escape_to_c == "\\000\\001\\010\\037 " + # assert "{0.code_point}{1.code_point}{8.code_point}{31.code_point}{32.code_point}".escape_to_c == "\\000\\001\\010\\037 " # # The exceptions are the common `\t` and `\n`. fun escape_to_c: String @@ -605,9 +605,9 @@ abstract class Text b.append("\\\'") else if c == '\\' then b.append("\\\\") - else if c.ascii < 32 then + else if c.code_point < 32 then b.add('\\') - var oct = c.ascii.to_base(8, false) + var oct = c.code_point.to_base(8, false) # Force 3 octal digits since it is the # maximum allowed in the C specification if oct.length == 1 then @@ -680,8 +680,8 @@ abstract class Text else if c == ':' or c == ' ' or c == '#' then b.add('\\') b.add(c) - else if c.ascii < 32 or c == ';' or c == '|' or c == '\\' or c == '=' then - b.append("?{c.ascii.to_base(16, false)}") + else if c.code_point < 32 or c == ';' or c == '|' or c == '\\' or c == '=' then + b.append("?{c.code_point.to_base(16, false)}") else b.add(c) end @@ -695,7 +695,7 @@ abstract class Text # assert s.length == 2 # var u = s.unescape_nit # assert u.length == 1 - # assert u.chars[0].ascii == 10 # (the ASCII value of the "new line" character) + # assert u.chars[0].code_point == 10 # (the ASCII value of the "new line" character) fun unescape_nit: String do var res = new Buffer.with_cap(self.length) @@ -787,7 +787,7 @@ abstract class Text if c == '%' then if i + 2 >= length then # What follows % has been cut off - buf[l] = '?'.ascii.to_b + buf[l] = '?'.ascii else i += 1 var hex_s = substring(i, 2) @@ -797,11 +797,11 @@ abstract class Text i += 1 else # What follows a % is not Hex - buf[l] = '?'.ascii.to_b + buf[l] = '?'.ascii i -= 1 end end - else buf[l] = c.ascii.to_b + else buf[l] = c.ascii i += 1 l += 1 @@ -905,7 +905,7 @@ abstract class Text for i in [0..length[ do var char = chars[i] - h = (h << 5) + h + char.ascii + h = (h << 5) + h + char.code_point end hash_cache = h @@ -1050,7 +1050,7 @@ private abstract class StringByteView redef fun is_empty do return target.is_empty - redef fun length do return target.length + redef fun length do return target.bytelen redef fun iterator do return self.iterator_from(0) @@ -1573,9 +1573,15 @@ end redef class Char + # Returns a sequence with the UTF-8 bytes of `self` + # + # assert 'a'.bytes == [0x61u8] + # assert 'ま'.bytes == [0xE3u8, 0x81u8, 0xBEu8] + fun bytes: SequenceRead[Byte] do return to_s.bytes + # Length of `self` in a UTF-8 String private fun u8char_len: Int do - var c = self.ascii + var c = self.code_point if c < 0x80 then return 1 if c <= 0x7FF then return 2 if c <= 0xFFFF then return 3 diff --git a/lib/core/text/flat.nit b/lib/core/text/flat.nit index 52de988..4d2ff48 100644 --- a/lib/core/text/flat.nit +++ b/lib/core/text/flat.nit @@ -1035,7 +1035,7 @@ redef class NativeString end var ok_c: Bool var c = char_at(pos) - var cp = c.ascii + var cp = c.code_point if nxst == 1 then ok_c = cp >= 0 and cp <= 0x7F else if nxst == 2 then diff --git a/lib/core/text/native.nit b/lib/core/text/native.nit index acc9a12..4028ea0 100644 --- a/lib/core/text/native.nit +++ b/lib/core/text/native.nit @@ -16,7 +16,7 @@ import math redef class Byte # Gives the length of the UTF-8 char starting with `self` - private fun u8len: Int do + fun u8len: Int do if self & 0b1000_0000u8 == 0u8 then return 1 else if self & 0b1110_0000u8 == 0b1100_0000u8 then diff --git a/lib/core/text/ropes.nit b/lib/core/text/ropes.nit index 3e7b761..c164529 100644 --- a/lib/core/text/ropes.nit +++ b/lib/core/text/ropes.nit @@ -468,7 +468,7 @@ class RopeBuffer rp = 0 end # TODO: Fix when supporting UTF-8 - ns[rp] = c.ascii.to_b + ns[rp] = c.ascii rp += 1 _bytelen += 1 rpos = rp diff --git a/lib/crypto.nit b/lib/crypto.nit index 310f725..011347d 100644 --- a/lib/crypto.nit +++ b/lib/crypto.nit @@ -30,7 +30,7 @@ redef class Char x = x % 26 if x < 0 then x += 26 var up = false - var val = ascii + var val = code_point if is_upper then up = true val += 32 @@ -38,7 +38,7 @@ redef class Char val += x if val > 122 then val -= 26 if up then val -= 32 - return val.ascii + return val.code_point end end diff --git a/lib/json/json_lexer.nit b/lib/json/json_lexer.nit index 88b270b..b6bf2c1 100644 --- a/lib/json/json_lexer.nit +++ b/lib/json/json_lexer.nit @@ -47,7 +47,7 @@ end private class DFAState0 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 8 then return null if c <= 10 then return dfastate_1 if c <= 31 then return null @@ -84,7 +84,7 @@ private class DFAState1 return null end redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 8 then return null if c <= 10 then return dfastate_1 if c <= 31 then return null @@ -95,7 +95,7 @@ end private class DFAState2 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 33 then return dfastate_2 if c <= 34 then return dfastate_29 if c <= 91 then return dfastate_2 @@ -116,7 +116,7 @@ end private class DFAState4 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 47 then return null if c <= 57 then return dfastate_5 return null @@ -132,7 +132,7 @@ private class DFAState5 return t end redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 45 then return null if c <= 46 then return dfastate_24 if c <= 47 then return null @@ -177,7 +177,7 @@ end private class DFAState9 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 96 then return null if c <= 97 then return dfastate_20 return null @@ -186,7 +186,7 @@ end private class DFAState10 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 116 then return null if c <= 117 then return dfastate_17 return null @@ -195,7 +195,7 @@ end private class DFAState11 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 113 then return null if c <= 114 then return dfastate_14 return null @@ -224,7 +224,7 @@ end private class DFAState14 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 116 then return null if c <= 117 then return dfastate_15 return null @@ -233,7 +233,7 @@ end private class DFAState15 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 100 then return null if c <= 101 then return dfastate_16 return null @@ -252,7 +252,7 @@ end private class DFAState17 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 107 then return null if c <= 108 then return dfastate_18 return null @@ -261,7 +261,7 @@ end private class DFAState18 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 107 then return null if c <= 108 then return dfastate_19 return null @@ -280,7 +280,7 @@ end private class DFAState20 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 107 then return null if c <= 108 then return dfastate_21 return null @@ -289,7 +289,7 @@ end private class DFAState21 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 114 then return null if c <= 115 then return dfastate_22 return null @@ -298,7 +298,7 @@ end private class DFAState22 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 100 then return null if c <= 101 then return dfastate_23 return null @@ -317,7 +317,7 @@ end private class DFAState24 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 47 then return null if c <= 57 then return dfastate_28 return null @@ -326,7 +326,7 @@ end private class DFAState25 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 42 then return null if c <= 43 then return dfastate_26 if c <= 44 then return null @@ -339,7 +339,7 @@ end private class DFAState26 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 47 then return null if c <= 57 then return dfastate_27 return null @@ -355,7 +355,7 @@ private class DFAState27 return t end redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 47 then return null if c <= 57 then return dfastate_27 return null @@ -371,7 +371,7 @@ private class DFAState28 return t end redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 47 then return null if c <= 57 then return dfastate_28 if c <= 68 then return null @@ -394,7 +394,7 @@ end private class DFAState30 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 33 then return null if c <= 34 then return dfastate_2 if c <= 46 then return null @@ -418,7 +418,7 @@ end private class DFAState31 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 47 then return null if c <= 57 then return dfastate_32 if c <= 64 then return null @@ -431,7 +431,7 @@ end private class DFAState32 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 47 then return null if c <= 57 then return dfastate_33 if c <= 64 then return null @@ -444,7 +444,7 @@ end private class DFAState33 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 47 then return null if c <= 57 then return dfastate_34 if c <= 64 then return null @@ -457,7 +457,7 @@ end private class DFAState34 super DFAState redef fun trans(char) do - var c = char.ascii + var c = char.code_point if c <= 47 then return null if c <= 57 then return dfastate_2 if c <= 64 then return null diff --git a/lib/json/static.nit b/lib/json/static.nit index fdb9f65..966f2c9 100644 --- a/lib/json/static.nit +++ b/lib/json/static.nit @@ -99,22 +99,22 @@ redef class Text buffer.append "\\\"" else if char == '\/' then buffer.append "\\/" - else if char < 16.ascii then + else if char < 16.code_point then if char == '\n' then buffer.append "\\n" else if char == '\r' then buffer.append "\\r" else if char == '\t' then buffer.append "\\t" - else if char == 0x0C.ascii then + else if char == 0x0C.code_point then buffer.append "\\f" - else if char == 0x08.ascii then + else if char == 0x08.code_point then buffer.append "\\b" else - buffer.append "\\u000{char.ascii.to_hex}" + buffer.append "\\u000{char.code_point.to_hex}" end else if char < ' ' then - buffer.append "\\u00{char.ascii.to_hex}" + buffer.append "\\u00{char.code_point.to_hex}" else buffer.add char end @@ -435,9 +435,9 @@ redef class Nstring i += 1 char = text[i] if char == 'b' then - char = 0x08.ascii + char = 0x08.code_point else if char == 'f' then - char = 0x0C.ascii + char = 0x0C.code_point else if char == 'n' then char = '\n' else if char == 'r' then @@ -450,7 +450,7 @@ redef class Nstring if code >= 128 then char = '?' else - char = code.ascii + char = code.code_point end i += 4 end diff --git a/lib/mnit/numbers.nit b/lib/mnit/numbers.nit index 1b7a017..e7462b4 100644 --- a/lib/mnit/numbers.nit +++ b/lib/mnit/numbers.nit @@ -41,7 +41,7 @@ redef class Display do var str = number.to_s for c in str.chars do - var d = c.ascii-'0'.ascii + var d = c.code_point-'0'.code_point assert d >= 0 and d <= 9 var img = imgs.imgs[d] blit(img, x, y) diff --git a/lib/saxophonit/lexer.nit b/lib/saxophonit/lexer.nit index acfe9fa..92f293b 100644 --- a/lib/saxophonit/lexer.nit +++ b/lib/saxophonit/lexer.nit @@ -49,9 +49,9 @@ class XophonLexer # read the next byte. Else, return `-1`. fun expect_delimiter: Int do if accept('"') then - return '"'.ascii + return '"'.code_point else if accept('\'') then - return '\''.ascii + return '\''.code_point else fire_unexpected_char(". Expecting `\"` or `'`") return -1 @@ -71,7 +71,7 @@ class XophonLexer # If the last read byte is forbidden, fire a fatal error instead. fun expect_xml_char(buffer: Buffer): Bool do if is_xml_char then - buffer.chars.push(last_char.ascii) + buffer.chars.push(last_char.code_point) read_char return true else if eof then @@ -91,7 +91,7 @@ class XophonLexer buffer.chars.push(' ') read_char return true - else if last_char == '<'.ascii then + else if last_char == '<'.code_point then return fire_fatal_error("`<` is forbidden in attribute values.") else return expect_xml_char(buffer) @@ -127,10 +127,10 @@ class XophonLexer # Is the last read byte matches the `NameStartChar` production? fun is_name_start_char: Bool do # TODO: Handle code points above 0x7F. - return ['A'.ascii .. 'Z'.ascii].has(last_char) or - ['a'.ascii .. 'z'.ascii].has(last_char) or - last_char == '_'.ascii or - last_char == ':'.ascii or + return ['A'.code_point .. 'Z'.code_point].has(last_char) or + ['a'.code_point .. 'z'.code_point].has(last_char) or + last_char == '_'.code_point or + last_char == ':'.code_point or last_char > 127 end @@ -138,8 +138,8 @@ class XophonLexer fun is_name_char: Bool do # TODO: Handle code points above 0x7F. return is_name_start_char or - last_char == '-'.ascii or - last_char == '.'.ascii or + last_char == '-'.code_point or + last_char == '.'.code_point or is_digit end @@ -150,10 +150,10 @@ class XophonLexer if not is_name_start_char then return fire_unexpected_char(" at the beginning of a name") end - buffer.chars.push(last_char.ascii) + buffer.chars.push(last_char.code_point) read_char while is_name_char do - buffer.chars.push(last_char.ascii) + buffer.chars.push(last_char.code_point) read_char end return true @@ -187,14 +187,14 @@ class XophonLexer # Is the last read byte matches the `[0-9]` production? fun is_digit: Bool do - return ['0'.ascii .. '9'.ascii].has(last_char) + return ['0'.code_point .. '9'.code_point].has(last_char) end # Accept a `[0-9]+` token. fun accept_digits(buffer: Buffer): Bool do if is_digit then loop - buffer.chars.push(last_char.ascii) + buffer.chars.push(last_char.code_point) read_char if not is_digit then return true end @@ -210,16 +210,16 @@ class XophonLexer # Is `last_char` matches the `[0-9a-fA-F]` production? fun is_hex: Bool do - return ['0'.ascii .. '9'.ascii].has(last_char) or - ['A'.ascii .. 'Z'.ascii].has(last_char) or - ['a'.ascii .. 'Z'.ascii].has(last_char) + return ['0'.code_point .. '9'.code_point].has(last_char) or + ['A'.code_point .. 'Z'.code_point].has(last_char) or + ['a'.code_point .. 'Z'.code_point].has(last_char) end # Expect a `[0-9a-fA-F]+` token. fun expect_hex(buffer: Buffer): Bool do if is_hex then loop - buffer.chars.push(last_char.ascii) + buffer.chars.push(last_char.code_point) read_char if not is_hex then return true end @@ -247,7 +247,7 @@ class XophonLexer else if last_char < 0 then fire_fatal_error("Internal error: Already at the end of the file.") return - else if last_char == '\n'.ascii then + else if last_char == '\n'.code_point then locator.line_number += 1 locator.column_number = 1 else @@ -264,7 +264,7 @@ class XophonLexer # XML 1.0 end-of-line handling # Note: Regardless the XML version, any EOL defined by the # recommandation MUST be reported as a single LINE FEED. - if was_cr and last_char == '\n'.ascii then + if was_cr and last_char == '\n'.code_point then # EOL already reported. => Skip this byte. s = input.read_byte if s == null then @@ -273,10 +273,10 @@ class XophonLexer last_char = s.to_i end end - was_cr = last_char == '\r'.ascii + was_cr = last_char == '\r'.code_point if was_cr then # Regardless the following byte, '\r' always introduce an EOL. - last_char = '\n'.ascii + last_char = '\n'.code_point end end @@ -303,7 +303,7 @@ class XophonLexer fun is_int(c: Int): Bool do return last_char == c # Does the last read byte equal `c`? - fun is_char(c: Char): Bool do return last_char == c.ascii + fun is_char(c: Char): Bool do return last_char == c.code_point # Expect the specified byte. fun accept_int(expected: Int): Bool do @@ -317,7 +317,7 @@ class XophonLexer # Accept the specified byte. fun accept(expected: Char): Bool do - return accept_int(expected.ascii) + return accept_int(expected.code_point) end # Ensure the last read byte is equal to `expected`. @@ -330,7 +330,7 @@ class XophonLexer # Return `true` if and only if the last read byte as the expected value. fun expect_int(expected: Int, context: String): Bool do return accept_int(expected) or - fire_unexpected_char("{context}. Expecting `{expected.ascii}`.") + fire_unexpected_char("{context}. Expecting `{expected.code_point}`.") end # Ensure the last read byte is equal to `expected`. @@ -363,7 +363,7 @@ class XophonLexer if not accept(chars[i]) then if is_xml_char then return fire_fatal_error("Unexpected " + - "`{expected.substring(0, i)}{last_char.ascii.to_s}`" + + "`{expected.substring(0, i)}{last_char.code_point.to_s}`" + "{context}. Expecting `{expected}`.") else if eof then return fire_fatal_error("Unexpected end of file{context}. " + @@ -386,7 +386,7 @@ class XophonLexer # Return `false`. fun fire_unexpected_char(rest_of_message: String): Bool do if is_xml_char then - return fire_fatal_error("Unexpected character `{last_char.ascii.to_s}`{rest_of_message}.") + return fire_fatal_error("Unexpected character `{last_char.code_point.to_s}`{rest_of_message}.") else if eof then return fire_fatal_error("Unexpected end of file{rest_of_message}.") else diff --git a/lib/saxophonit/saxophonit.nit b/lib/saxophonit/saxophonit.nit index 2693086..d5ddeb3 100644 --- a/lib/saxophonit/saxophonit.nit +++ b/lib/saxophonit/saxophonit.nit @@ -656,14 +656,14 @@ class XophonReader if lexer.accept('#') then if lexer.accept('x') then if lexer.expect_hex(ref) then - buffer.chars.add(ref.to_hex.ascii) + buffer.chars.add(ref.to_hex.code_point) return lexer.expect(';', "") else return lexer.fire_unexpected_char( ". Expecting an hexadecimal digit") end else if lexer.accept_digits(ref) then - buffer.chars.add(ref.to_i.ascii) + buffer.chars.add(ref.to_i.code_point) return lexer.expect(';', "") else return lexer.fire_unexpected_char(" in a character reference. " + diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index 2f83449..b79e9ba 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -1552,10 +1552,10 @@ abstract class AbstractCompilerVisitor do var t = mmodule.char_type - if value.ascii < 128 then + if value.code_point < 128 then return new RuntimeVariable("'{value.to_s.escape_to_c}'", t, t) else - return new RuntimeVariable("{value.ascii}", t, t) + return new RuntimeVariable("{value.code_point}", t, t) end end @@ -2243,9 +2243,6 @@ 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 == "ascii" then - v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null))) - return true end else if cname == "Char" then if pname == "object_id" then @@ -2279,9 +2276,6 @@ redef class AMethPropdef else if pname == "to_i" then v.ret(v.new_expr("{arguments[0]}-'0'", ret.as(not null))) return true - else if pname == "ascii" then - v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null))) - return true end else if cname == "Byte" then if pname == "output" then @@ -2351,9 +2345,6 @@ redef class AMethPropdef 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 end else if cname == "Bool" then if pname == "output" then @@ -2539,9 +2530,6 @@ 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 == "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 @@ -2641,9 +2629,6 @@ redef class AMethPropdef 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 @@ -2731,9 +2716,6 @@ redef class AMethPropdef 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 @@ -2821,9 +2803,6 @@ redef class AMethPropdef 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 @@ -2911,9 +2890,6 @@ redef class AMethPropdef 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 diff --git a/src/compiler/separate_compiler.nit b/src/compiler/separate_compiler.nit index ff5f3ba..00f3f00 100644 --- a/src/compiler/separate_compiler.nit +++ b/src/compiler/separate_compiler.nit @@ -998,10 +998,13 @@ class SeparateCompiler # use some Huffman coding. if t.name == "Int" then class_info[1] = t + t.mclass_type.tag_value = 1 else if t.name == "Char" then class_info[2] = t + t.mclass_type.tag_value = 2 else if t.name == "Bool" then class_info[3] = t + t.mclass_type.tag_value = 3 else continue end @@ -1858,7 +1861,7 @@ class SeparateCompilerVisitor else var mtype1 = value1.mtype.as(MClassType) self.require_declaration("class_{mtype1.c_name}") - self.add("{res} = ({value2} != NULL) && ({value2}->class == &class_{mtype1.c_name}); /* is_same_type_test */") + self.add("{res} = ({value2} != NULL) && ({class_info(value2)} == &class_{mtype1.c_name}); /* is_same_type_test */") end else self.add("{res} = ({value1} == {value2}) || ({value1} != NULL && {value2} != NULL && {class_info(value1)} == {class_info(value2)}); /* is_same_type_test */") @@ -1891,20 +1894,58 @@ class SeparateCompilerVisitor value2 = tmp end if value1.mtype.is_c_primitive then - if value2.mtype == value1.mtype then + var t1 = value1.mtype + assert t1 == value1.mcasttype + + # Fast case: same C type. + if value2.mtype == t1 then + # Same exact C primitive representation. self.add("{res} = {value1} == {value2};") - else if value2.mtype.is_c_primitive then - self.add("{res} = 0; /* incompatible types {value1.mtype} vs. {value2.mtype}*/") - else if value1.mtype.is_tagged then - self.add("{res} = ({value2} != NULL) && ({self.autobox(value2, value1.mtype)} == {value1});") + return res + end + + # Complex case: value2 has a different representation + # Thus, it should be checked if `value2` is type-compatible with `value1` + # This compatibility is done statically if possible and dynamically else + + # Conjunction (ands) of dynamic tests according to the static knowledge + var tests = new Array[String] + + var t2 = value2.mcasttype + if t2 isa MNullableType then + # The destination type cannot be null + tests.add("({value2} != NULL)") + t2 = t2.mtype + else if t2 isa MNullType then + # `value2` is known to be null, thus incompatible with a primitive + self.add("{res} = 0; /* incompatible types {t1} vs. {t2}*/") + return res + end + + if t2 == t1 then + # Same type but different representation. + else if t2.is_c_primitive then + # Type of `value2` is a different primitive type, thus incompatible + self.add("{res} = 0; /* incompatible types {t1} vs. {t2}*/") + return res + else if t1.is_tagged then + # To be equal, `value2` should also be correctly tagged + tests.add("({extract_tag(value2)} == {t1.tag_value})") else - var mtype1 = value1.mtype.as(MClassType) - self.require_declaration("class_{mtype1.c_name}") - self.add("{res} = ({value2} != NULL) && ({value2}->class == &class_{mtype1.c_name});") - self.add("if ({res}) \{") - self.add("{res} = ({self.autobox(value2, value1.mtype)} == {value1});") - self.add("\}") + # To be equal, `value2` should also be boxed with the same class + self.require_declaration("class_{t1.c_name}") + tests.add "({class_info(value2)} == &class_{t1.c_name})" end + + # Compare the unboxed `value2` with `value1` + if tests.not_empty then + self.add "if ({tests.join(" && ")}) \{" + end + self.add "{res} = {self.autobox(value2, t1)} == {value1};" + if tests.not_empty then + self.add "\} else {res} = 0;" + end + return res end var maybe_null = true @@ -2327,6 +2368,12 @@ redef class MType # Are values of `self` tagged? # If false, it means that the type is not primitive, or is boxed. var is_tagged = false + + # The tag value of the type + # + # ENSURE `is_tagged == (tag_value > 0)` + # ENSURE `not is_tagged == (tag_value == 0)` + var tag_value = 0 end redef class MEntity diff --git a/src/doc/doc_phases/doc_console.nit b/src/doc/doc_phases/doc_console.nit index e4f6bb1..b118019 100644 --- a/src/doc/doc_phases/doc_console.nit +++ b/src/doc/doc_phases/doc_console.nit @@ -551,8 +551,8 @@ private class Pager b.append("\\\\") else if c == '`' then b.append("'") - else if c.ascii < 32 then - b.append("\\{c.ascii.to_base(8, false)}") + else if c.code_point < 32 then + b.append("\\{c.code_point.to_base(8, false)}") else b.add(c) end diff --git a/src/interpreter/naive_interpreter.nit b/src/interpreter/naive_interpreter.nit index b484f15..da7b288 100644 --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@ -972,8 +972,6 @@ redef class AMethPropdef return v.bool_instance(recvval >= args[1].to_i) else if pname == "<=>" then return v.int_instance(recvval <=> args[1].to_i) - else if pname == "ascii" then - return v.char_instance(recvval.ascii) else if pname == "to_f" then return v.float_instance(recvval.to_f) else if pname == "to_b" then @@ -1045,9 +1043,7 @@ redef class AMethPropdef end else if cname == "Char" then var recv = args[0].val.as(Char) - if pname == "ascii" then - return v.int_instance(recv.ascii) - else if pname == "successor" then + if pname == "successor" then return v.char_instance(recv.successor(args[1].to_i)) else if pname == "predecessor" then return v.char_instance(recv.predecessor(args[1].to_i)) diff --git a/src/location.nit b/src/location.nit index 786ffc2..0c5b55d 100644 --- a/src/location.nit +++ b/src/location.nit @@ -246,7 +246,7 @@ class Location # * `"0;32"` for green fun colored_line(color: String): String do - var esc = 27.ascii + var esc = 27.code_point var def = "{esc}[0m" var col = "{esc}[{color}m" diff --git a/src/parser/lexer_work.nit b/src/parser/lexer_work.nit index 94810af..e061613 100644 --- a/src/parser/lexer_work.nit +++ b/src/parser/lexer_work.nit @@ -173,7 +173,7 @@ class Lexer # This does not corrupt the lexer and works perfectly on any character. # # TL;DR: Java fucked up, need retarded solution to cope for retarded decision - var c = string[sp].ascii + var c = string[sp].code_point if c >= 256 then c = 255 sp += 1 diff --git a/src/toolcontext.nit b/src/toolcontext.nit index 8be85d4..98b746a 100644 --- a/src/toolcontext.nit +++ b/src/toolcontext.nit @@ -84,7 +84,7 @@ class Message # A colored version of the message including the original source line fun to_color_string: String do - var esc = 27.ascii + var esc = 27.code_point #var red = "{esc}[0;31m" #var bred = "{esc}[1;31m" #var green = "{esc}[0;32m" diff --git a/tests/base_eq_int4.nit b/tests/base_eq_int4.nit new file mode 100644 index 0000000..60144b2 --- /dev/null +++ b/tests/base_eq_int4.nit @@ -0,0 +1,196 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import kernel + +var i = 1 +var b = true +var f = 1u8 +var ni: nullable Int = 1 +var nb: nullable Bool = true +var nf: nullable Byte = 1u8 +var oi: nullable Object = 1 +var ob: nullable Object = true +var of: nullable Object = 1u8 + + +(i == i).output +(b == i).output +(f == i).output + +'\n'.output + +(i == ni).output +(b == ni).output +(f == ni).output + +'\n'.output + +(i == oi).output +(b == oi).output +(f == oi).output + +'\n'.output +'\n'.output + +(ni == i).output +(nb == i).output +(nf == i).output + +'\n'.output + +(ni == ni).output +(nb == ni).output +(nf == ni).output + +'\n'.output + +(ni == oi).output +(nb == oi).output +(nf == oi).output + +'\n'.output +'\n'.output + +(oi == i).output +(ob == i).output +(of == i).output + +'\n'.output + +(oi == ni).output +(ob == ni).output +(of == ni).output + +'\n'.output + +(oi == oi).output +(ob == oi).output +(of == oi).output + +'\n'.output +'\n'.output +'\n'.output + +(i == b).output +(b == b).output +(f == b).output + +'\n'.output + +(i == nb).output +(b == nb).output +(f == nb).output + +'\n'.output + +(i == ob).output +(b == ob).output +(f == ob).output + +'\n'.output +'\n'.output + +(ni == b).output +(nb == b).output +(nf == b).output + +'\n'.output + +(ni == nb).output +(nb == nb).output +(nf == nb).output + +'\n'.output + +(ni == ob).output +(nb == ob).output +(nf == ob).output + +'\n'.output +'\n'.output + +(oi == b).output +(ob == b).output +(of == b).output + +'\n'.output + +(oi == nb).output +(ob == nb).output +(of == nb).output + +'\n'.output + +(oi == ob).output +(ob == ob).output +(of == ob).output + +'\n'.output +'\n'.output +'\n'.output + +(i == f).output +(b == f).output +(f == f).output + +'\n'.output + +(i == nf).output +(b == nf).output +(f == nf).output + +'\n'.output + +(i == of).output +(b == of).output +(f == of).output + +'\n'.output +'\n'.output + +(ni == f).output +(nb == f).output +(nf == f).output + +'\n'.output + +(ni == nf).output +(nb == nf).output +(nf == nf).output + +'\n'.output + +(ni == of).output +(nb == of).output +(nf == of).output + +'\n'.output +'\n'.output + +(oi == f).output +(ob == f).output +(of == f).output + +'\n'.output + +(oi == nf).output +(ob == nf).output +(of == nf).output + +'\n'.output + +(oi == of).output +(ob == of).output +(of == of).output diff --git a/tests/base_eq_int4b.nit b/tests/base_eq_int4b.nit new file mode 100644 index 0000000..fea2020 --- /dev/null +++ b/tests/base_eq_int4b.nit @@ -0,0 +1,196 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import kernel + +var i = 1 +var b = true +var f = 1u8 +var ni: nullable Int = 1 +var nb: nullable Bool = true +var nf: nullable Byte = 1u8 +var oi: nullable Object = 1 +var ob: nullable Object = true +var of: nullable Object = 1u8 + + +(i.is_same_instance(i)).output +(b.is_same_instance(i)).output +(f.is_same_instance(i)).output + +'\n'.output + +(i.is_same_instance(ni)).output +(b.is_same_instance(ni)).output +(f.is_same_instance(ni)).output + +'\n'.output + +(i.is_same_instance(oi)).output +(b.is_same_instance(oi)).output +(f.is_same_instance(oi)).output + +'\n'.output +'\n'.output + +(ni.is_same_instance(i)).output +(nb.is_same_instance(i)).output +(nf.is_same_instance(i)).output + +'\n'.output + +(ni.is_same_instance(ni)).output +(nb.is_same_instance(ni)).output +(nf.is_same_instance(ni)).output + +'\n'.output + +(ni.is_same_instance(oi)).output +(nb.is_same_instance(oi)).output +(nf.is_same_instance(oi)).output + +'\n'.output +'\n'.output + +(oi.is_same_instance(i)).output +(ob.is_same_instance(i)).output +(of.is_same_instance(i)).output + +'\n'.output + +(oi.is_same_instance(ni)).output +(ob.is_same_instance(ni)).output +(of.is_same_instance(ni)).output + +'\n'.output + +(oi.is_same_instance(oi)).output +(ob.is_same_instance(oi)).output +(of.is_same_instance(oi)).output + +'\n'.output +'\n'.output +'\n'.output + +(i.is_same_instance(b)).output +(b.is_same_instance(b)).output +(f.is_same_instance(b)).output + +'\n'.output + +(i.is_same_instance(nb)).output +(b.is_same_instance(nb)).output +(f.is_same_instance(nb)).output + +'\n'.output + +(i.is_same_instance(ob)).output +(b.is_same_instance(ob)).output +(f.is_same_instance(ob)).output + +'\n'.output +'\n'.output + +(ni.is_same_instance(b)).output +(nb.is_same_instance(b)).output +(nf.is_same_instance(b)).output + +'\n'.output + +(ni.is_same_instance(nb)).output +(nb.is_same_instance(nb)).output +(nf.is_same_instance(nb)).output + +'\n'.output + +(ni.is_same_instance(ob)).output +(nb.is_same_instance(ob)).output +(nf.is_same_instance(ob)).output + +'\n'.output +'\n'.output + +(oi.is_same_instance(b)).output +(ob.is_same_instance(b)).output +(of.is_same_instance(b)).output + +'\n'.output + +(oi.is_same_instance(nb)).output +(ob.is_same_instance(nb)).output +(of.is_same_instance(nb)).output + +'\n'.output + +(oi.is_same_instance(ob)).output +(ob.is_same_instance(ob)).output +(of.is_same_instance(ob)).output + +'\n'.output +'\n'.output +'\n'.output + +(i.is_same_instance(f)).output +(b.is_same_instance(f)).output +(f.is_same_instance(f)).output + +'\n'.output + +(i.is_same_instance(nf)).output +(b.is_same_instance(nf)).output +(f.is_same_instance(nf)).output + +'\n'.output + +(i.is_same_instance(of)).output +(b.is_same_instance(of)).output +(f.is_same_instance(of)).output + +'\n'.output +'\n'.output + +(ni.is_same_instance(f)).output +(nb.is_same_instance(f)).output +(nf.is_same_instance(f)).output + +'\n'.output + +(ni.is_same_instance(nf)).output +(nb.is_same_instance(nf)).output +(nf.is_same_instance(nf)).output + +'\n'.output + +(ni.is_same_instance(of)).output +(nb.is_same_instance(of)).output +(nf.is_same_instance(of)).output + +'\n'.output +'\n'.output + +(oi.is_same_instance(f)).output +(ob.is_same_instance(f)).output +(of.is_same_instance(f)).output + +'\n'.output + +(oi.is_same_instance(nf)).output +(ob.is_same_instance(nf)).output +(of.is_same_instance(nf)).output + +'\n'.output + +(oi.is_same_instance(of)).output +(ob.is_same_instance(of)).output +(of.is_same_instance(of)).output diff --git a/tests/base_eq_int4c.nit b/tests/base_eq_int4c.nit new file mode 100644 index 0000000..89e2882 --- /dev/null +++ b/tests/base_eq_int4c.nit @@ -0,0 +1,196 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import kernel + +var i = 1 +var b = true +var f = 1u8 +var ni: Int = 0 +var nb: Bool = false +var nf: Byte = 0u8 +var oi: Object = 1 +var ob: Object = true +var of: Object = 1u8 + + +(i.is_same_type(i)).output +(b.is_same_type(i)).output +(f.is_same_type(i)).output + +'\n'.output + +(i.is_same_type(ni)).output +(b.is_same_type(ni)).output +(f.is_same_type(ni)).output + +'\n'.output + +(i.is_same_type(oi)).output +(b.is_same_type(oi)).output +(f.is_same_type(oi)).output + +'\n'.output +'\n'.output + +(ni.is_same_type(i)).output +(nb.is_same_type(i)).output +(nf.is_same_type(i)).output + +'\n'.output + +(ni.is_same_type(ni)).output +(nb.is_same_type(ni)).output +(nf.is_same_type(ni)).output + +'\n'.output + +(ni.is_same_type(oi)).output +(nb.is_same_type(oi)).output +(nf.is_same_type(oi)).output + +'\n'.output +'\n'.output + +(oi.is_same_type(i)).output +(ob.is_same_type(i)).output +(of.is_same_type(i)).output + +'\n'.output + +(oi.is_same_type(ni)).output +(ob.is_same_type(ni)).output +(of.is_same_type(ni)).output + +'\n'.output + +(oi.is_same_type(oi)).output +(ob.is_same_type(oi)).output +(of.is_same_type(oi)).output + +'\n'.output +'\n'.output +'\n'.output + +(i.is_same_type(b)).output +(b.is_same_type(b)).output +(f.is_same_type(b)).output + +'\n'.output + +(i.is_same_type(nb)).output +(b.is_same_type(nb)).output +(f.is_same_type(nb)).output + +'\n'.output + +(i.is_same_type(ob)).output +(b.is_same_type(ob)).output +(f.is_same_type(ob)).output + +'\n'.output +'\n'.output + +(ni.is_same_type(b)).output +(nb.is_same_type(b)).output +(nf.is_same_type(b)).output + +'\n'.output + +(ni.is_same_type(nb)).output +(nb.is_same_type(nb)).output +(nf.is_same_type(nb)).output + +'\n'.output + +(ni.is_same_type(ob)).output +(nb.is_same_type(ob)).output +(nf.is_same_type(ob)).output + +'\n'.output +'\n'.output + +(oi.is_same_type(b)).output +(ob.is_same_type(b)).output +(of.is_same_type(b)).output + +'\n'.output + +(oi.is_same_type(nb)).output +(ob.is_same_type(nb)).output +(of.is_same_type(nb)).output + +'\n'.output + +(oi.is_same_type(ob)).output +(ob.is_same_type(ob)).output +(of.is_same_type(ob)).output + +'\n'.output +'\n'.output +'\n'.output + +(i.is_same_type(f)).output +(b.is_same_type(f)).output +(f.is_same_type(f)).output + +'\n'.output + +(i.is_same_type(nf)).output +(b.is_same_type(nf)).output +(f.is_same_type(nf)).output + +'\n'.output + +(i.is_same_type(of)).output +(b.is_same_type(of)).output +(f.is_same_type(of)).output + +'\n'.output +'\n'.output + +(ni.is_same_type(f)).output +(nb.is_same_type(f)).output +(nf.is_same_type(f)).output + +'\n'.output + +(ni.is_same_type(nf)).output +(nb.is_same_type(nf)).output +(nf.is_same_type(nf)).output + +'\n'.output + +(ni.is_same_type(of)).output +(nb.is_same_type(of)).output +(nf.is_same_type(of)).output + +'\n'.output +'\n'.output + +(oi.is_same_type(f)).output +(ob.is_same_type(f)).output +(of.is_same_type(f)).output + +'\n'.output + +(oi.is_same_type(nf)).output +(ob.is_same_type(nf)).output +(of.is_same_type(nf)).output + +'\n'.output + +(oi.is_same_type(of)).output +(ob.is_same_type(of)).output +(of.is_same_type(of)).output diff --git a/tests/base_primitive_null.nit b/tests/base_primitive_null.nit index 2ba5388..130d8fd 100644 --- a/tests/base_primitive_null.nit +++ b/tests/base_primitive_null.nit @@ -49,7 +49,7 @@ class A o = _c (o == null).output (not o == '\0').output - #alt3#_c.ascii.output + #alt3#_c.code_point.output end end diff --git a/tests/sav/base_eq_int4.res b/tests/sav/base_eq_int4.res new file mode 100644 index 0000000..cf1d59c --- /dev/null +++ b/tests/sav/base_eq_int4.res @@ -0,0 +1,117 @@ +true +false +false + +true +false +false + +true +false +false + + +true +false +false + +true +false +false + +true +false +false + + +true +false +false + +true +false +false + +true +false +false + + + +false +true +false + +false +true +false + +false +true +false + + +false +true +false + +false +true +false + +false +true +false + + +false +true +false + +false +true +false + +false +true +false + + + +false +false +true + +false +false +true + +false +false +true + + +false +false +true + +false +false +true + +false +false +true + + +false +false +true + +false +false +true + +false +false +true diff --git a/tests/sav/base_eq_int4b.res b/tests/sav/base_eq_int4b.res new file mode 100644 index 0000000..cf1d59c --- /dev/null +++ b/tests/sav/base_eq_int4b.res @@ -0,0 +1,117 @@ +true +false +false + +true +false +false + +true +false +false + + +true +false +false + +true +false +false + +true +false +false + + +true +false +false + +true +false +false + +true +false +false + + + +false +true +false + +false +true +false + +false +true +false + + +false +true +false + +false +true +false + +false +true +false + + +false +true +false + +false +true +false + +false +true +false + + + +false +false +true + +false +false +true + +false +false +true + + +false +false +true + +false +false +true + +false +false +true + + +false +false +true + +false +false +true + +false +false +true diff --git a/tests/sav/base_eq_int4c.res b/tests/sav/base_eq_int4c.res new file mode 100644 index 0000000..cf1d59c --- /dev/null +++ b/tests/sav/base_eq_int4c.res @@ -0,0 +1,117 @@ +true +false +false + +true +false +false + +true +false +false + + +true +false +false + +true +false +false + +true +false +false + + +true +false +false + +true +false +false + +true +false +false + + + +false +true +false + +false +true +false + +false +true +false + + +false +true +false + +false +true +false + +false +true +false + + +false +true +false + +false +true +false + +false +true +false + + + +false +false +true + +false +false +true + +false +false +true + + +false +false +true + +false +false +true + +false +false +true + + +false +false +true + +false +false +true + +false +false +true diff --git a/tests/sav/error_class_glob.res b/tests/sav/error_class_glob.res index b41f1d6..3d8ae36 100644 --- a/tests/sav/error_class_glob.res +++ b/tests/sav/error_class_glob.res @@ -6,7 +6,7 @@ ../lib/core/kernel.nit:431,1--486,3: Error: `kernel#Numeric` does not specialize `module_0#Object`. Possible duplication of the root class `Object`? ../lib/core/kernel.nit:492,1--515,3: Error: `kernel#Bool` does not specialize `module_0#Object`. Possible duplication of the root class `Object`? ../lib/core/kernel.nit:517,1--599,3: Error: `kernel#Float` does not specialize `module_0#Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:601,1--697,3: Error: `kernel#Byte` does not specialize `module_0#Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:699,1--884,3: Error: `kernel#Int` does not specialize `module_0#Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:886,1--1039,3: Error: `kernel#Char` does not specialize `module_0#Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:1041,1--1048,3: Error: `kernel#Pointer` does not specialize `module_0#Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:601,1--702,3: Error: `kernel#Byte` does not specialize `module_0#Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:704,1--890,3: Error: `kernel#Int` does not specialize `module_0#Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:892,1--1060,3: Error: `kernel#Char` does not specialize `module_0#Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:1062,1--1069,3: Error: `kernel#Pointer` does not specialize `module_0#Object`. Possible duplication of the root class `Object`? diff --git a/tests/sav/nitce/fixme/base_gen_reassign_alt4.res b/tests/sav/nitce/fixme/base_gen_reassign_alt4.res index 8e5869f..d556892 100644 --- a/tests/sav/nitce/fixme/base_gen_reassign_alt4.res +++ b/tests/sav/nitce/fixme/base_gen_reassign_alt4.res @@ -1,4 +1,4 @@ -Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:720) +Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:725) 11 21 31 diff --git a/tests/sav/nitce/fixme/base_gen_reassign_alt5.res b/tests/sav/nitce/fixme/base_gen_reassign_alt5.res index 8e5869f..d556892 100644 --- a/tests/sav/nitce/fixme/base_gen_reassign_alt5.res +++ b/tests/sav/nitce/fixme/base_gen_reassign_alt5.res @@ -1,4 +1,4 @@ -Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:720) +Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:725) 11 21 31 diff --git a/tests/sav/nitce/fixme/base_gen_reassign_alt6.res b/tests/sav/nitce/fixme/base_gen_reassign_alt6.res index 8e5869f..d556892 100644 --- a/tests/sav/nitce/fixme/base_gen_reassign_alt6.res +++ b/tests/sav/nitce/fixme/base_gen_reassign_alt6.res @@ -1,4 +1,4 @@ -Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:720) +Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:725) 11 21 31 diff --git a/tests/sav/nituml_args3.res b/tests/sav/nituml_args3.res index 6584bce..700f951 100644 --- a/tests/sav/nituml_args3.res +++ b/tests/sav/nituml_args3.res @@ -51,19 +51,19 @@ Float [ Numeric -> Float [dir=back arrowtail=open style=dashed]; Byte [ - label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l}" + label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l+ ascii(): Char\l}" ] Discrete -> Byte [dir=back arrowtail=open style=dashed]; Numeric -> Byte [dir=back arrowtail=open style=dashed]; Int [ - label = "{Int||+ %(i: Int): Int\l+ \<\<(i: Int): Int\l+ \>\>(i: Int): Int\l+ ascii(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l}" + label = "{Int||+ %(i: Int): Int\l+ \<\<(i: Int): Int\l+ \>\>(i: Int): Int\l+ code_point(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l}" ] Discrete -> Int [dir=back arrowtail=open style=dashed]; Numeric -> Int [dir=back arrowtail=open style=dashed]; Char [ - label = "{Char||+ to_i(): Int\l+ ascii(): Int\l+ to_lower(): Char\l+ to_upper(): Char\l+ is_digit(): Bool\l+ is_lower(): Bool\l+ is_upper(): Bool\l+ is_letter(): Bool\l+ is_whitespace(): Bool\l}" + label = "{Char||+ to_i(): Int\l+ ascii(): Byte\l+ code_point(): Int\l+ is_ascii(): Bool\l+ to_lower(): Char\l+ to_upper(): Char\l+ is_digit(): Bool\l+ is_lower(): Bool\l+ is_upper(): Bool\l+ is_letter(): Bool\l+ is_whitespace(): Bool\l}" ] Discrete -> Char [dir=back arrowtail=open style=dashed]; diff --git a/tests/sav/nituml_args4.res b/tests/sav/nituml_args4.res index 90afcec..f01534c 100644 --- a/tests/sav/nituml_args4.res +++ b/tests/sav/nituml_args4.res @@ -51,19 +51,19 @@ Float [ Numeric -> Float [dir=back arrowtail=open style=dashed]; Byte [ - label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l}" + label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l+ ascii(): Char\l}" ] Discrete -> Byte [dir=back arrowtail=open style=dashed]; Numeric -> Byte [dir=back arrowtail=open style=dashed]; Int [ - label = "{Int||+ %(i: Int): Int\l+ \<\<(i: Int): Int\l+ \>\>(i: Int): Int\l+ ascii(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l}" + label = "{Int||+ %(i: Int): Int\l+ \<\<(i: Int): Int\l+ \>\>(i: Int): Int\l+ code_point(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l}" ] Discrete -> Int [dir=back arrowtail=open style=dashed]; Numeric -> Int [dir=back arrowtail=open style=dashed]; Char [ - label = "{Char||+ to_i(): Int\l+ ascii(): Int\l+ to_lower(): Char\l+ to_upper(): Char\l+ is_digit(): Bool\l+ is_lower(): Bool\l+ is_upper(): Bool\l+ is_letter(): Bool\l+ is_whitespace(): Bool\l}" + label = "{Char||+ to_i(): Int\l+ ascii(): Byte\l+ code_point(): Int\l+ is_ascii(): Bool\l+ to_lower(): Char\l+ to_upper(): Char\l+ is_digit(): Bool\l+ is_lower(): Bool\l+ is_upper(): Bool\l+ is_letter(): Bool\l+ is_whitespace(): Bool\l}" ] Discrete -> Char [dir=back arrowtail=open style=dashed]; diff --git a/tests/test_string_unicode.nit b/tests/test_string_unicode.nit index 9dee4a7..4b09f4d 100644 --- a/tests/test_string_unicode.nit +++ b/tests/test_string_unicode.nit @@ -17,5 +17,5 @@ var a = "éè" print(a.length) for i in [0..a.length[ do - print("{i} is {a.chars[i]} ({a.chars[i].ascii})") + print("{i} is {a.chars[i]} ({a.chars[i].code_point})") end diff --git a/tests/test_unicode_4bytes.nit b/tests/test_unicode_4bytes.nit index de412ac..3739f9c 100644 --- a/tests/test_unicode_4bytes.nit +++ b/tests/test_unicode_4bytes.nit @@ -16,5 +16,5 @@ intrude import core::text::flat import core var s = "𐏓􏿿".as(FlatString) -print s.items.char_at(0).ascii.to_hex -print s.items.char_at(4).ascii.to_hex +print s.items.char_at(0).code_point.to_hex +print s.items.char_at(4).code_point.to_hex