From bc90fae43364bba600319f6ffd2a48f53baf6067 Mon Sep 17 00:00:00 2001 From: Jean Privat Date: Tue, 20 Jan 2009 14:59:50 -0500 Subject: [PATCH] Make 'self' a standard parameter (ParamVariable) 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. --- src/compiling/compiling_global.nit | 6 ++- src/compiling/compiling_methods.nit | 24 ++++++++---- src/syntax/syntax_base.nit | 12 +++++- src/syntax/typing.nit | 34 +++++++++-------- tests/base_isa_cast_self.nit | 65 +++++++++++++++++++++++++++++++++ tests/sav/base_isa_cast_self.sav | 5 +++ tests/sav/base_isa_cast_self_alt1.sav | 1 + tests/sav/base_isa_cast_self_alt2.sav | 1 + tests/sav/base_isa_cast_self_alt3.sav | 1 + tests/sav/base_isa_cast_self_alt4.sav | 1 + tests/sav/base_isa_cast_self_alt5.sav | 4 ++ tests/sav/base_isa_cast_self_alt6.sav | 5 +++ 12 files changed, 133 insertions(+), 26 deletions(-) create mode 100644 tests/base_isa_cast_self.nit create mode 100644 tests/sav/base_isa_cast_self.sav create mode 100644 tests/sav/base_isa_cast_self_alt1.sav create mode 100644 tests/sav/base_isa_cast_self_alt2.sav create mode 100644 tests/sav/base_isa_cast_self_alt3.sav create mode 100644 tests/sav/base_isa_cast_self_alt4.sav create mode 100644 tests/sav/base_isa_cast_self_alt5.sav create mode 100644 tests/sav/base_isa_cast_self_alt6.sav diff --git a/src/compiling/compiling_global.nit b/src/compiling/compiling_global.nit index 15f8376..519878e 100644 --- a/src/compiling/compiling_global.nit +++ b/src/compiling/compiling_global.nit @@ -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 diff --git a/src/compiling/compiling_methods.nit b/src/compiling/compiling_methods.nit index af1e848..2729ea1 100644 --- a/src/compiling/compiling_methods.nit +++ b/src/compiling/compiling_methods.nit @@ -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 diff --git a/src/syntax/syntax_base.nit b/src/syntax/syntax_base.nit index ecbeffa..4703700 100644 --- a/src/syntax/syntax_base.nit +++ b/src/syntax/syntax_base.nit @@ -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 diff --git a/src/syntax/typing.nit b/src/syntax/typing.nit index 7da9d4e..5d01a75 100644 --- a/src/syntax/typing.nit +++ b/src/syntax/typing.nit @@ -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 index 0000000..1bb78f4 --- /dev/null +++ b/tests/base_isa_cast_self.nit @@ -0,0 +1,65 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2009 Jean Privat +# +# 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 index 0000000..6473747 --- /dev/null +++ b/tests/sav/base_isa_cast_self.sav @@ -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 index 0000000..cc26292 --- /dev/null +++ b/tests/sav/base_isa_cast_self_alt1.sav @@ -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 index 0000000..d757bd5 --- /dev/null +++ b/tests/sav/base_isa_cast_self_alt2.sav @@ -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 index 0000000..730fb76 --- /dev/null +++ b/tests/sav/base_isa_cast_self_alt3.sav @@ -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 index 0000000..f41b3c1 --- /dev/null +++ b/tests/sav/base_isa_cast_self_alt4.sav @@ -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 index 0000000..44e0be8 --- /dev/null +++ b/tests/sav/base_isa_cast_self_alt5.sav @@ -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 index 0000000..7951723 --- /dev/null +++ b/tests/sav/base_isa_cast_self_alt6.sav @@ -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) +`------------------- - - - -- 1.7.9.5