Merge remote-tracking branch 'alexis/a_star'
authorJean Privat <jean@pryen.org>
Wed, 12 Mar 2014 15:29:47 +0000 (11:29 -0400)
committerJean Privat <jean@pryen.org>
Wed, 12 Mar 2014 15:29:47 +0000 (11:29 -0400)
The type error was detected by nitg in complex cases.

31 files changed:
src/abstract_compiler.nit
src/c_tools.nit
src/collect_super_sends.nit [deleted file]
src/compiling_writer.nit [deleted file]
src/modelize_property.nit
src/naive_interpreter.nit
src/nitni/nitni_callbacks.nit
src/rapid_type_analysis.nit
src/separate_compiler.nit
src/typing.nit
tests/nitg-e.skip
tests/nitg-g.skip
tests/nitg-s.skip
tests/niti.skip
tests/sav/a_star.res [new file with mode: 0644]
tests/sav/bucketed_game.res [new file with mode: 0644]
tests/sav/console.res [new file with mode: 0644]
tests/sav/counter.res [new file with mode: 0644]
tests/sav/cpp.res [new file with mode: 0644]
tests/sav/curl.res [new file with mode: 0644]
tests/sav/json_serialization.res [new file with mode: 0644]
tests/sav/mnit_linux.res [new file with mode: 0644]
tests/sav/more_collections.res [new file with mode: 0644]
tests/sav/ordered_tree.res [new file with mode: 0644]
tests/sav/poset.res [new file with mode: 0644]
tests/sav/serialization.res [new file with mode: 0644]
tests/sav/simple_json_reader.res [new file with mode: 0644]
tests/sav/template.res [new file with mode: 0644]
tests/test_extern_nit.c
tests/test_extern_nit.h
tests/tests.sh

index b4d0779..a472d8f 100644 (file)
@@ -236,7 +236,12 @@ class MakefileToolchain
                        hfile.write "#include \"{hfilename}\"\n"
                        for key in f.required_declarations do
                                if not compiler.provided_declarations.has_key(key) then
-                                       print "No provided declaration for {key}"
+                                       var node = compiler.requirers_of_declarations.get_or_null(key)
+                                       if node != null then
+                                               node.debug "No provided declaration for {key}"
+                                       else
+                                               print "No provided declaration for {key}"
+                                       end
                                        abort
                                end
                                hfile.write compiler.provided_declarations[key]
@@ -422,6 +427,8 @@ abstract class AbstractCompiler
 
        private var provided_declarations = new HashMap[String, String]
 
+       private var requirers_of_declarations = new HashMap[String, ANode]
+
        # Builds the .c and .h files to be used when generating a Stack Trace
        # Binds the generated C function names to Nit function names
        fun build_c_to_nit_bindings
@@ -1071,7 +1078,11 @@ abstract class AbstractCompilerVisitor
        # Request the presence of a global declaration
        fun require_declaration(key: String)
        do
-               self.writer.file.required_declarations.add(key)
+               var reqs = self.writer.file.required_declarations
+               if reqs.has(key) then return
+               reqs.add(key)
+               var node = current_node
+               if node != null then compiler.requirers_of_declarations[key] = node
        end
 
        # Add a declaration in the local-header
@@ -2499,7 +2510,7 @@ redef class ASuperExpr
                end
 
                # stantard call-next-method
-               return v.supercall(v.frame.mpropdef.as(MMethodDef), recv.mtype.as(MClassType), args)
+               return v.supercall(mpropdef.as(not null), recv.mtype.as(MClassType), args)
        end
 end
 
index e05f4bf..5d9c634 100644 (file)
 # provides tools to write C .c and .h files
 module c_tools
 
-import compiling_writer
+import template
 
 # Accumulates all C code for a compilation unit
 class CCompilationUnit
        ## header
        # comments and native interface imports
-       var header_c_base : Writer = new Writer
+       var header_c_base = new Template
 
        # custom C header code or generated for other languages
-       var header_custom : Writer = new Writer
+       var header_custom = new Template
 
        # types of extern classes and friendly types
-       var header_c_types : Writer = new Writer
+       var header_c_types = new Template
 
        # implementation declaration for extern methods
-       var header_decl : Writer = new Writer
+       var header_decl = new Template
 
        ## body
        # comments, imports, etc
-       var body_decl : Writer = new Writer
+       var body_decl = new Template
 
        # custom code and generated for ffi
-       var body_custom : Writer = new Writer
+       var body_custom = new Template
 
        # implementation body of extern methods
-       var body_impl : Writer = new Writer
+       var body_impl = new Template
 
        # files to compile TODO check is appropriate
        var files = new Array[String]
@@ -51,29 +51,29 @@ class CCompilationUnit
        do
                body_decl.add( "{efc.signature};\n" )
                body_impl.add( "\n" )
-               body_impl.append( efc.to_writer )
+               body_impl.add( efc.to_writer )
        end
 
        fun add_exported_function( efc : CFunction )
        do
                header_decl.add( "{efc.signature};\n" )
                body_impl.add( "\n" )
-               body_impl.append( efc.to_writer )
+               body_impl.add( efc.to_writer )
        end
 
        fun compile_header_core( stream : OStream )
        do
-               header_c_base.write_to_stream( stream )
-               header_custom.write_to_stream( stream )
-               header_c_types.write_to_stream( stream )
-               header_decl.write_to_stream( stream )
+               header_c_base.write_to( stream )
+               header_custom.write_to( stream )
+               header_c_types.write_to( stream )
+               header_decl.write_to( stream )
        end
 
        fun compile_body_core( stream : OStream )
        do
-               body_decl.write_to_stream( stream )
-               body_custom.write_to_stream( stream )
-               body_impl.write_to_stream( stream )
+               body_decl.write_to( stream )
+               body_custom.write_to( stream )
+               body_impl.write_to( stream )
        end
 end
 
@@ -81,20 +81,19 @@ end
 class CFunction
        var signature : String
 
-       var decls : Writer = new Writer
-       var exprs : Writer = new Writer
+       var decls = new Template
+       var exprs = new Template
 
-       fun to_writer : Writer
+       fun to_writer: Template
        do
-               var w = new Writer
-
-               w.add( "{signature}\n\{\n" )
-
-               w.append( decls )
-               w.add( "\n" )
-               w.append( exprs )
-
-               w.add( "\}\n" )
+               var w = new Template
+
+               w.add(signature)
+               w.add("\n\{\n")
+               w.add(decls)
+               w.add("\n")
+               w.add(exprs)
+               w.add("\}\n")
 
                return w
        end
diff --git a/src/collect_super_sends.nit b/src/collect_super_sends.nit
deleted file mode 100644 (file)
index 32bfb6a..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-# 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.
-
-# Collect super sends
-module collect_super_sends
-
-import modelbuilder
-private import modelize_property
-private import typing
-
-private class CollectSuperSends
-       super Visitor
-       var modelbuilder: ModelBuilder
-       var res = new ArraySet[MMethodDef]
-       var mpropdef: nullable MMethodDef
-
-       # Get a new visitor on a classef to add type count in `typecount`.
-       init(modelbuilder: ModelBuilder)
-       do
-               self.modelbuilder = modelbuilder
-       end
-
-       redef fun visit(n)
-       do
-               if n isa AMethPropdef then
-                       assert mpropdef == null
-                       mpropdef = n.mpropdef
-                       n.visit_all(self)
-                       mpropdef = null
-                       return
-               end
-               n.visit_all(self)
-               if (n isa ASuperExpr and n.callsite == null) or n isa ASuperExternCall then
-                       var mprop = mpropdef
-                       assert mprop != null
-                       res.add(mprop)
-               end
-       end
-end
-
-redef class ModelBuilder
-       # Visit the AST and return all method definitions that performs a `super`.
-       fun collect_super_sends: Set[MMethodDef]
-       do
-               var visitor = new CollectSuperSends(self)
-
-               # Visit all the source code to collect data
-               for nmodule in self.nmodules do
-                       visitor.enter_visit(nmodule)
-               end
-
-               return visitor.res
-       end
-end
diff --git a/src/compiling_writer.nit b/src/compiling_writer.nit
deleted file mode 100644 (file)
index 98e5cdc..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2010 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.
-
-# Helps to generate complex strings.
-# Can be used to simplify complex file generation where text addition is not only done at the end
-module compiling_writer
-
-# A writer is used to store a sequence of strings and sub-writers
-class Writer
-       # Add a new string at the end of the writer
-       fun add(s: String): Writer
-       do
-               assert not is_frozen
-               var c = _last_string
-               var c2 = new WriterStrings(s)
-               if c == null then
-                       internal_append(c2)
-               else
-                       c._next = c2
-               end
-               _last_string = c2
-               return self
-       end
-
-       # Add each string of the array but separate them
-       fun add_all(a: Array[String], separator: String): Writer
-       do
-               assert not is_frozen
-               var first = true
-               for s in a do
-                       if first then first = false else add(separator)
-                       add(s)
-               end
-               return self
-       end
-
-       var _first_sub_writer: nullable WriterNode = null
-       var _last_sub_writer: nullable WriterNode = null
-
-       # Last string added. Implies that _last_sub_writer isa WriterStrings
-       var _last_string: nullable WriterStrings = null
-
-       # Insert an other Writer at the end of the writer
-       fun append(c: Writer): Writer
-       do
-               assert not is_frozen
-               internal_append(new WriterCoreNode(c))
-               _last_string = null # next add will create a new WriterStrings after c
-               return self
-       end
-
-       # Insert a writer as a sub-one
-       private fun internal_append(c: WriterNode)
-       do
-               if _first_sub_writer == null then _first_sub_writer = c
-               var l = _last_sub_writer
-               if l != null then l._next_writer = c
-               _last_sub_writer = c
-       end
-
-       # Create a sub-writer that can be used as a new string insertion point
-       fun sub: Writer
-       do
-               var c = new Writer
-               append(c)
-               return c
-       end
-
-       var _is_writing: Bool = false
-
-       # Write all strings (including nested ones) to a stream
-       fun write_to_stream(s: OStream)
-       do
-               assert not _is_writing
-               _is_writing = true
-               var cur = _first_sub_writer
-               while cur != null do
-                       cur.internal_write_to_stream(s)
-                       cur = cur._next_writer
-               end
-               _is_writing = false
-       end
-
-       # Return true if the string writer is frozen
-       readable var _is_frozen: Bool = false
-
-       # Disable further writer modification: nor add or append are allowed
-       fun freeze
-       do
-               if is_frozen then return
-               _is_frozen = true
-       end
-
-       init do end
-end
-
-# Simple linked list of Writers contents
-private abstract class WriterNode
-       # The next writer in the list
-       var _next_writer: nullable WriterNode = null
-
-       # Write all strings (including nested ones) to a stream
-       fun internal_write_to_stream(s: OStream) is abstract
-end
-
-# A writer node that contains a full writer
-private class WriterCoreNode
-       super WriterNode
-       var _writer: Writer
-
-       redef fun internal_write_to_stream(s) do _writer.write_to_stream(s)
-
-       init(w: Writer) do _writer = w
-end
-
-# A simple writer node that contains only strings
-private class WriterStrings
-       super WriterNode
-       # The first string
-       var _string: String
-
-       # The next strings
-       var _next: nullable WriterStrings = null
-
-       init(s: String)
-       do
-               _string = s
-       end
-
-       redef fun internal_write_to_stream(s)
-       do
-               var cur: nullable WriterStrings = self
-               while cur != null do
-                       s.write(cur._string)
-                       cur = cur._next
-               end
-       end
-end
-
index 89eb0f3..980dfc7 100644 (file)
@@ -162,6 +162,12 @@ redef class MClassDef
        private var propdef_names = new HashSet[String]
 end
 
+redef class MPropDef
+       # Does the MPropDef contains a call to super or a call of a super-constructor?
+       # Subsequent phases of the frontend (esp. typing) set it if required
+       var has_supercall: Bool writable = false
+end
+
 redef class AClassdef
        var build_properties_is_done: Bool = false
        # The list of super-constructor to call at the start of the free constructor
index 4b1030a..afa3fd9 100644 (file)
@@ -716,6 +716,10 @@ redef class AInternMethPropdef
                                return v.char_instance(recv.succ)
                        else if pname == "prec" then
                                return v.char_instance(recv.prec)
+                       else if pname == "+" then
+                               return v.char_instance(recv + args[1].to_i)
+                       else if pname == "-" then
+                               return v.char_instance(recv - args[1].to_i)
                        else if pname == "<" then
                                return v.bool_instance(recv < args[1].val.as(Char))
                        else if pname == ">" then
@@ -929,6 +933,14 @@ redef class AExternMethPropdef
                                return v.float_instance(args[0].to_f.pow(args[1].to_f))
                        else if pname == "rand" then
                                return v.float_instance(args[0].to_f.rand)
+                       else if pname == "abs" then
+                               return v.float_instance(args[0].to_f.abs)
+                       else if pname == "hypot_with" then
+                               return v.float_instance(args[0].to_f.hypot_with(args[1].to_f))
+                       else if pname == "is_nan" then
+                               return v.bool_instance(args[0].to_f.is_nan)
+                       else if pname == "is_inf_extern" then
+                               return v.bool_instance(args[0].to_f.is_inf != 0)
                        end
                else if pname == "native_argc" then
                        return v.int_instance(v.arguments.length)
@@ -1586,9 +1598,8 @@ redef class ASuperExpr
                end
 
                # stantard call-next-method
-               var mpropdef = v.frame.mpropdef
+               var mpropdef = self.mpropdef
                mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
-               assert mpropdef isa MMethodDef
                var res = v.call_without_varargs(mpropdef, args)
                return res
        end
index 5cf389f..efe3667 100644 (file)
@@ -362,6 +362,7 @@ redef class ASuperExternCall
        do
                callback_set.supers.add( new MExplicitSuper( npropdef.mpropdef.as(not null) ) )
                callback_set.types.add( npropdef.mpropdef.mclassdef.mclass.mclass_type )
+               npropdef.mpropdef.has_supercall = true
        end
 end
 
index eecee11..50e4563 100644 (file)
@@ -544,7 +544,7 @@ redef class ASuperExpr
                        return
                end
 
-               v.analysis.add_super_send(v.receiver, v.mpropdef.as(MMethodDef))
+               v.analysis.add_super_send(v.receiver, mpropdef.as(not null))
        end
 end
 
index 4122fdd..f5dd05d 100644 (file)
@@ -18,7 +18,6 @@ module separate_compiler
 import abstract_compiler
 import layout_builders
 import rapid_type_analysis
-import collect_super_sends
 import compiler_ffi
 
 # Add separate compiler specific options
@@ -275,13 +274,27 @@ class SeparateCompiler
                        end
                end
 
+               # Collect all super calls (dead or not)
+               var all_super_calls = new HashSet[MMethodDef]
+               for mmodule in self.mainmodule.in_importation.greaters do
+                       for mclassdef in mmodule.mclassdefs do
+                               for mpropdef in mclassdef.mpropdefs do
+                                       if not mpropdef isa MMethodDef then continue
+                                       if mpropdef.has_supercall then
+                                               all_super_calls.add(mpropdef)
+                                       end
+                               end
+                       end
+               end
+
                # lookup super calls and add it to the list of mmethods to build layout with
                var super_calls
                if runtime_type_analysis != null then
                        super_calls = runtime_type_analysis.live_super_sends
                else
-                       super_calls = modelbuilder.collect_super_sends
+                       super_calls = all_super_calls
                end
+
                for mmethoddef in super_calls do
                        var mclass = mmethoddef.mclassdef.mclass
                        mmethods[mclass].add(mmethoddef)
@@ -296,14 +309,9 @@ class SeparateCompiler
                self.compile_color_consts(method_layout.pos)
 
                # attribute null color to dead supercalls
-               for mmodule in self.mainmodule.in_importation.greaters do
-                       for mclassdef in mmodule.mclassdefs do
-                               for mpropdef in mclassdef.mpropdefs do
-                                       if mpropdef.has_supercall then
-                                               compile_color_const(new_visitor, mpropdef, -1)
-                                       end
-                               end
-                       end
+               for mpropdef in all_super_calls do
+                       if super_calls.has(mpropdef) then continue
+                       compile_color_const(new_visitor, mpropdef, -1)
                end
 
                # attributes coloration
index 6838784..9feb83b 100644 (file)
@@ -27,11 +27,6 @@ redef class ToolContext
        var typing_phase: Phase = new TypingPhase(self, [flow_phase, modelize_property_phase, local_var_init_phase])
 end
 
-redef class MPropDef
-       # Does the MPropDef contains a call to super or a call of a super-constructor?
-       var has_supercall: Bool = false
-end
-
 private class TypingPhase
        super Phase
        redef fun process_npropdef(npropdef) do npropdef.do_typing(toolcontext.modelbuilder)
@@ -1425,6 +1420,10 @@ redef class ASuperExpr
        # Note: if the super is a normal call-next-method, then this attribute is null
        var callsite: nullable CallSite
 
+       # The method to call is the super is a standard `call-next-method` super-call
+       # Note: if the super is a special super-init-call, then this attribute is null
+       var mpropdef: nullable MMethodDef
+
        redef fun accept_typing(v)
        do
                var recvtype = v.nclassdef.mclassdef.bound_mtype
@@ -1453,6 +1452,7 @@ redef class ASuperExpr
                self.mtype = msignature.return_mtype
                self.is_typed = true
                v.mpropdef.has_supercall = true
+               mpropdef = v.mpropdef.as(MMethodDef)
        end
 
        private fun process_superinit(v: TypeVisitor)
index 83dbd73..4050a44 100644 (file)
@@ -1,7 +1,4 @@
-closure
 init_inherit
 init_linext
 inline
-test_extern
-nitc
 test_json
index a322ad1..8a7e8c7 100644 (file)
@@ -1,8 +1,5 @@
-closure
 init_inherit
 init_linext
 inline
-test_extern
-nitc
 nitg
 test_json
index 83dbd73..4050a44 100644 (file)
@@ -1,7 +1,4 @@
-closure
 init_inherit
 init_linext
 inline
-test_extern
-nitc
 test_json
index 96f6ba2..2d458dd 100644 (file)
@@ -1,4 +1,3 @@
-closure
 init_inherit
 init_linext
 inline
diff --git a/tests/sav/a_star.res b/tests/sav/a_star.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/bucketed_game.res b/tests/sav/bucketed_game.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/console.res b/tests/sav/console.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/counter.res b/tests/sav/counter.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/cpp.res b/tests/sav/cpp.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/curl.res b/tests/sav/curl.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/json_serialization.res b/tests/sav/json_serialization.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/mnit_linux.res b/tests/sav/mnit_linux.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/more_collections.res b/tests/sav/more_collections.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/ordered_tree.res b/tests/sav/ordered_tree.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/poset.res b/tests/sav/poset.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/serialization.res b/tests/sav/serialization.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/simple_json_reader.res b/tests/sav/simple_json_reader.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/template.res b/tests/sav/template.res
new file mode 100644 (file)
index 0000000..e69de29
index 0008e7e..5bc2013 100644 (file)
@@ -1,5 +1,5 @@
 #include "test_extern_nit.h"
 
-long int foo(Object s) { return 10; }
-long int bar(Object s, long int i) { return i*2; }
-Object baz(Object s, Object a) { return a; }
+long int foo(void *s) { return 10; }
+long int bar(void *s, long int i) { return i*2; }
+void *baz(void *s, void *a) { return a; }
index ea9875a..67b7fc8 100644 (file)
@@ -1,5 +1,4 @@
-#include <test_extern._nitni.h>
 
-long int foo(Object);
-long int bar(Object, long int);
-Object baz(Object, Object);
+long int foo(void *);
+long int bar(void *, long int);
+void *baz(void *, void *);
index 8de440f..87e4db1 100755 (executable)
@@ -145,6 +145,7 @@ function process_result()
                        remains="$remains $OLD"
                else
                        echo "[fixme] out/$pattern.res $FIXME"
+                       echo >>$xml "<skipped/>"
                fi
                todos="$todos $pattern"
        elif [ -n "$SOSO" ]; then
@@ -159,6 +160,7 @@ function process_result()
                        echo "not ok - $description # TODO not yet implemented"
                else
                        echo "[todo] out/$pattern.res -> not yet implemented"
+                       echo >>$xml "<skipped/>"
                fi
                todos="$todos $pattern"
        elif [ -n "$SOSOF" ]; then
@@ -166,6 +168,7 @@ function process_result()
                        echo "not ok - $description # TODO SOSO expected failure"
                else
                        echo "[fixme soso] out/$pattern.res $SOSOF"
+                       echo >>$xml "<skipped/>"
                fi
                todos="$todos $pattern"
        elif [ -n "$NSAV" ]; then
@@ -448,6 +451,13 @@ END
                                        # Sould we skip the input for this engine?
                                        need_skip $bff "  $name" $pack && continue
 
+                                       # use a specific inputs file, if required
+                                       if [ -f "$bff.inputs" ]; then
+                                               ffinputs="$bff.inputs"
+                                       else
+                                               ffinputs=$inputs
+                                       fi
+
                                        rm -rf "$fff.res" "$fff.err" "$fff.write" 2> /dev/null
                                        if [ "x$verbose" = "xtrue" ]; then
                                                echo ""
@@ -456,7 +466,7 @@ END
                                        test -z "$tap" && echo -n "==> $name "
                                        echo "./$ff.bin $args" > "./$fff.bin"
                                        chmod +x "./$fff.bin"
-                                       WRITE="$fff.write" sh -c "NIT_NO_STACK=1 $TIMEOUT ./$fff.bin < $inputs > $fff.res 2>$fff.err"
+                                       WRITE="$fff.write" sh -c "NIT_NO_STACK=1 $TIMEOUT ./$fff.bin < $ffinputs > $fff.res 2>$fff.err"
                                        if [ "x$verbose" = "xtrue" ]; then
                                                cat "$fff.res"
                                                cat >&2 "$fff.err"