Merge: Compilation to JavaScript using the Emscripten SDK
authorJean Privat <jean@pryen.org>
Tue, 17 Jun 2014 02:17:34 +0000 (22:17 -0400)
committerJean Privat <jean@pryen.org>
Tue, 17 Jun 2014 15:17:04 +0000 (11:17 -0400)
Published for review but still needs some doc and examples. Works with most small examples but not yet with the naive_interpreter (but it's not clear why).

Usage:

    apt-get emscripten
    nitg -m emscripten examples/hello_world.nit
    nodejs hello_wold.js

Pull-Request: #506
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

37 files changed:
examples/mnit_ballz/src/ballz_android.nit
examples/mnit_dino/src/dino.nit
examples/mnit_moles/src/moles.nit
examples/shoot/src/shoot.nit
lib/mnit/mnit.nit
lib/mnit/mnit_fps.nit [new file with mode: 0644]
lib/perfect_hashing.nit
src/modelize_class.nit
src/modelize_property.nit
src/nitvm.nit [new file with mode: 0644]
src/typing.nit
src/vm.nit [new file with mode: 0644]
tests/error_defs.nit
tests/error_toplevel.nit [new file with mode: 0644]
tests/niti.skip
tests/nitvm.args [new file with mode: 0644]
tests/sav/base_iterator3.res
tests/sav/error_defs_alt9.res [new file with mode: 0644]
tests/sav/error_expr_not_ok_alt4.res
tests/sav/error_expr_not_ok_alt5.res
tests/sav/error_expr_not_ok_alt6.res
tests/sav/error_for_coll.res
tests/sav/error_needed_method_alt2.res
tests/sav/error_needed_types_alt8.res
tests/sav/error_toplevel.res [new file with mode: 0644]
tests/sav/error_toplevel_alt1.res [new file with mode: 0644]
tests/sav/error_toplevel_alt2.res [new file with mode: 0644]
tests/sav/error_toplevel_alt3.res [new file with mode: 0644]
tests/sav/error_toplevel_alt4.res [new file with mode: 0644]
tests/sav/error_toplevel_alt5.res [new file with mode: 0644]
tests/sav/nitlight_args1.res
tests/sav/nitmetrics_args1.res
tests/sav/nitvm.res [new file with mode: 0644]
tests/sav/nitvm_args1.res [new file with mode: 0644]
tests/sav/nitvm_args2.res [new file with mode: 0644]
tests/sav/nitvm_args3.res [new file with mode: 0644]
tests/sav/nitx_args3.res

index 18e1b84..823edd9 100644 (file)
 
 module ballz_android
 
-import realtime
 import game_logic
 
 redef class App
 
        var screen: nullable Screen
 
-       var target_dt = 20000000
-
        redef fun run
        do
                sensors_support_enabled = true
@@ -34,6 +31,7 @@ redef class App
                gyroscope.enabled = true
                light.enabled = true
                proximity.enabled = true
+               maximum_fps = 50
 
                super
        end
@@ -48,16 +46,8 @@ redef class App
        do
                var screen = self.screen
                if screen != null then
-                       var clock = new Clock
-
                        screen.game.do_turn
                        screen.do_frame(display)
-                       
-                       var dt = clock.lapse
-                       if dt.sec == 0 and dt.nanosec < target_dt then
-                               var sleep_t = target_dt - dt.nanosec
-                               sys.nanosleep(0, sleep_t)
-                       end
                end
        end
 
index 23314f8..11efd91 100644 (file)
@@ -21,7 +21,6 @@ module dino is
 end
 
 import mnit
-import realtime
 
 import graphism
 import fancy_dino
@@ -31,8 +30,6 @@ redef class App
        var cavemen_at_first_level = 6
        var cavemen_incr = 4
 
-       var target_dt = 12000000
-
        var game : nullable Game = null
        var score = new Container[Int](0)
        var imgs : nullable ImageSet = null
@@ -42,6 +39,8 @@ redef class App
        do
                super
 
+               maximum_fps = 80
+
                var display = display
                assert display != null
 
@@ -59,16 +58,8 @@ redef class App
        do
                var game = game
                if game != null then
-                       var clock = new Clock
-
                        var turn = game.do_turn
                        game.draw( display, imgs.as(not null), turn )
-
-                       var dt = clock.lapse
-                       if dt.sec == 0 and dt.nanosec < target_dt then
-                               var sleep_t = target_dt - dt.nanosec
-                               sys.nanosleep(0, sleep_t)
-                       end
                else
                        splash.draw( display, true )
                end
index a0d783a..08642d1 100644 (file)
@@ -20,7 +20,6 @@
 module moles
 
 import mnit
-import realtime
 
 class Hole
        var game: Game
@@ -231,12 +230,11 @@ redef class App
 
        var screen: nullable Screen = null
 
-       var target_dt = 20000000
-
        redef fun window_created
        do
                super
 
+               maximum_fps = 50
                init_screen_and_game
        end
 
@@ -246,16 +244,8 @@ redef class App
        do
                var screen = self.screen
                if screen != null then
-                       var clock = new Clock
-
                        screen.game.do_turn
                        screen.do_frame(display)
-
-                       var dt = clock.lapse
-                       if dt.sec == 0 and dt.nanosec < target_dt then
-                               var sleep_t = target_dt - dt.nanosec
-                               sys.nanosleep(0, sleep_t)
-                       end
                end
        end
 
index f4001c8..48cadaa 100644 (file)
@@ -380,9 +380,6 @@ redef class App
                        if not self.scene.exists then quit = true
                end
                self.scene.draw_on_display(self)
-
-               # Wait the next frame
-               sys.nanosleep(0, 16000000)
        end
 
        var paused: Bool = false
index 3e313d4..53c4681 100644 (file)
@@ -21,3 +21,4 @@ import mnit_app
 import opengles1
 import assets
 import numbers
+import mnit_fps
diff --git a/lib/mnit/mnit_fps.nit b/lib/mnit/mnit_fps.nit
new file mode 100644 (file)
index 0000000..cd30e83
--- /dev/null
@@ -0,0 +1,75 @@
+# 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.
+
+# Frame-rate control for applications
+module mnit_fps
+
+import mnit_app
+private import realtime
+
+redef class App
+       # Limit the frame-rate to a given frequency
+       # This basically limits how much `frame_core` is called per second.
+       # Zero (or a negative value) means no limit.
+       #
+       # Applications can modify this value even during the main-loop.
+       var maximum_fps writable = 60
+
+       # Current frame-rate
+       # Updated each 5 seconds.
+       var current_fps = 0.0
+
+       redef fun full_frame
+       do
+               super
+               limit_fps
+       end
+
+       # The clock for limit_fps
+       private var clock = new Clock
+
+       # Number of frames since the last deadline
+       # Used tocompute `current_fps`.
+       private var frame_count = 0
+
+       # Deadline used to compute `current_fps`
+       private var frame_count_deadline = 0
+
+       # Check and sleep to maitain a frame-rate bellow `maximum_fps`
+       # Also periodically uptate `current_fps`
+       # Is automatically called at the end of `full_frame`.
+       fun limit_fps
+       do
+               var t = clock.total.sec
+               if t >= frame_count_deadline then
+                       var cfps = frame_count_deadline.to_f / 5.0
+                       self.current_fps = cfps
+                       frame_count = 0
+                       frame_count_deadline = t + 5
+               end
+               frame_count += 1
+
+               var mfps = maximum_fps
+               if mfps <= 0 then return
+               var dt = clock.lapse
+               var target_dt = 1000000000 / mfps
+               var sec = dt.sec
+               var nanosec = dt.nanosec
+               if sec == 0 and nanosec < target_dt then
+                       var sleep_t = target_dt - nanosec
+                       sys.nanosleep(0, sleep_t)
+                       dt = clock.lapse
+               end
+       end
+end
index 9ac59f3..a4b8417 100644 (file)
@@ -35,7 +35,7 @@ class Perfecthashing
        do
                # By default, all identifiers are available
                interval = new List[Couple[nullable Int, nullable Int]]
-               interval.push(new Couple[nullable Int, nullable Int](0, null))
+               interval.push(new Couple[nullable Int, nullable Int](1, null))
                tempht = new Array[nullable Int]
        end
        
index 4cd9475..09b7081 100644 (file)
@@ -97,7 +97,12 @@ redef class ModelBuilder
                        error(nvisibility, "Error: refinement changed the visibility from a {mclass.visibility} to a {mvisibility}")
                end
                nclassdef.mclass = mclass
-               nmodule.mclass2nclassdef[mclass] = nclassdef
+               if not nmodule.mclass2nclassdef.has_key(mclass) then
+                       nmodule.mclass2nclassdef[mclass] = nclassdef
+                       nclassdef.all_defs = [nclassdef]
+               else
+                       nmodule.mclass2nclassdef[mclass].all_defs.add(nclassdef)
+               end
        end
 
        # Visit the AST and create the `MClassDef` objects
@@ -107,7 +112,14 @@ redef class ModelBuilder
                var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
                var mclass = nclassdef.mclass
                if mclass == null then return # Skip error
-               #var mclassdef = nclassdef.mclassdef.as(not null)
+
+               # In case of non-standard AClassdef, try to attach to an already existing mclassdef
+               var other_nclassdef = nmodule.mclass2nclassdef[mclass]
+               if other_nclassdef != nclassdef then
+                       assert not nclassdef isa AStdClassdef
+                       nclassdef.mclassdef = other_nclassdef.mclassdef
+                       return
+               end
 
                var names = new Array[String]
                var bounds = new Array[MType]
@@ -281,8 +293,7 @@ redef class ModelBuilder
                if errcount != toolcontext.error_count then return
 
                # Create the mclassdef hierarchy
-               for nclassdef in nmodule.n_classdefs do
-                       var mclassdef = nclassdef.mclassdef.as(not null)
+               for mclassdef in mmodule.mclassdefs do
                        mclassdef.add_in_hierarchy
                end
 
@@ -505,6 +516,8 @@ redef class AClassdef
        var mclass: nullable MClass
        # The associated MClassDef once build by a `ModelBuilder`
        var mclassdef: nullable MClassDef
+       # All (self and other) definitions for the same mclassdef
+       var all_defs: nullable Array[AClassdef]
 end
 
 redef class AClasskind
index e24541e..3563862 100644 (file)
@@ -28,6 +28,7 @@ private class ModelizePropertyPhase
        redef fun process_nmodule(nmodule)
        do
                for nclassdef in nmodule.n_classdefs do
+                       if nclassdef.all_defs == null then continue # skip non principal classdef
                        toolcontext.modelbuilder.build_properties(nclassdef)
                end
        end
@@ -52,14 +53,16 @@ redef class ModelBuilder
                        build_properties(mclassdef2nclassdef[superclassdef])
                end
 
-               for npropdef in nclassdef.n_propdefs do
-                       npropdef.build_property(self, nclassdef)
-               end
-               for npropdef in nclassdef.n_propdefs do
-                       npropdef.build_signature(self)
-               end
-               for npropdef in nclassdef.n_propdefs do
-                       npropdef.check_signature(self)
+               for nclassdef2 in nclassdef.all_defs do
+                       for npropdef in nclassdef2.n_propdefs do
+                               npropdef.build_property(self, mclassdef)
+                       end
+                       for npropdef in nclassdef2.n_propdefs do
+                               npropdef.build_signature(self)
+                       end
+                       for npropdef in nclassdef2.n_propdefs do
+                               npropdef.check_signature(self)
+                       end
                end
                process_default_constructors(nclassdef)
        end
@@ -225,7 +228,9 @@ redef class AClassdef
 
        # The free init (implicitely constructed by the class if required)
        var mfree_init: nullable MMethodDef = null
+end
 
+redef class MClassDef
        # What is the `APropdef` associated to a `MProperty`?
        # Used to check multiple definition of a property.
        var mprop2npropdef: Map[MProperty, APropdef] = new HashMap[MProperty, APropdef]
@@ -260,7 +265,7 @@ redef class APropdef
        # The associated propdef once build by a `ModelBuilder`
        var mpropdef: nullable MPROPDEF writable
 
-       private fun build_property(modelbuilder: ModelBuilder, nclassdef: AClassdef) is abstract
+       private fun build_property(modelbuilder: ModelBuilder, mclassdef: MClassDef) is abstract
        private fun build_signature(modelbuilder: ModelBuilder) is abstract
        private fun check_signature(modelbuilder: ModelBuilder) is abstract
        private fun new_property_visibility(modelbuilder: ModelBuilder, mclassdef: MClassDef, nvisibility: nullable AVisibility): MVisibility
@@ -306,13 +311,13 @@ redef class APropdef
                end
        end
 
-       private fun check_redef_keyword(modelbuilder: ModelBuilder, nclassdef: AClassdef, kwredef: nullable Token, need_redef: Bool, mprop: MProperty): Bool
+       private fun check_redef_keyword(modelbuilder: ModelBuilder, mclassdef: MClassDef, kwredef: nullable Token, need_redef: Bool, mprop: MProperty): Bool
        do
-               if nclassdef.mprop2npropdef.has_key(mprop) then
-                       modelbuilder.error(self, "Error: A property {mprop} is already defined in class {nclassdef.mclassdef.mclass} at line {nclassdef.mprop2npropdef[mprop].location.line_start}.")
+               if mclassdef.mprop2npropdef.has_key(mprop) then
+                       modelbuilder.error(self, "Error: A property {mprop} is already defined in class {mclassdef.mclass} at line {mclassdef.mprop2npropdef[mprop].location.line_start}.")
                        return false
                end
-               if mprop isa MMethod and mprop.is_toplevel != (nclassdef isa ATopClassdef) then
+               if mprop isa MMethod and mprop.is_toplevel != (parent isa ATopClassdef) then
                        if mprop.is_toplevel then
                                modelbuilder.error(self, "Error: {mprop} is a top level method.")
                        else
@@ -323,12 +328,12 @@ redef class APropdef
                end
                if kwredef == null then
                        if need_redef then
-                               modelbuilder.error(self, "Redef error: {nclassdef.mclassdef.mclass}::{mprop.name} is an inherited property. To redefine it, add the redef keyword.")
+                               modelbuilder.error(self, "Redef error: {mclassdef.mclass}::{mprop.name} is an inherited property. To redefine it, add the redef keyword.")
                                return false
                        end
                else
                        if not need_redef then
-                               modelbuilder.error(self, "Error: No property {nclassdef.mclassdef.mclass}::{mprop.name} is inherited. Remove the redef keyword to define a new property.")
+                               modelbuilder.error(self, "Error: No property {mclassdef.mclass}::{mprop.name} is inherited. Remove the redef keyword to define a new property.")
                                return false
                        end
                end
@@ -416,12 +421,11 @@ end
 redef class AMethPropdef
        redef type MPROPDEF: MMethodDef
 
-       redef fun build_property(modelbuilder, nclassdef)
+       redef fun build_property(modelbuilder, mclassdef)
        do
                var n_kwinit = n_kwinit
                var n_kwnew = n_kwnew
                var is_init = n_kwinit != null or n_kwnew != null
-               var mclassdef = nclassdef.mclassdef.as(not null)
                var name: String
                var amethodid = self.n_methid
                var name_node: ANode
@@ -458,13 +462,13 @@ redef class AMethPropdef
                        mprop = new MMethod(mclassdef, name, mvisibility)
                        mprop.is_init = is_init
                        mprop.is_new = n_kwnew != null
-                       if nclassdef isa ATopClassdef then mprop.is_toplevel = true
-                       if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mprop) then return
+                       if parent isa ATopClassdef then mprop.is_toplevel = true
+                       if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mprop) then return
                else
-                       if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, not self isa AMainMethPropdef, mprop) then return
+                       if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, not self isa AMainMethPropdef, mprop) then return
                        check_redef_property_visibility(modelbuilder, self.n_visibility, mprop)
                end
-               nclassdef.mprop2npropdef[mprop] = self
+               mclassdef.mprop2npropdef[mprop] = self
 
                var mpropdef = new MMethodDef(mclassdef, mprop, self.location)
 
@@ -624,9 +628,8 @@ redef class AAttrPropdef
        var mreadpropdef: nullable MMethodDef writable
        # The associated setter (write accessor) if any
        var mwritepropdef: nullable MMethodDef writable
-       redef fun build_property(modelbuilder, nclassdef)
+       redef fun build_property(modelbuilder, mclassdef)
        do
-               var mclassdef = nclassdef.mclassdef.as(not null)
                var mclass = mclassdef.mclass
 
                var name: String
@@ -651,13 +654,13 @@ redef class AAttrPropdef
                        if mprop == null then
                                var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility)
                                mprop = new MAttribute(mclassdef, name, mvisibility)
-                               if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, false, mprop) then return
+                               if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, false, mprop) then return
                        else
                                assert mprop isa MAttribute
                                check_redef_property_visibility(modelbuilder, self.n_visibility, mprop)
-                               if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, true, mprop) then return
+                               if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, true, mprop) then return
                        end
-                       nclassdef.mprop2npropdef[mprop] = self
+                       mclassdef.mprop2npropdef[mprop] = self
 
                        var mpropdef = new MAttributeDef(mclassdef, mprop, self.location)
                        self.mpropdef = mpropdef
@@ -671,12 +674,12 @@ redef class AAttrPropdef
                                if mreadprop == null then
                                        var mvisibility = new_property_visibility(modelbuilder, mclassdef, nreadable.n_visibility)
                                        mreadprop = new MMethod(mclassdef, readname, mvisibility)
-                                       if not self.check_redef_keyword(modelbuilder, nclassdef, nreadable.n_kwredef, false, mreadprop) then return
+                                       if not self.check_redef_keyword(modelbuilder, mclassdef, nreadable.n_kwredef, false, mreadprop) then return
                                else
-                                       if not self.check_redef_keyword(modelbuilder, nclassdef, nreadable.n_kwredef, true, mreadprop) then return
+                                       if not self.check_redef_keyword(modelbuilder, mclassdef, nreadable.n_kwredef, true, mreadprop) then return
                                        check_redef_property_visibility(modelbuilder, nreadable.n_visibility, mreadprop)
                                end
-                               nclassdef.mprop2npropdef[mreadprop] = self
+                               mclassdef.mprop2npropdef[mreadprop] = self
 
                                var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location)
                                self.mreadpropdef = mreadpropdef
@@ -691,12 +694,12 @@ redef class AAttrPropdef
                                if mwriteprop == null then
                                        var mvisibility = new_property_visibility(modelbuilder, mclassdef, nwritable.n_visibility)
                                        mwriteprop = new MMethod(mclassdef, writename, mvisibility)
-                                       if not self.check_redef_keyword(modelbuilder, nclassdef, nwritable.n_kwredef, false, mwriteprop) then return
+                                       if not self.check_redef_keyword(modelbuilder, mclassdef, nwritable.n_kwredef, false, mwriteprop) then return
                                else
-                                       if not self.check_redef_keyword(modelbuilder, nclassdef, nwritable.n_kwredef, true, mwriteprop) then return
+                                       if not self.check_redef_keyword(modelbuilder, mclassdef, nwritable.n_kwredef, true, mwriteprop) then return
                                        check_redef_property_visibility(modelbuilder, nwritable.n_visibility, mwriteprop)
                                end
-                               nclassdef.mprop2npropdef[mwriteprop] = self
+                               mclassdef.mprop2npropdef[mwriteprop] = self
 
                                var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location)
                                self.mwritepropdef = mwritepropdef
@@ -717,12 +720,12 @@ redef class AAttrPropdef
                        if mreadprop == null then
                                var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility)
                                mreadprop = new MMethod(mclassdef, readname, mvisibility)
-                               if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mreadprop) then return
+                               if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mreadprop) then return
                        else
-                               if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, true, mreadprop) then return
+                               if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, true, mreadprop) then return
                                check_redef_property_visibility(modelbuilder, self.n_visibility, mreadprop)
                        end
-                       nclassdef.mprop2npropdef[mreadprop] = self
+                       mclassdef.mprop2npropdef[mreadprop] = self
 
                        var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location)
                        self.mreadpropdef = mreadpropdef
@@ -742,14 +745,14 @@ redef class AAttrPropdef
                                        mvisibility = private_visibility
                                end
                                mwriteprop = new MMethod(mclassdef, writename, mvisibility)
-                               if not self.check_redef_keyword(modelbuilder, nclassdef, nwkwredef, false, mwriteprop) then return
+                               if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef, false, mwriteprop) then return
                        else
-                               if not self.check_redef_keyword(modelbuilder, nclassdef, nwkwredef, true, mwriteprop) then return
+                               if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef, true, mwriteprop) then return
                                if nwritable != null then
                                        check_redef_property_visibility(modelbuilder, nwritable.n_visibility, mwriteprop)
                                end
                        end
-                       nclassdef.mprop2npropdef[mwriteprop] = self
+                       mclassdef.mprop2npropdef[mwriteprop] = self
 
                        var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location)
                        self.mwritepropdef = mwritepropdef
@@ -934,9 +937,8 @@ end
 redef class ATypePropdef
        redef type MPROPDEF: MVirtualTypeDef
 
-       redef fun build_property(modelbuilder, nclassdef)
+       redef fun build_property(modelbuilder, mclassdef)
        do
-               var mclassdef = nclassdef.mclassdef.as(not null)
                var name = self.n_id.text
                var mprop = modelbuilder.try_get_mproperty_by_name(self.n_id, mclassdef, name)
                if mprop == null then
@@ -946,13 +948,13 @@ redef class ATypePropdef
                                modelbuilder.warning(n_id, "Warning: lowercase in the virtual type {name}")
                                break
                        end
-                       if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, false, mprop) then return
+                       if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, false, mprop) then return
                else
-                       if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, true, mprop) then return
+                       if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, true, mprop) then return
                        assert mprop isa MVirtualTypeProp
                        check_redef_property_visibility(modelbuilder, self.n_visibility, mprop)
                end
-               nclassdef.mprop2npropdef[mprop] = self
+               mclassdef.mprop2npropdef[mprop] = self
 
                var mpropdef = new MVirtualTypeDef(mclassdef, mprop, self.location)
                self.mpropdef = mpropdef
diff --git a/src/nitvm.nit b/src/nitvm.nit
new file mode 100644 (file)
index 0000000..9a62208
--- /dev/null
@@ -0,0 +1,62 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2012 Jean Privat <jean@pryen.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.
+
+# The Nit virtual machine launcher
+module nitvm
+
+import vm
+
+# Create a tool context to handle options and paths
+var toolcontext = new ToolContext
+toolcontext.tooldescription = "Usage: nitvm [OPTION]... <file.nit>...\nExecutes Nit programs with a virtual machine."
+# Add an option "-o" to enable compatibility with the tests.sh script
+var opt = new OptionString("compatibility (does nothing)", "-o")
+toolcontext.option_context.add_option(opt)
+var opt_mixins = new OptionArray("Additional modules to min-in", "-m")
+toolcontext.option_context.add_option(opt_mixins)
+# We do not add other options, so process them now!
+toolcontext.process_options(args)
+
+# We need a model to collect stufs
+var model = new Model
+
+# Add a model builder to parse files
+var modelbuilder = new ModelBuilder(model, toolcontext.as(not null))
+
+var arguments = toolcontext.option_context.rest
+var progname = arguments.first
+
+# Here we load and process all modules passed on the command line
+var mmodules = modelbuilder.parse([progname])
+mmodules.add_all modelbuilder.parse(opt_mixins.value)
+modelbuilder.run_phases
+
+if toolcontext.opt_only_metamodel.value then exit(0)
+
+var mainmodule: nullable MModule
+
+# Here we launch the interpreter on the main module
+if mmodules.length == 1 then
+       mainmodule = mmodules.first
+else
+       mainmodule = new MModule(model, null, mmodules.first.name, mmodules.first.location)
+       mainmodule.set_imported_mmodules(mmodules)
+end
+
+var self_mm = mainmodule.as(not null)
+var self_args = arguments.as(not null)
+
+modelbuilder.run_naive_interpreter(self_mm, self_args)
index edb1c89..5db0ada 100644 (file)
@@ -51,6 +51,11 @@ private class TypeVisitor
 
        var selfvariable: Variable = new Variable("self")
 
+       # Is `self` use restricted?
+       # * no explicit `self`
+       # * method called on the implicit self must be top-level
+       var is_toplevel_context = false
+
        init(modelbuilder: ModelBuilder, mmodule: MModule, mpropdef: nullable MPropDef)
        do
                self.modelbuilder = modelbuilder
@@ -67,6 +72,11 @@ private class TypeVisitor
                        var selfvariable = new Variable("self")
                        self.selfvariable = selfvariable
                        selfvariable.declared_type = mclass.mclass_type
+
+                       var mprop = mpropdef.mproperty
+                       if mprop isa MMethod and mprop.is_toplevel then
+                               is_toplevel_context = true
+                       end
                end
        end
 
@@ -241,6 +251,15 @@ private class TypeVisitor
                end
 
                assert mproperty isa MMethod
+
+               if is_toplevel_context and recv_is_self and not mproperty.is_toplevel and name != "sys" and name != "exit" and name != "args" then
+                       # FIXME named methods are here as a workaround
+                       error(node, "Error: '{name}' is not a top-level method, thus need a receiver.")
+               end
+               if not recv_is_self and mproperty.is_toplevel then
+                       error(node, "Error: cannot call '{name}', a top-level method, with a receiver.")
+               end
+
                if mproperty.visibility == protected_visibility and not recv_is_self and self.mmodule.visibility_for(mproperty.intro_mclassdef.mmodule) < intrude_visibility and not modelbuilder.toolcontext.opt_ignore_visibility.value then
                        self.modelbuilder.error(node, "Error: Method '{name}' is protected and can only acceded by self.")
                        return null
@@ -833,7 +852,7 @@ redef class AForExpr
                if objcla == null then return
 
                # check iterator method
-               var itdef = v.get_method(self, mtype, "iterator", true)
+               var itdef = v.get_method(self, mtype, "iterator", n_expr isa ASelfExpr)
                if itdef == null then
                        v.error(self, "Type Error: 'for' expects a type providing 'iterator' method, got '{mtype}'.")
                        return
@@ -1199,6 +1218,9 @@ redef class ASelfExpr
        redef var its_variable: nullable Variable
        redef fun accept_typing(v)
        do
+               if v.is_toplevel_context and not self isa AImplicitSelfExpr then
+                       v.error(self, "Error: self cannot be used in top-level method.")
+               end
                var variable = v.selfvariable
                self.its_variable = variable
                self.mtype = v.get_variable(self, variable)
diff --git a/src/vm.nit b/src/vm.nit
new file mode 100644 (file)
index 0000000..3c8f048
--- /dev/null
@@ -0,0 +1,314 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Julien Pagès <julien.pages@lirmm.fr>
+#
+# 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.
+
+# Implementation of the Nit virtual machine
+module vm
+
+intrude import naive_interpreter
+import model_utils
+import perfect_hashing
+
+redef class ModelBuilder
+       redef fun run_naive_interpreter(mainmodule: MModule, arguments: Array[String])
+       do
+               var time0 = get_time
+               self.toolcontext.info("*** NITVM STARTING ***", 1)
+
+               var interpreter = new VirtualMachine(self, mainmodule, arguments)
+               init_naive_interpreter(interpreter, mainmodule)
+
+               var time1 = get_time
+               self.toolcontext.info("*** NITVM STOPPING : {time1-time0} ***", 2)
+       end
+end
+
+# A virtual machine based on the naive_interpreter
+class VirtualMachine super NaiveInterpreter
+
+       # Perfect hashing and perfect numbering
+       var ph: Perfecthashing = new Perfecthashing
+
+       # Handles memory and garbage collection
+       var memory_manager: MemoryManager = new MemoryManager
+
+       # Subtyping test for the virtual machine
+       redef fun is_subtype(sub, sup: MType): Bool
+       do
+               var anchor = self.frame.arguments.first.mtype.as(MClassType)
+               var sup_accept_null = false
+               if sup isa MNullableType then
+                       sup_accept_null = true
+                       sup = sup.mtype
+               else if sup isa MNullType then
+                       sup_accept_null = true
+               end
+
+               # Can `sub` provides null or not?
+               # Thus we can match with `sup_accept_null`
+               # Also discard the nullable marker if it exists
+               if sub isa MNullableType then
+                       if not sup_accept_null then return false
+                       sub = sub.mtype
+               else if sub isa MNullType then
+                       return sup_accept_null
+               end
+               # Now the case of direct null and nullable is over
+
+               # An unfixed formal type can only accept itself
+               if sup isa MParameterType or sup isa MVirtualType then
+                       return sub == sup
+               end
+               
+               if sub isa MParameterType or sub isa MVirtualType then
+                       sub = sub.anchor_to(mainmodule, anchor)
+                       # Manage the second layer of null/nullable
+                       if sub isa MNullableType then
+                               if not sup_accept_null then return false
+                               sub = sub.mtype
+                       else if sub isa MNullType then
+                               return sup_accept_null
+                       end
+               end
+
+               assert sub isa MClassType
+
+               # `sup` accepts only null
+               if sup isa MNullType then return false
+
+               assert sup isa MClassType
+
+               # Create the sup vtable if not create
+               if not sup.mclass.loaded then create_class(sup.mclass)
+
+               # Sub can be discovered inside a Generic type during the subtyping test
+               if not sub.mclass.loaded then create_class(sub.mclass)
+
+               if anchor == null then anchor = sub
+               if sup isa MGenericType then
+                       var sub2 = sub.supertype_to(mainmodule, anchor, sup.mclass)
+                       assert sub2.mclass == sup.mclass
+
+                       for i in [0..sup.mclass.arity[ do
+                               var sub_arg = sub2.arguments[i]
+                               var sup_arg = sup.arguments[i]
+                               var res = is_subtype(sub_arg, sup_arg)
+
+                               if res == false then return false
+                       end
+                       return true
+               end
+
+               var super_id = sup.mclass.vtable.id
+               var mask = sub.mclass.vtable.mask
+
+               return inter_is_subtype(super_id, mask, sub.mclass.vtable.internal_vtable)
+       end
+
+       # Subtyping test with perfect hashing
+       private fun inter_is_subtype(id: Int, mask:Int, vtable: Pointer): Bool `{
+               // hv is the position in hashtable
+               int hv = id & mask;
+
+               // Follow the pointer to somewhere in the vtable
+               long unsigned int *offset = (long unsigned int*)(((long int *)vtable)[-hv]);
+               
+               // If the pointed value is corresponding to the identifier, the test is true, otherwise false
+               return *offset == id;
+       `}
+       
+       # Redef init_instance to simulate the loading of a class
+       redef fun init_instance(recv: Instance)
+       do
+               if not recv.mtype.as(MClassType).mclass.loaded then create_class(recv.mtype.as(MClassType).mclass)
+               super
+
+               recv.vtable = recv.mtype.as(MClassType).mclass.vtable
+       end
+       
+       # Creates the runtime structures for this class
+       fun create_class(mclass: MClass) do     mclass.make_vt(self)
+end
+
+redef class MClass
+       # A reference to the virtual table of this class
+       var vtable: nullable VTable
+
+       # True when the class is effectively loaded by the vm, false otherwise
+       var loaded: Bool = false
+
+       # Allocates a VTable for this class and gives it an id
+       private fun make_vt(v: VirtualMachine)
+       do
+               if loaded then return
+
+               # Superclasses contains all superclasses except self
+               var superclasses = new Array[MClass]
+               superclasses.add_all(ancestors)
+               superclasses.remove(self)
+               v.mainmodule.linearize_mclasses(superclasses)
+
+               # Make_vt for super-classes
+               var ids = new Array[Int]
+               var nb_methods = new Array[Int]
+
+               for parent in superclasses do
+                       if parent.vtable == null then parent.make_vt(v)
+                       
+                       # Get the number of introduced methods for this class
+                       var count = 0
+                       var min_visibility = public_visibility
+                       for p in parent.intro_mproperties(min_visibility) do
+                               if p isa MMethod then
+                                       count += 1
+                               end
+                       end
+                       
+                       ids.push(parent.vtable.id)
+                       nb_methods.push(count)
+               end
+               
+               # When all super-classes have their identifiers and vtables, allocate current one
+               allocate_vtable(v, ids, nb_methods)
+               loaded = true
+               # The virtual table now needs to be filled with pointer to methods
+       end
+
+       # Allocate a single vtable
+       #       ids : Array of superclasses identifiers
+       #       nb_methods : Array which contain the number of methods for each class in ids
+       private fun allocate_vtable(v: VirtualMachine, ids: Array[Int], nb_methods: Array[Int])
+       do
+               vtable = new VTable
+               var idc = new Array[Int]
+
+               vtable.mask = v.ph.pnand(ids, 1, idc) - 1
+               vtable.id = idc[0]
+               vtable.classname = name
+
+               # Add current id to Array of super-ids
+               var ids_total = new Array[Int]
+               ids_total.add_all(ids)
+               ids_total.push(vtable.id)
+
+               var nb_methods_total = new Array[Int]
+               var count = 0
+               var min_visibility = public_visibility
+               for p in intro_mproperties(min_visibility) do
+                       if p isa MMethod then
+                               count += 1
+                       end
+               end
+               nb_methods_total.add_all(nb_methods)
+               nb_methods_total.push(count)
+               
+               vtable.internal_vtable = v.memory_manager.init_vtable(ids_total, nb_methods_total, vtable.mask)
+       end
+end
+
+# A VTable contains the virtual method table for the dispatch
+# and informations to perform subtyping tests
+class VTable
+       # The mask to perform perfect hashing
+       var mask: Int
+
+       # Unique identifier given by perfect hashing
+       var id: Int
+
+       # Pointer to the c-allocated area, represents the virtual table
+       var internal_vtable: Pointer
+
+       # The short classname of this class
+       var classname: String
+
+       init do end
+end
+
+redef class Instance
+       
+       var vtable: nullable VTable
+
+       init(mt: MType)
+       do
+               mtype = mt
+
+               # An instance is associated to its class virtual table
+               if mt isa MClassType then
+                       vtable = mt.mclass.vtable
+               end
+       end
+end
+
+# Handle memory, used for allocate virtual table and associated structures
+class MemoryManager
+
+       # Allocate and fill a virtual table
+       fun init_vtable(ids: Array[Int], nb_methods: Array[Int], mask: Int): Pointer 
+       do
+               # Allocate in C current virtual table
+               var res = intern_init_vtable(ids, nb_methods, mask)
+
+               return res
+       end
+
+       # Construct virtual tables with a bi-dimensional layout
+       private fun intern_init_vtable(ids: Array[Int], nb_methods: Array[Int], mask: Int): Pointer 
+               import Array[Int].length, Array[Int].[] `{
+
+               // Allocate and fill current virtual table
+               int i;
+               int total_size = 0; // total size of this virtual table
+               int nb_classes = Array_of_Int_length(nb_methods);
+               for(i = 0; i<nb_classes; i++) {
+                       /* - One for each method of this class
+                       *  - One for the delta (pointer to attributes)
+                       *  - One for the id 
+                       */
+                       total_size += Array_of_Int__index(nb_methods, i);
+                       total_size += 2;
+               }
+
+               // And the size of the perfect hashtable
+               total_size += mask+1;
+               long unsigned int* vtable = malloc(sizeof(long unsigned int)*total_size);
+               
+               // Initialisation to the first position of the virtual table (ie : Object)
+               long unsigned int *init = vtable + mask + 2;
+               for(i=0; i<total_size; i++)
+                       vtable[i] = (long unsigned int)init;
+
+               // Set the virtual table to its position 0 
+               // ie: after the hashtable
+               vtable = vtable + mask + 1;
+               
+               int current_size = 1;
+               for(i = 0; i < nb_classes; i++) {
+                       /*
+                               vtable[hv] contains a pointer to the group of introducted methods
+                               For each superclasse we have in virtual table :
+                                       (id | delta (attributes) | introduced methods)
+                       */
+                       int hv = mask & Array_of_Int__index(ids, i);
+
+                       vtable[current_size] = Array_of_Int__index(ids, i);
+                       vtable[-hv] = (long unsigned int)&(vtable[current_size]);
+                       
+                       current_size += 2;
+                       current_size += Array_of_Int__index(nb_methods, i);
+               }
+
+               return vtable;
+       `}
+end
index 4a5036c..ee4652c 100644 (file)
@@ -42,7 +42,7 @@ end
 #alt8# redef fun foo: Int do return 300 + bar
 #alt8#end
 
-
+#alt9#fun baz do abort
 fun baz: Int do return 1
 
 baz.output
diff --git a/tests/error_toplevel.nit b/tests/error_toplevel.nit
new file mode 100644 (file)
index 0000000..c33bcb0
--- /dev/null
@@ -0,0 +1,49 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import kernel
+
+redef class Object
+       fun baz do
+               output
+       end
+
+       fun foo1
+       do
+               bar(1)
+               bar(self)
+               #alt1#3.bar(3)
+
+               5.baz
+               baz
+       end
+end
+
+fun foo2
+do
+       bar(10)
+       #alt2#self.bar(20)
+       #alt3#bar(self)
+       #alt4#4.bar(40)
+
+       50.baz
+       #alt5#baz
+end
+
+fun bar(o: Object)
+do
+       o.output
+end
+
+0.foo1
+foo2
index 394cdeb..7c2762c 100644 (file)
@@ -6,6 +6,8 @@ shoot_logic
 bench_
 nit_args1
 nit_args3
+nitvm_args1
+nitvm_args3
 nitc_args1
 nitg_args1
 nitg_args3
diff --git a/tests/nitvm.args b/tests/nitvm.args
new file mode 100644 (file)
index 0000000..3011fc1
--- /dev/null
@@ -0,0 +1,3 @@
+--log --log-dir out/test_nitc_logs ../examples/hello_world.nit
+base_simple3.nit
+-m test_mixin.nit ../examples/hello_world.nit
index 7711bba..8163c32 100644 (file)
@@ -1,6 +1,6 @@
 base_iterator3.nit:35,1--25: Type Error: 'for' expects method 'iterator' to return an 'Iterator' or 'MapIterator' type'.
 base_iterator3.nit:39,1--25: Type Error: 'for' expects method 'iterator' to return an 'Iterator' or 'MapIterator' type'.
-base_iterator3.nit:43,1--25: Error: Method or variable 'iterator' unknown in Test3.
+base_iterator3.nit:43,1--25: Error: Method 'iterator' doesn't exists in Test3.
 base_iterator3.nit:43,1--25: Type Error: 'for' expects a type providing 'iterator' method, got 'Test3'.
 base_iterator3.nit:46,1--48: Type Error: 'for' expects only one variable when using 'Iterator'.
 base_iterator3.nit:47,1--47: Type Error: 'for' expects two variables when using 'MapIterator'.
diff --git a/tests/sav/error_defs_alt9.res b/tests/sav/error_defs_alt9.res
new file mode 100644 (file)
index 0000000..8c547a1
--- /dev/null
@@ -0,0 +1 @@
+alt/error_defs_alt9.nit:46,5--7: Error: A property baz is already defined in class Object at line 45.
index ac5bee9..3919001 100644 (file)
@@ -10,6 +10,7 @@ alt/error_expr_not_ok_alt4.nit:43,1--8: Error: Method 'fail' doesn't exists in I
 alt/error_expr_not_ok_alt4.nit:45,7--10: Type error: expected A, got Object
 alt/error_expr_not_ok_alt4.nit:46,1--9: Error: Method 'fail' doesn't exists in Object.
 alt/error_expr_not_ok_alt4.nit:49,7--10: Type error: expected A, got Object
+alt/error_expr_not_ok_alt4.nit:50,1--10: Error: cannot call 'trash', a top-level method, with a receiver.
 alt/error_expr_not_ok_alt4.nit:50,1--10: Error: Incorrect number of parameters. Got 0, expected 1. Signature is (x: A)
 alt/error_expr_not_ok_alt4.nit:60,4--7: Type error: expected Bool, got Int
 alt/error_expr_not_ok_alt4.nit:60,20: Type error: expected A, got Int
@@ -22,7 +23,7 @@ alt/error_expr_not_ok_alt4.nit:66,21: Type error: expected A, got Int
 alt/error_expr_not_ok_alt4.nit:67,1--18: Warning: use 'loop' instead of 'while true do'.
 alt/error_expr_not_ok_alt4.nit:69,24: Type error: expected A, got Int
 alt/error_expr_not_ok_alt4.nit:69,1--25: Type Error: 'for' expects a type providing 'iterator' method, got 'Int'.
-alt/error_expr_not_ok_alt4.nit:69,1--25: Error: Method or variable 'iterator' unknown in Int.
+alt/error_expr_not_ok_alt4.nit:69,1--25: Error: Method 'iterator' doesn't exists in Int.
 alt/error_expr_not_ok_alt4.nit:71,8--11: Type error: expected Bool, got Int
 alt/error_expr_not_ok_alt4.nit:72,7--15: Type error: expected A, got Int
 alt/error_expr_not_ok_alt4.nit:73,7--10: Type error: expected Bool, got Int
index 7b7b730..d9dd373 100644 (file)
@@ -18,7 +18,7 @@ alt/error_expr_not_ok_alt5.nit:66,21: Type error: expected A, got Int
 alt/error_expr_not_ok_alt5.nit:67,1--18: Warning: use 'loop' instead of 'while true do'.
 alt/error_expr_not_ok_alt5.nit:69,24: Type error: expected A, got Int
 alt/error_expr_not_ok_alt5.nit:69,1--25: Type Error: 'for' expects a type providing 'iterator' method, got 'Int'.
-alt/error_expr_not_ok_alt5.nit:69,1--25: Error: Method or variable 'iterator' unknown in Int.
+alt/error_expr_not_ok_alt5.nit:69,1--25: Error: Method 'iterator' doesn't exists in Int.
 alt/error_expr_not_ok_alt5.nit:71,8--11: Type error: expected Bool, got Int
 alt/error_expr_not_ok_alt5.nit:72,7--15: Type error: expected A, got Int
 alt/error_expr_not_ok_alt5.nit:73,7--10: Type error: expected Bool, got Int
index 50c3b32..212ed6f 100644 (file)
@@ -22,7 +22,7 @@ alt/error_expr_not_ok_alt6.nit:66,21: Type error: expected A, got Int
 alt/error_expr_not_ok_alt6.nit:67,1--18: Warning: use 'loop' instead of 'while true do'.
 alt/error_expr_not_ok_alt6.nit:69,24: Type error: expected A, got Int
 alt/error_expr_not_ok_alt6.nit:69,1--25: Type Error: 'for' expects a type providing 'iterator' method, got 'Int'.
-alt/error_expr_not_ok_alt6.nit:69,1--25: Error: Method or variable 'iterator' unknown in Int.
+alt/error_expr_not_ok_alt6.nit:69,1--25: Error: Method 'iterator' doesn't exists in Int.
 alt/error_expr_not_ok_alt6.nit:71,8--11: Type error: expected Bool, got Int
 alt/error_expr_not_ok_alt6.nit:72,7--15: Type error: expected A, got Int
 alt/error_expr_not_ok_alt6.nit:73,7--10: Type error: expected Bool, got Int
index d507465..4aa3dcd 100644 (file)
@@ -1,2 +1,2 @@
-error_for_coll.nit:17,1--18,3: Error: Method or variable 'iterator' unknown in Int.
+error_for_coll.nit:17,1--18,3: Error: Method 'iterator' doesn't exists in Int.
 error_for_coll.nit:17,1--18,3: Type Error: 'for' expects a type providing 'iterator' method, got 'Int'.
index 849db8b..8747eab 100644 (file)
@@ -1,3 +1,3 @@
 alt/error_needed_method_alt2.nit:47,10--27: Cannot instantiate interface Collection[Int].
-alt/error_needed_method_alt2.nit:47,1--40: Error: Method or variable 'iterator' unknown in Collection[Int].
+alt/error_needed_method_alt2.nit:47,1--40: Error: Method 'iterator' doesn't exists in Collection[Int].
 alt/error_needed_method_alt2.nit:47,1--40: Type Error: 'for' expects a type providing 'iterator' method, got 'Collection[Int]'.
index 2a2c208..f8c5a4f 100644 (file)
@@ -1,2 +1,2 @@
-alt/error_needed_types_alt8.nit:21,1--22,3: Error: Method or variable 'iterator' unknown in L.
+alt/error_needed_types_alt8.nit:21,1--22,3: Error: Method 'iterator' doesn't exists in L.
 alt/error_needed_types_alt8.nit:21,1--22,3: Type Error: 'for' expects a type providing 'iterator' method, got 'L'.
diff --git a/tests/sav/error_toplevel.res b/tests/sav/error_toplevel.res
new file mode 100644 (file)
index 0000000..f00464b
--- /dev/null
@@ -0,0 +1,6 @@
+1
+0
+5
+0
+10
+50
diff --git a/tests/sav/error_toplevel_alt1.res b/tests/sav/error_toplevel_alt1.res
new file mode 100644 (file)
index 0000000..b18282f
--- /dev/null
@@ -0,0 +1 @@
+alt/error_toplevel_alt1.nit:25,3--10: Error: cannot call 'bar', a top-level method, with a receiver.
diff --git a/tests/sav/error_toplevel_alt2.res b/tests/sav/error_toplevel_alt2.res
new file mode 100644 (file)
index 0000000..8b3cf76
--- /dev/null
@@ -0,0 +1 @@
+alt/error_toplevel_alt2.nit:35,2--5: Error: self cannot be used in top-level method.
diff --git a/tests/sav/error_toplevel_alt3.res b/tests/sav/error_toplevel_alt3.res
new file mode 100644 (file)
index 0000000..acfd7bf
--- /dev/null
@@ -0,0 +1 @@
+alt/error_toplevel_alt3.nit:36,6--9: Error: self cannot be used in top-level method.
diff --git a/tests/sav/error_toplevel_alt4.res b/tests/sav/error_toplevel_alt4.res
new file mode 100644 (file)
index 0000000..c1a37ee
--- /dev/null
@@ -0,0 +1 @@
+alt/error_toplevel_alt4.nit:37,2--10: Error: cannot call 'bar', a top-level method, with a receiver.
diff --git a/tests/sav/error_toplevel_alt5.res b/tests/sav/error_toplevel_alt5.res
new file mode 100644 (file)
index 0000000..dff56d2
--- /dev/null
@@ -0,0 +1 @@
+alt/error_toplevel_alt5.nit:40,2--4: Error: 'baz' is not a top-level method, thus need a receiver.
index 0b82282..f14eb40 100644 (file)
@@ -16,7 +16,7 @@
 </span></span><span class="line" id="L16">
 </span><span class="line" id="L17"><span class="nc_k">import</span> <span class="nc_k">end</span>
 </span><span class="line" id="L18">
-</span><span class="nc_cdef foldable" id="base_simple3#Object"><span class="line" id="L19"><span class="nc_k">interface</span> <span class="nc_def nc_t popupable" title="class Object" data-title="&lt;a href=&quot;base_simple3.html#base_simple3#Object&quot;&gt;class Object&lt;/a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;/b&gt; &lt;span&gt;Object&lt;/span&gt;&lt;br/&gt;&lt;div class=&quot;dropdown&quot;&gt; &lt;a data-toggle=&quot;dropdown&quot; href=&quot;#&quot;&gt;&lt;b&gt;hier&lt;/b&gt; super-classes&lt;span class=&quot;caret&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;ul class=&quot;dropdown-menu&quot; role=&quot;menu&quot; aria-labelledby=&quot;dLabel&quot;&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class=&quot;dropdown&quot;&gt; &lt;a data-toggle=&quot;dropdown&quot; href=&quot;#&quot;&gt;&lt;b&gt;hier&lt;/b&gt; sub-classes&lt;span class=&quot;caret&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;ul class=&quot;dropdown-menu&quot; role=&quot;menu&quot; aria-labelledby=&quot;dLabel&quot;&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#Bool&quot;&gt;Bool&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#Int&quot;&gt;Int&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#A&quot;&gt;A&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#B&quot;&gt;B&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#C&quot;&gt;C&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#Sys&quot;&gt;Sys&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class=&quot;dropdown&quot;&gt; &lt;a data-toggle=&quot;dropdown&quot; href=&quot;#&quot;&gt;&lt;b&gt;redefs&lt;/b&gt; refinements&lt;span class=&quot;caret&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;ul class=&quot;dropdown-menu&quot; role=&quot;menu&quot; aria-labelledby=&quot;dLabel&quot;&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#Object&quot;&gt;in base_simple3&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#Object&quot;&gt;in base_simple3&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#Object&quot;&gt;in base_simple3&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;" data-toggle="popover">Object</span>
+</span><span class="nc_cdef foldable" id="base_simple3#Object"><span class="line" id="L19"><span class="nc_k">interface</span> <span class="nc_def nc_t popupable" title="class Object" data-title="&lt;a href=&quot;base_simple3.html#base_simple3#Object&quot;&gt;class Object&lt;/a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;/b&gt; &lt;span&gt;Object&lt;/span&gt;&lt;br/&gt;&lt;div class=&quot;dropdown&quot;&gt; &lt;a data-toggle=&quot;dropdown&quot; href=&quot;#&quot;&gt;&lt;b&gt;hier&lt;/b&gt; sub-classes&lt;span class=&quot;caret&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;ul class=&quot;dropdown-menu&quot; role=&quot;menu&quot; aria-labelledby=&quot;dLabel&quot;&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#Bool&quot;&gt;Bool&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#Int&quot;&gt;Int&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#A&quot;&gt;A&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#B&quot;&gt;B&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#C&quot;&gt;C&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#Sys&quot;&gt;Sys&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;" data-toggle="popover">Object</span>
 </span><span class="line" id="L20"><span class="nc_k">end</span>
 </span></span><span class="line" id="L21">
 </span><span class="nc_cdef foldable" id="base_simple3#Bool"><span class="line" id="L22"><span class="nc_k">enum</span> <span class="nc_def nc_t popupable" title="class Bool" data-title="&lt;a href=&quot;base_simple3.html#base_simple3#Bool&quot;&gt;class Bool&lt;/a&gt;" data-content="&lt;div&gt;&lt;b&gt;class&lt;/b&gt; &lt;span&gt;Bool&lt;/span&gt;&lt;br/&gt;&lt;div class=&quot;dropdown&quot;&gt; &lt;a data-toggle=&quot;dropdown&quot; href=&quot;#&quot;&gt;&lt;b&gt;hier&lt;/b&gt; super-classes&lt;span class=&quot;caret&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;ul class=&quot;dropdown-menu&quot; role=&quot;menu&quot; aria-labelledby=&quot;dLabel&quot;&gt;&lt;li&gt;&lt;a href=&quot;base_simple3.html#base_simple3#Object&quot;&gt;Object&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;" data-toggle="popover">Bool</span>
index 0c177f8..4540753 100644 (file)
          std: 0.0
          sum: 7
        mnbr: number of refinement in module
-         avg: 3.0
-         max: base_simple3 (3)
-         min: base_simple3 (3)
+         avg: 0.0
+         max: base_simple3 (0)
+         min: base_simple3 (0)
          std: 0.0
-         sum: 3
+         sum: 0
        mnbcc: number of concrete class in module (intro + redef)
          avg: 4.0
          max: base_simple3 (4)
          std: 0.0
          sum: 0
        mnbic: number of interface in module (intro + redef)
-         avg: 4.0
-         max: base_simple3 (4)
-         min: base_simple3 (4)
+         avg: 1.0
+         max: base_simple3 (1)
+         min: base_simple3 (1)
          std: 0.0
-         sum: 4
+         sum: 1
 
  ## project base_empty_module
   `- group base_empty_module
          std: 3.0
          sum: 8
        mnbr: number of refinement in module
-         avg: 1.0
-         max: base_simple3 (3)
-         min: base_empty_module (0)
-         std: 1.581
-         sum: 3
+         avg: 0.0
+         max: base_simple3 (0)
+         min: base_simple3 (0)
+         std: 0.0
+         sum: 0
        mnbcc: number of concrete class in module (intro + redef)
          avg: 2.0
          max: base_simple3 (4)
          std: 0.0
          sum: 0
        mnbic: number of interface in module (intro + redef)
-         avg: 2.0
-         max: base_simple3 (4)
+         avg: 0.0
+         max: base_simple3 (1)
          min: base_empty_module (0)
-         std: 2.0
-         sum: 4
+         std: 0.707
+         sum: 1
 
 # MClasses metrics
 
@@ -421,48 +421,45 @@ Distribution of direct smallers
   <=0: sub-population=1 (33.33%); cumulated value=0 (0.0%)
   <=1: sub-population=2 (66.66%); cumulated value=2 (100.00%)
 ## Classdef hierarchy
-Number of nodes: 11
-Number of edges: 47 (4.27 per node)
-Number of direct edges: 9 (0.81 per node)
+Number of nodes: 8
+Number of edges: 14 (1.75 per node)
+Number of direct edges: 6 (0.75 per node)
 Distribution of greaters
- population: 11
+ population: 8
  minimum value: 1
- maximum value: 5
- total value: 47
- average value: 4.27
+ maximum value: 2
+ total value: 14
+ average value: 1.75
  distribution:
-  <=1: sub-population=1 (9.09%); cumulated value=1 (2.12%)
-  <=4: sub-population=4 (36.36%); cumulated value=16 (34.04%)
-  <=8: sub-population=6 (54.54%); cumulated value=30 (63.82%)
+  <=1: sub-population=2 (25.00%); cumulated value=2 (14.28%)
+  <=2: sub-population=6 (75.00%); cumulated value=12 (85.71%)
 Distribution of direct greaters
- population: 11
+ population: 8
  minimum value: 0
- maximum value: 3
- total value: 9
- average value: 0.81
+ maximum value: 1
+ total value: 6
+ average value: 0.75
  distribution:
-  <=0: sub-population=4 (36.36%); cumulated value=0 (0.0%)
-  <=1: sub-population=6 (54.54%); cumulated value=6 (66.66%)
-  <=4: sub-population=1 (9.09%); cumulated value=3 (33.33%)
+  <=0: sub-population=2 (25.00%); cumulated value=0 (0.0%)
+  <=1: sub-population=6 (75.00%); cumulated value=6 (100.00%)
 Distribution of smallers
- population: 11
+ population: 8
  minimum value: 1
- maximum value: 10
- total value: 47
- average value: 4.27
+ maximum value: 7
+ total value: 14
+ average value: 1.75
  distribution:
-  <=1: sub-population=7 (63.63%); cumulated value=7 (14.89%)
-  <=16: sub-population=4 (36.36%); cumulated value=40 (85.10%)
+  <=1: sub-population=7 (87.50%); cumulated value=7 (50.00%)
+  <=8: sub-population=1 (12.50%); cumulated value=7 (50.00%)
 Distribution of direct smallers
- population: 11
+ population: 8
  minimum value: 0
  maximum value: 6
- total value: 9
- average value: 0.81
+ total value: 6
+ average value: 0.75
  distribution:
-  <=0: sub-population=7 (63.63%); cumulated value=0 (0.0%)
-  <=1: sub-population=3 (27.27%); cumulated value=3 (33.33%)
-  <=8: sub-population=1 (9.09%); cumulated value=6 (66.66%)
+  <=0: sub-population=7 (87.50%); cumulated value=0 (0.0%)
+  <=8: sub-population=1 (12.50%); cumulated value=6 (100.00%)
 ## Class hierarchy
 Number of nodes: 8
 Number of edges: 14 (1.75 per node)
@@ -580,10 +577,10 @@ Number of classes: 8
   Number of enum kind: 2 (25.00%)
   Number of class kind: 5 (62.50%)
 
-Number of class definitions: 11
-Number of refined classes: 1 (12.50%)
-Average number of class refinments by classes: 0.37
-Average number of class refinments by refined classes: 3.00
+Number of class definitions: 8
+Number of refined classes: 0 (0.0%)
+Average number of class refinments by classes: 0.0
+Average number of class refinments by refined classes: na
 
 Number of properties: 20
   Number of MAttribute: 3 (15.00%)
@@ -614,7 +611,7 @@ Total number of self: 5
 Total number of implicit self: 4 (80.00%)
 --- Construction of tables ---
 Number of runtime classes: 7 (excluding interfaces and abstract classes)
-Average number of composing class definition by runtime class: 4.42
+Average number of composing class definition by runtime class: 1.85
 Total size of tables (classes and instances): 35 (not including stuff like info for subtyping or call-next-method)
 Average size of table by runtime class: 5.00
 Values never redefined: 35 (100.00%)
@@ -632,6 +629,8 @@ Values never redefined: 35 (100.00%)
        blooming mclasses (threshold: 2.388)
           B: 3.0
           C: 3.0
+generating out/nitmetrics_args1.write/project_hierarchy.dot
+generating out/nitmetrics_args1.write/module_hierarchy.dot
 
 # Nullable metrics
 
@@ -1075,8 +1074,6 @@ MMethodDef possibly invoked at runtime (by number of CallSites)
   base_simple3#Object#bar: 1 (4.54%)
   base_simple3#Object#foo: 1 (4.54%)
   base_simple3#C#init: 1 (4.54%)
-generating out/nitmetrics_args1.write/project_hierarchy.dot
-generating out/nitmetrics_args1.write/module_hierarchy.dot
 class_hierarchy.dot
 classdef_hierarchy.dot
 inheritance/
diff --git a/tests/sav/nitvm.res b/tests/sav/nitvm.res
new file mode 100644 (file)
index 0000000..742b9e8
--- /dev/null
@@ -0,0 +1,3 @@
+Usage: nitvm [OPTION]... <file.nit>...
+Executes Nit programs with a virtual machine.
+Use --help for help
diff --git a/tests/sav/nitvm_args1.res b/tests/sav/nitvm_args1.res
new file mode 100644 (file)
index 0000000..3b18e51
--- /dev/null
@@ -0,0 +1 @@
+hello world
diff --git a/tests/sav/nitvm_args2.res b/tests/sav/nitvm_args2.res
new file mode 100644 (file)
index 0000000..f00c965
--- /dev/null
@@ -0,0 +1,10 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
diff --git a/tests/sav/nitvm_args3.res b/tests/sav/nitvm_args3.res
new file mode 100644 (file)
index 0000000..c76ebf3
--- /dev/null
@@ -0,0 +1,3 @@
+MIX: Before
+MIX: hello world
+MIX: After
index 264e277..e3174b3 100644 (file)
       
       class \e[32m\e[1mSys\e[0m\e[0m
       \e[30m\e[1mbase_simple3::Sys\e[0m\e[0m\e[30m (lines 53-66)\e[0m
-    
-    \e[1m== refined classes\e[0m
-      
-      redef interface \e[32m\e[1mObject\e[0m\e[0m
-      \e[30m\e[1mbase_simple3::Object\e[0m\e[0m\e[30m (lines 49-49)\e[0m
-      
-      redef interface \e[32m\e[1mObject\e[0m\e[0m
-      \e[30m\e[1mbase_simple3::Object\e[0m\e[0m\e[30m (lines 50-50)\e[0m
-      
-      redef interface \e[32m\e[1mObject\e[0m\e[0m
-      \e[30m\e[1mbase_simple3::Object\e[0m\e[0m\e[30m (lines 51-51)\e[0m