Merge: Basename fix
authorJean Privat <jean@pryen.org>
Mon, 28 Sep 2015 14:42:57 +0000 (10:42 -0400)
committerJean Privat <jean@pryen.org>
Mon, 28 Sep 2015 14:42:57 +0000 (10:42 -0400)
Should close #1736 if performances are adequate for @privat.

This PR optimizes some methods in both `SequenceRead` and `FlatString`, on the test program exposed in #1736, the valgrind runtime has gone from 418,872,526 Ir to 136,522,095 Ir (~67.5% improvement)

Some more improvements could be observed if we could get rid of some useless Boxes in `NativeString::to_s_with_copy` because of a `is_same_instance` which boxes NativeStrings (24k allocations in total to remove).

Pull-Request: #1740
Reviewed-by: Jean Privat <jean@pryen.org>

26 files changed:
contrib/memory/Makefile
contrib/memory/org.nitlanguage.memory.txt
contrib/memory/package.ini
contrib/memory/src/memory.nit
contrib/mnit_test/package.ini
contrib/nitcc/tests/packages.ini [moved from contrib/nitcc/tests/package.ini with 100% similarity]
examples/draw_operation.ini
examples/mnit_ballz/org.nitlanguage.ballz.txt [moved from examples/mnit_ballz/org.nitlanguage.ballz_android.txt with 100% similarity]
lib/core/collection/abstract_collection.nit
lib/core/stream.nit
lib/gamnit/examples/triangle/src/portable_triangle.nit
lib/gamnit/examples/triangle/src/standalone_triangle.nit
lib/gen_nit.ini [new file with mode: 0644]
lib/glesv2/.gitignore [new file with mode: 0644]
lib/glesv2/Makefile [new file with mode: 0644]
lib/glesv2/examples/opengles2_hello_triangle.nit
lib/glesv2/glesv2.nit
lib/ordered_tree.nit
lib/text_stat.ini [new file with mode: 0644]
misc/vim/syntax/nit.vim
src/loader.nit
tests/sav/nitls_args1.res
tests/sav/nitls_args2.res
tests/sav/nitls_args4.res
tests/sav/test_with.res [new file with mode: 0644]
tests/test_with.nit [new file with mode: 0644]

index 8e39e1d..ac91a73 100644 (file)
@@ -33,4 +33,4 @@ bin/memory.apk: assets/images/drawing.png src/*.nit res/drawable-ldpi/icon.png
 
 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
+       ../../bin/nitc -o bin/memory.apk src/memory.nit -m ../../lib/mnit/android/android.nit -m ../../lib/android/landscape.nit  --release
index 1bef17b..77756da 100644 (file)
@@ -4,7 +4,7 @@ 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
+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.
index d271a73..9a79f36 100644 (file)
@@ -9,3 +9,4 @@ git=https://github.com/nitlang/nit.git
 git.directory=contrib/memory/
 homepage=http://nitlanguage.org
 issues=https://github.com/nitlang/nit/issues
+apk=http://nitlanguage.org/fdroid/apk/memory.apk
index 3e9877d..e184b99 100644 (file)
@@ -27,6 +27,7 @@
 # * Crappy UI element placement
 module memory is
        app_name("Memorize Shapes and Colors")
+       app_namespace "org.nitlanguage.memory"
        app_version(0, 1, git_revision)
 end
 
index adcdf8f..5247640 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name=mnit_test
-tags=
+tags=testing
 maintainer=Alexis Laferrière <alexis.laf@xymus.net>
 license=Apache-2.0
 [upstream]
index 189e88d..4ae4096 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name=draw_operation
-tags=
+tags=example
 maintainer=Alexis Laferrière <alexis.laf@xymus.net>
 license=Apache-2.0
 [upstream]
index b65db67..6b07149 100644 (file)
@@ -228,6 +228,16 @@ interface Iterator[E]
        # Iterate over `self`
        fun iterator: Iterator[E] do return self
 
+       # Pre-iteration hook.
+       #
+       # Used to inform `self` that the iteration is starting.
+       # Specific iterators can use this to prepare some resources.
+       #
+       # Is automatically invoked at the beginning of `for` structures.
+       #
+       # Do nothing by default.
+       fun start do end
+
        # Post-iteration hook.
        #
        # Used to inform `self` that the iteration is over.
@@ -708,6 +718,16 @@ interface MapIterator[K, V]
        # Set a new `item` at `key`.
        #fun item=(item: E) is abstract
 
+       # Pre-iteration hook.
+       #
+       # Used to inform `self` that the iteration is starting.
+       # Specific iterators can use this to prepare some resources.
+       #
+       # Is automatically invoked at the beginning of `for` structures.
+       #
+       # Do nothing by default.
+       fun start do end
+
        # Post-iteration hook.
        #
        # Used to inform `self` that the iteration is over.
index b4a0e2b..e8cb232 100644 (file)
@@ -39,6 +39,26 @@ abstract class Stream
 
        # close the stream
        fun close is abstract
+
+       # Pre-work hook.
+       #
+       # Used to inform `self` that operations will start.
+       # Specific streams can use this to prepare some resources.
+       #
+       # Is automatically invoked at the beginning of `with` structures.
+       #
+       # Do nothing by default.
+       fun start do end
+
+       # Post-work hook.
+       #
+       # Used to inform `self` that the operations are over.
+       # Specific streams can use this to free some resources.
+       #
+       # Is automatically invoked at the end of `woth` structures.
+       #
+       # call `close` by default.
+       fun finish do close
 end
 
 # A `Stream` that can be read from
@@ -425,6 +445,13 @@ interface Writable
        end
 end
 
+redef class Bytes
+       super Writable
+       redef fun write_to(s) do s.write_bytes(self)
+
+       redef fun write_to_string do return to_s
+end
+
 redef class Text
        super Writable
        redef fun write_to(stream) do stream.write(self)
index ac8e0e6..624ec47 100644 (file)
@@ -20,7 +20,7 @@
 module portable_triangle is
        app_name "gamnit Triangle"
        app_namespace "org.nitlanguage.triangle"
-       app_version(1, 0, git_revision)
+       app_version(1, 1, git_revision)
 end
 
 import gamnit
@@ -54,8 +54,8 @@ redef class App
 
                # GL program
                program = new GLProgram
-               if not program.is_ok then
-                       print "Program is not ok: {gl.error.to_s}\nLog:"
+               if not glIsProgram(program) then
+                       print "Program is not ok: {glGetError.to_s}\nLog:"
                        print program.info_log
                        abort
                end
@@ -63,37 +63,37 @@ redef class App
 
                # Vertex shader
                vertex_shader = new GLVertexShader
-               assert vertex_shader.is_ok else print "Vertex shader is not ok: {gl.error}"
-               vertex_shader.source = """
+               assert glIsShader(vertex_shader) else print "Vertex shader is not ok: {glGetError}"
+               glShaderSource(vertex_shader, """
                attribute vec4 vPosition;
                void main()
                {
                  gl_Position = vPosition;
                }
-               """@glsl_vertex_shader.to_cstring
-               vertex_shader.compile
+               """@glsl_vertex_shader.to_cstring)
+               glCompileShader(vertex_shader)
                assert vertex_shader.is_compiled else print "Vertex shader compilation failed with: {vertex_shader.info_log} {program.info_log}"
                assert_no_gl_error
 
                # Fragment shader
                fragment_shader = new GLFragmentShader
-               assert fragment_shader.is_ok else print "Fragment shader is not ok: {gl.error}"
-               fragment_shader.source = """
+               assert glIsShader(fragment_shader) else print "Fragment shader is not ok: {glGetError}"
+               glShaderSource(fragment_shader, """
                precision mediump float;
                void main()
                {
                        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
                }
-               """@glsl_fragment_shader.to_cstring
-               fragment_shader.compile
+               """@glsl_fragment_shader.to_cstring)
+               glCompileShader(fragment_shader)
                assert fragment_shader.is_compiled else print "Fragment shader compilation failed with: {fragment_shader.info_log}"
                assert_no_gl_error
 
                # Attach to program
-               program.attach_shader vertex_shader
-               program.attach_shader fragment_shader
+               glAttachShader(program, vertex_shader)
+               glAttachShader(program, fragment_shader)
                program.bind_attrib_location(0, "vPosition")
-               program.link
+               glLinkProgram program
                assert program.is_linked else print "Linking failed: {program.info_log}"
                assert_no_gl_error
 
@@ -103,30 +103,35 @@ redef class App
                vertex_array.attrib_pointer
        end
 
+       private var t = 0.0
+
        redef fun frame_core
        do
                var display = display
                if display != null then
-                       gl.clear_color(0.5, 0.0, 0.5, 1.0)
+                       glClearColor(t, t, t, 1.0)
 
                        assert_no_gl_error
-                       gl.viewport(0, 0, display.width, display.height)
-                       gl.clear((new GLBuffer).color)
-                       program.use
+                       glViewport(0, 0, display.width, display.height)
+                       glClear gl_COLOR_BUFFER_BIT
+                       glUseProgram program
                        vertex_array.enable
 
-                       glDrawArrays(new GLDrawMode.triangles, 0, 3)
+                       glDrawArrays(gl_TRIANGLES, 0, 3)
 
                        display.flip
+
+                       t += 0.01
+                       if t > 1.0 then t = 0.0
                end
        end
 
        redef fun on_stop
        do
                # Clean up
-               program.delete
-               vertex_shader.delete
-               fragment_shader.delete
+               glDeleteProgram program
+               glDeleteShader vertex_shader
+               glDeleteShader fragment_shader
 
                # Close gamnit
                var display = display
index 04e14db..209597f 100644 (file)
@@ -40,10 +40,10 @@ assert_no_gl_error
 assert gl.shader_compiler else print "Cannot compile shaders"
 
 # GL program
-print gl.error.to_s
+print glGetError.to_s
 var program = new GLProgram
-if not program.is_ok then
-       print "Program is not ok: {gl.error.to_s}\nLog:"
+if not glIsProgram(program) then
+       print "Program is not ok: {glGetError.to_s}\nLog:"
        print program.info_log
        abort
 end
@@ -51,37 +51,37 @@ assert_no_gl_error
 
 # Vertex shader
 var vertex_shader = new GLVertexShader
-assert vertex_shader.is_ok else print "Vertex shader is not ok: {gl.error}"
-vertex_shader.source = """
+assert glIsShader(vertex_shader) else print "Vertex shader is not ok: {glGetError}"
+glShaderSource(vertex_shader, """
 attribute vec4 vPosition;
 void main()
 {
   gl_Position = vPosition;
 }
-"""@glsl_vertex_shader.to_cstring
-vertex_shader.compile
+"""@glsl_vertex_shader.to_cstring)
+glCompileShader vertex_shader
 assert vertex_shader.is_compiled else print "Vertex shader compilation failed with: {vertex_shader.info_log} {program.info_log}"
 assert_no_gl_error
 
 # Fragment shader
 var fragment_shader = new GLFragmentShader
-assert fragment_shader.is_ok else print "Fragment shader is not ok: {gl.error}"
-fragment_shader.source = """
+assert glIsShader(fragment_shader) else print "Fragment shader is not ok: {glGetError}"
+glShaderSource(fragment_shader, """
 precision mediump float;
 void main()
 {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
 }
-"""@glsl_fragment_shader.to_cstring
-fragment_shader.compile
+"""@glsl_fragment_shader.to_cstring)
+glIsShader fragment_shader
 assert fragment_shader.is_compiled else print "Fragment shader compilation failed with: {fragment_shader.info_log}"
 assert_no_gl_error
 
 # Attach to program
-program.attach_shader vertex_shader
-program.attach_shader fragment_shader
+glAttachShader(program, vertex_shader)
+glAttachShader(program, fragment_shader)
 program.bind_attrib_location(0, "vPosition")
-program.link
+glLinkProgram program
 assert program.is_linked else print "Linking failed: {program.info_log}"
 assert_no_gl_error
 
@@ -89,24 +89,24 @@ assert_no_gl_error
 var vertices = [0.0, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0]
 var vertex_array = new VertexArray(0, 3, vertices)
 vertex_array.attrib_pointer
-gl.clear_color(0.5, 0.0, 0.5, 1.0)
+glClearColor(0.5, 0.0, 0.5, 1.0)
 for i in [0..1000[ do
        printn "."
        assert_no_gl_error
-       gl.viewport(0, 0, width, height)
-       gl.clear((new GLBuffer).color)
-       program.use
+       glViewport(0, 0, width, height)
+       glClear gl_COLOR_BUFFER_BIT
+       glUseProgram program
        vertex_array.enable
 
-       glDrawArrays(new GLDrawMode.triangles, 0, 3)
+       glDrawArrays(gl_TRIANGLES, 0, 3)
 
        display.flip
 end
 
 # Clean up
-program.delete
-vertex_shader.delete
-fragment_shader.delete
+glDeleteProgram program
+glDeleteShader vertex_shader
+glDeleteShader fragment_shader
 
 # Close gamnit
 display.close
diff --git a/lib/gen_nit.ini b/lib/gen_nit.ini
new file mode 100644 (file)
index 0000000..0f1530c
--- /dev/null
@@ -0,0 +1,11 @@
+[package]
+name=gen_nit
+tags=devel
+maintainer=Alexis Laferrière <alexis.laf@xymus.net>
+license=Apache-2.0
+[upstream]
+browse=https://github.com/nitlang/nit/tree/master/lib/gen_nit.nit
+git=https://github.com/nitlang/nit.git
+git.directory=lib/gen_nit.nit
+homepage=http://nitlanguage.org
+issues=https://github.com/nitlang/nit/issues
diff --git a/lib/glesv2/.gitignore b/lib/glesv2/.gitignore
new file mode 100644 (file)
index 0000000..6f7cefe
--- /dev/null
@@ -0,0 +1 @@
+glesv2_stub.nit
diff --git a/lib/glesv2/Makefile b/lib/glesv2/Makefile
new file mode 100644 (file)
index 0000000..df29bb6
--- /dev/null
@@ -0,0 +1,9 @@
+# Generate basic Nit wrapper for glesv2, must be adapted by hands afterwards
+glesv2_stub.nit:
+       cat /usr/include/GLES2/gl2.h | sed \
+               -e "s/GL_APICALL void GL_APIENTRY \([^ ]*\) /fun \1 \`{ \1/" \
+               -e "s/GL_APICALL [^ ]* GL_APIENTRY \([^ ]*\) /fun \1: Int \`{ return \1/" \
+               -e "s/;/; \`}/" \
+               -e "s/#define GL_\([^ ]*\) .*/fun gl_\1: Int \`{ return GL_\1; \`}/" | grep fun > $@
+
+.PHONY: glesv2_stub.nit
index 3a1e1c5..340c307 100644 (file)
@@ -112,10 +112,10 @@ assert_no_gl_error
 assert gl.shader_compiler else print "Cannot compile shaders"
 
 # gl program
-print gl.error.to_s
+print glGetError.to_s
 var program = new GLProgram
-if not program.is_ok then
-       print "Program is not ok: {gl.error.to_s}\nLog:"
+if not glIsProgram(program) then
+       print "Program is not ok: {glGetError.to_s}\nLog:"
        print program.info_log
        abort
 end
@@ -123,36 +123,36 @@ assert_no_gl_error
 
 # vertex shader
 var vertex_shader = new GLVertexShader
-assert vertex_shader.is_ok else print "Vertex shader is not ok: {gl.error}"
-vertex_shader.source = """
+assert glIsShader(vertex_shader) else print "Vertex shader is not ok: {glGetError}"
+glShaderSource(vertex_shader, """
 attribute vec4 vPosition;
 void main()
 {
   gl_Position = vPosition;
 }
-""".to_cstring
-vertex_shader.compile
+""".to_cstring)
+glCompileShader vertex_shader
 assert vertex_shader.is_compiled else print "Vertex shader compilation failed with: {vertex_shader.info_log} {program.info_log}"
 assert_no_gl_error
 
 # fragment shader
 var fragment_shader = new GLFragmentShader
-assert fragment_shader.is_ok else print "Fragment shader is not ok: {gl.error}"
-fragment_shader.source = """
+assert glIsShader(fragment_shader) else print "Fragment shader is not ok: {glGetError}"
+glShaderSource(fragment_shader, """
 precision mediump float;
 void main()
 {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
 }
-""".to_cstring
-fragment_shader.compile
+""".to_cstring)
+glCompileShader(fragment_shader)
 assert fragment_shader.is_compiled else print "Fragment shader compilation failed with: {fragment_shader.info_log}"
 assert_no_gl_error
 
-program.attach_shader vertex_shader
-program.attach_shader fragment_shader
+glAttachShader(program, vertex_shader)
+glAttachShader(program, fragment_shader)
 program.bind_attrib_location(0, "vPosition")
-program.link
+glLinkProgram program
 assert program.is_linked else print "Linking failed: {program.info_log}"
 assert_no_gl_error
 
@@ -160,30 +160,30 @@ assert_no_gl_error
 var vertices = [0.0, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0]
 var vertex_array = new VertexArray(0, 3, vertices)
 vertex_array.attrib_pointer
-gl.clear_color(0.5, 0.0, 0.5, 1.0)
+glClearColor(0.5, 0.0, 0.5, 1.0)
 for i in [0..10000[ do
        printn "."
        assert_no_gl_error
-       gl.viewport(0, 0, width, height)
-       gl.clear((new GLBuffer).color)
-       program.use
+       glViewport(0, 0, width, height)
+       glClear gl_COLOR_BUFFER_BIT
+       glUseProgram program
        vertex_array.enable
-       glDrawArrays(new GLDrawMode.triangles, 0, 3)
+       glDrawArrays(gl_TRIANGLES, 0, 3)
        egl_display.swap_buffers(surface)
 end
 
 # delete
-program.delete
-vertex_shader.delete
-fragment_shader.delete
+glDeleteProgram program
+glDeleteShader vertex_shader
+glDeleteShader fragment_shader
 
 #
 ## EGL
 #
 # close
 egl_display.make_current(new EGLSurface.none, new EGLSurface.none, new EGLContext.none)
-egl_display.destroy_context(context)
-egl_display.destroy_surface(surface)
+egl_display.destroy_context context
+egl_display.destroy_surface surface
 
 #
 ## SDL
index 9c3e1d7..526fc0b 100644 (file)
@@ -50,12 +50,6 @@ extern class GLProgram `{GLuint`}
        # The newly created instance should be checked using `is_ok`.
        new `{ return glCreateProgram(); `}
 
-       # Is this a valid program?
-       fun is_ok: Bool `{ return glIsProgram(self); `}
-
-       # Attach a `shader` to this program
-       fun attach_shader(shader: GLShader) `{ glAttachShader(self, shader); `}
-
        # Set the location for the attribute by `name`
        fun bind_attrib_location(index: Int, name: String) import String.to_cstring `{
                GLchar *c_name = String_to_cstring(name);
@@ -85,28 +79,12 @@ extern class GLProgram `{GLuint`}
                return val;
        `}
 
-       # Try to link this program
-       #
-       # Check result using `in_linked` and `info_log`.
-       fun link `{ glLinkProgram(self); `}
-
        # Is this program linked?
        fun is_linked: Bool do return query(0x8B82) != 0
 
-       # Use this program for the following operations
-       fun use `{ glUseProgram(self); `}
-
-       # Delete this program
-       fun delete `{ glDeleteProgram(self); `}
-
        # Has this program been deleted?
        fun is_deleted: Bool do return query(0x8B80) != 0
 
-       # Validate whether this program can be executed in the current OpenGL state
-       #
-       # Check results using `is_validated` and `info_log`.
-       fun validate `{ glValidateProgram(self); `}
-
        # Boolean result of `validate`, must be called after `validate`
        fun is_validated: Bool do return query(0x8B83) != 0
 
@@ -210,12 +188,32 @@ extern class GLProgram `{GLuint`}
        `}
 end
 
+# Create a program object
+fun glCreateProgram: GLProgram `{ return glCreateProgram(); `}
+
+# Install the `program` as part of current rendering state
+fun glUseProgram(program: GLProgram) `{ glUseProgram(program); `}
+
+# Link the `program` object
+fun glLinkProgram(program: GLProgram) `{ glLinkProgram(program); `}
+
+# Validate the `program` object
+fun glValidateProgram(program: GLProgram) `{ glValidateProgram(program); `}
+
+# Delete the `program` object
+fun glDeleteProgram(program: GLProgram) `{ glDeleteProgram(program); `}
+
+# Determine if `name` corresponds to a program object
+fun glIsProgram(name: GLProgram): Bool `{ return glIsProgram(name); `}
+
+# Attach a `shader` to `program`
+fun glAttachShader(program: GLProgram, shader: GLShader) `{ glAttachShader(program, shader); `}
+
+# Detach `shader` from `program`
+fun glDetachShader(program: GLProgram, shader: GLShader) `{ glDetachShader(program, shader); `}
+
 # Abstract OpenGL ES shader object, implemented by `GLFragmentShader` and `GLVertexShader`
 extern class GLShader `{GLuint`}
-       # Set the source of the shader
-       fun source=(code: NativeString) `{
-               glShaderSource(self, 1, (GLchar const **)&code, NULL);
-       `}
 
        # Source of the shader, if available
        #
@@ -241,23 +239,12 @@ extern class GLShader `{GLuint`}
                return val;
        `}
 
-       # Try to compile `source` into a binary GPU program
-       #
-       # Check the result using `is_compiled` and `info_log`
-       fun compile `{ glCompileShader(self); `}
-
        # Has this shader been compiled?
        fun is_compiled: Bool do return query(0x8B81) != 0
 
-       # Delete this shader
-       fun delete `{ glDeleteShader(self); `}
-
        # Has this shader been deleted?
        fun is_deleted: Bool do return query(0x8B80) != 0
 
-       # Is this a valid shader?
-       fun is_ok: Bool `{ return glIsShader(self); `}
-
        # Retrieve the information log of this shader
        #
        # Useful with `link` and `validate`
@@ -270,6 +257,33 @@ extern class GLShader `{GLuint`}
        `}
 end
 
+# Shader type
+extern class GLShaderType
+       super GLEnum
+end
+
+fun gl_VERTEX_SHADER: GLShaderType `{ return GL_VERTEX_SHADER; `}
+fun gl_FRAGMENT_SHADER: GLShaderType `{ return GL_FRAGMENT_SHADER; `}
+
+# Create a shader object of the `shader_type`
+fun glCreateShader(shader_type: GLShaderType): GLShader `{
+       return glCreateShader(shader_type);
+`}
+
+# Replace the source code in the `shader` object with `code`
+fun glShaderSource(shader: GLShader, code: NativeString) `{
+       glShaderSource(shader, 1, (GLchar const **)&code, NULL);
+`}
+
+# Compile the `shader` object
+fun glCompileShader(shader: GLShader) `{ glCompileShader(shader); `}
+
+# Delete the `shader` object
+fun glDeleteShader(shader: GLShader) `{ glDeleteShader(shader); `}
+
+# Determine if `name` corresponds to a shader object
+fun glIsShader(name: GLShader): Bool `{ return glIsShader(name); `}
+
 # An OpenGL ES 2.0 fragment shader
 extern class GLFragmentShader
        super GLShader
@@ -407,48 +421,119 @@ extern class GLEnum `{ GLenum `}
        redef fun ==(o) do return o != null and is_same_type(o) and o.hash == self.hash
 end
 
+# Error information
+fun glGetError: GLError `{ return glGetError(); `}
+
 # An OpenGL ES 2.0 error code
 extern class GLError
        super GLEnum
 
-       # Is there no error?
-       fun is_ok: Bool do return is_no_error
-
-       # Is this not an error?
-       fun is_no_error: Bool `{ return self == GL_NO_ERROR; `}
-
-       fun is_invalid_enum: Bool `{ return self == GL_INVALID_ENUM; `}
-       fun is_invalid_value: Bool `{ return self == GL_INVALID_VALUE; `}
-       fun is_invalid_operation: Bool `{ return self == GL_INVALID_OPERATION; `}
-       fun is_invalid_framebuffer_operation: Bool `{ return self == GL_INVALID_FRAMEBUFFER_OPERATION; `}
-       fun is_out_of_memory: Bool `{ return self == GL_OUT_OF_MEMORY; `}
-
        redef fun to_s
        do
-               if is_no_error then return "No error"
-               if is_invalid_enum then return "Invalid enum"
-               if is_invalid_value then return "Invalid value"
-               if is_invalid_operation then return "Invalid operation"
-               if is_invalid_framebuffer_operation then return "invalid framebuffer operation"
-               if is_out_of_memory then return "Out of memory"
-               return "Truely unknown error"
+               if self == gl_NO_ERROR then return "No error"
+               if self == gl_INVALID_ENUM then return "Invalid enum"
+               if self == gl_INVALID_VALUE then return "Invalid value"
+               if self == gl_INVALID_OPERATION then return "Invalid operation"
+               if self == gl_INVALID_FRAMEBUFFER_OPERATION then return "invalid framebuffer operation"
+               if self == gl_OUT_OF_MEMORY then return "Out of memory"
+               return "Unknown error"
        end
 end
 
+fun gl_NO_ERROR: GLError `{ return GL_NO_ERROR; `}
+fun gl_INVALID_ENUM: GLError `{ return GL_INVALID_ENUM; `}
+fun gl_INVALID_VALUE: GLError `{ return GL_INVALID_VALUE; `}
+fun gl_INVALID_OPERATION: GLError `{ return GL_INVALID_OPERATION; `}
+fun gl_INVALID_FRAMEBUFFER_OPERATION: GLError `{ return GL_INVALID_FRAMEBUFFER_OPERATION; `}
+fun gl_OUT_OF_MEMORY: GLError `{ return GL_OUT_OF_MEMORY; `}
+
 fun assert_no_gl_error
 do
-       var error = gl.error
-       if not error.is_ok then
+       var error = glGetError
+       if not error == gl_NO_ERROR then
                print "GL error: {error}"
                abort
        end
 end
 
-# Does `name` corresponds to a texture?
-fun glIsTexture(name: Int): Bool `{ return glIsTexture(name); `}
+# Texture unit, the number of texture units is implementation dependent
+extern class GLTextureUnit
+       super GLEnum
+end
+
+fun gl_TEXTURE0: GLTextureUnit `{ return GL_TEXTURE0; `}
+fun gl_TEXTURE1: GLTextureUnit `{ return GL_TEXTURE1; `}
+fun gl_TEXTURE2: GLTextureUnit `{ return GL_TEXTURE2; `}
+fun gl_TEXTURE3: GLTextureUnit `{ return GL_TEXTURE3; `}
+fun gl_TEXTURE4: GLTextureUnit `{ return GL_TEXTURE4; `}
+fun gl_TEXTURE5: GLTextureUnit `{ return GL_TEXTURE5; `}
+fun gl_TEXTURE6: GLTextureUnit `{ return GL_TEXTURE6; `}
+fun gl_TEXTURE7: GLTextureUnit `{ return GL_TEXTURE7; `}
+fun gl_TEXTURE8: GLTextureUnit `{ return GL_TEXTURE8; `}
+fun gl_TEXTURE9: GLTextureUnit `{ return GL_TEXTURE9; `}
+fun gl_TEXTURE10: GLTextureUnit `{ return GL_TEXTURE10; `}
+fun gl_TEXTURE11: GLTextureUnit `{ return GL_TEXTURE11; `}
+fun gl_TEXTURE12: GLTextureUnit `{ return GL_TEXTURE12; `}
+fun gl_TEXTURE13: GLTextureUnit `{ return GL_TEXTURE13; `}
+fun gl_TEXTURE14: GLTextureUnit `{ return GL_TEXTURE14; `}
+fun gl_TEXTURE15: GLTextureUnit `{ return GL_TEXTURE15; `}
+fun gl_TEXTURE16: GLTextureUnit `{ return GL_TEXTURE16; `}
+fun gl_TEXTURE17: GLTextureUnit `{ return GL_TEXTURE17; `}
+fun gl_TEXTURE18: GLTextureUnit `{ return GL_TEXTURE18; `}
+fun gl_TEXTURE19: GLTextureUnit `{ return GL_TEXTURE19; `}
+fun gl_TEXTURE20: GLTextureUnit `{ return GL_TEXTURE20; `}
+fun gl_TEXTURE21: GLTextureUnit `{ return GL_TEXTURE21; `}
+fun gl_TEXTURE22: GLTextureUnit `{ return GL_TEXTURE22; `}
+fun gl_TEXTURE23: GLTextureUnit `{ return GL_TEXTURE23; `}
+fun gl_TEXTURE24: GLTextureUnit `{ return GL_TEXTURE24; `}
+fun gl_TEXTURE25: GLTextureUnit `{ return GL_TEXTURE25; `}
+fun gl_TEXTURE26: GLTextureUnit `{ return GL_TEXTURE26; `}
+fun gl_TEXTURE27: GLTextureUnit `{ return GL_TEXTURE27; `}
+fun gl_TEXTURE28: GLTextureUnit `{ return GL_TEXTURE28; `}
+fun gl_TEXTURE29: GLTextureUnit `{ return GL_TEXTURE29; `}
+fun gl_TEXTURE30: GLTextureUnit `{ return GL_TEXTURE30; `}
+fun gl_TEXTURE31: GLTextureUnit `{ return GL_TEXTURE31; `}
+
+# Texture unit at `offset` after `gl_TEXTURE0`
+fun gl_TEXTURE(offset: Int): GLTextureUnit `{ return GL_TEXTURE0 + offset; `}
+
+# Generate `n` texture names
+fun glGenTextures(n: Int): Array[Int]
+do
+       var array = new CIntArray(n)
+       native_glGenTextures(n, array.native_array)
+       var a = array.to_a
+       array.destroy
+       return a
+end
+
+private fun native_glGenTextures(n: Int, textures: NativeCIntArray) `{
+       glGenTextures(n, (GLuint*)textures);
+`}
+
+# Select server-side active texture unit
+fun glActiveTexture(texture: GLTextureUnit) `{ glActiveTexture(texture); `}
 
 # Bind the named `texture` to a `target`
-fun glBindTexture(target: GLTextureTarget, texture: Int) `{ glBindTexture(target, texture); `}
+fun glBindTexture(target: GLTextureTarget, texture: Int) `{
+       glBindTexture(target, texture);
+`}
+
+# Delete named textures
+fun glDeleteTextures(textures: SequenceRead[Int])
+do
+       var n = textures.length
+       var array = new CIntArray.from(textures)
+       native_glDeleteTextures(n, array.native_array)
+       array.destroy
+end
+
+private fun native_glDeleteTextures(n: Int, textures: NativeCIntArray) `{
+       glDeleteTextures(n, (const GLuint *)textures);
+`}
+
+# Does `name` corresponds to a texture?
+fun glIsTexture(name: Int): Bool `{ return glIsTexture(name); `}
 
 # Set pixel storage modes
 fun glPixelStorei(parameter: GLPack, val: Int) `{ glPixelStorei(parameter, val); `}
@@ -468,34 +553,50 @@ fun gl_UNPACK_ALIGNEMENT: GLPack `{ return GL_UNPACK_ALIGNMENT; `}
 # GL_UNPACK_ROW_LENGTH, GL_UNPACK_IMAGE_HEIGHT, GL_UNPACK_SKIP_PIXELS, GL_UNPACK_SKIP_ROWS, GL_UNPACK_SKIP_IMAGES
 
 # Specify a two-dimensional texture image
-fun glTexImage2D(target: GLTextureTarget, level, internalformat, width, height, border: Int,
-                 format: GLPixelFormat, typ: GLPixelType, data: NativeCByteArray) `{
+fun glTexImage2D(target: GLTextureTarget, level: Int, internalformat: GLPixelFormat,
+                 width, height, border: Int,
+                 format: GLPixelFormat, typ: GLPixelType, data: Pointer) `{
        glTexImage2D(target, level, internalformat, width, height, border, format, typ, data);
 `}
 
-# Texture minifying and magnifying function
-extern class GLTextureFilter
-       super GLEnum
-end
+# Specify a two-dimensional texture subimage
+fun glTexSubImage2D(target: GLTextureTarget,
+                    level, xoffset, yoffset, width, height, border: Int,
+                    format: GLPixelFormat, typ: GLPixelType, data: Pointer) `{
+       glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, typ, data);
+`}
 
-fun gl_NEAREST: GLTextureFilter `{ return GL_NEAREST; `}
-fun gl_LINEAR: GLTextureFilter `{ return GL_LINEAR; `}
-fun gl_NEAREST_MIPMAP_NEAREST: GLTextureFilter `{ return GL_NEAREST_MIPMAP_NEAREST; `}
-fun gl_LINEAR_MIPMAP_NEAREST: GLTextureFilter `{ return GL_LINEAR_MIPMAP_NEAREST; `}
-fun gl_NEAREST_MIPMAP_NINEAR: GLTextureFilter `{ return GL_NEAREST_MIPMAP_LINEAR; `}
-fun gl_LINEAR_MIPMAP_LINEAR: GLTextureFilter `{ return GL_LINEAR_MIPMAP_LINEAR; `}
+# Copy pixels into a 2D texture image
+fun glCopyTexImage2D(target: GLTextureTarget, level: Int, internalformat: GLPixelFormat,
+                     x, y, width, height, border: Int) `{
+       glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+`}
 
-# Wrap parameter of a texture
-#
-# Used by: `tex_parameter_wrap_*`
-extern class GLTextureWrap
-       super GLEnum
+# Copy a two-dimensional texture subimage
+fun glCopyTexSubImage2D(target: GLTextureTarget, level, xoffset, yoffset, x, y, width, height: Int) `{
+       glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+`}
+
+# Copy a block of pixels from the framebuffer of `fomat` and `typ` at `data`
+fun glReadPixels(x, y, width, height: Int, format: GLPixelFormat, typ: GLPixelType, data: Pointer) `{
+       glReadPixels(x, y, width, height, format, typ, data);
+`}
 
-       new clamp_to_edge `{ return GL_CLAMP_TO_EDGE; `}
-       new mirrored_repeat `{ return GL_MIRRORED_REPEAT; `}
-       new repeat `{ return GL_REPEAT; `}
+# Texture minifying and magnifying function
+extern class GLTexParameteri
+       super GLEnum
 end
 
+fun gl_NEAREST: GLTexParameteri `{ return GL_NEAREST; `}
+fun gl_LINEAR: GLTexParameteri `{ return GL_LINEAR; `}
+fun gl_NEAREST_MIPMAP_NEAREST: GLTexParameteri `{ return GL_NEAREST_MIPMAP_NEAREST; `}
+fun gl_LINEAR_MIPMAP_NEAREST: GLTexParameteri `{ return GL_LINEAR_MIPMAP_NEAREST; `}
+fun gl_NEAREST_MIPMAP_NINEAR: GLTexParameteri `{ return GL_NEAREST_MIPMAP_LINEAR; `}
+fun gl_LINEAR_MIPMAP_LINEAR: GLTexParameteri `{ return GL_LINEAR_MIPMAP_LINEAR; `}
+fun gl_CLAMP_TO_EDGE: GLTexParameteri `{ return GL_CLAMP_TO_EDGE; `}
+fun gl_MIRRORED_REPEAT: GLTexParameteri `{ return GL_MIRRORED_REPEAT; `}
+fun gl_REPEAT: GLTexParameteri `{ return GL_REPEAT; `}
+
 # Target texture
 extern class GLTextureTarget
        super GLEnum
@@ -530,6 +631,38 @@ class GLCap
        redef fun ==(o) do return o != null and is_same_type(o) and o.hash == self.hash
 end
 
+# Generate `n` renderbuffer object names
+fun glGenRenderbuffers(n: Int): Array[Int]
+do
+       var array = new CIntArray(n)
+       native_glGenRenderbuffers(n, array.native_array)
+       var a = array.to_a
+       array.destroy
+       return a
+end
+
+private fun native_glGenRenderbuffers(n: Int, renderbuffers: NativeCIntArray) `{
+       glGenRenderbuffers(n, (GLuint *)renderbuffers);
+`}
+
+# Determine if `name` corresponds to a renderbuffer object
+fun glIsRenderbuffer(name: Int): Bool `{
+       return glIsRenderbuffer(name);
+`}
+
+# Delete named renderbuffer objects
+fun glDeleteRenderbuffers(renderbuffers: SequenceRead[Int])
+do
+       var n = renderbuffers.length
+       var array = new CIntArray.from(renderbuffers)
+       native_glDeleteRenderbuffers(n, array.native_array)
+       array.destroy
+end
+
+private fun native_glDeleteRenderbuffers(n: Int, renderbuffers: NativeCIntArray) `{
+       return glDeleteRenderbuffers(n, (const GLuint *)renderbuffers);
+`}
+
 # Attach a renderbuffer object to a framebuffer object
 fun glFramebufferRenderbuffer(target: GLFramebufferTarget, attachment: GLAttachment,
                               renderbuffertarget: GLRenderbufferTarget, renderbuffer: Int) `{
@@ -585,46 +718,6 @@ fun gl: GLES do return sys.gles
 # OpenGL ES 2.0 services
 class GLES
 
-       # Clear the color buffer to `red`, `green`, `blue` and `alpha`
-       fun clear_color(red, green, blue, alpha: Float) `{
-               glClearColor(red, green, blue, alpha);
-       `}
-
-       # Set the viewport
-       fun viewport(x, y, width, height: Int) `{ glViewport(x, y, width, height); `}
-
-       # Specify mapping of depth values from normalized device coordinates to window coordinates
-       #
-       # Default at `gl_depth_range(0.0, 1.0)`
-       fun depth_range(near, far: Float) `{ glDepthRangef(near, far); `}
-
-       # Define front- and back-facing polygons
-       #
-       # Front-facing polygons are clockwise if `value`, counter-clockwise otherwise.
-       fun front_face=(value: Bool) `{ glFrontFace(value? GL_CW: GL_CCW); `}
-
-       # Specify whether front- or back-facing polygons can be culled, default is `back` only
-       #
-       # One or both of `front` or `back` must be `true`. If you want to deactivate culling
-       # use `(new GLCap.cull_face).disable`.
-       #
-       # Require: `front or back`
-       fun cull_face(front, back: Bool)
-       do
-               assert not (front or back)
-               cull_face_native(front, back)
-       end
-
-       private fun cull_face_native(front, back: Bool) `{
-               glCullFace(front? back? GL_FRONT_AND_BACK: GL_BACK: GL_FRONT);
-       `}
-
-       # Clear the `buffer`
-       fun clear(buffer: GLBuffer) `{ glClear(buffer); `}
-
-       # Last error from OpenGL ES 2.0
-       fun error: GLError `{ return glGetError(); `}
-
        # Query the boolean value at `key`
        private fun get_bool(key: Int): Bool `{
                GLboolean val;
@@ -651,75 +744,51 @@ class GLES
        # Should always return `true` in OpenGL ES 2.0 and 3.0.
        fun shader_compiler: Bool do return get_bool(0x8DFA)
 
-       # Enable or disable writing into the depth buffer
-       fun depth_mask(value: Bool) `{ glDepthMask(value); `}
-
-       # Set the scale and units used to calculate depth values
-       fun polygon_offset(factor, units: Float) `{ glPolygonOffset(factor, units); `}
+       # OpenGL server-side capabilities
+       var capabilities = new GLCapabilities is lazy
+end
 
-       # Specify the width of rasterized lines
-       fun line_width(width: Float) `{ glLineWidth(width); `}
+# Specify the clear values for the color buffer, default values are at 0.0
+fun glClearColor(red, green, blue, alpha: Float) `{
+       glClearColor(red, green, blue, alpha);
+`}
 
-       # Set the pixel arithmetic for the blending operations
-       #
-       # Defaultvalues before assignation:
-       # * `src_factor`: `GLBlendFactor::one`
-       # * `dst_factor`: `GLBlendFactor::zero`
-       fun blend_func(src_factor, dst_factor: GLBlendFactor) `{
-               glBlendFunc(src_factor, dst_factor);
-       `}
+# Specify the clear `value` for the depth buffer, default at 1.0
+fun glClearDepthf(value: Float) `{ glClearDepthf(value); `}
 
-       # Specify the value used for depth buffer comparisons
-       #
-       # Default value is `GLDepthFunc::less`
-       #
-       # Foreign: glDepthFunc
-       fun depth_func(func: GLDepthFunc) `{ glDepthFunc(func); `}
+# Specify the clear `value` for the stencil buffer, default at 0
+fun glClearStencil(value: Int) `{ glClearStencil(value); `}
 
-       # Copy a block of pixels from the framebuffer of `fomat` and `typ` at `data`
-       #
-       # Foreign: glReadPixel
-       fun read_pixels(x, y, width, height: Int, format: GLPixelFormat, typ: GLPixelType, data: Pointer) `{
-               glReadPixels(x, y, width, height, format, typ, data);
-       `}
+# Clear the `buffer`
+fun glClear(buffer: GLBuffer) `{ glClear(buffer); `}
 
-       # Set the texture minifying function
-       #
-       # Foreign: glTexParameter with GL_TEXTURE_MIN_FILTER
-       fun tex_parameter_min_filter(target: GLTextureTarget, value: GLTextureFilter) `{
-               glTexParameteri(target, GL_TEXTURE_MIN_FILTER, value);
-       `}
+# Enable and disable writing of frame buffer color components
+fun glColorMask(red, green, blue, alpha: Bool) `{ glColorMask(red, green, blue, alpha); `}
 
-       # Set the texture magnification function
-       #
-       # Foreign: glTexParameter with GL_TEXTURE_MAG_FILTER
-       fun tex_parameter_mag_filter(target: GLTextureTarget, value: GLTextureFilter) `{
-               glTexParameteri(target, GL_TEXTURE_MAG_FILTER, value);
-       `}
+# Set the viewport
+fun glViewport(x, y, width, height: Int) `{ glViewport(x, y, width, height); `}
 
-       # Set the texture wrap parameter for coordinates _s_
-       #
-       # Foreign: glTexParameter with GL_TEXTURE_WRAP_S
-       fun tex_parameter_wrap_s(target: GLTextureTarget, value: GLTextureWrap) `{
-               glTexParameteri(target, GL_TEXTURE_WRAP_S, value);
-       `}
+# Block until all GL execution is complete
+fun glFinish `{ glFinish(); `}
 
-       # Set the texture wrap parameter for coordinates _t_
-       #
-       # Foreign: glTexParameter with GL_TEXTURE_WRAP_T
-       fun tex_parameter_wrap_t(target: GLTextureTarget, value: GLTextureWrap) `{
-               glTexParameteri(target, GL_TEXTURE_WRAP_T, value);
-       `}
+# Force execution of GL commands in finite time
+fun glFlush `{ glFlush(); `}
 
-       # Render primitives from array data
-       #
-       # Foreign: glDrawArrays
-       fun draw_arrays(mode: GLDrawMode, from, count: Int) `{ glDrawArrays(mode, from, count); `}
+# Set texture parameters
+fun glTexParameteri(target: GLTextureTarget, pname: GLTexParameteriName, param: GLTexParameteri) `{
+       glTexParameteri(target, pname, param);
+`}
 
-       # OpenGL server-side capabilities
-       var capabilities = new GLCapabilities is lazy
+# Name of parameters of textures
+extern class GLTexParameteriName
+       super GLEnum
 end
 
+fun gl_TEXTURE_MIN_FILTER: GLTexParameteriName `{ return GL_TEXTURE_MIN_FILTER; `}
+fun gl_TEXTURE_MAG_FILTER: GLTexParameteriName `{ return GL_TEXTURE_MAG_FILTER; `}
+fun gl_TEXTURE_WRAP_S: GLTexParameteriName `{ return GL_TEXTURE_WRAP_S; `}
+fun gl_TEXTURE_WRAP_T: GLTexParameteriName `{ return GL_TEXTURE_WRAP_T; `}
+
 # Bind `framebuffer` to a framebuffer target
 #
 # In OpenGL ES 2.0, `target` must be `gl_FRAMEBUFFER`.
@@ -839,6 +908,38 @@ fun gl_NICEST: GLHintMode `{ return GL_NICEST; `}
 # No preference
 fun gl_DONT_CARE: GLHintMode `{ return GL_DONT_CARE; `}
 
+# Generate `n` framebuffer object names
+fun glGenFramebuffers(n: Int): Array[Int]
+do
+       var array = new CIntArray(n)
+       native_glGenFramebuffers(n, array.native_array)
+       var a = array.to_a
+       array.destroy
+       return a
+end
+
+private fun native_glGenFramebuffers(n: Int, textures: NativeCIntArray) `{
+       glGenFramebuffers(n, (GLuint *)textures);
+`}
+
+# Determine if `name` corresponds to a framebuffer object
+fun glIsFramebuffer(name: Int): Bool `{
+       return glIsFramebuffer(name);
+`}
+
+# Delete named framebuffer objects
+fun glDeleteFramebuffers(framebuffers: SequenceRead[Int])
+do
+       var n = framebuffers.length
+       var array = new CIntArray.from(framebuffers)
+       native_glDeleteFramebuffers(n, array.native_array)
+       array.destroy
+end
+
+private fun native_glDeleteFramebuffers(n: Int, framebuffers: NativeCIntArray) `{
+       return glDeleteFramebuffers(n, (const GLuint *)framebuffers);
+`}
+
 # Attach a level of a texture object as a logical buffer to the currently bound framebuffer object
 fun glFramebufferTexture2D(target: GLFramebufferTarget, attachment: GLAttachment,
                            texture_target: GLTextureTarget,  texture, level: Int) `{
@@ -935,99 +1036,126 @@ extern class GLDataType
        fun is_sampler_cube: Bool `{ return self == GL_SAMPLER_CUBE; `}
 end
 
-# Kind of primitives to render with `GLES::draw_arrays`
+# Kind of primitives to render
 extern class GLDrawMode
        super GLEnum
-
-       new points `{ return GL_POINTS; `}
-       new line_strip `{ return GL_LINE_STRIP; `}
-       new line_loop `{ return GL_LINE_LOOP; `}
-       new lines `{ return GL_LINES; `}
-       new triangle_strip `{ return GL_TRIANGLE_STRIP; `}
-       new triangle_fan `{ return GL_TRIANGLE_FAN; `}
-       new triangles `{ return GL_TRIANGLES; `}
 end
 
+fun gl_POINTS: GLDrawMode `{ return GL_POINTS; `}
+fun gl_LINES: GLDrawMode `{ return GL_LINES; `}
+fun gl_LINE_LOOP: GLDrawMode `{ return GL_LINE_LOOP; `}
+fun gl_LINE_STRIP: GLDrawMode `{ return GL_LINE_STRIP; `}
+fun gl_TRIANGLES: GLDrawMode `{ return GL_TRIANGLES; `}
+fun gl_TRIANGLE_STRIP: GLDrawMode `{ return GL_TRIANGLE_STRIP; `}
+fun gl_TRIANGLE_FAN: GLDrawMode `{ return GL_TRIANGLE_FAN; `}
+
 # Pixel arithmetic for blending operations
-#
-# Used by `GLES::blend_func`
 extern class GLBlendFactor
        super GLEnum
-
-       new zero `{ return GL_ZERO; `}
-       new one `{ return GL_ONE; `}
-       new src_color `{ return GL_SRC_COLOR; `}
-       new one_minus_src_color `{ return GL_ONE_MINUS_SRC_COLOR; `}
-       new dst_color `{ return GL_DST_COLOR; `}
-       new one_minus_dst_color `{ return GL_ONE_MINUS_DST_COLOR; `}
-       new src_alpha `{ return GL_SRC_ALPHA; `}
-       new one_minus_src_alpha `{ return GL_ONE_MINUS_SRC_ALPHA; `}
-       new dst_alpha `{ return GL_DST_ALPHA; `}
-       new one_minus_dst_alpha `{ return GL_ONE_MINUS_DST_ALPHA; `}
-       new constant_color `{ return GL_CONSTANT_COLOR; `}
-       new one_minus_constant_color `{ return GL_ONE_MINUS_CONSTANT_COLOR; `}
-       new constant_alpha `{ return GL_CONSTANT_ALPHA; `}
-       new one_minus_constant_alpha `{ return GL_ONE_MINUS_CONSTANT_ALPHA; `}
-
-       # Used for destination only
-       new src_alpha_saturate `{ return GL_SRC_ALPHA_SATURATE; `}
 end
 
+fun gl_ZERO: GLBlendFactor `{ return GL_ZERO; `}
+fun gl_ONE: GLBlendFactor `{ return GL_ONE; `}
+fun gl_SRC_COLOR: GLBlendFactor `{ return GL_SRC_COLOR; `}
+fun gl_ONE_MINUS_SRC_COLOR: GLBlendFactor `{ return GL_ONE_MINUS_SRC_COLOR; `}
+fun gl_SRC_ALPHA: GLBlendFactor `{ return GL_SRC_ALPHA; `}
+fun gl_ONE_MINUS_SRC_ALPHA: GLBlendFactor `{ return GL_ONE_MINUS_SRC_ALPHA; `}
+fun gl_DST_ALPHA: GLBlendFactor `{ return GL_DST_ALPHA; `}
+fun gl_ONE_MINUS_DST_ALPHA: GLBlendFactor `{ return GL_ONE_MINUS_DST_ALPHA; `}
+fun gl_DST_COLOR: GLBlendFactor `{ return GL_DST_COLOR; `}
+fun gl_ONE_MINUS_DST_COLOR: GLBlendFactor `{ return GL_ONE_MINUS_DST_COLOR; `}
+fun gl_SRC_ALPHA_SATURATE: GLBlendFactor `{ return GL_SRC_ALPHA_SATURATE; `}
+
 # Condition under which a pixel will be drawn
-#
-# Used by `GLES::depth_func`
 extern class GLDepthFunc
        super GLEnum
-
-        new never `{ return GL_NEVER; `}
-        new less `{ return GL_LESS; `}
-        new equal `{ return GL_EQUAL; `}
-        new lequal `{ return GL_LEQUAL; `}
-        new greater `{ return GL_GREATER; `}
-        new not_equal `{ return GL_NOTEQUAL; `}
-        new gequal `{ return GL_GEQUAL; `}
-        new always `{ return GL_ALWAYS; `}
 end
 
+fun gl_NEVER: GLDepthFunc `{ return GL_NEVER; `}
+fun gl_LESS: GLDepthFunc `{ return GL_LESS; `}
+fun gl_EQUAL: GLDepthFunc `{ return GL_EQUAL; `}
+fun gl_LEQUAL: GLDepthFunc `{ return GL_LEQUAL; `}
+fun gl_GREATER: GLDepthFunc `{ return GL_GREATER; `}
+fun gl_NOTEQUAL: GLDepthFunc `{ return GL_NOTEQUAL; `}
+fun gl_GEQUAL: GLDepthFunc `{ return GL_GEQUAL; `}
+fun gl_ALWAYS: GLDepthFunc `{ return GL_ALWAYS; `}
+
 # Format of pixel data
-#
-# Used by `GLES::read_pixels`
 extern class GLPixelFormat
        super GLEnum
-
-       new alpha `{ return GL_ALPHA; `}
-       new rgb `{ return GL_RGB; `}
-       new rgba `{ return GL_RGBA; `}
 end
 
+fun gl_ALPHA: GLPixelFormat `{ return GL_ALPHA; `}
+fun gl_RGB: GLPixelFormat `{ return GL_RGB; `}
+fun gl_RGBA: GLPixelFormat `{ return GL_RGBA; `}
+
 # Data type of pixel data
-#
-# Used by `GLES::read_pixels`
 extern class GLPixelType
        super GLEnum
-
-       new unsigned_byte `{ return GL_UNSIGNED_BYTE; `}
-       new unsigned_short_5_6_5 `{ return GL_UNSIGNED_SHORT_5_6_5; `}
-       new unsigned_short_4_4_4_4 `{ return GL_UNSIGNED_SHORT_4_4_4_4; `}
-       new unsigned_short_5_5_5_1 `{ return GL_UNSIGNED_SHORT_5_5_5_1; `}
 end
 
-# Set of buffers as a bitwise OR mask, used by `GLES::clear`
-#
-# ~~~
-# var buffers = (new GLBuffer).color.depth
-# gl.clear buffers
-# ~~~
+fun gl_UNSIGNED_BYTE: GLPixelType `{ return GL_UNSIGNED_BYTE; `}
+fun gl_UNSIGNED_SHORT_5_6_5: GLPixelType `{ return GL_UNSIGNED_SHORT_5_6_5; `}
+fun gl_UNSIGNED_SHORT_4_4_4_4: GLPixelType `{ return GL_UNSIGNED_SHORT_4_4_4_4; `}
+fun gl_UNSIGNED_SHORT_5_5_5_1: GLPixelType `{ return GL_UNSIGNED_SHORT_5_5_5_1; `}
+
+# Set of buffers as a bitwise OR mask
 extern class GLBuffer `{ GLbitfield `}
-       # Get an empty set of buffers
-       new `{ return 0; `}
+       # Bitwise OR with `other`
+       fun |(other: GLBuffer): GLBuffer `{ return self | other; `}
+end
+
+fun gl_DEPTH_BUFFER_BIT: GLBuffer `{ return GL_DEPTH_BUFFER_BIT; `}
+fun gl_STENCIL_BUFFER_BIT: GLBuffer `{ return GL_STENCIL_BUFFER_BIT; `}
+fun gl_COLOR_BUFFER_BIT: GLBuffer `{ return GL_COLOR_BUFFER_BIT; `}
+
+# Define front- and back-facing polygons, `gc_CCW` by default
+fun glFrontFace(mode: GLFrontFaceMode) `{ glFrontFace(mode); `}
 
-       # Add the color buffer to the returned buffer set
-       fun color: GLBuffer `{ return self | GL_COLOR_BUFFER_BIT; `}
+# Orientation of front-facing polygons
+extern class GLFrontFaceMode
+       super GLEnum
+end
+
+fun gl_CW: GLFrontFaceMode `{ return GL_CW; `}
+fun gl_CCW: GLFrontFaceMode `{ return GL_CCW; `}
 
-       # Add the depth buffer to the returned buffer set
-       fun depth: GLBuffer `{ return self | GL_DEPTH_BUFFER_BIT; `}
+# Specify whether front- or back-facing polygons can be culled, default is `back` only
+fun glCullFace(mode: GLCullFaceMode) `{ glCullFace(mode); `}
 
-       # Add the stencil buffer to the returned buffer set
-       fun stencil: GLBuffer `{ return self | GL_STENCIL_BUFFER_BIT; `}
+# Candidates for culling
+extern class GLCullFaceMode
+       super GLEnum
 end
+
+fun gl_FRONT: GLCullFaceMode `{ return GL_FRONT; `}
+fun gl_BACK: GLCullFaceMode `{ return GL_BACK; `}
+fun gl_FRONT_AND_BACK: GLCullFaceMode `{ return GL_FRONT_AND_BACK; `}
+
+# Specify mapping of depth values from normalized device coordinates to window coordinates
+#
+# Default at 0.0, 1.0.
+fun glDepthRangef(near, far: Float) `{ glDepthRangef(near, far); `}
+
+# Enable or disable writing into the depth buffer
+fun glDepthMask(value: Bool) `{ glDepthMask(value); `}
+
+# Specify the value used for depth buffer comparisons
+#
+# Default value is `gl_LESS`
+fun glDepthFunc(func: GLDepthFunc) `{ glDepthFunc(func); `}
+
+# Set the pixel arithmetic for the blending operations
+#
+# Default values:
+# * `src_factor`: `gl_ONE`
+# * `dst_factor`: `gl_ZERO`
+fun glBlendFunc(src_factor, dst_factor: GLBlendFactor) `{
+       glBlendFunc(src_factor, dst_factor);
+`}
+
+# Set the scale and units used to calculate depth values
+fun glPolygonOffset(factor, units: Float) `{ glPolygonOffset(factor, units); `}
+
+# Specify the width of rasterized lines
+fun glLineWidth(width: Float) `{ glLineWidth(width); `}
index 0b1d383..d1dde15 100644 (file)
@@ -128,7 +128,15 @@ class OrderedTree[E: Object]
        do
                var old_parent = parents.get_or_null(e)
                if old_parent != null then
-                       sub[old_parent].remove(e)
+                       var subs = sub[old_parent]
+                       subs.remove(e)
+                       if subs.is_empty then
+                               # remove the sub when all children are detached
+                               # so that `==` and `hash` are sane
+                               # Otherwise an empty array will be considered
+                               # differently than no array.
+                               sub.keys.remove(old_parent)
+                       end
                else if roots.has(e) then
                        roots.remove(e)
                end
@@ -149,6 +157,7 @@ class OrderedTree[E: Object]
        do
                if not sub.has_key(e) then return
                var subs = sub[e]
+               if subs.is_empty then return
                var last = subs.last
                for e2 in subs do
                        if e2 != last then
diff --git a/lib/text_stat.ini b/lib/text_stat.ini
new file mode 100644 (file)
index 0000000..fb0ab2b
--- /dev/null
@@ -0,0 +1,11 @@
+[package]
+name=text_stat
+tags=debug,lib
+maintainer=Lucas Bajolet <r4pass@hotmail.com>
+license=Apache-2.0
+[upstream]
+browse=https://github.com/nitlang/nit/tree/master/lib/text_stat.nit
+git=https://github.com/nitlang/nit.git
+git.directory=lib/text_stat.nit
+homepage=http://nitlanguage.org
+issues=https://github.com/nitlang/nit/issues
index 2930d81..b5d86ac 100644 (file)
@@ -88,7 +88,7 @@ syn match  NITComment "#.*" contains=NITTodo,@Spell
 " Keywords
 syn keyword NITKeyword  abstract intern new
 syn keyword NITDefine   private public protected intrude readable writable redef
-syn keyword NITControl   if while for assert and or in as isa once break continue return abort
+syn keyword NITControl   if while for with assert and or in as isa once break continue return abort
 syn keyword NITClass     nullable
 syn keyword NITInclude   special
 syn keyword NITTodo      FIXME NOTE TODO XXX contained
index a59ccf0..a914b56 100644 (file)
@@ -323,7 +323,7 @@ redef class ModelBuilder
        fun identify_file(path: String): nullable ModulePath
        do
                # special case for not a nit file
-               if path.file_extension != "nit" then
+               if not path.has_suffix(".nit") then
                        # search dirless files in known -I paths
                        if not path.chars.has('/') then
                                var res = search_module_in_paths(null, path, self.paths)
@@ -352,10 +352,12 @@ redef class ModelBuilder
                end
 
                # Fast track, the path is already known
-               var pn = path.basename(".nit")
+               if identified_files_by_path.has_key(path) then return identified_files_by_path[path]
                var rp = module_absolute_path(path)
                if identified_files_by_path.has_key(rp) then return identified_files_by_path[rp]
 
+               var pn = path.basename(".nit")
+
                # Search for a group
                var mgrouppath = path.join_path("..").simplify_path
                var mgroup = get_mgroup(mgrouppath)
@@ -380,6 +382,7 @@ redef class ModelBuilder
                mgroup.module_paths.add(res)
 
                identified_files_by_path[rp] = res
+               identified_files_by_path[path] = res
                identified_files.add(res)
                return res
        end
@@ -393,10 +396,15 @@ redef class ModelBuilder
        # Note: `paths` is also used to look for mgroups
        fun get_mgroup(dirpath: String): nullable MGroup
        do
-               if not dirpath.file_exists then do
+               var stat = dirpath.file_stat
+
+               if stat == null then do
+                       # search dirless directories in known -I paths
+                       if dirpath.chars.has('/') then return null
                        for p in paths do
                                var try = p / dirpath
-                               if try.file_exists then
+                               stat = try.file_stat
+                               if stat != null then
                                        dirpath = try
                                        break label
                                end
@@ -404,20 +412,19 @@ redef class ModelBuilder
                        return null
                end label
 
+               # Filter out non-directories
+               if not stat.is_dir then
+                       return null
+               end
+
+               # Fast track, the path is already known
                var rdp = module_absolute_path(dirpath)
                if mgroups.has_key(rdp) then
                        return mgroups[rdp]
                end
 
-               # Filter out non-directories
-               var stat = dirpath.file_stat
-               if stat == null or not stat.is_dir then
-                       mgroups[rdp] = null
-                       return null
-               end
-
                # By default, the name of the package or group is the base_name of the directory
-               var pn = rdp.basename(".nit")
+               var pn = rdp.basename
 
                # Check `package.ini` that indicate a package
                var ini = null
@@ -525,23 +532,24 @@ redef class ModelBuilder
                        var fp = p/f
                        var g = get_mgroup(fp)
                        # Recursively scan for groups of the same package
-                       if g != null and g.mpackage == mgroup.mpackage then
+                       if g == null then
+                               identify_file(fp)
+                       else if g.mpackage == mgroup.mpackage then
                                scan_group(g)
                        end
-                       identify_file(fp)
                end
        end
 
        # Transform relative paths (starting with '../') into absolute paths
        private fun module_absolute_path(path: String): String do
-               return getcwd.join_path(path).simplify_path
+               return path.realpath
        end
 
        # Try to load a module AST using a path.
        # Display an error if there is a problem (IO / lexer / parser) and return null
        fun load_module_ast(filename: String): nullable AModule
        do
-               if filename.file_extension != "nit" then
+               if not filename.has_suffix(".nit") then
                        self.toolcontext.error(null, "Error: file `{filename}` is not a valid nit module.")
                        return null
                end
index 19b7801..eca970e 100644 (file)
@@ -10,4 +10,3 @@ project1 (\e[33mproject1\e[m)
 `--subdir (\e[33mproject1/subdir\e[m)
    |--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
    `--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
-\e[1mproject2\e[m (\e[33mproject1/project2/project2.nit\e[m)
index 19b7801..eca970e 100644 (file)
@@ -10,4 +10,3 @@ project1 (\e[33mproject1\e[m)
 `--subdir (\e[33mproject1/subdir\e[m)
    |--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
    `--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
-\e[1mproject2\e[m (\e[33mproject1/project2/project2.nit\e[m)
index a8b51a5..267bbdb 100644 (file)
@@ -8,4 +8,3 @@ project1/subdir/\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
 project1/\e[1mmodule_01\e[m (\e[33mproject1/module_01.nit\e[m)
 project1/\e[1mmodule_02\e[m (\e[33mproject1/module_02.nit\e[m)
 project1/\e[1mproject1\e[m (\e[33mproject1/project1.nit\e[m)
-project2/\e[1mproject2\e[m (\e[33mproject1/project2/project2.nit\e[m)
diff --git a/tests/sav/test_with.res b/tests/sav/test_with.res
new file mode 100644 (file)
index 0000000..bd8974e
--- /dev/null
@@ -0,0 +1,9 @@
+1
+2
+3
+4
+1
+one
+2
+two
+# Regression test for the Nit project
diff --git a/tests/test_with.nit b/tests/test_with.nit
new file mode 100644 (file)
index 0000000..89757d4
--- /dev/null
@@ -0,0 +1,32 @@
+# 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.
+
+var a = [1,2,3,4]
+with i = a.iterator do while i.is_ok do
+       print i.item
+       i.next
+end
+
+var m = new HashMap[Int, String]
+m[1] = "one"
+m[2] = "two"
+with i = m.iterator do while i.is_ok do
+       print i.key
+       print i.item
+       i.next
+end
+
+with f = "README.md".to_path.open_ro do
+       print f.read_line
+end