model: remove `new_msignature` and special call as the new signature is the method...
[nit.git] / src / compiler / abstract_compiler.nit
index 821ad31..b8681bc 100644 (file)
@@ -349,7 +349,7 @@ class MakefileToolchain
                end
                var debug = toolcontext.opt_debug.value
 
-               makefile.write("CC = ccache cc\nCXX = ccache c++\nCFLAGS = -g{ if not debug then " -O2 " else " "}-Wno-unused-value -Wno-switch -Wno-attributes\nCINCL =\nLDFLAGS ?= \nLDLIBS  ?= -lm {linker_options.join(" ")}\n\n")
+               makefile.write("CC = ccache cc\nCXX = ccache c++\nCFLAGS = -g{ if not debug then " -O2 " else " "}-Wno-unused-value -Wno-switch -Wno-attributes -Wno-trigraphs\nCINCL =\nLDFLAGS ?= \nLDLIBS  ?= -lm {linker_options.join(" ")}\n\n")
 
                makefile.write "\n# SPECIAL CONFIGURATION FLAGS\n"
                if platform.supports_libunwind then
@@ -654,9 +654,21 @@ abstract class AbstractCompiler
                self.header.add_decl("#include <sys/types.h>\n")
                self.header.add_decl("#include <unistd.h>\n")
                self.header.add_decl("#include <stdint.h>\n")
+               self.header.add_decl("#ifdef __linux__")
+               self.header.add_decl("  #include <endian.h>")
+               self.header.add_decl("#endif")
                self.header.add_decl("#include <inttypes.h>\n")
                self.header.add_decl("#include \"gc_chooser.h\"")
+               self.header.add_decl("#ifdef __APPLE__")
+               self.header.add_decl("  #include <libkern/OSByteOrder.h>")
+               self.header.add_decl("  #define be32toh(x) OSSwapBigToHostInt32(x)")
+               self.header.add_decl("#endif")
+               self.header.add_decl("#ifdef __pnacl__")
+               self.header.add_decl("  #define be16toh(val) (((val) >> 8) | ((val) << 8))")
+               self.header.add_decl("  #define be32toh(val) ((be16toh((val) << 16) | (be16toh((val) >> 16))))")
+               self.header.add_decl("#endif")
                self.header.add_decl("#ifdef ANDROID")
+               self.header.add_decl("  #define be32toh(val) betoh32(val)")
                self.header.add_decl("  #include <android/log.h>")
                self.header.add_decl("  #define PRINT_ERROR(...) (void)__android_log_print(ANDROID_LOG_WARN, \"Nit\", __VA_ARGS__)")
                self.header.add_decl("#else")
@@ -853,7 +865,7 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref );
                        v.add_decl("int main(int argc, char** argv) \{")
                end
 
-               v.add "#ifndef ANDROID"
+               v.add "#if !defined(__ANDROID__) && !defined(TARGET_OS_IPHONE)"
                v.add("signal(SIGABRT, sig_handler);")
                v.add("signal(SIGFPE, sig_handler);")
                v.add("signal(SIGILL, sig_handler);")
@@ -1150,29 +1162,6 @@ abstract class AbstractCompilerVisitor
        fun compile_callsite(callsite: CallSite, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
        do
                if callsite.is_broken then return null
-               var initializers = callsite.mpropdef.initializers
-               if not initializers.is_empty then
-                       var recv = arguments.first
-
-                       var i = 1
-                       for p in initializers do
-                               if p isa MMethod then
-                                       var args = [recv]
-                                       for x in p.intro.msignature.mparameters do
-                                               args.add arguments[i]
-                                               i += 1
-                                       end
-                                       self.send(p, args)
-                               else if p isa MAttribute then
-                                       self.write_attribute(p, recv, arguments[i])
-                                       i += 1
-                               else abort
-                       end
-                       assert i == arguments.length
-
-                       return self.send(callsite.mproperty, [recv])
-               end
-
                return self.send(callsite.mproperty, arguments)
        end
 
@@ -1180,7 +1169,7 @@ abstract class AbstractCompilerVisitor
 
        fun calloc_array(ret_type: MType, arguments: Array[RuntimeVariable]) is abstract
 
-       fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable]) is abstract
+       fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable]): Bool do return false
 
        # Return an element of a native array.
        # The method is unsafe and is just a direct wrapper for the specific implementation of native arrays
@@ -1195,7 +1184,7 @@ abstract class AbstractCompilerVisitor
        # of runtime variables to use in the call.
        fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: RuntimeVariable, args: SequenceRead[AExpr]): Array[RuntimeVariable]
        do
-               var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null)
+               var msignature = mpropdef.msignature.as(not null)
                var res = new Array[RuntimeVariable]
                res.add(recv)
 
@@ -1224,8 +1213,8 @@ abstract class AbstractCompilerVisitor
                                res.add(null_instance)
                                continue
                        end
-                       if param.is_vararg and map.vararg_decl > 0 then
-                               var vararg = exprs.sub(j, map.vararg_decl)
+                       if param.is_vararg and args[i].vararg_decl > 0 then
+                               var vararg = exprs.sub(j, args[i].vararg_decl)
                                var elttype = param.mtype
                                var arg = self.vararg_instance(mpropdef, recv, vararg, elttype)
                                res.add(arg)
@@ -1659,7 +1648,7 @@ abstract class AbstractCompilerVisitor
        # This is used for the legacy FFI
        fun add_extern(mmodule: MModule)
        do
-               var file = mmodule.location.file.filename
+               var file = mmodule.filepath
                file = file.strip_extension(".nit")
                var tryfile = file + ".nit.h"
                if tryfile.file_exists then
@@ -2080,19 +2069,20 @@ redef class MMethodDef
                var msignature = self.msignature.as(not null)
 
                for i in [0..msignature.arity[ do
+                       var mp = msignature.mparameters[i]
                        # skip test for vararg since the array is instantiated with the correct polymorphic type
-                       if msignature.vararg_rank == i then continue
+                       if mp.is_vararg then continue
 
                        # skip if the cast is not required
                        var origmtype =  self.mproperty.intro.msignature.mparameters[i].mtype
                        if not origmtype.need_anchor then continue
 
                        # get the parameter type
-                       var mtype = msignature.mparameters[i].mtype
+                       var mtype = mp.mtype
 
                        # generate the cast
                        # note that v decides if and how to implements the cast
-                       v.add("/* Covariant cast for argument {i} ({msignature.mparameters[i].name}) {arguments[i+1].inspect} isa {mtype} */")
+                       v.add("/* Covariant cast for argument {i} ({mp.name}) {arguments[i+1].inspect} isa {mtype} */")
                        v.add_cast(arguments[i+1], mtype, "covariance")
                end
        end
@@ -2134,7 +2124,8 @@ redef class AMethPropdef
                # Try special compilation
                if mpropdef.is_intern then
                        if compile_intern_to_c(v, mpropdef, arguments) then return
-               else if mpropdef.is_extern then
+               end
+               if mpropdef.is_extern then
                        if mpropdef.mproperty.is_init then
                                if compile_externinit_to_c(v, mpropdef, arguments) then return
                        else
@@ -2249,6 +2240,21 @@ redef class AMethPropdef
                        else if pname == "to_b" then
                                v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
                                return true
+                       else if pname == "code_point" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "&" then
+                               v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "|" then
+                               v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == ">>" then
+                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "<<" then
+                               v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
+                               return true
                        end
                else if cname == "Char" then
                        if pname == "object_id" then
@@ -2282,6 +2288,9 @@ redef class AMethPropdef
                        else if pname == "to_i" then
                                v.ret(v.new_expr("{arguments[0]}-'0'", ret.as(not null)))
                                return true
+                       else if pname == "code_point" then
+                               v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+                               return true
                        end
                else if cname == "Byte" then
                        if pname == "output" then
@@ -2330,6 +2339,15 @@ redef class AMethPropdef
                        else if pname == ">=" then
                                v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
                                return true
+                       else if pname == ">>" then
+                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "<<" then
+                               v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "&" then
+                               v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
+                               return true
                        else if pname == "to_i" then
                                v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
                                return true
@@ -2351,6 +2369,9 @@ redef class AMethPropdef
                        else if pname == "to_u32" then
                                v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
                                return true
+                       else if pname == "ascii" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
                        end
                else if cname == "Bool" then
                        if pname == "output" then
@@ -2455,13 +2476,25 @@ redef class AMethPropdef
                        else if pname == "fast_cstring" then
                                v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
                                return true
+                       else if pname == "==" then
+                               v.ret(v.equal_test(arguments[0], arguments[1]))
+                               return true
+                       else if pname == "!=" then
+                               var res = v.equal_test(arguments[0], arguments[1])
+                               v.ret(v.new_expr("!{res}", ret.as(not null)))
+                               return true
                        else if pname == "new" then
                                v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null)))
                                return true
+                       else if pname == "fetch_4_chars" then
+                               v.ret(v.new_expr("(long)*((uint32_t*)({arguments[0]} + {arguments[1]}))", ret.as(not null)))
+                               return true
+                       else if pname == "fetch_4_hchars" then
+                               v.ret(v.new_expr("(long)be32toh(*((uint32_t*)({arguments[0]} + {arguments[1]})))", ret.as(not null)))
+                               return true
                        end
                else if cname == "NativeArray" then
-                       v.native_array_def(pname, ret, arguments)
-                       return true
+                       return v.native_array_def(pname, ret, arguments)
                else if cname == "Int8" then
                        if pname == "output" then
                                v.add("printf(\"%\"PRIi8 \"\\n\", {arguments.first});")
@@ -3111,13 +3144,38 @@ end
 redef class AClassdef
        private fun compile_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable])
        do
-               if mpropdef == self.mfree_init then
-                       assert mpropdef.mproperty.is_root_init
+               if mpropdef.mproperty.is_root_init then
                        assert arguments.length == 1
                        if not mpropdef.is_intro then
                                v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
                        end
                        return
+               else if mclassdef.auto_init == mpropdef then
+                       var recv = arguments.first
+                       var initializers = mpropdef.initializers
+                       var no_init = false
+                       if not initializers.is_empty then
+
+                               var i = 1
+                               for p in initializers do
+                                       if p isa MMethod then
+                                               var args = [recv]
+                                               for x in p.intro.msignature.mparameters do
+                                                       args.add arguments[i]
+                                                       i += 1
+                                               end
+                                               v.send(p, args)
+                                               if p.intro.is_calling_init then no_init = true
+                                       else if p isa MAttribute then
+                                               v.write_attribute(p, recv, arguments[i])
+                                               i += 1
+                                       else abort
+                               end
+                               assert i == arguments.length
+
+                       end
+                       if not no_init then v.send(mclass.the_root_init_mmethod.as(not null), [recv])
+                       return
                else
                        abort
                end