src: Compiler, interpreter and parser updates for UTF-8
[nit.git] / src / compiler / abstract_compiler.nit
index 9d3b0f3..3dcfab1 100644 (file)
@@ -220,7 +220,7 @@ class MakefileToolchain
 
                # Copy original .[ch] files to compile_dir
                for src in compiler.files_to_copy do
-                       var basename = src.basename("")
+                       var basename = src.basename
                        var dst = "{compile_dir}/{basename}"
                        src.file_copy_to dst
                end
@@ -444,7 +444,7 @@ endif
                # Compile each required extern body into a specific .o
                for f in compiler.extern_bodies do
                        var o = f.makefile_rule_name
-                       var ff = f.filename.basename("")
+                       var ff = f.filename.basename
                        makefile.write("{o}: {ff}\n")
                        makefile.write("\t{f.makefile_rule_content}\n\n")
                        dep_rules.add(f.makefile_rule_name)
@@ -842,7 +842,7 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref );
                v.add("signal(SIGINT, sig_handler);")
                v.add("signal(SIGTERM, sig_handler);")
                v.add("signal(SIGSEGV, sig_handler);")
-               v.add("signal(SIGPIPE, sig_handler);")
+               v.add("signal(SIGPIPE, SIG_IGN);")
 
                v.add("glob_argc = argc; glob_argv = argv;")
                v.add("initialize_gc_option();")
@@ -1494,8 +1494,12 @@ abstract class AbstractCompilerVisitor
        fun char_instance(value: Char): RuntimeVariable
        do
                var t = mmodule.char_type
-               var res = new RuntimeVariable("'{value.to_s.escape_to_c}'", t, t)
-               return res
+
+               if value.ascii < 128 then
+                       return new RuntimeVariable("'{value.to_s.escape_to_c}'", t, t)
+               else
+                       return new RuntimeVariable("{value.ascii}", t, t)
+               end
        end
 
        # Generate a float value
@@ -1537,7 +1541,7 @@ abstract class AbstractCompilerVisitor
                var native_mtype = mmodule.native_string_type
                var nat = self.new_var(native_mtype)
                self.add("{nat} = \"{string.escape_to_c}\";")
-               var length = self.int_instance(string.length)
+               var length = self.int_instance(string.bytelen)
                self.add("{res} = {self.send(self.get_property("to_s_with_length", native_mtype), [nat, length]).as(not null)};")
                self.add("{name} = {res};")
                self.add("\}")
@@ -1598,12 +1602,12 @@ abstract class AbstractCompilerVisitor
                file = file.strip_extension(".nit")
                var tryfile = file + ".nit.h"
                if tryfile.file_exists then
-                       self.declare_once("#include \"{tryfile.basename("")}\"")
+                       self.declare_once("#include \"{tryfile.basename}\"")
                        self.compiler.files_to_copy.add(tryfile)
                end
                tryfile = file + "_nit.h"
                if tryfile.file_exists then
-                       self.declare_once("#include \"{tryfile.basename("")}\"")
+                       self.declare_once("#include \"{tryfile.basename}\"")
                        self.compiler.files_to_copy.add(tryfile)
                end
 
@@ -1614,7 +1618,7 @@ abstract class AbstractCompilerVisitor
                        tryfile = file + "_nit.c"
                        if not tryfile.file_exists then return
                end
-               var f = new ExternCFile(tryfile.basename(""), "")
+               var f = new ExternCFile(tryfile.basename, "")
                self.compiler.extern_bodies.add(f)
                self.compiler.files_to_copy.add(tryfile)
        end
@@ -1696,18 +1700,27 @@ abstract class AbstractCompilerVisitor
        # `mtype` is the expected return type, pass null if no specific type is expected.
        fun expr(nexpr: AExpr, mtype: nullable MType): RuntimeVariable
        do
-               if nexpr.mtype == null then
+               var old = self.current_node
+               self.current_node = nexpr
+
+               var res = null
+               if nexpr.mtype != null then
+                       res = nexpr.expr(self)
+               end
+
+               if res == null then
                        # Untyped expression.
                        # Might mean dead code or invalid code.
                        # so aborts
                        add_abort("FATAL: bad expression executed.")
                        # and return a placebo result to please the C compiler
                        if mtype == null then mtype = compiler.mainmodule.object_type
-                       return new_var(mtype)
+                       res = new_var(mtype)
+
+                       self.current_node = old
+                       return res
                end
-               var old = self.current_node
-               self.current_node = nexpr
-               var res = nexpr.expr(self).as(not null)
+
                if mtype != null then
                        mtype = self.anchor(mtype)
                        res = self.autobox(res, mtype)
@@ -1879,7 +1892,7 @@ redef class MClassType
                else if mclass.name == "Byte" then
                        return "unsigned char"
                else if mclass.name == "NativeString" then
-                       return "unsigned char*"
+                       return "char*"
                else if mclass.name == "NativeArray" then
                        return "val*"
                else
@@ -2148,10 +2161,7 @@ redef class AMethPropdef
                                return true
                        end
                else if cname == "Char" then
-                       if pname == "output" then
-                               v.add("printf(\"%c\", ((unsigned char){arguments.first}));")
-                               return true
-                       else if pname == "object_id" then
+                       if pname == "object_id" then
                                v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
                                return true
                        else if pname == "successor" then
@@ -2323,7 +2333,7 @@ redef class AMethPropdef
                        end
                else if cname == "NativeString" then
                        if pname == "[]" then
-                               v.ret(v.new_expr("(uint32_t){arguments[0]}[{arguments[1]}]", ret.as(not null)))
+                               v.ret(v.new_expr("(unsigned char)((int){arguments[0]}[{arguments[1]}])", ret.as(not null)))
                                return true
                        else if pname == "[]=" then
                                v.add("{arguments[0]}[{arguments[1]}]=(unsigned char){arguments[2]};")
@@ -2338,7 +2348,7 @@ redef class AMethPropdef
                                v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null)))
                                return true
                        else if pname == "new" then
-                               v.ret(v.new_expr("(unsigned char*)nit_alloc({arguments[1]})", ret.as(not null)))
+                               v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null)))
                                return true
                        end
                else if cname == "NativeArray" then
@@ -2352,7 +2362,7 @@ redef class AMethPropdef
                        v.ret(v.new_expr("glob_sys", ret.as(not null)))
                        return true
                else if pname == "calloc_string" then
-                       v.ret(v.new_expr("(unsigned char*)nit_alloc({arguments[1]})", ret.as(not null)))
+                       v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null)))
                        return true
                else if pname == "calloc_array" then
                        v.calloc_array(ret.as(not null), arguments)
@@ -2457,7 +2467,7 @@ redef class AAttrPropdef
                        var res
                        if is_lazy then
                                var set
-                               var ret = self.mpropdef.static_mtype
+                               var ret = self.mtype
                                var useiset = not ret.is_c_primitive and not ret isa MNullableType
                                var guard = self.mlazypropdef.mproperty
                                if useiset then
@@ -2485,7 +2495,7 @@ redef class AAttrPropdef
                        assert arguments.length == 2
                        v.write_attribute(self.mpropdef.mproperty, arguments.first, arguments[1])
                        if is_lazy then
-                               var ret = self.mpropdef.static_mtype
+                               var ret = self.mtype
                                var useiset = not ret.is_c_primitive and not ret isa MNullableType
                                if not useiset then
                                        v.write_attribute(self.mlazypropdef.mproperty, arguments.first, v.bool_instance(true))
@@ -2507,11 +2517,11 @@ redef class AAttrPropdef
                var oldnode = v.current_node
                v.current_node = self
                var old_frame = v.frame
-               var frame = new StaticFrame(v, self.mpropdef.as(not null), recv.mcasttype.undecorate.as(MClassType), [recv])
+               var frame = new StaticFrame(v, self.mreadpropdef.as(not null), recv.mcasttype.undecorate.as(MClassType), [recv])
                v.frame = frame
 
                var value
-               var mtype = self.mpropdef.static_mtype
+               var mtype = self.mtype
                assert mtype != null
 
                var nexpr = self.n_expr
@@ -3035,7 +3045,9 @@ redef class AIsaExpr
        redef fun expr(v)
        do
                var i = v.expr(self.n_expr, null)
-               return v.type_test(i, self.cast_type.as(not null), "isa")
+               var cast_type = self.cast_type
+               if cast_type == null then return null # no-no on broken node
+               return v.type_test(i, cast_type, "isa")
        end
 end