syntax: 'meth' -> 'fun', 'attr' -> 'var'
[nit.git] / src / syntax / syntax_base.nit
index 85231ed..cb3b15e 100644 (file)
@@ -24,14 +24,14 @@ import mmloader
 class MMSrcModule
 special MMModule
        # The related AST node
-       readable attr _node: AModule
+       readable var _node: AModule
 
        # Concrete NIT source local classs by name
-       readable attr _src_local_classes: Map[Symbol, MMSrcLocalClass]
+       readable var _src_local_classes: Map[Symbol, MMSrcLocalClass]
 
-       init(c: MMContext, source: AModule, dir: MMDirectory, name: Symbol)
+       init(c: MMContext, source: AModule, dir: MMDirectory, name: Symbol, filename: String)
        do
-               super(name, dir, c)
+               super(name, dir, c, filename)
                _node = source
                _src_local_classes = new HashMap[Symbol, MMSrcLocalClass]
        end
@@ -39,7 +39,7 @@ end
 
 redef class MMGlobalClass
        # Check that a module can access a class
-       meth check_visibility(v: AbsSyntaxVisitor, n: PNode, cm: MMSrcModule): Bool do
+       fun check_visibility(v: AbsSyntaxVisitor, n: PNode, cm: MMSrcModule): Bool do
                var pm = intro.module
                assert pm isa MMSrcModule
                var vpm = cm.visibility_for(pm)
@@ -60,13 +60,13 @@ end
 class MMSrcLocalClass
 special MMConcreteClass
        # The related AST nodes
-       readable attr _nodes: Array[PClassdef]
+       readable var _nodes: Array[PClassdef]
 
        # Concrete NIT source generic formal parameter by name
-       readable writable attr _formal_dict: Map[Symbol, MMTypeFormalParameter]
+       readable var _formal_dict: Map[Symbol, MMTypeFormalParameter] = new HashMap[Symbol, MMTypeFormalParameter]
 
        # Concrete NIT source properties by name
-       readable attr _src_local_properties: Map[Symbol, MMLocalProperty] 
+       readable var _src_local_properties: Map[Symbol, MMLocalProperty]
 
        init(mod: MMSrcModule, n: Symbol, cla: PClassdef, a: Int)
        do
@@ -78,7 +78,7 @@ end
 
 redef class MMGlobalProperty
        # Check that a module can access a property
-       meth check_visibility(v: AbsSyntaxVisitor, n: PNode, cm: MMSrcModule, allows_protected: Bool): Bool do
+       fun check_visibility(v: AbsSyntaxVisitor, n: PNode, cm: MMSrcModule, allows_protected: Bool): Bool do
                var pm = local_class.module
                assert pm isa MMSrcModule
                var vpm = cm.visibility_for(pm)
@@ -101,16 +101,16 @@ end
 
 redef class MMLocalProperty
        # The attached node (if any)
-       meth node: PNode do return null
+       fun node: nullable PNode do return null
 
        # Is the concrete method defined as init
-       meth is_init: Bool do return false
+       fun is_init: Bool do return false
 end
 
 # Concrete NIT source attribute
 class MMSrcAttribute
 special MMAttribute
-       redef readable attr _node: AAttrPropdef
+       redef readable var _node: AAttrPropdef
        init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
        do
                super(name, cla)
@@ -126,7 +126,7 @@ end
 # Concrete NIT source method for an automatic accesor
 class MMAttrImplementationMethod
 special MMSrcMethod
-       redef readable attr _node: AAttrPropdef
+       redef readable var _node: AAttrPropdef
        init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
        do
                super(name, cla)
@@ -155,9 +155,9 @@ end
 # Concrete NIT source method for an explicit method
 class MMMethSrcMethod
 special MMSrcMethod
-       redef meth is_init do return _node isa AConcreteInitPropdef
-       redef readable attr _node: AMethPropdef
-       init(name: Symbol, cla: MMLocalClass, n: AMethPropdef)
+       redef fun is_init do return _node isa AConcreteInitPropdef
+       redef readable var _node: nullable AMethPropdef
+       init(name: Symbol, cla: MMLocalClass, n: nullable AMethPropdef)
        do
                super(name, cla)
                _node = n
@@ -168,7 +168,7 @@ end
 class MMSrcTypeProperty
 special MMLocalProperty
 special MMTypeProperty
-       redef readable attr _node: ATypePropdef
+       redef readable var _node: ATypePropdef
        init(name: Symbol, cla: MMLocalClass, n: ATypePropdef)
        do
                super(name, cla)
@@ -179,9 +179,9 @@ end
 # Concrete NIT implicit constructor
 class MMImplicitInit
 special MMMethSrcMethod
-       redef meth is_init do return true
-       readable attr _unassigned_attributes: Array[MMSrcAttribute]
-       readable attr _super_inits: Array[MMLocalProperty]
+       redef fun is_init do return true
+       readable var _unassigned_attributes: Array[MMSrcAttribute]
+       readable var _super_inits: Array[MMLocalProperty]
        init(cla: MMLocalClass, unassigned_attributes: Array[MMSrcAttribute], super_inits: Array[MMLocalProperty])
        do
                super(once "init".to_symbol, cla, null)
@@ -193,22 +193,20 @@ end
 # Local variables
 abstract class Variable
        # Name of the variable
-       readable attr _name: Symbol 
+       readable var _name: Symbol
 
        # Declaration AST node
-       readable attr _decl: PNode
+       readable var _decl: nullable PNode
 
        # Static type
-       readable writable attr _stype: MMType 
+       readable writable var _stype: nullable MMType
 
-       redef meth to_s do return _name.to_s
+       redef fun to_s do return _name.to_s
 
-       meth kind: String is abstract
+       fun kind: String is abstract
 
-       init(n: Symbol, d: PNode)
+       init(n: Symbol, d: nullable PNode)
        do
-               #assert n != null
-               #assert d != null
                _name = n
                _decl = d
        end
@@ -217,21 +215,21 @@ end
 # Variable declared with 'var'
 class VarVariable
 special Variable
-       redef meth kind do return once "variable"
+       redef fun kind do return once "variable"
        init(n: Symbol, d: PNode) do super
 end
 
 # Parameter of method (declared in signature)
 class ParamVariable
 special Variable
-       redef meth kind do return once "parameter"
-       init(n: Symbol, d: PNode) do super
+       redef fun kind do return once "parameter"
+       init(n: Symbol, d: nullable PNode) do super
 end
 
 # Automatic variable (like in the 'for' statement)
 class AutoVariable
 special Variable
-       redef meth kind do return once "automatic variable"
+       redef fun kind do return once "automatic variable"
        init(n: Symbol, d: PNode) do super
 end
 
@@ -239,10 +237,10 @@ end
 # Lives in the same namespace than variables
 class ClosureVariable
 special Variable
-       redef meth kind do return once "closure"
+       redef fun kind do return once "closure"
 
        # The signature of the closure
-       readable attr _closure: MMClosure
+       readable var _closure: MMClosure
 
        init(n: Symbol, d: PNode, c: MMClosure)
        do
@@ -257,121 +255,121 @@ end
 class AbsSyntaxVisitor
 special Visitor
        # The root type Object
-       meth type_object: MMType
+       fun type_object: MMType
        do
                return _module.class_by_name(once ("Object".to_symbol)).get_type
        end
 
        # The primitive type Bool
-       meth type_bool: MMType
+       fun type_bool: MMType
        do
                return _module.class_by_name(once ("Bool".to_symbol)).get_type
        end
        
        # The primitive type Int 
-       meth type_int: MMType
+       fun type_int: MMType
        do
                return _module.class_by_name(once ("Int".to_symbol)).get_type
        end
 
        # The primitive type Float
-       meth type_float: MMType
+       fun type_float: MMType
        do
                return _module.class_by_name(once ("Float".to_symbol)).get_type
        end
 
        # The primitive type Char
-       meth type_char: MMType
+       fun type_char: MMType
        do
                return _module.class_by_name(once ("Char".to_symbol)).get_type
        end
 
        # The primitive type String
-       meth type_string: MMType
+       fun type_string: MMType
        do
                return _module.class_by_name(once ("String".to_symbol)).get_type
        end
 
-       # The primitive type Collection[Object]
-       meth type_collection: MMType
+       # The primitive type Collection[nullable Object]
+       fun type_collection: MMType
        do
-               return _module.class_by_name(once ("Collection".to_symbol)).get_type
+               return _module.class_by_name(once ("Collection".to_symbol)).get_instantiate_type([type_object.as_nullable])
        end
 
        # The primitive type Array[?]
-       meth type_array(stype: MMType): MMType
+       fun type_array(stype: MMType): MMType
        do
                return _module.class_by_name(once ("Array".to_symbol)).get_instantiate_type([stype])
        end
 
        # The primitive type Discrete
-       meth type_discrete: MMType
+       fun type_discrete: MMType
        do
                return _module.class_by_name(once ("Discrete".to_symbol)).get_type
        end
 
        # The primitive type Range[?]
-       meth type_range(stype: MMType): MMType
+       fun type_range(stype: MMType): MMType
        do
                return _module.class_by_name(once ("Range".to_symbol)).get_instantiate_type([stype])
        end
 
        # The primitive type of null
-       meth type_none: MMType
+       fun type_none: MMType
        do
                return _module.type_none
        end
 
        # The current module
-       readable writable attr _module: MMSrcModule 
+       readable var _module: MMSrcModule
 
        # The current class
-       readable writable attr _local_class: MMSrcLocalClass 
+       fun local_class: MMSrcLocalClass do return _local_class.as(not null)
+       writable var _local_class: nullable MMSrcLocalClass
 
        # The current property
-       readable writable attr _local_property: MMLocalProperty
+       fun local_property: MMLocalProperty do return _local_property.as(not null)
+       writable var _local_property: nullable MMLocalProperty
 
        # The current tool configuration/status
-       readable attr _tc: ToolContext 
+       readable var _tc: ToolContext 
 
        # Display an error for a given syntax node
-       meth error(n: PNode, s: String)
+       fun error(n: nullable PNode, s: String)
        do
                _tc.error("{locate(n)}: {s}")
        end
 
        # Display a warning for a given syntax node
-       meth warning(n: PNode, s: String)
+       fun warning(n: nullable PNode, s: String)
        do
                _tc.warning("{locate(n)}: {s}")
        end
 
        #
-       meth locate(n: PNode): String
+       fun locate(n: nullable PNode): String
        do
                if n != null then return n.locate
                return _module.filename
        end
 
        # Check conformity and display error
-       meth check_conform(n: PNode, subtype: MMType, stype: MMType): Bool
+       fun check_conform(n: PNode, subtype: nullable MMType, stype: nullable MMType): Bool
        do
                if stype == null or subtype == null then
                        return false
                end
-               if subtype < stype then
+               if subtype < stype  then
                        return true
                end
-               #error(n, "Type error: expected {stype}'{stype.module}, got {subtype}'{subtype.module}")
-               #abort
                error(n, "Type error: expected {stype}, got {subtype}")
                return false
        end
-       
+
        # Check that an expression has a static type and that 
        # Display an error and return false if n is a statement
        # Require that the static type of n is known
-       meth check_expr(n: PExpr): Bool
+       fun check_expr(n: PExpr): Bool
        do
                if not n.is_typed then
                        if tc.error_count == 0 then
@@ -389,8 +387,9 @@ special Visitor
        end
 
        # Combine check_conform and check_expr
-       meth check_conform_expr(n: PExpr, stype: MMType): Bool
+       fun check_conform_expr(n: PExpr, stype: nullable MMType): Bool
        do
+               if stype == null then return false
                if check_expr(n) then return check_conform(n, n.stype, stype) else return false
        end
 
@@ -398,23 +397,30 @@ special Visitor
        # Conformance is granted if among them there is a most general type
        # Return the most general type if a conformance is found
        # Display an error and return null if no conformance is found
+       # The only allowed combinaison is with the nullable marker
        # @param stype is a possible additional type (without node)
        # Examples:
        #   Int, Int, Object => return Object
        #   Int, Float => display error, return null
-       meth check_conform_multiexpr(stype: MMType, nodes: Collection[PExpr]): MMType
+       #   nullable Int, Object => return nullable Object
+       fun check_conform_multiexpr(stype: nullable MMType, nodes: Collection[PExpr]): nullable MMType
        do
-               var node: PExpr = null # candidate node
+               var node: nullable PExpr = null # candidate node
                for n in nodes do
                        if not check_expr(n) then return null
                        var ntype = n.stype
-                       if stype == null or (ntype != null and stype < ntype) then
+                       if stype != null and stype.is_nullable != ntype.is_nullable then
+                               # nullable combinaison: if one of them is nulable, considers that both are
+                               stype = stype.as_nullable
+                               ntype = ntype.as_nullable
+                       end
+                       if stype == null or stype < ntype then
                                stype = ntype
                                node = n
                        end
                end
                for n in nodes do
-                       if not n.stype < stype then
+                       if not n.stype < stype.as(not null) then
                                if node == null then
                                        error(n, "Type error: no most general type. Got {n.stype} and {stype}.")
                                else
@@ -436,20 +442,20 @@ end
 ###############################################################################
 
 redef class PNode
-       protected meth accept_abs_syntax_visitor(v: AbsSyntaxVisitor) do visit_all(v)
+       protected fun accept_abs_syntax_visitor(v: AbsSyntaxVisitor) do visit_all(v)
 end
 
 redef class Token
-       attr _symbol: Symbol
+       var _symbol_cache: nullable Symbol
 
        # Symbol associated with the text
        # Lazily computed
-       meth to_symbol: Symbol
+       fun to_symbol: Symbol
        do
-               var s = _symbol
+               var s = _symbol_cache
                if s == null then
                        s = text.to_symbol
-                       _symbol = s
+                       _symbol_cache = s
                end
                return s
        end
@@ -457,79 +463,79 @@ end
 
 redef class PClassdef
        # Associated class (MM entity)
-       meth local_class: MMSrcLocalClass is abstract
+       fun local_class: MMSrcLocalClass is abstract
 end
 
 redef class AAttrPropdef
        # Associated attribute (MM entity)
-       meth prop: MMSrcAttribute is abstract
+       fun prop: MMSrcAttribute is abstract
 
        # Associated read accessor (MM entity)
-       meth readmethod: MMSrcMethod is abstract
+       fun readmethod: nullable MMSrcMethod is abstract
 
        # Associated write accessor (MM entity)
-       meth writemethod: MMSrcMethod is abstract
+       fun writemethod: nullable MMSrcMethod is abstract
 end
 
 redef class AMethPropdef
        # Associated method (MM entity)
-       meth method: MMMethSrcMethod is abstract
+       fun method: MMMethSrcMethod is abstract
 
        # Associated 'self' variable
-       meth self_var: ParamVariable is abstract
+       fun self_var: ParamVariable is abstract
 end
 
 redef class ATypePropdef
        # Associated formal type (MM entity)
-       meth prop: MMSrcTypeProperty is abstract
+       fun prop: MMSrcTypeProperty is abstract
 end
 
 redef class PParam
        # Position in the signature
-       meth position: Int is abstract
+       fun position: Int is abstract
 
        # Associated local variable
-       meth variable: ParamVariable is abstract 
+       fun variable: ParamVariable is abstract 
 end
 
 redef class PClosureDecl
        # Associated closure variable
-       meth variable: ClosureVariable is abstract
+       fun variable: ClosureVariable is abstract
 end
 
 redef class PType
        # Retrieve the local class corresponding to the type.
        # Display an error and return null if there is no class
        # Display an error and return null if the type is not class based (formal one)
-       meth get_local_class(v: AbsSyntaxVisitor): MMLocalClass is abstract
+       fun get_local_class(v: AbsSyntaxVisitor): nullable MMLocalClass is abstract
 
        # Retrieve corresponding static type.
        # Display an error and return null if there is a problem
-       meth get_stype(v: AbsSyntaxVisitor): MMType is abstract
+       fun get_stype(v: AbsSyntaxVisitor): nullable MMType is abstract
 
        # Retrieve corresponding static type.
        # Display an error and return null if there is a problem
        # But do not performs any subtype check.
        # get_unchecked_stype should be called to check that the static type is fully valid
-       meth get_unchecked_stype(v: AbsSyntaxVisitor): MMType is abstract
+       fun get_unchecked_stype(v: AbsSyntaxVisitor): nullable MMType is abstract
 
        # Check that a static definition type is conform with regard to formal types
        # Useful with get_unchecked_stype
        # Remember that conformance check need that ancestors are totaly computed
-       meth check_conform(v: AbsSyntaxVisitor) is abstract
+       fun check_conform(v: AbsSyntaxVisitor) is abstract
 end
 
 redef class AType
-       attr _stype_cache: MMType
-       attr _stype_cached: Bool = false
+       var _stype_cache: nullable MMType = null
+       var _stype_cached: Bool = false
 
-       redef meth get_local_class(v)
+       redef fun get_local_class(v)
        do
                var name = n_id.to_symbol
                var mod = v.module
                var cla = v.local_class
 
-               if (cla.formal_dict != null and cla.formal_dict.has_key(name)) or (cla.global_properties != null and cla.has_global_property_by_name(name)) then
+               if cla.formal_dict.has_key(name) or cla.has_global_property_by_name(name) then
                        v.error(n_id, "Type error: {name} is a formal type")
                        _stype_cached = true
                        return null
@@ -546,7 +552,7 @@ redef class AType
                return local_class
        end
 
-       redef meth get_unchecked_stype(v)
+       redef fun get_unchecked_stype(v)
        do
                if _stype_cached then return _stype_cache
                _stype_cached = true
@@ -554,27 +560,30 @@ redef class AType
                var name = n_id.to_symbol
                var mod = v.module
                var cla = v.local_class
+               var t: nullable MMType
 
                if cla.formal_dict.has_key(name) then
                        if n_types.length > 0 then
                                v.error(self, "Type error: formal type {name} cannot have formal parameters.")
                                return null
                        end
-                       var formal = cla.formal_dict[name]
-                       _stype_cache = formal
-                       return formal
+                       t = cla.formal_dict[name]
+                       if n_kwnullable != null then t = t.as_nullable
+                       _stype_cache = t
+                       return t
                end
 
-               if cla.global_properties != null and cla.has_global_property_by_name(name) then
+               if cla.has_global_property_by_name(name) then
                        if n_types.length > 0 then
                                v.error(self, "Type error: formal type {name} cannot have formal parameters.")
                                return null
                        end
-                       var t = cla.get_type.local_class.select_virtual_type(name).stype_for(cla.get_type)
+                       t = cla.get_type.local_class.select_virtual_type(name).stype_for(cla.get_type)
                        if t == null then
                                v.error(self, "Type error: circular definition in formal type {name}.")
                                return null
                        end
+                       if n_kwnullable != null then t = t.as_nullable
                        _stype_cache = t
                        return t
                end
@@ -591,26 +600,29 @@ redef class AType
                if arity > 0 then
                        var tab = new Array[MMType]
                        for p in n_types do
-                               tab.add(p.get_unchecked_stype(v))
+                               var t2 = p.get_unchecked_stype(v)
+                               if t2 == null then return null
+                               tab.add(t2)
                        end
-                       var t = local_class.get_instantiate_type(tab)
-                       _stype_cache = t
-                       return t
+                       t = local_class.get_instantiate_type(tab)
                else
-                       var t = local_class.get_type
-                       _stype_cache = t
-                       return t
+                       t = local_class.get_type
                end
+               if n_kwnullable != null then t = t.as_nullable
+               _stype_cache = t
+               return t
        end
        
-       redef meth get_stype(v)
+       redef fun get_stype(v)
        do
                var t = get_unchecked_stype(v)
-               if t != null then check_conform(v)
+               if t == null then return null
+               if not t.is_valid then return null
+               check_conform(v)
                return t
        end
 
-       redef meth check_conform(v)
+       redef fun check_conform(v)
        do
                var st = get_unchecked_stype(v)
                if st == null then return 
@@ -620,8 +632,9 @@ redef class AType
                        for i in [0..arity[ do
                                var p = n_types[i]
                                var pt = p.get_stype(v)
-                               var bt = local_class.get_formal(i).bound
-                               if bt == null then return
+                               var b = local_class.get_formal(i)
+                               if not b.is_valid then return
+                               var bt = b.bound
                                bt = bt.adapt_to(st) # We need to abapt because of F-genericity
                                v.check_conform(p, pt, bt)
                        end
@@ -633,46 +646,52 @@ redef class PExpr
        # Is the expression node correcly typed
        # Return false if typed was not yet computed or
        # if an error occured during the typing computation
-       meth is_typed: Bool is abstract
+       fun is_typed: Bool is abstract
 
        # Is the expression node a statement? (ie has no return value)
        # require: is_typed
-       meth is_statement: Bool is abstract
+       fun is_statement: Bool is abstract
 
        # The static type of the expression
        # require: is_typed and not is_statement
-       meth stype: MMType is abstract
+       fun stype: MMType is abstract
 end
 
 redef class AVardeclExpr
        # Assiociated local variable
-       readable writable attr _variable: VarVariable
+       fun variable: VarVariable is abstract
+       #readable writable var _variable: nullable VarVariable
 end
 
 redef class AForExpr
        # Associated automatic local variable
-       readable writable attr _variable: AutoVariable
+       fun variable: AutoVariable is abstract
+       #readable writable var _variable: nullable AutoVariable
 end
 
 redef class ASelfExpr
        # Associated local variable
-       readable writable attr _variable: ParamVariable 
+       fun variable: ParamVariable is abstract
+       #readable writable var _variable: nullable ParamVariable
 end
 
 redef class AVarFormExpr
        # Associated local variable
-       readable writable attr _variable: Variable 
+       fun variable: Variable is abstract
+       #readable writable var _variable: nullable Variable
 end
 
 redef class AClosureCallExpr
        # Associated closure variable
-       readable writable attr _variable: ClosureVariable
+       fun variable: ClosureVariable is abstract
+       #readable writable var _variable: nullable ClosureVariable
 end
 
 redef class PClosureDef
        # Associated closure
-       readable writable attr _closure: MMClosure
+       #readable writable var _closure: nullable MMClosure
+       fun closure: MMClosure is abstract
 
        # Automatic variables
-       readable writable attr _variables: Array[AutoVariable]
+       readable writable var _variables: nullable Array[AutoVariable]
 end