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.
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
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)
# 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
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
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
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
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
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
init(n: Symbol, d: PNode)
do
- assert n != null
- assert d != null
+ #assert n != null
+ #assert d != null
_name = n
_decl = d
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
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
# 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
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
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
# 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
end
redef class AVarExpr
- redef meth is_variable do return true
+ redef meth its_variable do return variable
redef meth after_typing(v)
do
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
_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
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
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
--- /dev/null
+# 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
--- /dev/null
+0
+1
+0
+0
+0
--- /dev/null
+alt/base_isa_cast_self_alt1.nit:29,4--6: Error: Method or variable 'bar' unknown in B.
--- /dev/null
+alt/base_isa_cast_self_alt2.nit:32,4--6: Error: Method or variable 'foo' unknown in A.
--- /dev/null
+alt/base_isa_cast_self_alt3.nit:34,3--5: Error: Method or variable 'foo' unknown in A.
--- /dev/null
+alt/base_isa_cast_self_alt4.nit:41,4--6: Error: Method or variable 'foo' unknown in A.
--- /dev/null
+0
+0
+0
+0
--- /dev/null
+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)
+`------------------- - - -