Merge: Bench strings update
authorJean Privat <jean@pryen.org>
Thu, 29 Oct 2015 19:04:02 +0000 (15:04 -0400)
committerJean Privat <jean@pryen.org>
Thu, 29 Oct 2015 19:04:02 +0000 (15:04 -0400)
A few things happening here:

* Added some line-producing output to `bench_plot.sh`, use both functions to produce lines instead of histograms
* `bench_strings.sh` underwent a few transformations: now you can try with different values of `maxlen` (threshold at which a flat concatenation produces a new Concat node instead of a new FlatString), you can also work on HEAD only with a new option, also, all benches now produce lines instead of histograms

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

20 files changed:
Makefile
README.md
examples/shoot/src/shoot_linux.nit
lib/trees/abstract_tree.nit
lib/trees/rbtree.nit
misc/nit_env.sh [new file with mode: 0644]
src/compiler/abstract_compiler.nit
src/model/model.nit
src/modelize/modelize_property.nit
tests/error_redef_vt.nit [new file with mode: 0644]
tests/nitc.args
tests/sav/error_redef_vt.res [new file with mode: 0644]
tests/sav/error_virtual_type2_alt1.res
tests/sav/error_virtual_type2_alt2.res
tests/sav/error_virtual_type2_alt3.res
tests/sav/error_virtual_type2_alt4.res
tests/sav/error_virtual_type2_alt5.res
tests/sav/error_virtual_type2_alt6.res
tests/sav/error_virtual_type_alt3.res
tests/sav/nitc_args10.res [new file with mode: 0644]

index cad3ffa..6d3bc86 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,11 @@ NITCOPT=
 # Additional program directories (contrib and examples) that are buildable
 PROGS=$(dir $(wildcard examples/*/Makefile contrib/*/Makefile))
 
-all: tools
+all: tools man
+       @echo ""
+       @echo "Congratulations! Nit was succesfully compiled."
+       @echo "To configure your shell environment, execute the following command:"
+       @echo "    source misc/nit_env.sh install"
 
 # Compile all programs in $PROGS
 full: all
index fb0e27c..0df1fcc 100644 (file)
--- a/README.md
+++ b/README.md
@@ -52,11 +52,9 @@ How to start:
     $ bin/nitc examples/hello_world.nit
     $ ./hello_world
 
-You can put the `bin/` directory in your PATH
+You can source `misc/nit_env.sh` to setup your environment like PATH, MANPATH and bash completion.
+To have your environment automatically configured at login, just source it with `install` as argument.
 
-Using bash completion with Nit tools:
-
-    $ echo source /absolute/path/to/misc/bash_completion/nit >> ~/.bash_completion
-    $ source ~/.bash_completion
+    $ . misc/nit_env.sh install
 
 More information: <http://www.nitlanguage.org>
index 1587d36..5ca2dca 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Linex version of the shoot program
+# Linux version of the shoot program
 module shoot_linux
 
 import shoot
index 6626036..dccde3a 100644 (file)
@@ -36,10 +36,16 @@ abstract class TreeMap[K: Comparable, E]
        fun show_dot is abstract
 end
 
-# Node used in Tree implementation
-# nodes are used to store values
-# * `E`: type of value
-class TreeNode[K: Comparable, E]
+# Abstract node structure used in `Tree` implementation
+#
+# Nodes are defined recursively each node (except the root one) pointing to a parent.
+# Nodes can be used to store data with the `TreeNode::value` attribute.
+#
+# Formal parameters:
+# * `K`: key type (a `Comparable` one so nodes can be sorted by their keys)
+# * `E`: value type (to store your data)
+abstract class TreeNode[K: Comparable, E]
+       super Comparable
 
        # TreeNode type
        type N: TreeNode[K, E]
@@ -50,18 +56,44 @@ class TreeNode[K: Comparable, E]
        # `value` stored in the node
        var value: E
 
-       # Direct parent of this node (null if the node is root)
+       # Direct parent of this node (`null` if the node is root)
+       #
+       # See `Tree::root`.
        var parent: nullable N = null is writable
 
+       # Depth in tree (length of the path from `self` to `root`)
+       fun depth: Int do
+               var node = parent
+               var i = 0
+               while node != null do
+                       node = node.parent
+                       i += 1
+               end
+               return i
+       end
+
        redef fun to_s do return "\{{value or else ""}\}"
 
        # Return dot representation of this node
-       # Used for debugging by `AbstractTree::show_dot`
+       #
+       # See `Tree::show_dot`.
        fun to_dot: String do
                var res = new FlatBuffer
                res.append "\"{self}\";\n"
                if parent != null then res.append "\"{parent.as(not null)}\" -> \"{self}\"[dir=back];\n"
                return res.to_s
        end
-end
 
+       redef type OTHER: N
+
+       # Nodes equality is done on `value` equality
+       #
+       # Redefine this method to change the default behavior.
+       redef fun ==(o) do
+               if not o isa N then return false
+               return self.value == o.value
+       end
+
+       # Nodes ordering is based on the `key`
+       redef fun <(o) do return self.key < o.key
+end
index 51ddfc0..7310ac7 100644 (file)
@@ -144,4 +144,3 @@ class RBTreeNode[K: Comparable, E]
 
        end
 end
-
diff --git a/misc/nit_env.sh b/misc/nit_env.sh
new file mode 100644 (file)
index 0000000..d0c1c0a
--- /dev/null
@@ -0,0 +1,126 @@
+# 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.
+
+# Source this script inside a bash or sh session to setup:
+#
+# * PATH
+# * MANPATH
+# * bash_completion
+#
+# If `install` is given as an argument, then the script sourcing is automatically inserted in the `.profile`.
+
+# Final function that sets up the shell environment.
+__nit_env() {
+       #echo "Install in $1:"
+
+       local str="$1/bin"
+       echo "$PATH" | grep -q "$str" || export PATH="$str:$PATH"
+       str="$1/share/bin"
+       echo "$MANPATH" | grep -q "$str" || export MANPATH="$str:$MANPATH"
+
+       if [ -n "$BASH" -a -n "$PS1" ]; then
+               . "$1/misc/bash_completion/nit"
+       fi
+
+}
+
+# Fast setup when invoked from .profile (see `install` at the end)
+#
+# Because [d]ash does not support argument to source (`.`),
+# we pass the root dir as a local environment variable.
+if [ -n "$NIT_DIR" ]; then
+       __nit_env "$NIT_DIR"
+       return 2> /dev/null # `return` fails if invoked as is; i.e. not trough source (`.`)
+       exit
+fi
+
+# Guess the nit root directory and return it in `dirname`.
+__nit_env_guess() {
+       dirname=$NIT_DIR
+       [ -f "$dirname/src/nitc.nit" ] && return 0
+
+       dirname=$PWD
+       [ -f "$dirname/src/nitc.nit" ] && return 0
+
+       if [ -n "$BASH_SOURCE" ]; then
+               dirname=`dirname "$BASH_SOURCE"`/..
+               [ -f "$dirname/src/nitc.nit" ] && return 0
+       fi
+
+       dirname=`dirname "$0"`/..
+       [ -f "$dirname/src/nitc.nit" ] && return 0
+
+       echo "Cannot find the Nit root directory. Run the script from the Nit root directory."
+       return 1
+}
+
+# Main method of the script.
+#
+# A function is used so that `return` have a sane effect
+__nit_env_main() {
+       local install
+       local dirname
+
+       # Install required?
+       if [ "$1" = "install" ]; then
+               install=true
+               shift
+       fi
+
+       # Get the root directory
+       case "$#" in
+               1)
+                       # Get it from the argument
+                       dirname=$1
+                       if [ ! -f "$dirname/src/nitc.nit" ]; then
+                               if [ -d "$dirname/" ]; then
+                                       echo "$dirname: not a Nit root directory"
+                               else
+                                       echo "$dirname: not a directory"
+                               fi
+                               return 1
+                       fi
+                       ;;
+               0)
+                       # Guess it
+                       __nit_env_guess || return 1
+                       ;;
+               *) echo "usage: source nit_env.sh [install] [path/to/nitdir]"
+                       return 1
+                       ;;
+       esac
+
+       # Get a canonical path
+       local ret=`pwd`
+       cd $dirname > /dev/null
+       local fulldir=`pwd`
+       cd "$ret"
+
+       # Check misuse
+       if [ -n "$BASH" -a "$0" = "$BASH_SOURCE" ]; then
+               echo "nit_env.sh should be sourced not executed as is. E.g. run with 'source ./nit_env.sh'"
+       fi
+
+       # Setup the environment
+       __nit_env "$fulldir"
+
+       # Register in the .profile if required
+       if [ -n "$install" ]; then
+               local ne="$fulldir/misc/nit_env.sh"
+               local str="test -r \"$ne\" && NIT_DIR=\"$fulldir\" . \"$ne\""
+               grep -q "$str" "$HOME/.profile" || echo "$str" >> "$HOME/.profile"
+       fi
+}
+
+__nit_env_main "$@"
index c6cdb26..9584179 100644 (file)
@@ -2022,6 +2022,7 @@ redef class MMethodDef
        fun can_inline(v: VISITOR): Bool
        do
                if is_abstract then return true
+               if constant_value != null then return true
                var modelbuilder = v.compiler.modelbuilder
                var node = modelbuilder.mpropdef2node(self)
                if node isa APropdef then
index 3841daf..ccb7522 100644 (file)
@@ -809,19 +809,19 @@ abstract class MType
                end
                #print "4.is {sub} a {sup}? <- no more resolution"
 
-               assert sub isa MClassType else print "{sub} <? {sub}" # It is the only remaining type
-
-               # A unfixed formal type can only accept itself
-               if sup isa MFormalType then
-                       return false
+               if sub isa MBottomType then
+                       return true
                end
 
-               if sup isa MNullType then
-                       # `sup` accepts only null
+               assert sub isa MClassType else print "{sub} <? {sub}" # It is the only remaining type
+
+               # Handle sup-type when the sub-type is class-based (other cases must have be identified before).
+               if sup isa MFormalType or sup isa MNullType or sup isa MBottomType then
+                       # These types are not super-types of Class-based types.
                        return false
                end
 
-               assert sup isa MClassType # It is the only remaining type
+               assert sup isa MClassType else print "got {sup} {sub.inspect}" # It is the only remaining type
 
                # Now both are MClassType, we need to dig
 
@@ -1010,7 +1010,7 @@ abstract class MType
        # The result is returned exactly as declared in the "type" property (verbatim).
        # So it could be another formal type.
        #
-       # In case of conflict, the method aborts.
+       # In case of conflicts or inconsistencies in the model, the method returns a `MBottomType`.
        fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType do return self
 
        # Resolve the formal type to its simplest equivalent form.
@@ -1024,6 +1024,8 @@ abstract class MType
        #
        # By default, return self.
        # See the redefinitions for specific behavior in each kind of type.
+       #
+       # In case of conflicts or inconsistencies in the model, the method returns a `MBottomType`.
        fun lookup_fixed(mmodule: MModule, resolved_receiver: MType): MType do return self
 
        # Can the type be resolved?
@@ -1365,7 +1367,7 @@ class MVirtualType
 
        redef fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType
        do
-               return lookup_single_definition(mmodule, resolved_receiver).bound.as(not null)
+               return lookup_single_definition(mmodule, resolved_receiver).bound or else new MBottomType(model)
        end
 
        private fun lookup_single_definition(mmodule: MModule, resolved_receiver: MType): MVirtualTypeDef
@@ -1400,7 +1402,8 @@ class MVirtualType
                assert resolved_receiver isa MClassType # It is the only remaining type
 
                var prop = lookup_single_definition(mmodule, resolved_receiver)
-               var res = prop.bound.as(not null)
+               var res = prop.bound
+               if res == null then return new MBottomType(model)
 
                # Recursively lookup the fixed result
                res = res.lookup_fixed(mmodule, resolved_receiver)
index 0161ad0..23feb87 100644 (file)
@@ -111,7 +111,7 @@ redef class ModelBuilder
                                if not check_virtual_types_circularity(npropdef, mpropdef.mproperty, mclassdef.bound_mtype, mclassdef.mmodule) then
                                        # Invalidate the bound
                                        mpropdef.is_broken = true
-                                       mpropdef.bound = mclassdef.mmodule.model.null_type
+                                       mpropdef.bound = new MBottomType(mclassdef.mmodule.model)
                                end
                        end
                        for npropdef in nclassdef2.n_propdefs do
@@ -386,6 +386,8 @@ redef class ModelBuilder
                        # nothing, always visible
                else if mtype isa MNullType then
                        # nothing to do.
+               else if mtype isa MBottomType then
+                       # nothing to do.
                else
                        node.debug "Unexpected type {mtype}"
                        abort
@@ -445,8 +447,7 @@ redef class ModelBuilder
                                var vt = t.mproperty
                                # Because `vt` is possibly unchecked, we have to do the bound-lookup manually
                                var defs = vt.lookup_definitions(mmodule, recv)
-                               # TODO something to manage correctly bound conflicts
-                               assert not defs.is_empty
+                               if defs.is_empty then return false
                                nexts = new Array[MType]
                                for d in defs do
                                        var next = defs.first.bound
@@ -1580,22 +1581,23 @@ redef class ATypePropdef
                                modelbuilder.warning(n_id, "bad-type-name", "Warning: lowercase in the virtual type `{name}`.")
                                break
                        end
-                       if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, false, mprop) then return
                else
-                       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
-               mclassdef.mprop2npropdef[mprop] = self
 
                var mpropdef = new MVirtualTypeDef(mclassdef, mprop, self.location)
                self.mpropdef = mpropdef
-               modelbuilder.mpropdef2npropdef[mpropdef] = self
                if mpropdef.is_intro then
                        modelbuilder.toolcontext.info("{mpropdef} introduces new type {mprop.full_name}", 4)
                else
                        modelbuilder.toolcontext.info("{mpropdef} redefines type {mprop.full_name}", 4)
                end
+               if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, not mpropdef.is_intro, mprop) then
+                       mpropdef.is_broken =true
+               end
+               mclassdef.mprop2npropdef[mprop] = self
+               modelbuilder.mpropdef2npropdef[mpropdef] = self
                set_doc(mpropdef, modelbuilder)
 
                var atfixed = get_single_annotation("fixed", modelbuilder)
@@ -1643,7 +1645,7 @@ redef class ATypePropdef
                # Check redefinitions
                for p in mpropdef.mproperty.lookup_super_definitions(mmodule, anchor) do
                        var supbound = p.bound
-                       if supbound == null then break # broken super bound, skip error
+                       if supbound == null or supbound isa MBottomType or p.is_broken then break # broken super bound, skip error
                        if p.is_fixed then
                                modelbuilder.error(self, "Redef Error: virtual type `{mpropdef.mproperty}` is fixed in super-class `{p.mclassdef.mclass}`.")
                                break
diff --git a/tests/error_redef_vt.nit b/tests/error_redef_vt.nit
new file mode 100644 (file)
index 0000000..eb4ef40
--- /dev/null
@@ -0,0 +1,29 @@
+# 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 core::kernel
+
+class G[E: Object]
+end
+
+class A
+       redef type N1: A
+       redef type N2: FAIL
+       fun foo1: G[N1] do return new G[N1]
+       fun foo2: G[N2] do return new G[N2]
+end
+
+var a = new A
+a.foo1
+a.foo2
index a11d29a..e6e6aff 100644 (file)
@@ -7,3 +7,4 @@
 base_simple_import.nit base_simple.nit --dir out/ ; out/base_simple ; out/base_simple_import
 test_define.nit -D text=hello -D num=42 -D flag --dir out/ ; out/test_define
 --log --log-dir $WRITE test_prog -o out/test_prog.bin
+test_define.nit --semi-global -D text=hello -D num=42 -D flag --dir out/ ; out/test_define
diff --git a/tests/sav/error_redef_vt.res b/tests/sav/error_redef_vt.res
new file mode 100644 (file)
index 0000000..320fa12
--- /dev/null
@@ -0,0 +1,3 @@
+error_redef_vt.nit:21,2--17: Error: no property `A::N1` is inherited. Remove the `redef` keyword to define a new property.
+error_redef_vt.nit:22,17--20: Error: class `FAIL` not found in module `error_redef_vt`.
+error_redef_vt.nit:22,2--20: Error: no property `A::N2` is inherited. Remove the `redef` keyword to define a new property.
index 102039e..17280d8 100644 (file)
@@ -1,5 +1,2 @@
 alt/error_virtual_type2_alt1.nit:22,2--24,14: Error: circularity of virtual type definition: GT -> T <-> T.
 alt/error_virtual_type2_alt1.nit:25,2--10: Error: circularity of virtual type definition: T <-> T.
-alt/error_virtual_type2_alt1.nit:38,23: Redef Error: expected `Comparable` for return type; got `T`.
-alt/error_virtual_type2_alt1.nit:40,17--27: Redef Error: expected `null` bound type; got `G[Discrete]`.
-alt/error_virtual_type2_alt1.nit:42,23: Redef Error: expected `Comparable` for return type; got `T`.
index a591422..31774e9 100644 (file)
@@ -1,5 +1,2 @@
 alt/error_virtual_type2_alt2.nit:22,2--24,14: Error: circularity of virtual type definition: GT -> T <-> nullable T.
 alt/error_virtual_type2_alt2.nit:25,2--26,19: Error: circularity of virtual type definition: T <-> nullable T.
-alt/error_virtual_type2_alt2.nit:38,23: Redef Error: expected `Comparable` for return type; got `T`.
-alt/error_virtual_type2_alt2.nit:40,17--27: Redef Error: expected `null` bound type; got `G[Discrete]`.
-alt/error_virtual_type2_alt2.nit:42,23: Redef Error: expected `Comparable` for return type; got `T`.
index 0a01c3d..9f5edb2 100644 (file)
@@ -1,5 +1,2 @@
 alt/error_virtual_type2_alt3.nit:22,2--24,14: Error: circularity of virtual type definition: GT -> G[T] <-> T.
 alt/error_virtual_type2_alt3.nit:25,2--27,13: Error: circularity of virtual type definition: T <-> G[T].
-alt/error_virtual_type2_alt3.nit:38,23: Redef Error: expected `Comparable` for return type; got `T`.
-alt/error_virtual_type2_alt3.nit:40,17--27: Redef Error: expected `null` bound type; got `G[Discrete]`.
-alt/error_virtual_type2_alt3.nit:42,23: Redef Error: expected `Comparable` for return type; got `T`.
index 4d60ab3..03a96d6 100644 (file)
@@ -1,4 +1 @@
 alt/error_virtual_type2_alt4.nit:29,10--13: Error: class `FAIL` not found in module `error_virtual_type2_alt4`.
-alt/error_virtual_type2_alt4.nit:38,23: Redef Error: expected `Comparable` for return type; got `T`.
-alt/error_virtual_type2_alt4.nit:40,17--27: Redef Error: expected `null` bound type; got `G[Discrete]`.
-alt/error_virtual_type2_alt4.nit:42,23: Redef Error: expected `Comparable` for return type; got `T`.
index 62974d7..07e038b 100644 (file)
@@ -1,5 +1,2 @@
 alt/error_virtual_type2_alt5.nit:22,2--24,14: Error: circularity of virtual type definition: GT -> T <-> U.
 alt/error_virtual_type2_alt5.nit:25,2--30,10: Error: circularity of virtual type definition: T <-> U.
-alt/error_virtual_type2_alt5.nit:38,23: Redef Error: expected `Comparable` for return type; got `T`.
-alt/error_virtual_type2_alt5.nit:40,17--27: Redef Error: expected `null` bound type; got `G[Discrete]`.
-alt/error_virtual_type2_alt5.nit:42,23: Redef Error: expected `Comparable` for return type; got `T`.
index 48dc700..ce3c98c 100644 (file)
@@ -1,2 +1,3 @@
 alt/error_virtual_type2_alt6.nit:40,17--27: Redef Error: expected `G[T]` bound type; got `G[Discrete]`.
+alt/error_virtual_type2_alt6.nit:41,17--23: Redef Error: expected `G[T]` bound type; got `G[Bool]`.
 alt/error_virtual_type2_alt6.nit:41,2--23: Error: a property `GT` is already defined in class `B` at line 39.
index 7514f5f..74c01ee 100644 (file)
@@ -1,2 +1 @@
-alt/error_virtual_type_alt3.nit:25,12: Type Error: expected `Object`, got `T`.
 alt/error_virtual_type_alt3.nit:22,2--25,13: Error: circularity of virtual type definition: T <-> G[T].
diff --git a/tests/sav/nitc_args10.res b/tests/sav/nitc_args10.res
new file mode 100644 (file)
index 0000000..483d841
--- /dev/null
@@ -0,0 +1,3 @@
+hello
+42
+true