Merge remote-tracking branch 'upstream/master' into init_auto
[nit.git] / src / compiler / java_compiler.nit
index 3da2a81..7b83104 100644 (file)
@@ -90,14 +90,32 @@ redef class ModelBuilder
        fun write_java_files(compiler: JavaCompiler): Array[String] do
                var jfiles = new Array[String]
                for f in compiler.files do
-                       var file = new FileWriter.open("{compiler.compile_dir}/{f.filename}")
+                       var filepath = "{compiler.compile_dir}/{f.filename}"
+                       var file = cache_file(filepath)
                        for line in f.lines do file.write(line)
-                       file.close
+                       close_cache(filepath, file)
                        jfiles.add(f.filename)
                end
                return jfiles
        end
 
+       # Cache a file as `{filepath}.tmp` and replace the original if different
+       private fun cache_file(filepath: String): FileWriter do
+               if toolcontext.opt_ant.value and filepath.file_exists then
+                       return new FileWriter.open("{filepath}.tmp")
+               else
+                       return new FileWriter.open(filepath)
+               end
+       end
+
+       # Close the writer and move tmp file to original if modified
+       private fun close_cache(filepath: String, file: FileWriter) do
+               file.close
+               if "{filepath}.tmp".file_exists then
+                       sys.system("if ! diff {filepath}.tmp {filepath} > /dev/null; then mv {filepath}.tmp {filepath}; else rm {filepath}.tmp; fi")
+               end
+       end
+
        # Compile Java generated files using `make`
        fun build_with_make(compiler: JavaCompiler, jfiles: Array[String]) do
                write_manifest(compiler)
@@ -172,18 +190,18 @@ redef class ModelBuilder
                antfile.write("<project>")
                antfile.write(" <target name=\"compile\">")
                antfile.write("  <mkdir dir=\"classes\"/>")
-        antfile.write("  <javac includes=\"{compiler.mainmodule.jname}_Main.java {jfiles.join(" ")}\" srcdir=\".\" destdir=\"classes\"/>")
+               antfile.write("  <javac includes=\"{compiler.mainmodule.jname}_Main.java {jfiles.join(" ")}\" srcdir=\".\" destdir=\"classes\"/>")
                antfile.write(" </target>")
                antfile.write(" <target name=\"jar\" depends=\"compile\">")
                antfile.write("  <jar destfile=\"{outpath}.jar\" basedir=\"classes\">")
                antfile.write("   <manifest>")
-        antfile.write("    <attribute name=\"Main-Class\" value=\"{jname}_Main\"/>")
+               antfile.write("    <attribute name=\"Main-Class\" value=\"{jname}_Main\"/>")
                antfile.write("   </manifest>")
                antfile.write("  </jar>")
                antfile.write(" </target>")
                antfile.write("</project>")
                antfile.close
-               self.toolcontext.info("Generated antfile: {antname}", 2)
+               toolcontext.info("Generated antfile: {antname}", 2)
        end
 
        # Write the Java manifest file
@@ -479,7 +497,7 @@ class JavaCompilerVisitor
        # This method is used to manage varargs in signatures and returns the real array
        # 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)
 
@@ -508,8 +526,8 @@ class JavaCompilerVisitor
                                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)
@@ -1283,7 +1301,7 @@ redef class MType
 
        # Is the associated Java type a primitive one?
        #
-       # ENSURE `result == (java_type != "Object")`
+       # ENSURE `result == (java_type != "RTVal")`
        var is_java_primitive: Bool is lazy do return java_type != "RTVal"
 end
 
@@ -1300,7 +1318,7 @@ redef class MClassType
                        return "double"
                else if mclass.name == "Byte" then
                        return "byte"
-               else if mclass.name == "NativeString" then
+               else if mclass.name == "CString" then
                        return "String"
                else if mclass.name == "NativeArray" then
                        return "Array"
@@ -1312,7 +1330,7 @@ end
 redef class MClass
 
        # Runtime name
-       private fun rt_name: String do return "RTClass_{intro.mmodule.jname}_{jname}"
+       private fun rt_name: String do return "RTClass_{intro_mmodule.jname}_{jname}"
 
        # Generate a Java RTClass for a Nit MClass
        fun compile_to_java(v: JavaCompilerVisitor) do
@@ -1464,8 +1482,7 @@ end
 
 redef class AClassdef
        private fun compile_to_java(v: JavaCompilerVisitor, 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
                        if not mpropdef.is_intro then
                                v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
                        end
@@ -1570,10 +1587,10 @@ 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 == "lshift" then
+                       else if pname == "<<" then
                                v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
                                return true
-                       else if pname == "rshift" then
+                       else if pname == ">>" then
                                v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
                                return true
                        else if pname == "==" then
@@ -1674,10 +1691,10 @@ redef class AMethPropdef
                        else if pname == "%" then
                                v.ret(v.new_expr("(byte)({arguments[0]} % {arguments[1]})", ret.as(not null)))
                                return true
-                       else if pname == "lshift" then
+                       else if pname == "<<" then
                                v.ret(v.new_expr("(byte)({arguments[0]} << {arguments[1]})", ret.as(not null)))
                                return true
-                       else if pname == "rshift" then
+                       else if pname == ">>" then
                                v.ret(v.new_expr("(byte)({arguments[0]} >> {arguments[1]})", ret.as(not null)))
                                return true
                        else if pname == "==" then
@@ -2212,12 +2229,17 @@ redef class ANotExpr
        end
 end
 
-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))
+redef class AIntegerExpr
+       redef fun expr(v) do
+               if value isa Int then
+                       return v.int_instance(self.value.as(Int))
+               else if value isa Byte then
+                       return v.byte_instance(self.value.as(Byte))
+               else
+                       # Should not happen
+                       abort
+               end
+       end
 end
 
 redef class AFloatExpr