Merge: Clean nit compilation directory
[nit.git] / src / compiler / abstract_compiler.nit
index 904e73b..2cf47e2 100644 (file)
@@ -142,14 +142,21 @@ class Toolchain
        # Compiler of the target program
        var compiler: AbstractCompiler
 
-       # Directory where to generate all C files
-       fun compile_dir: String
+       # Directory where to generate all files
+       #
+       # The option `--compile_dir` change this directory.
+       fun root_compile_dir: String
        do
                var compile_dir = toolcontext.opt_compile_dir.value
                if compile_dir == null then compile_dir = "nit_compile"
                return compile_dir
        end
 
+       # Directory where to generate all C files
+       #
+       # By default it is `root_compile_dir` but some platform may require that it is a subdirectory.
+       fun compile_dir: String do return root_compile_dir
+
        # Write all C files and compile them
        fun write_and_make is abstract
 end
@@ -162,12 +169,16 @@ class MakefileToolchain
        do
                var compile_dir = compile_dir
 
+               # Remove the compilation directory unless explicitly set
+               var auto_remove = toolcontext.opt_compile_dir.value == null
+
                # Generate the .h and .c files
                # A single C file regroups many compiled rumtime functions
                # Note that we do not try to be clever an a small change in a Nit source file may change the content of all the generated .c files
                var time0 = get_time
                self.toolcontext.info("*** WRITING C ***", 1)
 
+               root_compile_dir.mkdir
                compile_dir.mkdir
 
                var cfiles = new Array[String]
@@ -189,6 +200,10 @@ class MakefileToolchain
 
                compile_c_code(compile_dir)
 
+               if auto_remove then
+                       sys.system("rm -r -- '{root_compile_dir.escape_to_sh}/'")
+               end
+
                time1 = get_time
                self.toolcontext.info("*** END COMPILING C: {time1-time0} ***", 2)
        end
@@ -1457,6 +1472,14 @@ abstract class AbstractCompilerVisitor
                return res
        end
 
+       # Generate a byte value
+       fun byte_instance(value: Byte): RuntimeVariable
+       do
+               var t = mmodule.byte_type
+               var res = new RuntimeVariable("((unsigned char){value.to_s})", t, t)
+               return res
+       end
+
        # Generate a char value
        fun char_instance(value: Char): RuntimeVariable
        do
@@ -1840,6 +1863,8 @@ redef class MClassType
                        return "char"
                else if mclass.name == "Float" then
                        return "double"
+               else if mclass.name == "Byte" then
+                       return "unsigned char"
                else if mclass.name == "NativeString" then
                        return "char*"
                else if mclass.name == "NativeArray" then
@@ -1870,6 +1895,8 @@ redef class MClassType
                        return "c"
                else if mclass.name == "Float" then
                        return "d"
+               else if mclass.name == "Byte" then
+                       return "b"
                else if mclass.name == "NativeString" then
                        return "str"
                else if mclass.name == "NativeArray" then
@@ -2100,6 +2127,9 @@ redef class AMethPropdef
                        else if pname == "to_f" then
                                v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
                                return true
+                       else if pname == "to_b" then
+                               v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+                               return true
                        else if pname == "ascii" then
                                v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
                                return true
@@ -2143,6 +2173,69 @@ redef class AMethPropdef
                                v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
                                return true
                        end
+               else if cname == "Byte" then
+                       if pname == "output" then
+                               v.add("printf(\"%x\\n\", {arguments.first});")
+                               return true
+                       else if pname == "object_id" then
+                               v.ret(v.new_expr("(long){arguments.first}", 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 == "unary -" then
+                               v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary +" then
+                               v.ret(arguments[0])
+                               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 == "lshift" then
+                               v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "rshift" 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 == "<" 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
+                       else if pname == "to_f" then
+                               v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "ascii" then
+                               v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
+                               return true
+                       end
                else if cname == "Bool" then
                        if pname == "output" then
                                v.add("printf({arguments.first}?\"true\\n\":\"false\\n\");")
@@ -2211,6 +2304,9 @@ redef class AMethPropdef
                        else if pname == "to_i" then
                                v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
                                return true
+                       else if pname == "to_b" then
+                               v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+                               return true
                        end
                else if cname == "NativeString" then
                        if pname == "[]" then
@@ -2787,6 +2883,10 @@ redef class AIntExpr
        redef fun expr(v) do return v.int_instance(self.value.as(not null))
 end
 
+redef class AByteExpr
+       redef fun expr(v) do return v.byte_instance(self.value.as(not null))
+end
+
 redef class AFloatExpr
        redef fun expr(v) do return v.float_instance("{self.n_float.text}") # FIXME use value, not n_float
 end