Merge: Misc text: some improvement on `join` and `to_base`
authorJean Privat <jean@pryen.org>
Thu, 10 Mar 2016 04:55:35 +0000 (23:55 -0500)
committerJean Privat <jean@pryen.org>
Thu, 10 Mar 2016 04:55:35 +0000 (23:55 -0500)
Pull-Request: #1977
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>

lib/core/file.nit
src/compiler/compiler_ffi/compiler_ffi.nit
src/interpreter/dynamic_loading_ffi/on_demand_compiler.nit
src/nitni/nitni_utilities.nit

index 66b81aa..0454f1d 100644 (file)
@@ -1145,11 +1145,16 @@ redef class String
 
        # Create a directory (and all intermediate directories if needed)
        #
+       # The optional `mode` parameter specifies the permissions of the directory,
+       # the default value is `0o777`.
+       #
        # Return an error object in case of error.
        #
        #    assert "/etc/".mkdir != null
-       fun mkdir: nullable Error
+       fun mkdir(mode: nullable Int): nullable Error
        do
+               mode = mode or else 0o777
+
                var dirs = self.split_with("/")
                var path = new FlatBuffer
                if dirs.is_empty then return null
@@ -1162,7 +1167,7 @@ redef class String
                        if d.is_empty then continue
                        path.append(d)
                        path.add('/')
-                       var res = path.to_s.to_cstring.file_mkdir
+                       var res = path.to_s.to_cstring.file_mkdir(mode)
                        if not res and error == null then
                                error = new IOError("Cannot create directory `{path}`: {sys.errno.strerror}")
                        end
@@ -1326,7 +1331,7 @@ redef class NativeString
                return stat_element;
        `}
 
-       private fun file_mkdir: Bool `{ return !mkdir(self, 0777); `}
+       private fun file_mkdir(mode: Int): Bool `{ return !mkdir(self, mode); `}
 
        private fun rmdir: Bool `{ return !rmdir(self); `}
 
index 79c2f14..7a536b1 100644 (file)
@@ -262,18 +262,20 @@ redef class MExplicitCast
                #
 
                # In nitni files, declare internal function as extern
-               var full_friendly_csignature = "int {v.compiler.mainmodule.name }___{from.mangled_cname}_is_a_{to.mangled_cname}({from.cname_blind})"
+               var full_friendly_csignature = "int {v.compiler.mainmodule.c_name }___{from.mangled_cname}_is_a_{to.mangled_cname}({from.cname_blind})"
                ccu.header_decl.add("extern {full_friendly_csignature};\n")
 
                # In nitni files, #define friendly as extern
-               ccu.header_decl.add("#define {check_cname} {v.compiler.mainmodule.name}___{check_cname}\n")
+               ccu.header_decl.add "#ifndef {check_cname}\n"
+               ccu.header_decl.add "#define {check_cname} {v.compiler.mainmodule.c_name}___{check_cname}\n"
+               ccu.header_decl.add "#endif\n"
 
                if compile_implementation_too then
                        # Internally, implement internal function
                        var nitni_visitor = v.compiler.new_visitor
                        nitni_visitor.frame = v.frame
 
-                       var full_internal_csignature = "int {v.compiler.mainmodule.name }___{from.mangled_cname}_is_a_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
+                       var full_internal_csignature = "int {v.compiler.mainmodule.c_name }___{from.mangled_cname}_is_a_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
 
                        nitni_visitor.add_decl("/* nitni check for {from} to {to} */")
                        nitni_visitor.add_decl("{full_internal_csignature} \{")
@@ -289,7 +291,9 @@ redef class MExplicitCast
                # special checks
                if from == to.as_nullable then
                        # format A_is_null
-                       ccu.header_decl.add("#define {from.mangled_cname}_is_null !{from.mangled_cname}_is_a_{to.mangled_cname}\n")
+                       ccu.header_decl.add "#ifndef {from.mangled_cname}_is_null\n"
+                       ccu.header_decl.add "#define {from.mangled_cname}_is_null !{from.mangled_cname}_is_a_{to.mangled_cname}\n"
+                       ccu.header_decl.add "#endif\n"
                end
 
                #
@@ -297,18 +301,20 @@ redef class MExplicitCast
                #
 
                # In nitni files, declare internal function as extern
-               full_friendly_csignature = "{to.cname_blind} {v.compiler.mainmodule.name }___{from.mangled_cname}_as_{to.mangled_cname}({from.cname_blind})"
+               full_friendly_csignature = "{to.cname_blind} {v.compiler.mainmodule.c_name }___{from.mangled_cname}_as_{to.mangled_cname}({from.cname_blind})"
                ccu.header_decl.add("extern {full_friendly_csignature};\n")
 
                # In nitni files, #define friendly as extern
-               ccu.header_decl.add("#define {cast_cname} {v.compiler.mainmodule.name}___{cast_cname}\n")
+               ccu.header_decl.add "#ifndef {cast_cname}\n"
+               ccu.header_decl.add "#define {cast_cname} {v.compiler.mainmodule.c_name}___{cast_cname}\n"
+               ccu.header_decl.add "#endif\n"
 
                if compile_implementation_too then
                        # Internally, implement internal function
                        var nitni_visitor = v.compiler.new_visitor
                        nitni_visitor.frame = v.frame
 
-                       var full_internal_csignature = "{to.cname_blind} {v.compiler.mainmodule.name }___{from.mangled_cname}_as_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
+                       var full_internal_csignature = "{to.cname_blind} {v.compiler.mainmodule.c_name }___{from.mangled_cname}_as_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
                        nitni_visitor.add_decl("/* nitni cast for {from} to {to} */")
                        nitni_visitor.add_decl("{full_internal_csignature} \{")
 
@@ -333,12 +339,16 @@ redef class MExplicitCast
                # special casts
                if from.as_nullable == to then
                        # format A_as_nullable
-                       ccu.header_decl.add("#define {from.mangled_cname}_as_nullable {from.mangled_cname}_as_{to.mangled_cname}\n")
+                       ccu.header_decl.add "#ifndef {from.mangled_cname}_as_nullable\n"
+                       ccu.header_decl.add "#define {from.mangled_cname}_as_nullable {from.mangled_cname}_as_{to.mangled_cname}\n"
+                       ccu.header_decl.add "#endif\n"
                end
 
                if from == to.as_nullable then
                        # format A_as_nullable
-                       ccu.header_decl.add("#define {to.mangled_cname}_as_not_nullable {from.mangled_cname}_as_{to.mangled_cname}\n")
+                       ccu.header_decl.add "#ifndef {to.mangled_cname}_as_not_nullable\n"
+                       ccu.header_decl.add "#define {to.mangled_cname}_as_not_nullable {from.mangled_cname}_as_{to.mangled_cname}\n"
+                       ccu.header_decl.add "#endif\n"
                end
        end
 end
index 85deec6..ab9e845 100644 (file)
@@ -20,6 +20,15 @@ import c_tools
 import nitni
 import ffi
 import naive_interpreter
+import debugger_socket # To linearize `ToolContext::init`
+
+redef class ToolContext
+
+       # --compile-dir
+       var opt_compile_dir = new OptionString("Directory used to generate temporary files", "--compile-dir")
+
+       init do option_context.add_option opt_compile_dir
+end
 
 redef class AMethPropdef
        # Does this method definition use the FFI and is it supported by the interpreter?
@@ -45,10 +54,25 @@ redef class AMethPropdef
 end
 
 redef class NaiveInterpreter
+       redef fun start(mainmodule)
+       do
+               super
+
+               # Delete temporary files
+               var compile_dir = compile_dir
+               if compile_dir.file_exists then compile_dir.rmdir
+       end
+
        # Where to store generated C and extracted code
-       #
-       # TODO make customizable and delete when execution completes
-       private var compile_dir = "nit_compile"
+       private var compile_dir: String is lazy do
+               # Prioritize the user supplied directory
+               var opt = modelbuilder.toolcontext.opt_compile_dir.value
+               if opt != null then return opt
+               return "/tmp/niti_ffi_{process_id}"
+       end
+
+       # Identifier for this process, unique between running interpreters
+       private fun process_id: Int `{ return getpid(); `}
 
        # Path of the compiled foreign code library
        #
@@ -75,7 +99,7 @@ redef class AModule
                var compile_dir = v.compile_dir
                var foreign_code_lib_path = v.foreign_code_lib_path(mmodule)
 
-               if not compile_dir.file_exists then compile_dir.mkdir
+               if not compile_dir.file_exists then compile_dir.mkdir(0o700)
 
                # Compile the common FFI part
                ensure_compile_ffi_wrapper
index c0a8a15..910877b 100644 (file)
@@ -19,7 +19,7 @@ import nitni_base
 
 redef class MMethod
        # Build a C function name for the FFI implementation (uses friendly naming).
-       # * On a specific static receiver mype `recv_mtype` 
+       # * On a specific static receiver type `recv_mtype`
        # * In referene to the module `from_module` (used for type resolving and as a possible prefix)
        # * Has a possible `suffix` to the method name (may be "__super", "__impl", null, etc.)
        # * With a specified length indicating whether it uses the sort name or the long name with
@@ -39,13 +39,13 @@ redef class MMethod
 
                if suffix != null then cname = "{cname}{suffix}"
 
-               if length.long then cname = "{from_mmodule.name}___{cname}"
+               if length.long then cname = "{from_mmodule.c_name}___{cname}"
 
                return cname
        end
 
        # Build a C function signature for the FFI implementation (uses friendly naming).
-       # * On a specific static receiver mype `recv_mtype` 
+       # * On a specific static receiver type `recv_mtype`
        # * In referene to the module `from_module` (used for type resolving and as a possible prefix)
        # * Has a possible `suffix` to the method name (may be "__super", "__impl", null, etc.)
        # * With a specified length indicating whether it uses the sort name or the long name with
@@ -83,7 +83,7 @@ redef class MMethod
        end
 
        # Build a C function call for the FFI implementation (uses friendly naming).
-       # * On a specific static receiver mype `recv_mtype` 
+       # * On a specific static receiver type `recv_mtype`
        # * In referene to the module `from_module` (used for type resolving and as a possible prefix)
        # * Has a possible `suffix` to the method name (may be "__super", "__impl", null, etc.)
        # * With a specified length indicating whether it uses the sort name or the long name with