redef class ITypeCheck
redef fun dump_intern(icd)
do
- return "CHECKTYPE {icd.register(expr)} isa {stype}"
+ return "CHECKTYPE {icd.register(expr2)} isa {stype}"
end
end
do
return "ATTR_{intro.cname}"
end
+
+ # C symbol refering a virtual type class color
+ fun vt_class_color: String
+ do
+ return "VTCOLOR_{intro.cname}"
+ end
+
+ # C symbol refering a virtual type class id
+ fun vt_class_id: String
+ do
+ return "VTID_{intro.cname}"
+ end
end
redef class MMGlobalClass
end
end
+redef class TableEltVTClassColor
+ redef fun compile_macros(v, value)
+ do
+ var pg = property.global
+ v.add_decl("#define {pg.vt_class_color}(recv) (VAL2VFT(recv)[{value}].i)")
+ end
+
+ redef fun compile_to_c(v, c)
+ do
+ var prog = v.program
+ var p = c[property.global]
+ var g = p.signature_for(c.get_type).return_type.local_class.global
+ var col = g.intro.as(MMConcreteClass).class_color_pos
+ return "{prog.table_information.color(col)} /* {prog.table_information.color(self)}: VT {c}::{p} : color of {g} */"
+ end
+end
+
+redef class TableEltVTClassId
+ redef fun compile_macros(v, value)
+ do
+ var pg = property.global
+ v.add_decl("#define {pg.vt_class_id}(recv) (VAL2VFT(recv)[{value}].i)")
+ end
+
+ redef fun compile_to_c(v, c)
+ do
+ var prog = v.program
+ var p = c[property.global]
+ var g = p.signature_for(c.get_type).return_type.local_class.global
+ return "{prog.compiled_classes[g].id} /* {prog.table_information.color(self)}: VT {c}::{p} : id of {g} */"
+ end
+end
+
redef class TableEltAttr
redef fun compile_macros(v, value)
do
end
end
+
redef class AbsTableEltClass
# The C macro name refering the value
fun symbol: String is abstract
redef fun compile_to_c(v)
do
if not need_result then return
- # FIXME handle formaltypes
v.add_location(location)
- var g = stype.local_class.global
- var recv = v.register(expr)
+ var recv = v.register(expr2)
var w = new_result(v)
w.add("TAG_Bool(")
- if expr.stype.is_nullable then
+ if expr2.stype.is_nullable then
if stype.is_nullable then
w.add("(")
w.add(recv)
w.add("==NIT_NULL) || ")
- else if stype.as_nullable == expr.stype then
+ else if stype.as_nullable == expr2.stype then
w.add(recv)
w.add("!=NIT_NULL)")
return
w.add("!=NIT_NULL) && ")
end
end
- w.add("VAL_ISA(")
- w.add(recv)
- w.add(", ")
- w.add(g.color_id)
- w.add(", ")
- w.add(g.id_id)
- w.add(")) /*cast ")
- w.add(stype.to_s)
- w.add("*/")
+ # FIXME handle formaltypes
+ var t = stype
+ if t isa MMVirtualType then
+ var slf = v.register(expr1)
+ var g = t.property.global
+ w.add("VAL_ISA(")
+ w.add(recv)
+ w.add(", ")
+ w.add(g.vt_class_color)
+ w.add("(")
+ w.add(slf)
+ w.add(")")
+ w.add(", ")
+ w.add(g.vt_class_id)
+ w.add("(")
+ w.add(slf)
+ w.add(")")
+ w.add(")) /*cast ")
+ w.add(t.to_s)
+ w.add("*/")
+ else
+ var g = t.local_class.global
+ w.add("VAL_ISA(")
+ w.add(recv)
+ w.add(", ")
+ w.add(g.color_id)
+ w.add(", ")
+ w.add(g.id_id)
+ w.add(")) /*cast ")
+ w.add(t.to_s)
+ w.add("*/")
+ end
end
end
ilt.add(new TableEltAttr(p))
else if p isa MMMethod then
clt.add(new TableEltMeth(p))
+ else if p isa MMTypeProperty then
+ clt.add(new TableEltVTClassId(p))
+ clt.add(new TableEltVTClassColor(p))
end
end
if p isa MMMethod and p.need_super then
super TableEltProp
end
+# An element that represents a class color value for a virtual type
+class TableEltVTClassColor
+ super TableEltProp
+end
+
+# An element that represents a class id value for a virtual type
+class TableEltVTClassId
+ super TableEltProp
+end
+
# An element that represents a function pointer to the super method of a local method
class TableEltSuper
super TableEltProp
end
# A type check
-# expr is the expression checked
+# expr1 is the type reciever (self)
+# expr2 is the expression checked
class ITypeCheck
- super ICode1
+ super ICode2
# The static type checkes to
readable var _stype: MMType
- init(e: IRegister, t: MMType)
+ init(e1, e2: IRegister, t: MMType)
do
- super(e)
+ super(e1, e2)
_stype = t
end
# Add a type cast (ITypeCheck + IAbort) in the current icode sequence
fun add_type_cast(e: IRegister, stype: MMType)
do
- var c = expr(new ITypeCheck(e, stype), mmmodule.type_bool)
+ var c = expr(new ITypeCheck(iroutine.params.first, e, stype), mmmodule.type_bool)
var iif = new IIf(c)
stmt(iif)
var old_seq = seq
end
iroutine.closure_decls = clos
end
+ # Add automatic test for virtual types
+ var icb = new ICodeBuilder(recv.mmmodule, iroutine)
+ for i in [0..arity[ do
+ var t = self[i]
+ if t isa MMVirtualType then
+ icb.add_type_cast(args[i+1], t)
+ end
+ end
return iroutine
end
end
iroutine.closure_decls = clos
end
+ # TODO: add automatic test for virtual types?
return iroutine
end
end
redef class ITypeCheck
redef fun inner_dup_with(d)
do
- return new ITypeCheck(d.dup_ireg(expr), stype)
+ return new ITypeCheck(d.dup_ireg(expr1), d.dup_ireg(expr2), stype)
end
end
# The method associated to the iroutine (if any)
readable var _method: nullable MMMethod
+ # The register of self (if any)
+ var selfreg: nullable IRegister writable
+
init(visitor: AbsSyntaxVisitor, r: IRoutine, m: nullable MMMethod)
do
super(visitor.mmmodule, r)
var params = v.iroutine.params.to_a
var selfreg = v.variable(self_var)
v.stmt(new IMove(selfreg, params[0]))
+ v.selfreg = selfreg
params.shift
var orig_meth: MMLocalProperty = method.global.intro
if n_block != null then
v.generate_stmt(n_block)
end
+ v.selfreg = null
end
end
redef fun generate_icode(v)
do
var e = v.generate_expr(n_expr)
- return v.expr(new ITypeCheck(e, n_type.stype), stype)
+ return v.expr(new ITypeCheck(v.selfreg.as(not null), e, n_type.stype), stype)
end
end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.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
+ type T: K
+ type U: T
+ fun check(o: Object)
+ do
+ o.output
+ '<'.output
+ 'T'.output
+ (o isa T).output
+ o.output
+ '<'.output
+ 'U'.output
+ (o isa U).output
+ end
+ fun check2(o: T)
+ do
+ o.output
+ '<'.output
+ 'T'.output
+ '\n'.output
+ end
+ fun check3(o: U)
+ do
+ o.output
+ '<'.output
+ 'U'.output
+ '\n'.output
+ end
+end
+class B
+ super A
+ redef type T: L
+end
+class J
+ redef fun output do 'J'.output
+end
+class K
+ super J
+ redef fun output do 'K'.output
+end
+class L
+ super K
+ redef fun output do 'L'.output
+end
+
+var a = new A
+a.check(new J)
+a.check(new K)
+a.check(new L)
+#alt1#a.check2(new J) # Static error
+a.check2(new K)
+a.check2(new L)
+#alt2#a.check3(new J) # Static error
+a.check3(new K)
+a.check3(new L)
+var b = new B
+b.check(new J)
+b.check(new K)
+b.check(new L)
+#alt3#b.check2(new J) # Static error
+#alt4#b.check2(new K) # Static error
+b.check2(new L)
+#alt5#b.check3(new J) # Static error
+#alt6#b.check3(new K) # Static error
+b.check3(new L)
+var ab: A = new B
+ab.check(new J)
+ab.check(new K)
+ab.check(new L)
+#alt7#ab.check2(new J) # Static error
+#alt8#ab.check2(new K) # Dynamic error
+ab.check2(new L)
+#alt9#ab.check3(new J) # Static error
+#alt10#ab.check3(new K) # Dynamic error
+ab.check3(new L)
--- /dev/null
+J<Tfalse
+J<Ufalse
+K<Ttrue
+K<Utrue
+L<Ttrue
+L<Utrue
+K<T
+L<T
+K<U
+L<U
+J<Tfalse
+J<Ufalse
+K<Tfalse
+K<Ufalse
+L<Ttrue
+L<Utrue
+L<T
+L<U
+J<Tfalse
+J<Ufalse
+K<Tfalse
+K<Ufalse
+L<Ttrue
+L<Utrue
+L<T
+L<U
--- /dev/null
+alt/base_virtual_type_check_alt1.nit:65,10--14: Type error: expected K, got J
--- /dev/null
+J<Tfalse
+J<Ufalse
+K<Ttrue
+K<Utrue
+L<Ttrue
+L<Utrue
+K<T
+L<T
+K<U
+L<U
+J<Tfalse
+J<Ufalse
+K<Tfalse
+K<Ufalse
+L<Ttrue
+L<Utrue
+L<T
+L<U
+J<Tfalse
+J<Ufalse
+K<Tfalse
+K<Ufalse
+L<Ttrue
+L<Utrue
+L<T
+Cast failed (alt/base_virtual_type_check_alt10.nit)
--- /dev/null
+alt/base_virtual_type_check_alt2.nit:68,10--14: Type error: expected K, got J
--- /dev/null
+alt/base_virtual_type_check_alt3.nit:75,10--14: Type error: expected L, got J
--- /dev/null
+alt/base_virtual_type_check_alt4.nit:76,10--14: Type error: expected L, got K
--- /dev/null
+alt/base_virtual_type_check_alt5.nit:78,10--14: Type error: expected L, got J
--- /dev/null
+alt/base_virtual_type_check_alt6.nit:79,10--14: Type error: expected L, got K
--- /dev/null
+alt/base_virtual_type_check_alt7.nit:85,11--15: Type error: expected K, got J
--- /dev/null
+J<Tfalse
+J<Ufalse
+K<Ttrue
+K<Utrue
+L<Ttrue
+L<Utrue
+K<T
+L<T
+K<U
+L<U
+J<Tfalse
+J<Ufalse
+K<Tfalse
+K<Ufalse
+L<Ttrue
+L<Utrue
+L<T
+L<U
+J<Tfalse
+J<Ufalse
+K<Tfalse
+K<Ufalse
+L<Ttrue
+L<Utrue
+Cast failed (alt/base_virtual_type_check_alt8.nit)
--- /dev/null
+alt/base_virtual_type_check_alt9.nit:88,11--15: Type error: expected K, got J
+++ /dev/null
-AB5
-B5
-5
-AB5
-5
-5
-5
-5
-5
-B5
-5
-5
-5
-5
-5
-5
-5
-5
--- /dev/null
+AB5
+B5
+5
+Cast failed (alt/test_variance_param_alt1.nit)
+++ /dev/null
-AB5
-B5
-5
-B5
-B5
-5
-5
-5
-5
-B5
-5
-5
-5
-5
-5
-5
-5
-5
--- /dev/null
+AB5
+B5
+5
+B5
+Cast failed (alt/test_variance_param_alt2.nit)
+++ /dev/null
-AB5
-B5
-5
-B5
-5
-5
-A5
-5
-5
-B5
-5
-5
-5
-5
-5
-5
-5
-5
--- /dev/null
+AB5
+B5
+5
+B5
+5
+5
+Cast failed (alt/test_variance_param_alt3.nit)
+++ /dev/null
-AB5
-B5
-5
-B5
-5
-5
-B5
-5
-5
-B5
-5
-5
-5
-5
-5
-5
-5
-5
--- /dev/null
+AB5
+B5
+5
+B5
+5
+5
+Cast failed (alt/test_variance_param_alt4.nit)
+++ /dev/null
-AB5
-B5
-5
-B5
-5
-5
-5
-B5
-5
-B5
-5
-5
-5
-5
-5
-5
-5
-5
--- /dev/null
+AB5
+B5
+5
+B5
+5
+5
+5
+Cast failed (alt/test_variance_param_alt5.nit)
+++ /dev/null
-AB5
-B5
-5
-B5
-5
-5
-5
-5
-5
-B5
-5
-5
-B5
-5
-5
-5
-5
-5
--- /dev/null
+AB5
+B5
+5
+B5
+5
+5
+5
+5
+5
+B5
+5
+5
+Cast failed (alt/test_variance_param_alt6.nit)