From: Jean Privat Date: Wed, 7 Jan 2015 02:05:51 +0000 (-0500) Subject: Merge: Tools works with groups X-Git-Tag: v0.7.1~49 X-Git-Url: http://nitlanguage.org?hp=985cfca6c4581523bbe04f8314f6ddc2cf9b674e Merge: Tools works with groups Make Nit tools more POLA when projects (or groups) are given on the command line. eg. people using `nitunit ../lib/mylib` may expect that all the unit tests of the lib are executed, not just those from the default module `../lib/mylib/mylib.nit` (that often is basically an empty bottom module) So this PR introduces `parse_full` in the loader that loads and returns all the modules of given groups, then adapt most tools to use `parse_full`. No more crazy shell pipelines with `nitls` or `find` to use nitunit, nitpick and other on all the modules of your libs or programs. Pull-Request: #1070 Reviewed-by: Alexis Laferrière Reviewed-by: Romain Chanoir --- diff --git a/VERSION b/VERSION index 882307c..03776fb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.6.11 +v0.7 diff --git a/clib/gc_chooser.h b/clib/gc_chooser.h index fa395b0..255e07a 100644 --- a/clib/gc_chooser.h +++ b/clib/gc_chooser.h @@ -20,7 +20,7 @@ void *nit_raw_alloc(size_t); /* allocate raw memory to store a raw stram of byte void nit_gcollect(void); /* force a garbage collection */ void initialize_gc_option(void); /* Select the wanted GC using envvar `NIT_GC_OPTION` */ -void gc_set_finializer(void*); /* Tag a pointer for finalization */ +void gc_register_finalizer(void*); /* Tag a pointer for finalization */ void gc_finalize(void*, void*); /* Finalize a pointer, implemented in the generated code. */ #endif diff --git a/contrib/friendz/.gitignore b/contrib/friendz/.gitignore new file mode 100644 index 0000000..700b511 --- /dev/null +++ b/contrib/friendz/.gitignore @@ -0,0 +1 @@ +res/ diff --git a/contrib/friendz/Makefile b/contrib/friendz/Makefile index 0039fff..f236a1d 100644 --- a/contrib/friendz/Makefile +++ b/contrib/friendz/Makefile @@ -5,7 +5,8 @@ linux: ../../bin/nitc -o bin/friendz src/friendz_linux.nit android: - mkdir -p bin + mkdir -p bin res + ../inkscape_tools/bin/svg_to_icons art/icon.svg --android --out res/ ../../bin/nitc -o bin/friendz.apk src/friendz_android.nit doc: @@ -13,4 +14,4 @@ doc: ../../bin/nitdoc -d doc/ src/friendz.nit src/friendz_linux.nit clean: - rm -rf bin/ doc/ + rm -rf bin/ doc/ res/ diff --git a/contrib/friendz/README.md b/contrib/friendz/README.md index bd5f5e5..48be94e 100644 --- a/contrib/friendz/README.md +++ b/contrib/friendz/README.md @@ -33,3 +33,8 @@ In challenge level you have to place as much as monster as possible. This game was originally developed for the [Casual Gameplay Design Competition \#9](http://jayisgames.com/cgdc9). + +# Artwork + +The artwork was created by Sam Hocevar for the Monsterz arcade +puzzle game http://sam.zoy.org/monsterz/ diff --git a/contrib/friendz/art/icon.svg b/contrib/friendz/art/icon.svg new file mode 100644 index 0000000..3584b06 --- /dev/null +++ b/contrib/friendz/art/icon.svg @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/friendz/src/friendz.nit b/contrib/friendz/src/friendz.nit index 13915e6..2dd8d80 100644 --- a/contrib/friendz/src/friendz.nit +++ b/contrib/friendz/src/friendz.nit @@ -17,6 +17,8 @@ import mnit import realtime import solver import mnit::tileset +import app::data_store +import md5 intrude import grid intrude import level @@ -1080,8 +1082,8 @@ redef class Game level = null var i = levels.first for l in levels do - if l.get_state == l.l_open then break i = l + if l.get_state == l.l_open then break end entities.push(new StartButton(self, i)) end @@ -1142,7 +1144,8 @@ redef class Game end var ev = lastev if ev isa Event then - display.blit(img[4,0],ev.offset_x-42,ev.offset_y-6) + # Cursor, kept for debugging + #display.blit(img[4,0],ev.offset_x-42,ev.offset_y-6) end dirty_all = false end @@ -1267,6 +1270,18 @@ redef class Game end end end + + redef fun load_levels + do + super + + for level in levels do + var score = app.data_store["s{level.str.md5}"] + if score isa Int then + level.score = score + end + end + end end # The spash title image @@ -1634,3 +1649,10 @@ redef class KeyEvent return "unknown" end end + +redef class Level + redef fun save + do + app.data_store["s{str.md5}"] = if score > 0 then score else null + end +end diff --git a/contrib/friendz/src/friendz_android.nit b/contrib/friendz/src/friendz_android.nit index 94b9d2b..13a139e 100644 --- a/contrib/friendz/src/friendz_android.nit +++ b/contrib/friendz/src/friendz_android.nit @@ -12,16 +12,26 @@ module friendz_android import friendz import mnit_android +import android::landscape redef class App + # Zoom applied for the device display from the game logic coordinates + var zoom = 1.0 + redef fun window_created do super - var w = screen_width - display.set_viewport(0,0,w,w*display.height/display.width) + + var h = screen_height + display.set_viewport(0,0,h*display.width/display.height,h) + + zoom = display.height.to_f / h.to_f end end redef class AndroidPointerEvent - redef fun is_motion do return not motion_event.just_went_down + redef fun is_motion do return not just_went_down + + redef fun x do return super / app.zoom + redef fun y do return super / app.zoom end diff --git a/contrib/friendz/src/level.nit b/contrib/friendz/src/level.nit index d459875..9d8029e 100644 --- a/contrib/friendz/src/level.nit +++ b/contrib/friendz/src/level.nit @@ -96,10 +96,8 @@ class Level return true end - fun save - do - #save_cookie("s"+self.hash, self.score>0?self.score:"") - end + # Save the score of the level + fun save do end end # main game object @@ -174,8 +172,6 @@ class Game for i in [0..levels_code.length[ do var l = new Level(self,i, levels_code[i]) levels[i] = l - #var v = read_cookie("s"+l.hash) - #l = v end end diff --git a/examples/mnit_ballz/src/ballz_android.nit b/examples/mnit_ballz/src/ballz_android.nit index affb3e9..ace5787 100644 --- a/examples/mnit_ballz/src/ballz_android.nit +++ b/examples/mnit_ballz/src/ballz_android.nit @@ -19,6 +19,8 @@ module ballz_android is app_name("Ballz") end +import android::portrait + import game_logic redef class App diff --git a/examples/mnit_dino/src/dino_android.nit b/examples/mnit_dino/src/dino_android.nit index 1a3459a..aac6d47 100644 --- a/examples/mnit_dino/src/dino_android.nit +++ b/examples/mnit_dino/src/dino_android.nit @@ -21,6 +21,7 @@ end import dino import mnit_android +import android::portrait import android::vibration redef class ImageSet diff --git a/examples/mnit_moles/src/moles_android.nit b/examples/mnit_moles/src/moles_android.nit index ecc8b6e..ad2b1f1 100644 --- a/examples/mnit_moles/src/moles_android.nit +++ b/examples/mnit_moles/src/moles_android.nit @@ -16,8 +16,10 @@ module moles_android -import moles import mnit_android +import android::portrait + +import moles redef class Game redef fun columns do return 3 diff --git a/examples/mnit_simple/src/simple_android.nit b/examples/mnit_simple/src/simple_android.nit index bf2bd23..b108f8b 100644 --- a/examples/mnit_simple/src/simple_android.nit +++ b/examples/mnit_simple/src/simple_android.nit @@ -18,10 +18,12 @@ module simple_android is android_manifest("""""") end -import simple import mnit_android +import android::portrait import serialization +import simple + in "Java" `{ import android.content.Context; import android.widget.Toast; diff --git a/lib/android/cardboard.nit b/lib/android/cardboard.nit new file mode 100644 index 0000000..30ec5eb --- /dev/null +++ b/lib/android/cardboard.nit @@ -0,0 +1,70 @@ +# This file is part of NIT (http://www.nitlanguage.org). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Services from the Google Cardboard SDK for virtual reality on Android +# +# Projects using this module should keep the `cardboard.jar` archive in the +# `libs` folder at the root of the project. +# +# External resources: +# * Download `cardboard.jar` from +# https://raw.githubusercontent.com/googlesamples/cardboard-java/master/CardboardSample/libs/cardboard.jar +# * Read about Cardboard at +# https://developers.google.com/cardboard/ +# * Find the Cardboard SDK documentation at +# https://developers.google.com/cardboard/android/latest/reference/com/google/vrtoolkit/cardboard/package-summary +module cardboard + +import java::collections +import native_app_glue + +in "Java" `{ + import com.google.vrtoolkit.cardboard.CardboardActivity; + import com.google.vrtoolkit.cardboard.sensors.HeadTracker; +`} + +# Provides head tracking information from the device IMU +# +# The corresponding Java class is no longer documented, but it is still useful. +extern class NativeHeadTracker in "Java" `{ com.google.vrtoolkit.cardboard.sensors.HeadTracker `} + super JavaObject + + # Instantiate a new `NativeHeadTracker` for the given `context` + new (context: NativeContext) in "Java" `{ + return HeadTracker.createFromContext(context); + `} + + # Start tracking head movement + fun start_tracking in "Java" `{ recv.startTracking(); `} + + # Stop tracking head movement + fun stop_tracking in "Java" `{ recv.stopTracking(); `} + + # Apply correction to the gyroscope values + fun gyro_bias=(matrix: JavaFloatArray) in "Java" `{ + recv.setGyroBias(matrix); + `} + + # Enable finer analysis using the neck as center of movement + fun neck_model_enabled=(value: Bool) in "Java" `{ + recv.setNeckModelEnabled(value); + `} + + # Fill `matrix` with the last rotation matrix calculated from head movements + # + # Require: matrix.length >= offset + 16 + fun last_head_view(matrix: JavaFloatArray, offset: Int) in "Java" `{ + recv.getLastHeadView(matrix, (int)offset); + `} +end diff --git a/lib/android/input_events.nit b/lib/android/input_events.nit new file mode 100644 index 0000000..c766a16 --- /dev/null +++ b/lib/android/input_events.nit @@ -0,0 +1,252 @@ +# This file is part of NIT (http://www.nitlanguage.org). +# +# Copyright 2012-2014 Alexis Laferrière +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# 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. + +# Pointer and hardware key events +module input_events + +import mnit_input +import android + +in "C header" `{ + #include + #include + + #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "mnit", __VA_ARGS__)) + #ifdef DEBUG + #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "mnit", __VA_ARGS__)) + #else + #define LOGI(...) (void)0 + #endif +`} + +in "C" `{ + /* Handle inputs from the Android platform and sort them before + sending them in the Nit App */ + static int32_t mnit_handle_input(struct android_app* app, AInputEvent* event) { + App nit_app = app->userData; + LOGI("handle input %i", (int)pthread_self()); + if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { + LOGI("key"); + return App_native_input_key(nit_app, event); + } + else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { + LOGI("motion"); + return App_native_input_motion(nit_app, event); + } + + return 0; + } +`} + +private extern class NativeAndroidMotionEvent `{AInputEvent *`} + + fun pointers_count: Int `{ + return AMotionEvent_getPointerCount(recv); + `} + + # Did this motion event just started? + fun just_went_down: Bool `{ + return (AMotionEvent_getAction(recv) & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN; + `} + + fun edge: Int `{ + return AMotionEvent_getEdgeFlags(recv); + `} + + # Get the non-primary pointer id that just went down (returns -1 or > 0) + fun index_down_pointer: Int `{ + int a = AMotionEvent_getAction(recv); + if ((a & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_POINTER_DOWN) + return (a & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + else return -1; + `} + + fun action: AMotionEventAction `{ return AMotionEvent_getAction(recv); `} +end + +private extern class AMotionEventAction `{ int32_t `} + fun action: Int `{ return recv & AMOTION_EVENT_ACTION_MASK; `} + + fun is_down: Bool do return action == 0 + fun is_up: Bool do return action == 1 + fun is_move: Bool do return action == 2 + fun is_cancel: Bool do return action == 3 + fun is_outside: Bool do return action == 4 + fun is_pointer_down: Bool do return action == 5 + fun is_pointer_up: Bool do return action == 6 +end + +# An input event on Android +interface AndroidInputEvent + super InputEvent +end + +# A motion event concerning a single or more `pointers` +class AndroidMotionEvent + super AndroidInputEvent + super MotionEvent + + private var native: NativeAndroidMotionEvent + + private var pointers_cache: nullable Array[AndroidPointerEvent] = null + + # Pointers (or fingers) composing this motion event + fun pointers: Array[AndroidPointerEvent] + do + if pointers_cache != null then + return pointers_cache.as(not null) + else + var pointers = new Array[AndroidPointerEvent] + var pointers_count = native.pointers_count + for i in [0 .. pointers_count [do + var pointer_event = new AndroidPointerEvent(self, i) + pointers.add(pointer_event) + end + pointers_cache = pointers + return pointers + end + end + + redef fun just_went_down: Bool do return native.just_went_down + + # Was the top edge of the screen intersected by this event? + fun touch_to_edge: Bool do return native.edge == 1 + + # Was the bottom edge of the screen intersected by this event? + fun touch_bottom_edge: Bool do return native.edge == 2 + + # Was the left edge of the screen intersected by this event? + fun touch_left_edge: Bool do return native.edge == 4 + + # Was the right edge of the screen intersected by this event? + fun touch_right_edge: Bool do return native.edge == 8 + + redef fun down_pointer: nullable AndroidPointerEvent + do + if just_went_down then + # The primary pointer went down + return pointers[0] + end + + var i = native.index_down_pointer + if i > 0 then + # A secondary pointer went down + return pointers[i] + else + return null + end + end +end + +# A pointer event +class AndroidPointerEvent + super PointerEvent + super AndroidInputEvent + + private var motion_event: AndroidMotionEvent + + private var pointer_id: Int + + redef fun x: Float do return native_x(motion_event.native, pointer_id) + + private fun native_x(motion_event: NativeAndroidMotionEvent, pointer_id: Int): Float `{ + return AMotionEvent_getX(motion_event, pointer_id); + `} + + redef fun y: Float do return native_y(motion_event.native, pointer_id) + + private fun native_y(motion_event: NativeAndroidMotionEvent, pointer_id: Int): Float `{ + return AMotionEvent_getY(motion_event, pointer_id); + `} + + # Pressure applied by this pointer + fun pressure: Float do return native_pressure(motion_event.native, pointer_id) + + private fun native_pressure(motion_event: NativeAndroidMotionEvent, pointer_id: Int): Float `{ + return AMotionEvent_getPressure(motion_event, pointer_id); + `} + + redef fun pressed + do + var action = motion_event.native.action + return action.is_down or action.is_move + end + + redef fun depressed do return not pressed + + # Does this pointer just began touching the screen? + fun just_went_down: Bool + do + return motion_event.down_pointer == self + end +end + +# An hardware key event +extern class AndroidKeyEvent `{AInputEvent *`} + super KeyEvent + super AndroidInputEvent + + private fun action: Int `{ return AKeyEvent_getAction(recv); `} + + redef fun is_down: Bool do return action == 0 + redef fun is_up: Bool do return action == 1 + + # Hardware code of the key raising this event + fun key_code: Int `{ return AKeyEvent_getKeyCode(recv); `} + + redef fun to_c `{ + int code = AKeyEvent_getKeyCode(recv); + if (code >= AKEYCODE_0 && code <= AKEYCODE_9) + return '0'+code-AKEYCODE_0; + if (code >= AKEYCODE_A && code <= AKEYCODE_Z) + return 'a'+code-AKEYCODE_A; + return 0; + `} + + # Was this event raised by the back key? + fun is_back_key: Bool do return key_code == 4 + + # Was this event raised by the menu key? + fun is_menu_key: Bool do return key_code == 82 + + # Was this event raised by the search key? + fun is_search_key: Bool do return key_code == 84 + + # Was this event raised by the volume up key? + fun is_volume_up: Bool do return key_code == 24 + + # Was this event raised by the volume down key? + fun is_volume_down: Bool do return key_code == 25 +end + +redef class App + + redef fun init_window + do + set_as_input_handler native_app_glue + super + end + + private fun set_as_input_handler(app_glue: NativeAppGlue) + import native_input_key, native_input_motion `{ + app_glue->onInputEvent = mnit_handle_input; + `} + + # these are used as a callback from native to type incoming events + private fun native_input_key(event: AndroidKeyEvent): Bool is abstract + + private fun native_input_motion(event: NativeAndroidMotionEvent): Bool is abstract +end diff --git a/lib/android/landscape.nit b/lib/android/landscape.nit new file mode 100644 index 0000000..a3fceaf --- /dev/null +++ b/lib/android/landscape.nit @@ -0,0 +1,20 @@ +# 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. + +# Config to set the landscape orientation +module landscape is android_manifest_activity """ + android:screenOrientation="landscape" +""" + +import platform diff --git a/lib/android/portrait.nit b/lib/android/portrait.nit new file mode 100644 index 0000000..e8f5720 --- /dev/null +++ b/lib/android/portrait.nit @@ -0,0 +1,20 @@ +# 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. + +# Config to set the portrait orientation +module portrait is android_manifest_activity """ + android:screenOrientation="portrait" +""" + +import platform diff --git a/lib/glesv2/examples/opengles2_hello_triangle.nit b/lib/glesv2/examples/opengles2_hello_triangle.nit index d62153f..cfab7ae 100644 --- a/lib/glesv2/examples/opengles2_hello_triangle.nit +++ b/lib/glesv2/examples/opengles2_hello_triangle.nit @@ -106,16 +106,16 @@ assert egl_bind_opengl_es_api else print "eglBingAPI failed: {egl_display.error} ## GLESv2 # -print "Can compile shaders? {gl_shader_compiler}" +print "Can compile shaders? {gl.shader_compiler}" assert_no_gl_error -assert gl_shader_compiler else print "Cannot compile shaders" +assert gl.shader_compiler else print "Cannot compile shaders" # gl program -print gl_error.to_s +print gl.error.to_s var program = new GLProgram if not program.is_ok then - print "Program is not ok: {gl_error.to_s}\nLog:" + print "Program is not ok: {gl.error.to_s}\nLog:" print program.info_log abort end @@ -123,27 +123,28 @@ 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}" +assert vertex_shader.is_ok else print "Vertex shader is not ok: {gl.error}" vertex_shader.source = """ attribute vec4 vPosition; void main() { gl_Position = vPosition; -} """ +} +""".to_cstring vertex_shader.compile 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}" +assert fragment_shader.is_ok else print "Fragment shader is not ok: {gl.error}" fragment_shader.source = """ precision mediump float; void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } -""" +""".to_cstring fragment_shader.compile assert fragment_shader.is_compiled else print "Fragment shader compilation failed with: {fragment_shader.info_log}" assert_no_gl_error @@ -159,12 +160,12 @@ 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) +gl.clear_color(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_color_buffer + gl.viewport(0, 0, width, height) + gl.clear((new GLBuffer).color) program.use vertex_array.enable vertex_array.draw_arrays_triangles diff --git a/lib/glesv2/glesv2.nit b/lib/glesv2/glesv2.nit index 8d5ec6a..01ca43c 100644 --- a/lib/glesv2/glesv2.nit +++ b/lib/glesv2/glesv2.nit @@ -199,9 +199,8 @@ end # Abstract OpenGL ES shader object, implemented by `GLFragmentShader` and `GLVertexShader` extern class GLShader `{GLuint`} # Set the source of the shader - fun source=(code: String) import String.to_cstring, String.length `{ - GLchar *c_code = String_to_cstring(code); - glShaderSource(recv, 1, (const GLchar * const*)&c_code, NULL); + fun source=(code: NativeString) `{ + glShaderSource(recv, 1, (GLchar const **)&code, NULL); `} # Source of the shader, if available @@ -318,10 +317,24 @@ extern class GLfloatArray `{GLfloat *`} `} end +# General type for OpenGL enumerations +extern class GLEnum `{ GLenum `} + + redef fun hash `{ return recv; `} + + redef fun ==(o) do return o != null and is_same_type(o) and o.hash == self.hash +end + # An OpenGL ES 2.0 error code -extern class GLError `{ GLenum `} +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 recv == GL_NO_ERROR; `} + fun is_invalid_enum: Bool `{ return recv == GL_INVALID_ENUM; `} fun is_invalid_value: Bool `{ return recv == GL_INVALID_VALUE; `} fun is_invalid_operation: Bool `{ return recv == GL_INVALID_OPERATION; `} @@ -340,65 +353,280 @@ extern class GLError `{ GLenum `} end end -# Clear the color buffer with `r`, `g`, `b`, `a` -protected fun gl_clear_color(r, g, b, a: Float) `{ glClearColor(r, g, b, a); `} - -# Set the viewport -protected fun gl_viewport(x, y, width, height: Int) `{ glViewport(x, y, width, height); `} - -# Direct call to `glClear`, call with a combinaison of `gl_clear_color_buffer`, -# `gl_stencil_buffer_bit` and `gl_color_buffer_bit`. -private fun gl_clear(flag: Int) `{ glClear(flag); `} - -protected fun gl_depth_buffer_bit: Int do return 0x0100 -protected fun gl_stencil_buffer_bit: Int do return 0x0400 -protected fun gl_color_buffer_bit: Int do return 0x4000 - -protected fun gl_clear_color_buffer do gl_clear(gl_color_buffer_bit) -protected fun gl_clear_depth_buffer do gl_clear(gl_depth_buffer_bit) -protected fun gl_clear_stencil_buffer do gl_clear(gl_stencil_buffer_bit) - -protected fun gl_error: GLError `{ return glGetError(); `} protected fun assert_no_gl_error do - var error = gl_error + var error = gl.error if not error.is_ok then print "GL error: {error}" abort end end -# Query the boolean value at `key` -private fun gl_get_bool(key: Int): Bool `{ - GLboolean val; - glGetBooleanv(key, &val); - return val == GL_TRUE; -`} +# Texture minifying function +# +# Used by: `GLES::tex_parameter_min_filter` +extern class GLTextureMinFilter + super GLEnum -# Query the floating point value at `key` -private fun gl_get_float(key: Int): Float `{ - GLfloat val; - glGetFloatv(key, &val); - return val; -`} + new nearest `{ return GL_NEAREST; `} + new linear `{ return GL_LINEAR; `} +end -# Query the integer value at `key` -private fun gl_get_int(key: Int): Int `{ - GLint val; - glGetIntegerv(key, &val); - return val; -`} +# Texture magnification function +# +# Used by: `GLES::tex_parameter_mag_filter` +extern class GLTextureMagFilter + super GLEnum + + new nearest `{ return GL_NEAREST; `} + new linear `{ return GL_LINEAR; `} + new nearest_mipmap_nearest `{ return GL_NEAREST_MIPMAP_NEAREST; `} + new linear_mipmap_nearest `{ return GL_LINEAR_MIPMAP_NEAREST; `} + new nearest_mipmap_linear `{ return GL_NEAREST_MIPMAP_LINEAR; `} + new linear_mipmap_linear `{ return GL_LINEAR_MIPMAP_LINEAR; `} +end + +# Wrap parameter of a texture +# +# Used by: `tex_parameter_wrap_*` +extern class GLTextureWrap + super GLEnum -# Does this driver support shader compilation? + new clamp_to_edge `{ return GL_CLAMP_TO_EDGE; `} + new mirrored_repeat `{ return GL_MIRRORED_REPEAT; `} + new repeat `{ return GL_REPEAT; `} +end + +# Target texture # -# Should always return `true` in OpenGL ES 2.0 and 3.0. -fun gl_shader_compiler: Bool do return gl_get_bool(0x8DFA) +# Used by: `tex_parameter_*` +extern class GLTextureTarget + super GLEnum + + new flat `{ return GL_TEXTURE_2D; `} + new cube_map `{ return GL_TEXTURE_CUBE_MAP; `} +end + +# A server-side capability +class GLCap + + # TODO private init + + # Internal OpenGL integer for this capability + private var val: Int + + # Enable this server-side capability + fun enable do enable_native(val) + private fun enable_native(cap: Int) `{ glEnable(cap); `} + + # Disable this server-side capability + fun disable do disable_native(val) + private fun disable_native(cap: Int) `{ glDisable(cap); `} + + redef fun hash do return val + redef fun ==(o) do return o != null and is_same_type(o) and o.hash == self.hash +end +redef class Sys + private var gles = new GLES is lazy +end + +# Entry points to OpenGL ES 2.0 services +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; + glGetBooleanv(key, &val); + return val == GL_TRUE; + `} + + # Query the floating point value at `key` + private fun get_float(key: Int): Float `{ + GLfloat val; + glGetFloatv(key, &val); + return val; + `} + + # Query the integer value at `key` + private fun get_int(key: Int): Int `{ + GLint val; + glGetIntegerv(key, &val); + return val; + `} + + # Does this driver support shader compilation? + # + # 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); `} + + # Specify the width of rasterized lines + fun line_width(width: Float) `{ glLineWidth(width); `} + + # 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 value used for depth buffer comparisons + # + # Default value is `GLDepthFunc::less` + # + # Foreign: glDepthFunc + fun depth_func(func: GLDepthFunc) `{ glDepthFunc(func); `} + + # 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, GL_RGBA, GL_UNSIGNED_BYTE, data); + `} + + # Set the texture minifying function + # + # Foreign: glTexParameter with GL_TEXTURE_MIN_FILTER + fun tex_parameter_min_filter(target: GLTextureTarget, value: GLTextureMinFilter) `{ + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, value); + `} + + # Set the texture magnification function + # + # Foreign: glTexParameter with GL_TEXTURE_MAG_FILTER + fun tex_parameter_mag_filter(target: GLTextureTarget, value: GLTextureMagFilter) `{ + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, value); + `} + + # 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); + `} + + # 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); + `} + + # Render primitives from array data + # + # Foreign: glDrawArrays + fun draw_arrays(mode: GLDrawMode, from, count: Int) `{ glDrawArrays(mode, from, count); `} + + # OpenGL server-side capabilities + var capabilities = new GLCapabilities is lazy +end + +# Entry point to OpenGL server-side capabilities +class GLCapabilities + + # GL capability: blend the computed fragment color values + # + # Foreign: GL_BLEND + fun blend: GLCap is lazy do return new GLCap(0x0BE2) + + # GL capability: cull polygons based of their winding in window coordinates + # + # Foreign: GL_CULL_FACE + fun cull_face: GLCap is lazy do return new GLCap(0x0B44) + + # GL capability: do depth comparisons and update the depth buffer + # + # Foreign: GL_DEPTH_TEST + fun depth_test: GLCap is lazy do return new GLCap(0x0B71) + + # GL capability: dither color components or indices before they are written to the color buffer + # + # Foreign: GL_DITHER + fun dither: GLCap is lazy do return new GLCap(0x0BE2) + + # GL capability: add an offset to depth values of a polygon fragment before depth test + # + # Foreign: GL_POLYGON_OFFSET_FILL + fun polygon_offset_fill: GLCap is lazy do return new GLCap(0x8037) + + # GL capability: compute a temporary coverage value where each bit is determined by the alpha value at the corresponding location + # + # Foreign: GL_SAMPLE_ALPHA_TO_COVERAGE + fun sample_alpha_to_coverage: GLCap is lazy do return new GLCap(0x809E) + + # GL capability: AND the fragment coverage with the temporary coverage value + # + # Foreign: GL_SAMPLE_COVERAGE + fun sample_coverage: GLCap is lazy do return new GLCap(0x80A0) + + # GL capability: discard fragments that are outside the scissor rectangle + # + # Foreign: GL_SCISSOR_TEST + fun scissor_test: GLCap is lazy do return new GLCap(0x0C11) + + # GL capability: do stencil testing and update the stencil buffer + # + # Foreign: GL_STENCIL_TEST + fun stencil_test: GLCap is lazy do return new GLCap(0x0B90) +end # Float related data types of OpenGL ES 2.0 shaders # # Only data types supported by shader attributes, as seen with # `GLProgram::active_attrib_type`. -extern class GLFloatDataType `{ GLenum `} +extern class GLFloatDataType + super GLEnum + fun is_float: Bool `{ return recv == GL_FLOAT; `} fun is_float_vec2: Bool `{ return recv == GL_FLOAT_VEC2; `} fun is_float_vec3: Bool `{ return recv == GL_FLOAT_VEC3; `} @@ -406,6 +634,12 @@ extern class GLFloatDataType `{ GLenum `} fun is_float_mat2: Bool `{ return recv == GL_FLOAT_MAT2; `} fun is_float_mat3: Bool `{ return recv == GL_FLOAT_MAT3; `} fun is_float_mat4: Bool `{ return recv == GL_FLOAT_MAT4; `} + + # Instances of `GLFloatDataType` can be equal to instances of `GLDataType` + redef fun ==(o) + do + return o != null and o isa GLFloatDataType and o.hash == self.hash + end end # All data types of OpenGL ES 2.0 shaders @@ -426,3 +660,100 @@ extern class GLDataType fun is_sampler_2d: Bool `{ return recv == GL_SAMPLER_2D; `} fun is_sampler_cube: Bool `{ return recv == GL_SAMPLER_CUBE; `} end + +# Kind of primitives to render with `GLES::draw_arrays` +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 + +# 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 + +# 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 + +# 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 + +# 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 +# ~~~ +extern class GLBuffer `{ GLbitfield `} + # Get an empty set of buffers + new `{ return 0; `} + + # Add the color buffer to the returned buffer set + fun color: GLBuffer `{ return recv | GL_COLOR_BUFFER_BIT; `} + + # Add the depth buffer to the returned buffer set + fun depth: GLBuffer `{ return recv | GL_DEPTH_BUFFER_BIT; `} + + # Add the stencil buffer to the returned buffer set + fun stencil: GLBuffer `{ return recv | GL_STENCIL_BUFFER_BIT; `} +end diff --git a/lib/gtk/v3_4/gtk_core.nit b/lib/gtk/v3_4/gtk_core.nit index 561139b..f6f10aa 100644 --- a/lib/gtk/v3_4/gtk_core.nit +++ b/lib/gtk/v3_4/gtk_core.nit @@ -116,6 +116,17 @@ extern class GtkWidget `{GtkWidget *`} fun visible_self: Bool is extern `{ return gtk_widget_get_visible(recv); `} + + # Destroy the widget + fun destroy `{ gtk_widget_destroy(recv); `} + + # Show the widget on screen + # + # See: `show_all` to recursively show this widget and contained widgets. + fun show `{ gtk_widget_show(recv); `} + + # Hide the widget (reverse the effects of `show`) + fun hide `{ gtk_widget_hide(recv); `} end #Base class for widgets which contain other widgets @@ -348,6 +359,13 @@ extern class GtkGrid `{GtkGrid *`} `} end +# A container box +# +# @https://developer.gnome.org/gtk3/3.4/GtkBox.html +extern class GtkBox `{ GtkBox * `} + super GtkContainer +end + #The tree interface used by GtkTreeView #@https://developer.gnome.org/gtk3/stable/GtkTreeModel.html extern class GtkTreeModel `{GtkTreeModel *`} @@ -386,7 +404,7 @@ extern class GtkEntry `{GtkEntry *`} return (GtkEntry *)gtk_entry_new(); `} - fun text : String is extern import String.to_cstring`{ + fun text : String is extern import NativeString.to_s `{ return NativeString_to_s( (char *)gtk_entry_get_text( recv ) ); `} diff --git a/lib/gtk/v3_4/gtk_dialogs.nit b/lib/gtk/v3_4/gtk_dialogs.nit index 7da083f..079eb71 100644 --- a/lib/gtk/v3_4/gtk_dialogs.nit +++ b/lib/gtk/v3_4/gtk_dialogs.nit @@ -119,8 +119,8 @@ extern class GtkAboutDialog `{GtkAboutDialog *`} # gtk_about_dialog_set_authors( recv, String_to_cstring( authors_list ) ); #`} - fun show ( parent : GtkWindow, params : String ) is extern import String.to_cstring`{ - gtk_show_about_dialog( parent, String_to_cstring( params ), NULL); + fun show_about_dialog(parent: GtkWindow, params: String) import String.to_cstring `{ + gtk_show_about_dialog(parent, String_to_cstring(params), NULL); `} end diff --git a/lib/java/collections.nit b/lib/java/collections.nit new file mode 100644 index 0000000..4da0250 --- /dev/null +++ b/lib/java/collections.nit @@ -0,0 +1,130 @@ +# 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. + +# Basic Java collections +# +# ~~~ +# var coll = new JavaArray(2) +# +# assert coll[0].is_java_null +# coll[0] = "zero".to_java_string +# coll[1] = "one".to_java_string +# +# assert coll.length == 2 +# assert coll.first.to_s == "zero" +# assert coll[1].to_s == "one" +# assert [for e in coll do e.to_s] == ["zero", "one"] +# ~~~ +module collections + +import java + +# Java primitive array +# +# These have fixed size so they offer the same services as `SequenceRead` and +# `[]=`, but would not support `Sequence::add`. +extern class AbstractJavaArray[E: Object] + super SequenceRead[E] + super JavaObject + + # Set the `value` at `key` + fun []=(key: Int, value: E) is abstract + + redef fun iterator do return new JavaArrayIterator[E](self) + + redef fun reverse_iterator do return new JavaArrayReverseIterator[E](self) +end + +# Java primitive array `float[]` +# +# Note that Nit `Float` is the size of a double, so storing them in a +# `JavaFloatArray` may lead to a loss of precision. +extern class JavaFloatArray in "Java" `{ float[] `} + super AbstractJavaArray[Float] + + # Get a new array of the given `size` + new(size: Int) in "Java" `{ return new float[(int)size]; `} + + redef fun [](i) in "Java" `{ return (double)recv[(int)i]; `} + + redef fun []=(i, e) in "Java" `{ recv[(int)i] = (float)e; `} + + redef fun length in "Java" `{ return recv.length; `} +end + +# Java primitive array `double[]` +extern class JavaDoubleArray in "Java" `{ double[] `} + super AbstractJavaArray[Float] + + # Get a new array of the given `size` + new(size: Int) in "Java" `{ return new double[(int)size]; `} + + redef fun [](i) in "Java" `{ return recv[(int)i]; `} + + redef fun []=(i, e) in "Java" `{ recv[(int)i] = (float)e; `} + + redef fun length in "Java" `{ return recv.length; `} +end + +# Java primitive array `Object[]` +extern class JavaArray in "Java" `{ java.lang.Object[] `} + super AbstractJavaArray[JavaObject] + + # Get a new array of the given `size` + new(size: Int) in "Java" `{ return new Object[(int)size]; `} + + redef fun [](i) in "Java" `{ return recv[(int)i]; `} + + redef fun []=(i, e) in "Java" `{ recv[(int)i] = e; `} + + redef fun length in "Java" `{ return recv.length; `} +end + +# TODO other primitive arrays: +# * Java primitive array `byte[]` +# * Java primitive array `short[]` +# * Java primitive array `int[]` +# * Java primitive array `long[]` +# * Java primitive array `boolean[]` +# * Java primitive array `char[]` + +# An `Iterator` on Java primitive arrays +private class JavaArrayIterator[E: Object] + super IndexedIterator[E] + + var array: AbstractJavaArray[E] + + redef fun item do return array[index] + + redef fun is_ok do return index < array.length + + redef fun next do index += 1 + + redef var index = 0 +end + +# A reverse `Iterator` on Java primitive arrays +private class JavaArrayReverseIterator[E: Object] + super IndexedIterator[E] + + var array: AbstractJavaArray[E] + + redef fun item do return array[index] + + redef fun is_ok do return index >= 0 + + redef fun next do index -= 1 + + redef var index = array.length - 1 +end diff --git a/lib/mnit/opengles1.nit b/lib/mnit/opengles1.nit index ebdd8b6..eb1061b 100644 --- a/lib/mnit/opengles1.nit +++ b/lib/mnit/opengles1.nit @@ -29,7 +29,6 @@ in "C header" `{ EGLConfig mnit_config; int32_t mnit_width; int32_t mnit_height; - float mnit_zoom; struct mnit_opengles_Texture { GLuint texture; @@ -207,7 +206,6 @@ class Opengles1Display mnit_config = config; mnit_width = w; mnit_height = h; - mnit_zoom = 1.0f; LOGI("surface", (int)surface); LOGI("display", (int)display); @@ -263,7 +261,6 @@ class Opengles1Display glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrthof(x, x+w, y+h, y, 0.0f, 1.0f); - mnit_zoom = ((float)w)/mnit_width; glMatrixMode(GL_MODELVIEW); glFrontFace( GL_CW ); `} diff --git a/lib/mnit_android/android_app.nit b/lib/mnit_android/android_app.nit index 87afb4a..9d0d6c4 100644 --- a/lib/mnit_android/android_app.nit +++ b/lib/mnit_android/android_app.nit @@ -15,37 +15,18 @@ # limitations under the License. # Impements the services of `mnit:app` using the API from the Android ndk -module android_app is - android_manifest_activity """ +module android_app is android_manifest_activity """ android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:configChanges="orientation|keyboardHidden" - android:screenOrientation="portrait"""" -end +""" import mnit import android import mnit::opengles1 - -in "C header" `{ - #include - #include - #include - #include - - #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "mnit", __VA_ARGS__)) - #ifdef DEBUG - #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "mnit", __VA_ARGS__)) - #else - #define LOGI(...) (void)0 - #endif -`} +intrude import ::android::input_events in "C" `{ #include - #include - #define GL_GLEXT_PROTOTYPES 1 - #include - #include extern EGLDisplay mnit_display; extern EGLSurface mnit_surface; @@ -53,189 +34,28 @@ in "C" `{ extern EGLConfig mnit_config; extern int32_t mnit_width; extern int32_t mnit_height; - extern float mnit_zoom; - - //int mnit_orientation_changed; - float mnit_zoom; - - /* Handle inputs from the Android platform and sort them before - sending them in the Nit App */ - static int32_t mnit_handle_input(struct android_app* app, AInputEvent* event) { - App nit_app = app->userData; - LOGI("handle input %i", (int)pthread_self()); - if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { - LOGI("key"); - return App_extern_input_key(nit_app, event); - } - else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { - LOGI("motion"); - return App_extern_input_motion(nit_app, event); - } - - return 0; - } `} - -extern class InnerAndroidMotionEvent in "C" `{AInputEvent *`} - super Pointer - private fun pointers_count: Int is extern `{ - return AMotionEvent_getPointerCount(recv); - `} - private fun just_went_down: Bool is extern `{ - return (AMotionEvent_getAction(recv) & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN; - `} - private fun edge: Int is extern `{ - return AMotionEvent_getEdgeFlags(recv); - `} - private fun index_down_pointer: Int is extern `{ - int a = AMotionEvent_getAction(recv); - if ((a & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_POINTER_DOWN) - return (a & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; - else return -1; - `} - - private fun action: AMotionEventAction `{ return AMotionEvent_getAction(recv); `} -end - -extern class AMotionEventAction `{ int32_t `} - protected fun action: Int `{ return recv & AMOTION_EVENT_ACTION_MASK; `} - fun is_down: Bool do return action == 0 - fun is_up: Bool do return action == 1 - fun is_move: Bool do return action == 2 - fun is_cancel: Bool do return action == 3 - fun is_outside: Bool do return action == 4 - fun is_pointer_down: Bool do return action == 5 - fun is_pointer_up: Bool do return action == 6 -end - -interface AndroidInputEvent - super InputEvent -end - -class AndroidMotionEvent - super AndroidInputEvent - super MotionEvent - - private init(ie: InnerAndroidMotionEvent) do inner_event = ie - private var inner_event: InnerAndroidMotionEvent - - private var pointers_cache: nullable Array[AndroidPointerEvent] = null - fun pointers: Array[AndroidPointerEvent] - do - if pointers_cache != null then - return pointers_cache.as(not null) - else - var pointers = new Array[AndroidPointerEvent] - var pointers_count = inner_event.pointers_count - for i in [0 .. pointers_count [do - var pointer_event = new AndroidPointerEvent(self, i) - pointers.add(pointer_event) - end - pointers_cache = pointers - return pointers - end - end - - redef fun just_went_down: Bool do return inner_event.just_went_down - fun edge: Int do return inner_event.edge - - redef fun down_pointer: nullable AndroidPointerEvent - do - var i = inner_event.index_down_pointer - if i > 0 then - return pointers[i] - else - return null - end - end -end - -class AndroidPointerEvent - super PointerEvent - super AndroidInputEvent - - protected var motion_event: AndroidMotionEvent - protected var pointer_id: Int - - redef fun x: Float do return extern_x(motion_event.inner_event, pointer_id) - private fun extern_x(motion_event: InnerAndroidMotionEvent, pointer_id: Int): Float is extern `{ - return ((int) AMotionEvent_getX(motion_event, pointer_id)); - `} - - redef fun y: Float do return extern_y(motion_event.inner_event, pointer_id) - private fun extern_y(motion_event: InnerAndroidMotionEvent, pointer_id: Int): Float is extern `{ - return ((int) AMotionEvent_getY(motion_event, pointer_id)); - `} - - fun pressure: Float do return extern_pressure(motion_event.inner_event, pointer_id) - private fun extern_pressure(motion_event: InnerAndroidMotionEvent, pointer_id: Int): Float is extern `{ - return AMotionEvent_getPressure(motion_event, pointer_id); - `} - - redef fun pressed - do - var action = motion_event.inner_event.action - return action.is_down or action.is_move - end - - redef fun depressed do return not pressed -end - -extern class AndroidKeyEvent in "C" `{AInputEvent *`} - super KeyEvent - super AndroidInputEvent - - fun action: Int is extern `{ - return AKeyEvent_getAction(recv); - `} - redef fun is_down: Bool do return action == 0 - redef fun is_up: Bool do return action == 1 - - fun key_code: Int is extern `{ - return AKeyEvent_getKeyCode(recv); - `} - - redef fun to_c `{ - int code = AKeyEvent_getKeyCode(recv); - if (code >= AKEYCODE_0 && code <= AKEYCODE_9) - return '0'+code-AKEYCODE_0; - if (code >= AKEYCODE_A && code <= AKEYCODE_Z) - return 'a'+code-AKEYCODE_A; - return 0; - `} - - fun is_back_key: Bool do return key_code == 4 - fun is_menu_key: Bool do return key_code == 82 - fun is_search_key: Bool do return key_code == 84 - - fun is_volume_up: Bool do return key_code == 24 - fun is_volume_down: Bool do return key_code == 25 -end - redef class App redef type D: Opengles1Display redef fun init_window do - set_as_input_handler native_app_glue display = new Opengles1Display super end - private fun set_as_input_handler(app_glue: NativeAppGlue) import extern_input_key, extern_input_motion `{ - app_glue->onInputEvent = mnit_handle_input; - `} - redef fun full_frame do if not paused then super - # these are used as a callback from native to type incoming events - private fun extern_input_key(event: AndroidKeyEvent): Bool + redef fun generate_input do poll_looper 0 + + redef fun native_input_key(event) do return input(event) end - private fun extern_input_motion(event: InnerAndroidMotionEvent): Bool + + redef fun native_input_motion(event) do var ie = new AndroidMotionEvent(event) var handled = input(ie) @@ -248,6 +68,4 @@ redef class App return handled end - - redef fun generate_input do poll_looper 0 end diff --git a/lib/standard/collection/array.nit b/lib/standard/collection/array.nit index 4b73471..e70acd2 100644 --- a/lib/standard/collection/array.nit +++ b/lib/standard/collection/array.nit @@ -281,6 +281,32 @@ class Array[E] _items[l] = item end + # Slight optimization for arrays + redef fun add_all(items) + do + var l = _length + var nl = l + items.length + if _capacity < nl then + enlarge nl + end + + if items isa Array[E] then + var k = 0 + while l < nl do + _items[l] = items._items[k] + l += 1 + k += 1 + end + else + for item in items do + _items[l] = item + l += 1 + end + end + + _length = nl + end + redef fun enlarge(cap) do var c = _capacity diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index eea089a..f64fc79 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -481,6 +481,10 @@ abstract class AbstractCompiler self.realmainmodule = mainmodule end + # Do the full code generation of the program `mainmodule` + # It is the main method usually called after the instantiation + fun do_compilation is abstract + # Force the creation of a new file # The point is to avoid contamination between must-be-compiled-separately files fun new_file(name: String): CodeFile @@ -2151,7 +2155,7 @@ redef class AMethPropdef do var externname var at = self.get_single_annotation("extern", v.compiler.modelbuilder) - if at != null then + if at != null and at.n_args.length == 1 then externname = at.arg_as_string(v.compiler.modelbuilder) if externname == null then return false else diff --git a/src/compiler/android_platform.nit b/src/compiler/android_platform.nit index 1cf6ba8..5d6d312 100644 --- a/src/compiler/android_platform.nit +++ b/src/compiler/android_platform.nit @@ -234,21 +234,22 @@ $(call import-module,android/native_app_glue) end end - ### copy resources (for android) - # This will be accessed from `android_project_root` - var res_dir + ### Copy resources and libs where expected by the SDK + var project_root if compiler.mainmodule.location.file != null then # it is a real file, use "{file}/../res" - res_dir = "{compiler.mainmodule.location.file.filename.dirname}/../res" + project_root = "{compiler.mainmodule.location.file.filename.dirname}/.." else # probably used -m, use "." - res_dir = "res" + project_root = "." end + + # Android resources folder + var res_dir = project_root / "res" if res_dir.file_exists then # copy the res folder to .nit_compile res_dir = res_dir.realpath - var target_res_dir = "{android_project_root}" - toolcontext.exec_and_check(["cp", "-R", res_dir, target_res_dir], "Android project error") + toolcontext.exec_and_check(["cp", "-R", res_dir, android_project_root], "Android project error") end if not res_dir.file_exists or not "{res_dir}/values/strings.xml".file_exists then @@ -258,6 +259,12 @@ $(call import-module,android/native_app_glue) {{{app_name}}} """.write_to_file "{dir}/res/values/strings.xml" end + + # Android libs folder + var libs_dir = project_root / "libs" + if libs_dir.file_exists then + toolcontext.exec_and_check(["cp", "-r", libs_dir, android_project_root], "Android project error") + end end redef fun write_makefile(compiler, compile_dir, cfiles) diff --git a/src/compiler/global_compiler.nit b/src/compiler/global_compiler.nit index 94dda37..0b42b7b 100644 --- a/src/compiler/global_compiler.nit +++ b/src/compiler/global_compiler.nit @@ -59,6 +59,43 @@ redef class ModelBuilder self.toolcontext.info("*** GENERATING C ***", 1) var compiler = new GlobalCompiler(mainmodule, self, runtime_type_analysis) + compiler.do_compilation + compiler.display_stats + + var time1 = get_time + self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2) + write_and_make(compiler) + end +end + +# Compiler that use global compilation and perform hard optimisations like: +# * customization +# * switch dispatch +# * inlining +class GlobalCompiler + super AbstractCompiler + + redef type VISITOR: GlobalCompilerVisitor + + # The result of the RTA (used to know live types and methods) + var runtime_type_analysis: RapidTypeAnalysis + + init + do + var file = new_file("{mainmodule.c_name}.nitgg") + self.header = new CodeWriter(file) + self.live_primitive_types = new Array[MClassType] + for t in runtime_type_analysis.live_types do + if t.ctype != "val*" or t.mclass.name == "Pointer" then + self.live_primitive_types.add(t) + end + end + end + + redef fun do_compilation + do + var compiler = self + compiler.compile_header if mainmodule.model.get_mclasses_by_name("Pointer") != null then @@ -89,41 +126,11 @@ redef class ModelBuilder # Compile until all runtime_functions are visited while not compiler.todos.is_empty do var m = compiler.todos.shift - self.toolcontext.info("Compile {m} ({compiler.seen.length-compiler.todos.length}/{compiler.seen.length})", 3) + modelbuilder.toolcontext.info("Compile {m} ({compiler.seen.length-compiler.todos.length}/{compiler.seen.length})", 3) m.compile_to_c(compiler) end - self.toolcontext.info("Total methods to compile to C: {compiler.seen.length}", 2) - - compiler.display_stats - - var time1 = get_time - self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2) - write_and_make(compiler) - end -end - -# Compiler that use global compilation and perform hard optimisations like: -# * customization -# * switch dispatch -# * inlining -class GlobalCompiler - super AbstractCompiler - - redef type VISITOR: GlobalCompilerVisitor - - # The result of the RTA (used to know live types and methods) - var runtime_type_analysis: RapidTypeAnalysis + modelbuilder.toolcontext.info("Total methods to compile to C: {compiler.seen.length}", 2) - init - do - var file = new_file("{mainmodule.c_name}.nitgg") - self.header = new CodeWriter(file) - self.live_primitive_types = new Array[MClassType] - for t in runtime_type_analysis.live_types do - if t.ctype != "val*" or t.mclass.name == "Pointer" then - self.live_primitive_types.add(t) - end - end end # Compile class names (for the class_name and output_class_name methods) diff --git a/src/compiler/separate_compiler.nit b/src/compiler/separate_compiler.nit index 13f0bd7..c298f93 100644 --- a/src/compiler/separate_compiler.nit +++ b/src/compiler/separate_compiler.nit @@ -90,12 +90,55 @@ redef class ModelBuilder self.toolcontext.info("*** GENERATING C ***", 1) var compiler = new SeparateCompiler(mainmodule, self, runtime_type_analysis) + compiler.do_compilation + compiler.display_stats + + var time1 = get_time + self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2) + write_and_make(compiler) + end + + # Count number of invocations by VFT + private var nb_invok_by_tables = 0 + # Count number of invocations by direct call + private var nb_invok_by_direct = 0 + # Count number of invocations by inlining + private var nb_invok_by_inline = 0 +end + +# Singleton that store the knowledge about the separate compilation process +class SeparateCompiler + super AbstractCompiler + + redef type VISITOR: SeparateCompilerVisitor + + # The result of the RTA (used to know live types and methods) + var runtime_type_analysis: nullable RapidTypeAnalysis + + private var undead_types: Set[MType] = new HashSet[MType] + private var live_unresolved_types: Map[MClassDef, Set[MType]] = new HashMap[MClassDef, HashSet[MType]] + + private var type_ids: Map[MType, Int] is noinit + private var type_colors: Map[MType, Int] is noinit + private var opentype_colors: Map[MType, Int] is noinit + protected var method_colors: Map[PropertyLayoutElement, Int] is noinit + protected var attr_colors: Map[MAttribute, Int] is noinit + + init do + var file = new_file("nit.common") + self.header = new CodeWriter(file) + self.compile_box_kinds + end + + redef fun do_compilation + do + var compiler = self compiler.compile_header var c_name = mainmodule.c_name # compile class structures - self.toolcontext.info("Property coloring", 2) + modelbuilder.toolcontext.info("Property coloring", 2) compiler.new_file("{c_name}.classes") compiler.do_property_coloring for m in mainmodule.in_importation.greaters do @@ -113,14 +156,22 @@ redef class ModelBuilder # compile methods for m in mainmodule.in_importation.greaters do - self.toolcontext.info("Generate C for module {m.full_name}", 2) + modelbuilder.toolcontext.info("Generate C for module {m.full_name}", 2) compiler.new_file("{m.c_name}.sep") compiler.compile_module_to_c(m) end # compile live & cast type structures - self.toolcontext.info("Type coloring", 2) + modelbuilder.toolcontext.info("Type coloring", 2) compiler.new_file("{c_name}.types") + compiler.compile_types + end + + # Color and compile type structures and cast information + fun compile_types + do + var compiler = self + var mtypes = compiler.do_type_coloring for t in mtypes do compiler.compile_type_to_c(t) @@ -131,43 +182,6 @@ redef class ModelBuilder compiler.compile_type_to_c(t) end - compiler.display_stats - - var time1 = get_time - self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2) - write_and_make(compiler) - end - - # Count number of invocations by VFT - private var nb_invok_by_tables = 0 - # Count number of invocations by direct call - private var nb_invok_by_direct = 0 - # Count number of invocations by inlining - private var nb_invok_by_inline = 0 -end - -# Singleton that store the knowledge about the separate compilation process -class SeparateCompiler - super AbstractCompiler - - redef type VISITOR: SeparateCompilerVisitor - - # The result of the RTA (used to know live types and methods) - var runtime_type_analysis: nullable RapidTypeAnalysis - - private var undead_types: Set[MType] = new HashSet[MType] - private var live_unresolved_types: Map[MClassDef, Set[MType]] = new HashMap[MClassDef, HashSet[MType]] - - private var type_ids: Map[MType, Int] is noinit - private var type_colors: Map[MType, Int] is noinit - private var opentype_colors: Map[MType, Int] is noinit - protected var method_colors: Map[PropertyLayoutElement, Int] is noinit - protected var attr_colors: Map[MAttribute, Int] is noinit - - init do - var file = new_file("nit.common") - self.header = new CodeWriter(file) - self.compile_box_kinds end redef fun compile_header_structs do diff --git a/src/compiler/separate_erasure_compiler.nit b/src/compiler/separate_erasure_compiler.nit index 233bf54..8a33265 100644 --- a/src/compiler/separate_erasure_compiler.nit +++ b/src/compiler/separate_erasure_compiler.nit @@ -65,35 +65,8 @@ redef class ModelBuilder self.toolcontext.info("*** GENERATING C ***", 1) var compiler = new SeparateErasureCompiler(mainmodule, self, runtime_type_analysis) - compiler.compile_header - - var c_name = mainmodule.c_name - - # compile class structures - self.toolcontext.info("Property coloring", 2) - compiler.new_file("{c_name}.tables") - compiler.do_property_coloring - for m in mainmodule.in_importation.greaters do - for mclass in m.intro_mclasses do - compiler.compile_class_to_c(mclass) - end - end - compiler.compile_color_consts(compiler.vt_colors) - - # The main function of the C - compiler.new_file("{c_name}.main") - compiler.compile_nitni_global_ref_functions - compiler.compile_main_function - - # compile methods - for m in mainmodule.in_importation.greaters do - self.toolcontext.info("Generate C for module {m.full_name}", 2) - compiler.new_file("{m.c_name}.sep") - compiler.compile_module_to_c(m) - end - + compiler.do_compilation compiler.display_stats - var time1 = get_time self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2) write_and_make(compiler) @@ -298,7 +271,7 @@ class SeparateErasureCompiler self.header.add_decl("\};") #Build BOX - self.provide_declaration("BOX_{c_name}", "val* BOX_{c_name}({mtype.ctype});") + self.provide_declaration("BOX_{c_name}", "val* BOX_{c_name}({mtype.ctype_extern});") v.add_decl("/* allocate {mtype} */") v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype} value) \{") v.add("struct instance_{c_name}*res = nit_alloc(sizeof(struct instance_{c_name}));") @@ -435,6 +408,11 @@ class SeparateErasureCompiler end end + redef fun compile_types + do + compile_color_consts(vt_colors) + end + redef fun new_visitor do return new SeparateErasureCompilerVisitor(self) # Stats diff --git a/src/ffi/java.nit b/src/ffi/java.nit index 9191141..1fa56e9 100644 --- a/src/ffi/java.nit +++ b/src/ffi/java.nit @@ -518,6 +518,35 @@ redef class MClassType else break end + # Change `float[]` to `[float` + if jni_type.has('[') then + var depth = jni_type.chars.count('[') + var java_type = jni_type.replace("[]", "") + var short + + if java_type == "boolean" then + short = "Z" + else if java_type == "byte" then + short = "B" + else if java_type == "char" then + short = "C" + else if java_type == "short" then + short = "S" + else if java_type == "int" then + short = "I" + else if java_type == "long" then + short = "J" + else if java_type == "float" then + short = "F" + else if java_type == "double" then + short = "D" + else + short = "L{java_type};" + end + + return "["*depth + short + end + return "L{jni_type};" end if mclass.name == "Bool" then return "Z" @@ -530,6 +559,7 @@ redef class MClassType redef fun jni_signature_alt do var ftype = mclass.ftype + if ftype isa ForeignJavaType then return "Object" if mclass.name == "Bool" then return "Boolean" if mclass.name == "Char" then return "Char" diff --git a/src/frontend/no_warning.nit b/src/frontend/no_warning.nit index 3c31b65..931440e 100644 --- a/src/frontend/no_warning.nit +++ b/src/frontend/no_warning.nit @@ -32,20 +32,25 @@ private class NoWarningPhase var mmodule = nmodule.mmodule assert mmodule != null + var source = nmodule.location.file + # If no decl block then quit var nmoduledecl = nmodule.n_moduledecl - if nmoduledecl == null then return + if nmoduledecl == null then + # Disable `missing-doc` if there is no `module` clause + # Rationale: the presence of a `module` clause is a good heuristic to + # discriminate quick and dirty prototypes from nice and clean modules + if source != null then toolcontext.warning_blacklist[source].add("missing-doc") + return + end var modelbuilder = toolcontext.modelbuilder - var source = nmodule.location.file - # Disable `missing-doc` for `test_suite` if source != null and not nmoduledecl.get_annotations("test_suite").is_empty then toolcontext.warning_blacklist[source].add("missing-doc") end - # Get all the `no_warning` annotations var name = "no_warning" var annots = nmoduledecl.get_annotations(name) diff --git a/src/modelize/modelize_property.nit b/src/modelize/modelize_property.nit index 11fa271..0fd7acc 100644 --- a/src/modelize/modelize_property.nit +++ b/src/modelize/modelize_property.nit @@ -45,11 +45,16 @@ redef class ModelBuilder # Retrieve the associated AST node of a mpropertydef. # This method is used to associate model entity with syntactic entities. # - # If the property definition is not associated with a node, returns node. + # If the property definition is not associated with a node, returns `null`. fun mpropdef2node(mpropdef: MPropDef): nullable ANode do - var res: nullable ANode = mpropdef2npropdef.get_or_null(mpropdef) - if res != null then return res + var res + res = mpropdef2npropdef.get_or_null(mpropdef) + if res != null then + # Run the phases on it + toolcontext.run_phases_on_npropdef(res) + return res + end if mpropdef isa MMethodDef and mpropdef.mproperty.is_root_init then res = mclassdef2nclassdef.get_or_null(mpropdef.mclassdef) if res != null then return res @@ -66,6 +71,8 @@ redef class ModelBuilder if n == null then return res for npropdef in n.n_propdefs do if npropdef isa AAttrPropdef then + # Run the phases on it + toolcontext.run_phases_on_npropdef(npropdef) res.add(npropdef) end end diff --git a/src/phase.nit b/src/phase.nit index 5729313..1a10cf2 100644 --- a/src/phase.nit +++ b/src/phase.nit @@ -30,11 +30,14 @@ redef class ToolContext # --disable-phase var opt_disable_phase = new OptionArray("DEBUG: Disable a specific phase; use `list` to get the list.", "--disable-phase") + # --disable-phase + var opt_sloppy = new OptionBool("DEBUG: force lazy semantic analysis of the source-code", "--sloppy") + redef init do super - option_context.add_option(opt_disable_phase) + option_context.add_option(opt_disable_phase, opt_sloppy) end redef fun process_options(args) @@ -62,16 +65,24 @@ redef class ToolContext end if not found then fatal_error(null, "Error: no phase named `{v}`. Use `list` to list all phases.") end + + if opt_sloppy.value then semantize_is_lazy = true end # The list of registered phases in the application order. - fun phases_list: Sequence[Phase] - do + var phases_list: Sequence[Phase] is lazy do var phases = self.phases.to_a self.phases.sort(phases) return phases end + # Is `phase_process_npropdef` not called automatically by `run_phases`? + # + # When set to true, it is the responsibility of the tools + # + # Is false by default. + var semantize_is_lazy = false is writable + # Set of already analyzed modules. private var phased_modules = new HashSet[AModule] @@ -111,7 +122,7 @@ redef class ToolContext for nclassdef in nmodule.n_classdefs do assert phase.toolcontext == self phase.process_nclassdef(nclassdef) - for npropdef in nclassdef.n_propdefs do + if not semantize_is_lazy then for npropdef in nclassdef.n_propdefs do assert phase.toolcontext == self phase_process_npropdef(phase, npropdef) end @@ -143,6 +154,31 @@ redef class ToolContext do phase.process_npropdef(npropdef) end + + # Run the phase on the given npropdef. + # Does nothing if `semantize_is_lazy` is false. + fun run_phases_on_npropdef(npropdef: APropdef) + do + if not semantize_is_lazy then return + if npropdef.is_phased then return + npropdef.is_phased = true + + #self.info("Semantic analysis of property {npropdef.location.file.filename}", 0) + + var phases = phases_list + for phase in phases do + if phase.disabled then continue + assert phase.toolcontext == self + phase_process_npropdef(phase, npropdef) + self.check_errors + end + end +end + +redef class APropdef + # Is the propdef already analyzed by `run_phases_on_npropdef`. + # Unused unless `semantize_is_lazy` is true. + private var is_phased = false end # Collect all annotation diff --git a/src/semantize/typing.nit b/src/semantize/typing.nit index 1dfaec6..9d24a21 100644 --- a/src/semantize/typing.nit +++ b/src/semantize/typing.nit @@ -1243,7 +1243,7 @@ redef class AArrayExpr if mtype == null then mtype = v.merge_types(self, mtypes) end - if mtype == null then + if mtype == null or mtype isa MNullType then v.error(self, "Type Error: ambiguous array type {mtypes.join(" ")}") return end diff --git a/tests/base_array.nit b/tests/base_array.nit index f37dd3a..3071768 100644 --- a/tests/base_array.nit +++ b/tests/base_array.nit @@ -25,3 +25,4 @@ for i in a do end #alt1# var b = [10, true] +#alt2# var c = [null, null] diff --git a/tests/bench_add_all.nit b/tests/bench_add_all.nit new file mode 100644 index 0000000..733ac9b --- /dev/null +++ b/tests/bench_add_all.nit @@ -0,0 +1,30 @@ +# 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. + +# Performance test for Array::add_all + +import standard::collection + +var a = new Array[Numeric] +var b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +for i in 10000.times do + a.add_all b +end + +var c = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0] +for i in 10000.times do + a.add_all c +end + +a.length.output diff --git a/tests/sav/base_array_alt2.res b/tests/sav/base_array_alt2.res new file mode 100644 index 0000000..e9c5053 --- /dev/null +++ b/tests/sav/base_array_alt2.res @@ -0,0 +1 @@ +alt/base_array_alt2.nit:28,9--20: Type Error: ambiguous array type null null diff --git a/tests/sav/bench_add_all.res b/tests/sav/bench_add_all.res new file mode 100644 index 0000000..87766d8 --- /dev/null +++ b/tests/sav/bench_add_all.res @@ -0,0 +1 @@ +200000 diff --git a/tests/sav/test_new_native_alt1.res b/tests/sav/test_new_native_alt1.res index c4db140..2ebac03 100644 --- a/tests/sav/test_new_native_alt1.res +++ b/tests/sav/test_new_native_alt1.res @@ -1,4 +1,4 @@ -Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:786) +Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:812) NativeString N Nit