Merge: Enforce namespace rules
[nit.git] / src / compiler / abstract_compiler.nit
index ca3269e..2312544 100644 (file)
@@ -481,6 +481,10 @@ abstract class AbstractCompiler
                self.realmainmodule = mainmodule
        end
 
+       # Do the full code generation of the program `mainmodule`
+       # It is the main method usually called after the instantiation
+       fun do_compilation is abstract
+
        # Force the creation of a new file
        # The point is to avoid contamination between must-be-compiled-separately files
        fun new_file(name: String): CodeFile
@@ -1036,8 +1040,8 @@ abstract class AbstractCompilerVisitor
        # The current visited AST node
        var current_node: nullable ANode = null is writable
 
-       # The current `Frame`
-       var frame: nullable Frame = null is writable
+       # The current `StaticFrame`
+       var frame: nullable StaticFrame = null is writable
 
        # Alias for self.compiler.mainmodule.object_type
        fun object_type: MClassType do return self.compiler.mainmodule.object_type
@@ -1279,11 +1283,11 @@ abstract class AbstractCompilerVisitor
        fun escapemark_name(e: nullable EscapeMark): String
        do
                assert e != null
-               if escapemark_names.has_key(e) then return escapemark_names[e]
+               if frame.escapemark_names.has_key(e) then return frame.escapemark_names[e]
                var name = e.name
                if name == null then name = "label"
                name = get_name(name)
-               escapemark_names[e] = name
+               frame.escapemark_names[e] = name
                return name
        end
 
@@ -1295,8 +1299,6 @@ abstract class AbstractCompilerVisitor
                add("BREAK_{escapemark_name(e)}: (void)0;")
        end
 
-       private var escapemark_names = new HashMap[EscapeMark, String]
-
        # Return a "const char*" variable associated to the classname of the dynamic type of an object
        # NOTE: we do not return a `RuntimeVariable` "NativeString" as the class may not exist in the module/program
        fun class_name_string(value: RuntimeVariable): String is abstract
@@ -1460,10 +1462,11 @@ abstract class AbstractCompilerVisitor
                self.require_declaration(s)
        end
 
-       # look for a needed .h and .c file for a given .nit source-file
-       # FIXME: bad API, parameter should be a `MModule`, not its source-file
-       fun add_extern(file: String)
+       # Look for a needed .h and .c file for a given module
+       # This is used for the legacy FFI
+       fun add_extern(mmodule: MModule)
        do
+               var file = mmodule.location.file.filename
                file = file.strip_extension(".nit")
                var tryfile = file + ".nit.h"
                if tryfile.file_exists then
@@ -1536,6 +1539,15 @@ abstract class AbstractCompilerVisitor
        fun stmt(nexpr: nullable AExpr)
        do
                if nexpr == null then return
+
+               var narray = nexpr.comprehension
+               if narray != null then
+                       var recv = frame.comprehension.as(not null)
+                       var val = expr(nexpr, narray.element_mtype)
+                       compile_callsite(narray.push_callsite.as(not null), [recv, val])
+                       return
+               end
+
                var old = self.current_node
                self.current_node = nexpr
                nexpr.stmt(self)
@@ -1658,8 +1670,8 @@ class RuntimeVariable
        end
 end
 
-# A frame correspond to a visited property in a `GlobalCompilerVisitor`
-class Frame
+# The static context of a visited property in a `AbstractCompilerVisitor`
+class StaticFrame
 
        type VISITOR: AbstractCompilerVisitor
 
@@ -1681,6 +1693,13 @@ class Frame
 
        # The label at the end of the property
        var returnlabel: nullable String = null is writable
+
+       # Labels associated to a each escapemarks.
+       # Because of inlinings, escape-marks must be associated to their context (the frame)
+       private var escapemark_names = new HashMap[EscapeMark, String]
+
+       # The array comprehension currently filled, if any
+       private var comprehension: nullable RuntimeVariable = null
 end
 
 redef class MType
@@ -1692,21 +1711,9 @@ redef class MType
 
        # Short name of the `ctype` to use in unions
        fun ctypename: String do return "val"
-
-       # Return the name of the C structure associated to a Nit live type
-       fun c_name: String is abstract
-       protected var c_name_cache: nullable String is protected writable
 end
 
 redef class MClassType
-       redef fun c_name
-       do
-               var res = self.c_name_cache
-               if res != null then return res
-               res = "{mclass.intro_mmodule.c_name}__{mclass.name.to_cmangle}"
-               self.c_name_cache = res
-               return res
-       end
 
        redef fun ctype: String
        do
@@ -1757,90 +1764,8 @@ redef class MClassType
        end
 end
 
-redef class MGenericType
-       redef fun c_name
-       do
-               var res = self.c_name_cache
-               if res != null then return res
-               res = super
-               for t in self.arguments do
-                       res = res + t.c_name
-               end
-               self.c_name_cache = res
-               return res
-       end
-end
-
-redef class MParameterType
-       redef fun c_name
-       do
-               var res = self.c_name_cache
-               if res != null then return res
-               res = "{self.mclass.c_name}_FT{self.rank}"
-               self.c_name_cache = res
-               return res
-       end
-end
-
-redef class MVirtualType
-       redef fun c_name
-       do
-               var res = self.c_name_cache
-               if res != null then return res
-               res = "{self.mproperty.intro.mclassdef.mclass.c_name}_VT{self.mproperty.name}"
-               self.c_name_cache = res
-               return res
-       end
-end
-
-redef class MNullableType
-       redef fun c_name
-       do
-               var res = self.c_name_cache
-               if res != null then return res
-               res = "nullable_{self.mtype.c_name}"
-               self.c_name_cache = res
-               return res
-       end
-end
-
-redef class MClass
-       # Return the name of the C structure associated to a Nit class
-       fun c_name: String do
-               var res = self.c_name_cache
-               if res != null then return res
-               res = "{intro_mmodule.c_name}__{name.to_cmangle}"
-               self.c_name_cache = res
-               return res
-       end
-       private var c_name_cache: nullable String
-end
-
-redef class MProperty
-       fun c_name: String do
-               var res = self.c_name_cache
-               if res != null then return res
-               res = "{self.intro.c_name}"
-               self.c_name_cache = res
-               return res
-       end
-       private var c_name_cache: nullable String
-end
-
 redef class MPropDef
        type VISITOR: AbstractCompilerVisitor
-
-       private var c_name_cache: nullable String
-
-       # The mangled name associated to the property
-       fun c_name: String
-       do
-               var res = self.c_name_cache
-               if res != null then return res
-               res = "{self.mclassdef.mmodule.c_name}__{self.mclassdef.mclass.name.to_cmangle}__{self.mproperty.name.to_cmangle}"
-               self.c_name_cache = res
-               return res
-       end
 end
 
 redef class MMethodDef
@@ -2231,16 +2156,13 @@ redef class AMethPropdef
        do
                var externname
                var at = self.get_single_annotation("extern", v.compiler.modelbuilder)
-               if at != null then
+               if at != null and at.n_args.length == 1 then
                        externname = at.arg_as_string(v.compiler.modelbuilder)
                        if externname == null then return false
                else
                        return false
                end
-               if location.file != null then
-                       var file = location.file.filename
-                       v.add_extern(file)
-               end
+               v.add_extern(mpropdef.mclassdef.mmodule)
                var res: nullable RuntimeVariable = null
                var ret = mpropdef.msignature.return_mtype
                if ret != null then
@@ -2272,10 +2194,7 @@ redef class AMethPropdef
                else
                        return false
                end
-               if location.file != null then
-                       var file = location.file.filename
-                       v.add_extern(file)
-               end
+               v.add_extern(mpropdef.mclassdef.mmodule)
                v.adapt_signature(mpropdef, arguments)
                v.unbox_signature_extern(mpropdef, arguments)
                var ret = arguments.first.mtype
@@ -2291,6 +2210,8 @@ redef class AMethPropdef
 end
 
 redef class AAttrPropdef
+       redef fun can_inline: Bool do return not is_lazy
+
        redef fun compile_to_c(v, mpropdef, arguments)
        do
                if mpropdef == mreadpropdef then
@@ -2349,7 +2270,7 @@ redef class AAttrPropdef
                var oldnode = v.current_node
                v.current_node = self
                var old_frame = v.frame
-               var frame = new Frame(v, self.mpropdef.as(not null), recv.mcasttype.as(MClassType), [recv])
+               var frame = new StaticFrame(v, self.mpropdef.as(not null), recv.mcasttype.as_notnullable.as(MClassType), [recv])
                v.frame = frame
 
                var value
@@ -2388,7 +2309,7 @@ redef class AAttrPropdef
                var oldnode = v.current_node
                v.current_node = self
                var old_frame = v.frame
-               var frame = new Frame(v, self.mpropdef.as(not null), recv.mtype.as(MClassType), [recv])
+               var frame = new StaticFrame(v, self.mpropdef.as(not null), recv.mtype.as(MClassType), [recv])
                v.frame = frame
                # Force read to check the initialization
                v.read_attribute(self.mpropdef.mproperty, recv)
@@ -2742,13 +2663,18 @@ end
 redef class AArrayExpr
        redef fun expr(v)
        do
-               var mtype = self.mtype.as(MClassType).arguments.first
+               var mtype = self.element_mtype.as(not null)
                var array = new Array[RuntimeVariable]
-               for nexpr in self.n_exprs.n_exprs do
-                       var i = v.expr(nexpr, mtype)
-                       array.add(i)
+               var res = v.array_instance(array, mtype)
+
+               var old_comprehension = v.frame.comprehension
+               v.frame.comprehension = res
+               for nexpr in self.n_exprs do
+                       v.stmt(nexpr)
                end
-               return v.array_instance(array, mtype)
+               v.frame.comprehension = old_comprehension
+
+               return res
        end
 end
 
@@ -3020,19 +2946,6 @@ redef class Array[E]
 end
 
 redef class MModule
-       # Return the name of the global C identifier associated to `self`.
-       # This name is used to prefix files and other C identifiers associated with `self`.
-       var c_name: String is lazy do
-               var g = mgroup
-               var res
-               if g != null and g.mproject.name != name then
-                       res = g.mproject.name.to_cmangle + "__" + name.to_cmangle
-               else
-                       res = name.to_cmangle
-               end
-               return res
-       end
-
        # All `MProperty` associated to all `MClassDef` of `mclass`
        fun properties(mclass: MClass): Set[MProperty] do
                if not self.properties_cache.has_key(mclass) then