Make 'self' a standard parameter (ParamVariable)
authorJean Privat <jean@pryen.org>
Tue, 20 Jan 2009 19:59:50 +0000 (14:59 -0500)
committerJean Privat <jean@pryen.org>
Tue, 20 Jan 2009 19:59:50 +0000 (14:59 -0500)
This simplify the implementation and allows isa to work on self.
A new test, base_isa_cast_self, is also added to check cast on self.

12 files changed:
src/compiling/compiling_global.nit
src/compiling/compiling_methods.nit
src/syntax/syntax_base.nit
src/syntax/typing.nit
tests/base_isa_cast_self.nit [new file with mode: 0644]
tests/sav/base_isa_cast_self.sav [new file with mode: 0644]
tests/sav/base_isa_cast_self_alt1.sav [new file with mode: 0644]
tests/sav/base_isa_cast_self_alt2.sav [new file with mode: 0644]
tests/sav/base_isa_cast_self_alt3.sav [new file with mode: 0644]
tests/sav/base_isa_cast_self_alt4.sav [new file with mode: 0644]
tests/sav/base_isa_cast_self_alt5.sav [new file with mode: 0644]
tests/sav/base_isa_cast_self_alt6.sav [new file with mode: 0644]

index 15f8376..519878e 100644 (file)
@@ -845,11 +845,15 @@ redef class MMLocalClass
                        var ctx_old = v.ctx
                        v.ctx = new CContext
 
-                       v.nmc.method_params = ["OBJ2VAL(obj)"]
+                       var self_var = new ParamVariable(null, null)
+                       var self_var_cname = v.cfc.register_variable(self_var)
+                       v.nmc.method_params = [self_var]
 
                        v.add_instr("obj_t obj;")
                        v.add_instr("obj = alloc(sizeof(val_t) * {itab.length});")
                        v.add_instr("obj->vft = (classtable_elt_t*)VFT_{name};")
+                       v.add_assignment(self_var_cname, "OBJ2VAL(obj)")
+
                        for g in global_properties do
                                var p = self[g]
                                var t = p.signature.return_type
index af1e848..2729ea1 100644 (file)
@@ -114,9 +114,13 @@ redef class CompilerVisitor
                while i < l do
                        var p = n.super_init_calls[i]
                        if p == stop_prop then break
-                       var cargs = nmc.method_params
+                       var cargs = new Array[String]
                        if p.signature.arity == 0 then
-                               cargs = [nmc.method_params[0]]
+                               cargs.add(cfc.varname(nmc.method_params[0]))
+                       else
+                               for va in nmc.method_params do
+                                       cargs.add(cfc.varname(va))
+                               end
                        end
                        #s.append(" {p}")
                        p.compile_call(self, cargs)
@@ -205,8 +209,8 @@ class NitMethodContext
        # Is a "return" found in the method body
        readable writable attr _has_return: Bool = false
 
-       # Association between parameters and the corresponding c variables
-       readable writable attr _method_params: Array[String] 
+       # Association between parameters and the corresponding variables
+       readable writable attr _method_params: Array[ParamVariable] 
 
        # Where a nit return must branch
        readable writable attr _return_label: String 
@@ -463,6 +467,10 @@ redef class AConcreteMethPropdef
                var old_nmc = v.nmc
                v.nmc = new NitMethodContext(method)
 
+               var cname = v.cfc.register_variable(self_var)
+               v.add_assignment(cname, params[0])
+               v.nmc.method_params = [self_var]
+
                var orig_meth: MMLocalProperty = method.global.intro
                var orig_sig = orig_meth.signature_for(method.signature.recv)
                if n_signature != null then
@@ -470,6 +478,7 @@ redef class AConcreteMethPropdef
                        assert sig isa ASignature
                        for ap in sig.n_params do
                                var cname = v.cfc.register_variable(ap.variable)
+                               v.nmc.method_params.add(ap.variable)
                                var orig_type = orig_sig[ap.position]
                                if not orig_type < ap.variable.stype then
                                        # FIXME: do not test always
@@ -488,7 +497,6 @@ redef class AConcreteMethPropdef
                        v.add_instr("if (init_table[{itpos}]) return;")
                end
 
-               v.nmc.method_params = params
                v.nmc.return_label = "return_label{v.new_number}"
                if method.signature.return_type != null then
                        v.nmc.return_value = v.cfc.get_var
@@ -993,7 +1001,7 @@ end
 redef class ASelfExpr
        redef meth compile_expr(v)
        do
-               return v.nmc.method_params[0]
+               return v.cfc.varname(v.nmc.method_params[0])
        end
 end
 
@@ -1227,10 +1235,10 @@ redef class ASuperExpr
                        arity = init_in_superclass.signature.arity
                end
                var args = new Array[String].with_capacity(arity + 1)
-               args.add(v.nmc.method_params[0])
+               args.add(v.cfc.varname(v.nmc.method_params[0]))
                if n_args.length != arity then
                        for i in [0..arity[ do
-                               args.add(v.nmc.method_params[i + 1])
+                               args.add(v.cfc.varname(v.nmc.method_params[i + 1]))
                        end
                else
                        for na in n_args do
index ecbeffa..4703700 100644 (file)
@@ -207,8 +207,8 @@ abstract class Variable
 
        init(n: Symbol, d: PNode)
        do
-               assert n != null
-               assert d != null
+               #assert n != null
+               #assert d != null
                _name = n
                _decl = d
        end
@@ -415,6 +415,9 @@ end
 redef class AMethPropdef
        # Associated method (MM entity)
        meth method: MMMethSrcMethod is abstract
+
+       # Associated 'self' variable
+       meth self_var: ParamVariable is abstract
 end
 
 redef class ATypePropdef
@@ -578,6 +581,11 @@ redef class AForVardeclExpr
        readable writable attr _variable: AutoVariable
 end
 
+redef class ASelfExpr
+       # Associated local variable
+       readable writable attr _variable: ParamVariable 
+end
+
 redef class AVarFormExpr
        # Associated local variable
        readable writable attr _variable: Variable 
index 7da9d4e..5d01a75 100644 (file)
@@ -44,8 +44,8 @@ special AbsSyntaxVisitor
        # Current knowledge about variables names and types
        readable writable attr _variable_ctx: VariableContext
 
-       # Type of the receiver
-       readable writable attr _self_type: MMType
+       # The current reciever
+       readable writable attr _self_var: ParamVariable
 
        # Block of the current method
        readable writable attr _top_block: PExpr
@@ -196,7 +196,8 @@ end
 redef class PClassdef
        redef meth accept_typing(v)
        do
-               v.self_type = local_class.get_type
+               v.self_var = new ParamVariable("self".to_symbol, self)
+               v.self_var.stype = local_class.get_type
                super
        end
 end
@@ -212,9 +213,11 @@ redef class AAttrPropdef
 end
 
 redef class AMethPropdef
+       redef readable attr _self_var: ParamVariable
        redef meth accept_typing(v)
        do
                v.variable_ctx = new VariableContext
+               _self_var = v.self_var
                super
        end
 end
@@ -293,8 +296,8 @@ redef class PExpr
        # Is the expression the current receiver (implicit or explicit)
        meth is_self: Bool do return false
 
-       # Is the expression a variable access
-       meth is_variable: Bool do return false
+       # The variable accessed is any
+       meth its_variable: Variable do return null
 
        # The variable type information if current boolean expression is true
        readable private attr _if_true_variable_ctx: VariableContext
@@ -422,7 +425,7 @@ redef class AAssertExpr
 end
 
 redef class AVarExpr
-       redef meth is_variable do return true
+       redef meth its_variable do return variable
 
        redef meth after_typing(v)
        do
@@ -481,10 +484,12 @@ redef class AMinusAssignOp
 end
 
 redef class ASelfExpr
+       redef meth its_variable do return variable
+
        redef meth after_typing(v)
        do
-               assert v.self_type != null
-               _stype = v.self_type
+               variable = v.self_var
+               _stype = v.variable_ctx.stype(variable)
        end
 
         redef meth is_self do return true
@@ -682,7 +687,7 @@ special ASuperInitCall
                        _init_in_superclass = p
                        register_super_init_call(v, p)
                        if n_args.length > 0 then
-                               var signature = get_signature(v, v.self_type, p, true)
+                               var signature = get_signature(v, v.self_var.stype, p, true)
                                _arguments = process_signature(v, signature, p, n_args.to_a)
                        end
                else
@@ -690,12 +695,12 @@ special ASuperInitCall
                        return
                end
 
-               if precs.first.signature_for(v.self_type).return_type != null then
+               if precs.first.signature_for(v.self_var.stype).return_type != null then
                        var stypes = new Array[MMType]
                        var stype: MMType = null
                        for prop in precs do
                                assert prop isa MMMethod
-                               var t = prop.signature_for(v.self_type).return_type.for_module(v.module).adapt_to(v.local_property.signature.recv)
+                               var t = prop.signature_for(v.self_var.stype).return_type.for_module(v.module).adapt_to(v.local_property.signature.recv)
                                stypes.add(t)
                                if stype == null or stype < t then
                                        stype = t
@@ -1138,10 +1143,9 @@ end
 redef class AIsaExpr
        redef meth after_typing(v)
        do
-               if n_expr.is_variable then
-                       var n = n_expr
-                       assert n isa AVarExpr
-                       _if_true_variable_ctx = v.variable_ctx.sub_with(n.variable, n_type.stype)
+               var variable = n_expr.its_variable
+               if variable != null then
+                       _if_true_variable_ctx = v.variable_ctx.sub_with(variable, n_type.stype)
                end
                _stype = v.type_bool
        end
diff --git a/tests/base_isa_cast_self.nit b/tests/base_isa_cast_self.nit
new file mode 100644 (file)
index 0000000..1bb78f4
--- /dev/null
@@ -0,0 +1,65 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2009 Jean Privat <jean@pryen.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class A
+       init do end
+
+       meth work
+       do
+               if self isa B then
+                       foo
+                       if self isa C then
+                               bar
+                       end
+#alt1#                 bar
+                       foo
+               else
+#alt2#                 foo
+               end
+#alt3#         foo
+
+               if self isa B and self == self then
+                       foo
+               end
+
+               if self isa B or self == self then
+#alt4#                 foo
+               end
+
+               assert self isa B
+               foo
+       end
+end
+
+class B
+special A
+       meth foo do 0.output
+       init do end
+end
+
+class C
+special B
+       meth bar do 1.output
+       init do end
+end
+
+var a: A
+a = new C
+#alt5#a = new B
+#alt6#a = new A
+a.work
diff --git a/tests/sav/base_isa_cast_self.sav b/tests/sav/base_isa_cast_self.sav
new file mode 100644 (file)
index 0000000..6473747
--- /dev/null
@@ -0,0 +1,5 @@
+0
+1
+0
+0
+0
diff --git a/tests/sav/base_isa_cast_self_alt1.sav b/tests/sav/base_isa_cast_self_alt1.sav
new file mode 100644 (file)
index 0000000..cc26292
--- /dev/null
@@ -0,0 +1 @@
+alt/base_isa_cast_self_alt1.nit:29,4--6: Error: Method or variable 'bar' unknown in B.
diff --git a/tests/sav/base_isa_cast_self_alt2.sav b/tests/sav/base_isa_cast_self_alt2.sav
new file mode 100644 (file)
index 0000000..d757bd5
--- /dev/null
@@ -0,0 +1 @@
+alt/base_isa_cast_self_alt2.nit:32,4--6: Error: Method or variable 'foo' unknown in A.
diff --git a/tests/sav/base_isa_cast_self_alt3.sav b/tests/sav/base_isa_cast_self_alt3.sav
new file mode 100644 (file)
index 0000000..730fb76
--- /dev/null
@@ -0,0 +1 @@
+alt/base_isa_cast_self_alt3.nit:34,3--5: Error: Method or variable 'foo' unknown in A.
diff --git a/tests/sav/base_isa_cast_self_alt4.sav b/tests/sav/base_isa_cast_self_alt4.sav
new file mode 100644 (file)
index 0000000..f41b3c1
--- /dev/null
@@ -0,0 +1 @@
+alt/base_isa_cast_self_alt4.nit:41,4--6: Error: Method or variable 'foo' unknown in A.
diff --git a/tests/sav/base_isa_cast_self_alt5.sav b/tests/sav/base_isa_cast_self_alt5.sav
new file mode 100644 (file)
index 0000000..44e0be8
--- /dev/null
@@ -0,0 +1,4 @@
+0
+0
+0
+0
diff --git a/tests/sav/base_isa_cast_self_alt6.sav b/tests/sav/base_isa_cast_self_alt6.sav
new file mode 100644 (file)
index 0000000..7951723
--- /dev/null
@@ -0,0 +1,5 @@
+Assert failed in base_isa_cast_self_alt6::A::work (alt/base_isa_cast_self_alt6.nit:44)
+,---- Stack trace -- - -  -
+| base_isa_cast_self_alt6::A::work (alt/base_isa_cast_self_alt6.nit:22)
+| base_isa_cast_self_alt6::Sys::(kernel::Sys::main) (alt/base_isa_cast_self_alt6.nit:61)
+`------------------- - -  -