parser: new class SourceFile
[nit.git] / src / compiling / compiling_icode.nit
index 17a70d2..40894fe 100644 (file)
@@ -168,7 +168,7 @@ class I2CCompilerVisitor
                if l != null then
                        visitor.add_indent(w)
                        w.add("/* ")
-                       w.add(l.file)
+                       w.add(l.file.filename)
                        w.add(":")
                        w.add(l.line_start.to_s)
                        w.add(" */\n")
@@ -266,7 +266,7 @@ redef class IRoutine
                else
                        p = cparams.join(", ")
                end
-               if human_name != null then v.add_decl("#define LOCATE_{cname} \"{human_name}\"")
+               if human_name != null then v.add_decl("static const char * const LOCATE_{cname} = \"{human_name}\";")
                v.add_decl("{r} {cname}({p});")
                v.add_decl("typedef {r} (*{cname}_t)({p});")
                v.add_instr("{r} {cname}({p})\{")
@@ -289,7 +289,7 @@ redef class IRoutine
                        v.add_decl("struct \{struct stack_frame_t me;\} fra;")
                end
                v.add_instr("fra.me.prev = stack_frame_head; stack_frame_head = &fra.me;")
-               v.add_instr("fra.me.file = LOCATE_{v.visitor.module.name};")
+               v.add_instr("fra.me.file = LOCATE_{v.visitor.mmmodule.name};")
                v.add_instr("fra.me.line = {ll};")
                v.add_instr("fra.me.meth = LOCATE_{v.basecname};")
                v.add_instr("fra.me.has_broke = 0;")
@@ -577,16 +577,10 @@ redef class ICall
                var w = new Writer
                var prop = property
                if prop.global.is_init then args.add("init_table")
-               if prop.name == (once ("add".to_symbol)) and prop.local_class.name == (once ("Array".to_symbol)) then
-                       w.add(prop.cname)
-                       w.add("(")
-               else
-                       w.add(prop.global.meth_call)
-                       w.add("(")
-                       w.add(args.first)
-                       w.add(")(")
-               end
-               var first = true
+               w.add(prop.global.meth_call)
+               w.add("(")
+               w.add(args.first)
+               w.add(")(")
                w.add_all(args, ", ")
                w.add(")")
                return w
@@ -679,51 +673,285 @@ redef class INative
        redef fun compile_to_c(v)
        do
                v.add_location(location)
-               var w = new_result(v)
-               if exprs.is_empty then
-                       w.add(code)
+               if method.is_intern then
+                       compile_intern_method_to_c(v)
                else
-                       var i = 0
-                       var c = code.split_with("@@@")
-                       for s in c do
-                               w.add(s)
-                               if i < exprs.length and i < c.length-1 then
-                                       w.add(v.register(exprs[i]))
-                               end
-                               i += 1
+                       compile_extern_method_to_c(v)
+               end
+       end
+
+       fun compile_extern_method_to_c(v: I2CCompilerVisitor)
+       do
+               var ename = method.extern_name.as(not null)#"{method.module.name}_{method.local_class.name}_{method.local_class.name}_{method.name}_{method.signature.arity}"
+               var sig = method.signature
+               assert exprs.length == sig.arity + 1
+
+               var regs = v.registers(exprs)
+
+               var args = new Array[String]
+               args.add(sig.recv.unboxtype(regs[0]))
+               for i in [0..sig.arity[ do
+                       args.add(sig[i].unboxtype(regs[i+1]))
+               end
+               var s = "{ename}({args.join(", ")})"
+
+               if need_result then s = sig.return_type.boxtype(s)
+               var w = new_result(v)
+               w.add(s)
+       end
+
+       fun compile_intern_method_to_c(v: I2CCompilerVisitor)
+       do
+               var sig = method.signature
+               assert exprs.length == sig.arity + 1
+               var c = method.local_class.name
+               var n = method.name
+               var regs = v.registers(exprs)
+               var s: nullable String = null
+               if c == once "Int".to_symbol then
+                       if n == once "object_id".to_symbol then
+                               s = regs[0]
+                       else if n == once "unary -".to_symbol then
+                               s = "TAG_Int(-UNTAG_Int({regs[0]}))"
+                       else if n == once "output".to_symbol then
+                               s = "printf(\"%ld\\n\", UNTAG_Int({regs[0]}));"
+                       else if n == once "ascii".to_symbol then
+                               s = "TAG_Char(UNTAG_Int({regs[0]}))"
+                       else if n == once "succ".to_symbol then
+                               s = "TAG_Int(UNTAG_Int({regs[0]})+1)"
+                       else if n == once "prec".to_symbol then
+                               s = "TAG_Int(UNTAG_Int({regs[0]})-1)"
+                       else if n == once "to_f".to_symbol then
+                               s = "BOX_Float((float)UNTAG_Int({regs[0]}))"
+                       else if n == once "+".to_symbol then
+                               s = "TAG_Int(UNTAG_Int({regs[0]})+UNTAG_Int({regs[1]}))"
+                       else if n == once "-".to_symbol then
+                               s = "TAG_Int(UNTAG_Int({regs[0]})-UNTAG_Int({regs[1]}))"
+                       else if n == once "*".to_symbol then
+                               s = "TAG_Int(UNTAG_Int({regs[0]})*UNTAG_Int({regs[1]}))"
+                       else if n == once "/".to_symbol then
+                               s = "TAG_Int(UNTAG_Int({regs[0]})/UNTAG_Int({regs[1]}))"
+                       else if n == once "%".to_symbol then
+                               s = "TAG_Int(UNTAG_Int({regs[0]})%UNTAG_Int({regs[1]}))"
+                       else if n == once "<".to_symbol then
+                               s = "TAG_Bool(UNTAG_Int({regs[0]})<UNTAG_Int({regs[1]}))"
+                       else if n == once ">".to_symbol then
+                               s = "TAG_Bool(UNTAG_Int({regs[0]})>UNTAG_Int({regs[1]}))"
+                       else if n == once "<=".to_symbol then
+                               s = "TAG_Bool(UNTAG_Int({regs[0]})<=UNTAG_Int({regs[1]}))"
+                       else if n == once ">=".to_symbol then
+                               s = "TAG_Bool(UNTAG_Int({regs[0]})>=UNTAG_Int({regs[1]}))"
+                       else if n == once "lshift".to_symbol then
+                               s = "TAG_Int(UNTAG_Int({regs[0]})<<UNTAG_Int({regs[1]}))"
+                       else if n == once "rshift".to_symbol then
+                               s = "TAG_Int(UNTAG_Int({regs[0]})>>UNTAG_Int({regs[1]}))"
+                       else if n == once "==".to_symbol then
+                               s = "TAG_Bool(({regs[0]})==({regs[1]}))"
+                       else if n == once "!=".to_symbol then
+                               s = "TAG_Bool(({regs[0]})!=({regs[1]}))"
+                       end
+               else if c == once "Float".to_symbol then
+                       if n == once "object_id".to_symbol then
+                               s = "TAG_Int((bigint)UNBOX_Float({regs[0]}))"
+                       else if n == once "unary -".to_symbol then
+                               s = "BOX_Float(-UNBOX_Float({regs[0]}))"
+                       else if n == once "output".to_symbol then
+                               s = "printf(\"%f\\n\", UNBOX_Float({regs[0]}));"
+                       else if n == once "to_i".to_symbol then
+                               s = "TAG_Int((bigint)UNBOX_Float({regs[0]}))"
+                       else if n == once "+".to_symbol then
+                               s = "BOX_Float(UNBOX_Float({regs[0]})+UNBOX_Float({regs[1]}))"
+                       else if n == once "-".to_symbol then
+                               s = "BOX_Float(UNBOX_Float({regs[0]})-UNBOX_Float({regs[1]}))"
+                       else if n == once "*".to_symbol then
+                               s = "BOX_Float(UNBOX_Float({regs[0]})*UNBOX_Float({regs[1]}))"
+                       else if n == once "/".to_symbol then
+                               s = "BOX_Float(UNBOX_Float({regs[0]})/UNBOX_Float({regs[1]}))"
+                       else if n == once "<".to_symbol then
+                               s = "TAG_Bool(UNBOX_Float({regs[0]})<UNBOX_Float({regs[1]}))"
+                       else if n == once ">".to_symbol then
+                               s = "TAG_Bool(UNBOX_Float({regs[0]})>UNBOX_Float({regs[1]}))"
+                       else if n == once "<=".to_symbol then
+                               s = "TAG_Bool(UNBOX_Float({regs[0]})<=UNBOX_Float({regs[1]}))"
+                       else if n == once ">=".to_symbol then
+                               s = "TAG_Bool(UNBOX_Float({regs[0]})>=UNBOX_Float({regs[1]}))"
+                       end
+               else if c == once "Char".to_symbol then
+                       if n == once "object_id".to_symbol then
+                               s = "TAG_Int(UNTAG_Char({regs[0]}))"
+                       else if n == once "unary -".to_symbol then
+                               s = "TAG_Char(-UNTAG_Char({regs[0]}))"
+                       else if n == once "output".to_symbol then
+                               s = "printf(\"%c\", (unsigned char)UNTAG_Char({regs[0]}));"
+                       else if n == once "ascii".to_symbol then
+                               s = "TAG_Int((unsigned char)UNTAG_Char({regs[0]}))"
+                       else if n == once "succ".to_symbol then
+                               s = "TAG_Char(UNTAG_Char({regs[0]})+1)"
+                       else if n == once "prec".to_symbol then
+                               s = "TAG_Char(UNTAG_Char({regs[0]})-1)"
+                       else if n == once "to_i".to_symbol then
+                               s = "TAG_Int(UNTAG_Char({regs[0]})-'0')"
+                       else if n == once "+".to_symbol then
+                               s = "TAG_Char(UNTAG_Char({regs[0]})+UNTAG_Char({regs[1]}))"
+                       else if n == once "-".to_symbol then
+                               s = "TAG_Char(UNTAG_Char({regs[0]})-UNTAG_Char({regs[1]}))"
+                       else if n == once "*".to_symbol then
+                               s = "TAG_Char(UNTAG_Char({regs[0]})*UNTAG_Char({regs[1]}))"
+                       else if n == once "/".to_symbol then
+                               s = "TAG_Char(UNTAG_Char({regs[0]})/UNTAG_Char({regs[1]}))"
+                       else if n == once "%".to_symbol then
+                               s = "TAG_Char(UNTAG_Char({regs[0]})%UNTAG_Char({regs[1]}))"
+                       else if n == once "<".to_symbol then
+                               s = "TAG_Bool(UNTAG_Char({regs[0]})<UNTAG_Char({regs[1]}))"
+                       else if n == once ">".to_symbol then
+                               s = "TAG_Bool(UNTAG_Char({regs[0]})>UNTAG_Char({regs[1]}))"
+                       else if n == once "<=".to_symbol then
+                               s = "TAG_Bool(UNTAG_Char({regs[0]})<=UNTAG_Char({regs[1]}))"
+                       else if n == once ">=".to_symbol then
+                               s = "TAG_Bool(UNTAG_Char({regs[0]})>=UNTAG_Char({regs[1]}))"
+                       else if n == once "==".to_symbol then
+                               s = "TAG_Bool(({regs[0]})==({regs[1]}))"
+                       else if n == once "!=".to_symbol then
+                               s = "TAG_Bool(({regs[0]})!=({regs[1]}))"
+                       end
+               else if c == once "Bool".to_symbol then
+                       if n == once "object_id".to_symbol then
+                               s = "TAG_Int(UNTAG_Bool({regs[0]}))"
+                       else if n == once "unary -".to_symbol then
+                               s = "TAG_Bool(-UNTAG_Bool({regs[0]}))"
+                       else if n == once "output".to_symbol then
+                               s = "(void)printf(UNTAG_Bool({regs[0]})?\"true\\n\":\"false\\n\");"
+                       else if n == once "ascii".to_symbol then
+                               s = "TAG_Bool(UNTAG_Bool({regs[0]}))"
+                       else if n == once "to_i".to_symbol then
+                               s = "TAG_Int(UNTAG_Bool({regs[0]}))"
+                       else if n == once "==".to_symbol then
+                               s = "TAG_Bool(({regs[0]})==({regs[1]}))"
+                       else if n == once "!=".to_symbol then
+                               s = "TAG_Bool(({regs[0]})!=({regs[1]}))"
+                       end
+               else if c == once "NativeArray".to_symbol then
+                       if n == once "object_id".to_symbol then
+                               s = "TAG_Int(((Nit_NativeArray){regs[0]})->object_id)"
+                       else if n == once "[]".to_symbol then
+                               s = "((Nit_NativeArray){regs[0]})->val[UNTAG_Int({regs[1]})]"
+                       else if n == once "[]=".to_symbol then
+                               s = "((Nit_NativeArray){regs[0]})->val[UNTAG_Int({regs[1]})]={regs[2]}"
+                       else if n == once "copy_to".to_symbol then
+                               s = "(void)memcpy(((Nit_NativeArray ){regs[1]})->val, ((Nit_NativeArray){regs[0]})->val, UNTAG_Int({regs[2]})*sizeof(val_t))"
                        end
+               else if c == once "NativeString".to_symbol then
+                       if n == once "object_id".to_symbol then
+                               s = "TAG_Int(UNBOX_NativeString({regs[0]}))"
+                       else if n == once "atoi".to_symbol then
+                               s = "TAG_Int(atoi(UNBOX_NativeString({regs[0]})))"
+                       else if n == once "[]".to_symbol then
+                               s = "TAG_Char(UNBOX_NativeString({regs[0]})[UNTAG_Int({regs[1]})])"
+                       else if n == once "[]=".to_symbol then
+                               s = "UNBOX_NativeString({regs[0]})[UNTAG_Int({regs[1]})]=UNTAG_Char({regs[2]});"
+                       else if n == once "copy_to".to_symbol then
+                               s = "(void)memcpy(UNBOX_NativeString({regs[1]})+UNTAG_Int({regs[4]}), UNBOX_NativeString({regs[0]})+UNTAG_Int({regs[3]}), UNTAG_Int({regs[2]}));"
+                       end
+               else if n == once "object_id".to_symbol then
+                       s = "TAG_Int((bigint)((obj_t){regs[0]})[1].object_id)"
+               else if n == once "sys".to_symbol then
+                       s = "(G_sys)"
+               else if n == once "is_same_type".to_symbol then
+                       s = "TAG_Bool((VAL2VFT({regs[0]})==VAL2VFT({regs[1]})))"
+               else if n == once "exit".to_symbol then
+                       s = "exit(UNTAG_Int({regs[1]}));"
+               else if n == once "calloc_array".to_symbol then
+                       s = "NEW_NativeArray(UNTAG_Int({regs[1]}), sizeof(val_t))"
+               else if n == once "calloc_string".to_symbol then
+                       s = "BOX_NativeString((char*)raw_alloc((UNTAG_Int({regs[1]}) * sizeof(char))))"
+               end
+               if s == null then
+                       var ll = location
+                       if ll != null then v.add_instr("fprintf(stderr, \"{ll.to_s}: \");")
+                       v.add_instr("fprintf(stderr, \"Fatal error: unknown intern method {method.full_name}.\\n\");")
+                       v.add_instr("nit_exit(1);")
+                       s = "NIT_NULL"
+               end
+               if result == null then
+                       v.new_instr.add(s).add(";\n")
+               else if need_result then
+                       var w = new_result(v)
+                       w.add(s)
                end
        end
 end
 
+redef class IIntValue
+       redef fun compile_to_c(v)
+       do
+               v.add_location(location)
+               var w = new_result(v)
+               w.add("TAG_Int(").add(value.to_s).add(")")
+       end
+end
+
+redef class IBoolValue
+       redef fun compile_to_c(v)
+       do
+               v.add_location(location)
+               var w = new_result(v)
+               w.add("TAG_Bool(")
+               if value then w.add("true") else w.add("false")
+               w.add(")")
+       end
+end
+
+redef class ICharValue
+       redef fun compile_to_c(v)
+       do
+               v.add_location(location)
+               var w = new_result(v)
+               w.add("TAG_Char(").add(value).add(")")
+       end
+end
+
+redef class IFloatValue
+       redef fun compile_to_c(v)
+       do
+               v.add_location(location)
+               var w = new_result(v)
+               w.add("BOX_Float(").add(value).add(")")
+       end
+end
+
+redef class IStringValue
+       redef fun compile_to_c(v)
+       do
+               v.add_location(location)
+               var w = new_result(v)
+               w.add("BOX_NativeString(\"").add(value).add("\")")
+       end
+end
+
 redef class IAbort
        redef fun compile_to_c(v)
        do
                v.add_location(location)
                var w = v.new_instr
-               w.add("fprintf(stderr")
-               for t in texts do
-                       w.add(", \"")
-                       w.add(t)
+               w.add("nit_abort(\"")
+               w.add(texts[0])
+               if texts.length > 1 then
+                       w.add("\", \"")
+                       w.add(texts[1])
                        w.add("\"")
+               else
+                       w.add("\", NULL")
                end
-               w.add(");\n")
-
-               var ll = location
-               w = v.new_instr
-               w.add("fprintf(stderr, \" (%s")
-               if ll != null then
-                       w.add(":%d")
-               end
-               w.add(")\\n\", LOCATE_")
+               w.add(", LOCATE_")
                w.add(module_location.name.to_s)
+               var ll = location
                if ll != null then
                        w.add(", ")
                        w.add(ll.line_start.to_s)
+               else
+                       w.add(", 0")
                end
                w.add(");\n")
-
-               v.add_instr("nit_exit(1);")
        end
 end