X-Git-Url: http://nitlanguage.org diff --git a/src/syntax/typing.nit b/src/syntax/typing.nit index 5338a91..3c92473 100644 --- a/src/syntax/typing.nit +++ b/src/syntax/typing.nit @@ -18,8 +18,8 @@ package typing import syntax_base -import escape -import control_flow +import flow +import scope redef class MMSrcModule # Walk trough the module and type statments and expressions @@ -37,15 +37,14 @@ end # * Resolve call and attribute access # * Check type conformance private class TypingVisitor -special AbsSyntaxVisitor + super AbsSyntaxVisitor redef fun visit(n) do if n != null then n.accept_typing(self) end - # Current knowledge about variables names and types - fun scope_ctx: ScopeContext do return _scope_ctx.as(not null) - writable var _scope_ctx: nullable ScopeContext + # Current knowledge about scoped things (variable, labels, etc.) + readable var _scope_ctx: ScopeContext = new ScopeContext(self) # Current knowledge about control flow fun flow_ctx: FlowContext do return _flow_ctx.as(not null) @@ -68,19 +67,15 @@ special AbsSyntaxVisitor fun enter_visit_block(node: nullable AExpr) do if node == null then return - var old_scope_ctx = scope_ctx - scope_ctx = scope_ctx.sub(node) + scope_ctx.push(node) enter_visit(node) - scope_ctx = old_scope_ctx + scope_ctx.pop end # Non-bypassable knowledge about variables names and types fun base_flow_ctx: FlowContext do return _base_flow_ctx.as(not null) writable var _base_flow_ctx: nullable FlowContext - # Current knowledge about escapable blocks - readable writable var _escapable_ctx: EscapableContext = new EscapableContext(self) - # The current reciever fun self_var: ParamVariable do return _self_var.as(not null) writable var _self_var: nullable ParamVariable @@ -101,7 +96,7 @@ special AbsSyntaxVisitor if ctx != null then flow_ctx = ctx end - # Make the if_false_scope_ctx of the expression effective + # Make the if_false_flow_ctx of the expression effective private fun use_if_false_flow_ctx(e: AExpr) do var ctx = e.if_false_flow_ctx @@ -114,7 +109,7 @@ special AbsSyntaxVisitor # Number of nested once readable writable var _once_count: Int = 0 - init(tc, module) do super + init(tc, mod) do super private fun get_default_constructor_for(n: ANode, c: MMLocalClass, prop: MMSrcMethod): nullable MMMethod do @@ -157,10 +152,10 @@ special AbsSyntaxVisitor for p in false_candidates do a.add("{p.full_name}{p.signature.as(not null)}") end - v.error(n, "Error: there is no available compatible constrctor in {c}. Discarded candidates are {a.join(", ")}.") + v.error(n, "Error: there is no available compatible constructor in {c}. Discarded candidates are {a.join(", ")}.") return null else - v.error(n, "Error: there is no available compatible constrctor in {c}.") + v.error(n, "Error: there is no available compatible constructor in {c}.") return null end end @@ -181,7 +176,6 @@ end redef class AClassdef redef fun accept_typing(v) do - v.scope_ctx = new RootScopeContext(v, self) v.self_var = new ParamVariable("self".to_symbol, self) v.self_var.stype = local_class.get_type super @@ -199,15 +193,13 @@ redef class AAttrPropdef v.flow_ctx = new RootFlowContext(v, self) v.base_flow_ctx = v.flow_ctx - var old_scope_ctx = v.scope_ctx - v.scope_ctx = old_scope_ctx.sub(self) - + v.scope_ctx.push(self) _self_var = v.self_var super if n_expr != null then v.check_conform_expr(n_expr.as(not null), prop.signature.return_type.as(not null)) end - v.scope_ctx = old_scope_ctx + v.scope_ctx.pop end end @@ -217,11 +209,10 @@ redef class AMethPropdef v.flow_ctx = new RootFlowContext(v, self) v.base_flow_ctx = v.flow_ctx - var old_scope_ctx = v.scope_ctx - v.scope_ctx = old_scope_ctx.sub(self) + v.scope_ctx.push(self) _self_var = v.self_var super - v.scope_ctx = old_scope_ctx + v.scope_ctx.pop end end @@ -256,12 +247,12 @@ redef class AConcreteInitPropdef var cur_c: nullable MMLocalClass = null if i < l then cur_m = explicit_super_init_calls[i] - cur_c = cur_m.global.intro.local_class.for_module(v.module) + cur_c = cur_m.global.intro.local_class.for_module(v.mmmodule) end var j = 0 while j < v.local_class.cshe.direct_greaters.length do var c = v.local_class.cshe.direct_greaters[j] - if c.global.is_interface or c.global.is_universal or c.global.is_mixin then + if c.global.is_interface or c.global.is_enum or c.global.is_extern or c.global.is_mixin then j += 1 else if cur_c != null and (c.cshe <= cur_c or cur_c.global.is_mixin) then if c == cur_c then j += 1 @@ -269,7 +260,7 @@ redef class AConcreteInitPropdef i += 1 if i < l then cur_m = explicit_super_init_calls[i] - cur_c = cur_m.global.intro.local_class.for_module(v.module) + cur_c = cur_m.global.intro.local_class.for_module(v.mmmodule) else cur_m = null cur_c = null @@ -286,10 +277,31 @@ redef class AConcreteInitPropdef end end +redef class AExternInitPropdef + redef fun accept_typing(v) + do + v.explicit_other_init_call = false + super + end + redef fun after_typing(v) + do + super + end +end + +redef class ASignature + redef fun after_typing(v) + do + if self.n_opar != null and self.n_params.is_empty then + v.warning(self, "Warning: superfluous parentheses.") + end + end +end + redef class AParam redef fun after_typing(v) do - v.scope_ctx.add(variable) + v.scope_ctx.add_variable(variable) end end @@ -300,20 +312,18 @@ redef class AClosureDecl redef fun accept_typing(v) do # Register the closure for ClosureCallExpr - v.scope_ctx.add(variable) + v.scope_ctx.add_variable(variable) - var old_scope_ctx = v.scope_ctx var old_flow_ctx = v.flow_ctx var old_base_flow_ctx = v.base_flow_ctx v.base_flow_ctx = v.flow_ctx - v.scope_ctx = v.scope_ctx.sub(self) var blist: nullable Array[AExpr] = null var t = v.local_property.signature.return_type if t != null then blist = new Array[AExpr] var escapable = new EscapableClosure(self, variable.closure, blist) _escapable = escapable - v.escapable_ctx.push(escapable, null) + v.scope_ctx.push_escapable(escapable, null) v.is_default_closure_definition = true @@ -334,10 +344,9 @@ redef class AClosureDecl v.check_conform_expr(x, t) end - v.scope_ctx = old_scope_ctx v.flow_ctx = old_flow_ctx v.base_flow_ctx = old_base_flow_ctx - v.escapable_ctx.pop + v.scope_ctx.pop end end @@ -389,6 +398,27 @@ redef class AExpr # The control flow information if current boolean expression is false readable private var _if_false_flow_ctx: nullable FlowContext + + # Wharn in case of superfluous parentheses + private fun warn_parentheses(v: AbsSyntaxVisitor) + do + end +end + +redef class AParExpr + redef fun warn_parentheses(v) + do + v.warning(self, "Warning: superfluous parentheses.") + end +end + +redef class AParExprs + redef fun after_typing(v) + do + if n_exprs.is_empty then + v.warning(self, "Warning: superfluous parentheses.") + end + end end redef class AVardeclExpr @@ -399,7 +429,7 @@ redef class AVardeclExpr do var va = new VarVariable(n_id.to_symbol, n_id) _variable = va - v.scope_ctx.add(va) + v.scope_ctx.add_variable(va) var ne = n_expr if ne != null then v.mark_is_set(va) @@ -454,6 +484,9 @@ redef class AReturnExpr else if e != null and t != null then v.check_conform_expr(e, t) end + if e != null then + e.warn_parentheses(v) + end _is_typed = true end end @@ -462,7 +495,7 @@ redef class AContinueExpr redef fun after_typing(v) do v.mark_unreash(self) - var esc = compute_escapable_block(v.escapable_ctx) + var esc = compute_escapable_block(v.scope_ctx) if esc == null then return if esc.is_break_block then @@ -471,12 +504,16 @@ redef class AContinueExpr end var t = esc.continue_stype - if n_expr == null and t != null then + var e = n_expr + if e == null and t != null then v.error(self, "Error: continue with a value required in this block.") - else if n_expr != null and t == null then + else if e != null and t == null then v.error(self, "Error: continue without value required in this block.") - else if n_expr != null and t != null then - v.check_conform_expr(n_expr.as(not null), t) + else if e != null and t != null then + v.check_conform_expr(e, t) + end + if e != null then + e.warn_parentheses(v) end _is_typed = true end @@ -487,19 +524,23 @@ redef class ABreakExpr do var old_flow_ctx = v.flow_ctx v.mark_unreash(self) - var esc = compute_escapable_block(v.escapable_ctx) + var esc = compute_escapable_block(v.scope_ctx) if esc == null then return esc.break_flow_contexts.add(old_flow_ctx) var bl = esc.break_list - if n_expr == null and bl != null then + var e = n_expr + if e == null and bl != null then v.error(self, "Error: break with a value required in this block.") - else if n_expr != null and bl == null then + else if e != null and bl == null then v.error(self, "Error: break without value required in this block.") - else if n_expr != null and bl != null then + else if e != null and bl != null then # Typing check can only be done later - bl.add(n_expr.as(not null)) + bl.add(e) + end + if e != null then + e.warn_parentheses(v) end _is_typed = true end @@ -514,8 +555,8 @@ redef class AAbortExpr end # An abstract control structure with feature escapable block -class AAbsControl -special AExpr +abstract class AAbsControl + super AExpr # The corresponding escapable block readable var _escapable: nullable EscapableBlock @@ -524,7 +565,7 @@ special AExpr do # Register the escapable block _escapable = escapable - v.escapable_ctx.push(escapable, n_label) + v.scope_ctx.push_escapable(escapable, n_label) # Save an prepare the contextes var old_flow_ctx = v.flow_ctx @@ -548,7 +589,7 @@ special AExpr end if is_loop then v.base_flow_ctx = old_base_flow_ctx - v.escapable_ctx.pop + v.scope_ctx.pop _is_typed = true end @@ -557,7 +598,7 @@ special AExpr end redef class ADoExpr -special AAbsControl + super AAbsControl redef fun accept_typing(v) do process_control(v, new BreakOnlyEscapableBlock(self), n_label, false) @@ -575,6 +616,8 @@ redef class AIfExpr v.enter_visit(n_expr) v.check_conform_expr(n_expr, v.type_bool) + n_expr.warn_parentheses(v) + # Prepare 'then' context var old_flow_ctx = v.flow_ctx v.use_if_true_flow_ctx(n_expr) @@ -599,7 +642,7 @@ redef class AIfExpr end redef class AWhileExpr -special AAbsControl + super AAbsControl redef fun accept_typing(v) do process_control(v, new EscapableBlock(self), n_label, true) @@ -615,6 +658,8 @@ special AAbsControl if n_expr isa ATrueExpr then v.warning(self, "Warning: use 'loop' instead of 'while true do'.") + else + n_expr.warn_parentheses(v) end # Prepare inside context (assert cond) @@ -631,7 +676,7 @@ special AAbsControl end redef class ALoopExpr -special AAbsControl + super AAbsControl redef fun accept_typing(v) do process_control(v, new EscapableBlock(self), n_label, true) @@ -648,9 +693,9 @@ special AAbsControl end redef class AForExpr -special AAbsControl - var _variable: nullable AutoVariable - redef fun variable do return _variable.as(not null) + super AAbsControl + var _variables: nullable Array[AutoVariable] + redef fun variables do return _variables.as(not null) redef fun accept_typing(v) do @@ -659,35 +704,76 @@ special AAbsControl redef fun process_control_inside(v) do - var old_scope_ctx = v.scope_ctx - v.scope_ctx = v.scope_ctx.sub(self) + v.scope_ctx.push(self) var old_flow_ctx = v.flow_ctx - # Create the automatic variable - var va = new AutoVariable(n_id.to_symbol, n_id) - _variable = va - v.scope_ctx.add(va) - - # Process collection - v.enter_visit(n_expr) - - if not v.check_conform_expr(n_expr, v.type_collection) then return - var expr_type = n_expr.stype - - # Get iterator - var meth_iterator = v.get_method(expr_type, once "iterator".to_symbol) - var iter_type = meth_iterator.signature_for(expr_type).return_type.as(not null) - var meth_item = v.get_method(iter_type, once ("item".to_symbol)) - var va_stype = meth_item.signature_for(iter_type).return_type.as(not null) - if not n_expr.is_self then va_stype = va_stype.not_for_self - va.stype = va_stype + do_typing(v) # Process inside v.enter_visit_block(n_block) # end == begin of the loop v.flow_ctx = old_flow_ctx - v.scope_ctx = old_scope_ctx + v.scope_ctx.pop + end + + private fun do_typing(v: TypingVisitor) + do + # Create the automatic variables + var vas = new Array[AutoVariable] + for n_id in n_ids do + var va = new AutoVariable(n_id.to_symbol, n_id) + v.scope_ctx.add_variable(va) + vas.add(va) + end + _variables = vas + + # Process reciever + v.enter_visit(n_expr) + if not v.check_expr(n_expr) then return + var expr_type = n_expr.stype + + if expr_type.is_nullable then + v.error(n_expr, "Type error: 'for' on a nullable expression.") + return + end + n_expr.warn_parentheses(v) + + # Get iterate + var iterate_name = once "iterate".to_symbol + if not expr_type.local_class.has_global_property_by_name(iterate_name) then + v.error(n_expr, "Type error: Expected a type with an 'iterate' method. Found {expr_type}.") + return + end + var prop = expr_type.local_class.select_method(iterate_name) + prop.global.check_visibility(v, self, v.mmmodule, n_expr.is_self) + var psig = prop.signature_for(expr_type) + if not n_expr.is_self then psig = psig.not_for_self + if psig.arity != 0 then + v.error(self, "Error: 'iterate' incompatible with 'for': require no arguments.") + return + else if psig.closures.length != 1 then + v.error(self, "Error: 'iterate' incompatible with 'for': require one closure.") + return + end + psig = psig.closures.first.signature + if psig.return_type != null then + v.error(self, "Error: 'iterate' incompatible with 'for': require one procedural closure.") + return + end + if vas.length != psig.arity then + if psig.arity == 1 then + v.error(self, "Error: Expected {psig.arity} variable {psig}, found {vas.length}.") + else + v.error(self, "Error: Expected {psig.arity} variables {psig}, found {vas.length}.") + end + return + end + + # Type the automatic variables + for i in [0..vas.length[ do + vas[i].stype = psig[i] + end end end @@ -697,6 +783,7 @@ redef class AAssertExpr # Process condition v.enter_visit(n_expr) v.check_conform_expr(n_expr, v.type_bool) + n_expr.warn_parentheses(v) # Process optional 'else' part if n_else != null then @@ -765,7 +852,7 @@ redef class AReassignFormExpr return null end var prop = lc.select_method(name) - prop.global.check_visibility(v, self, v.module, false) + prop.global.check_visibility(v, self, v.mmmodule, false) var psig = prop.signature_for(type_lvalue) _assign_method = prop if not v.check_conform_expr(n_value, psig[0].not_for_self) then return null @@ -956,7 +1043,7 @@ redef class AOrElseExpr # Consider the type of the left operand var t = n_expr.stype if not t.is_nullable then - v.warning(n_expr, "Warning: left operant of a 'or else' is not a nullable type.") + v.warning(n_expr, "Warning: left operand of a 'or else' is not a nullable type.") else t = t.as_notnull end @@ -1041,7 +1128,7 @@ end redef class AArrayExpr redef fun after_typing(v) do - var stype = v.check_conform_multiexpr(null, n_exprs) + var stype = v.check_conform_multiexpr(null, n_exprs.n_exprs) if stype != null then do_typing(v, stype) end @@ -1099,7 +1186,7 @@ redef class ASuperExpr assert p isa MMMethod _init_in_superclass = p register_super_init_call(v, p) - if n_args.length > 0 then + if n_args.n_exprs.length > 0 then var signature = get_signature(v, v.self_var.stype.as(not null), p, true) process_signature(v, signature, p.name, compute_raw_arguments) end @@ -1113,7 +1200,7 @@ redef class ASuperExpr var stype: nullable MMType = null for prop in precs do assert prop isa MMMethod - var t = prop.signature_for(v.self_var.stype.as(not null)).return_type.for_module(v.module).adapt_to(v.local_property.signature.recv) + var t = prop.signature_for(v.self_var.stype.as(not null)).return_type.for_module(v.mmmodule).adapt_to(v.local_property.signature.recv) stypes.add(t) if stype == null or stype < t then stype = t @@ -1131,6 +1218,123 @@ redef class ASuperExpr end end +redef class AExternCall + fun target_class_name : nullable Symbol do return null + fun target_method_name : Symbol is abstract + + redef fun after_typing(v) + do + var target_class_name = self.target_class_name + var target_method_name = self.target_method_name + + var target_class : MMLocalClass + var target_method : MMMethod + + # find class + # self.target_class_name can be redef'd by sub-classes + if target_class_name == null then + target_class = v.local_property.local_class + else + if v.local_property.mmmodule.has_global_class_named( target_class_name ) then + var global_class = v.local_property.mmmodule.global_class_named( target_class_name ) + target_class = v.local_property.mmmodule[ global_class ] + else + v.error( self, "Error: class {target_class_name.to_s}, not found." ) + return + end + end + + if target_class.has_global_property_by_name( target_method_name ) then + var global_property = target_class.get_property_by_name( target_method_name ) + + var target_property = target_class[global_property] + + if target_property isa MMMethod then + target_method = target_property + else + v.error( self, "Error: property {target_method_name.to_s} is not a method." ) + return + end + else + v.error( self, "Error: property {target_method_name.to_s} not found in target class." ) + return + end + + var explicit_import = new MMExplicitImport( target_class, target_method ) + v.local_property.as(MMSrcMethod).explicit_imports.add( explicit_import ) + end +end + +redef class ALocalPropExternCall + redef fun target_class_name do return null + redef fun target_method_name do return n_methid.name.as(not null) +end + +redef class ASuperExternCall + redef fun after_typing(v) + do + var precs: Array[MMLocalProperty] = v.local_property.prhe.direct_greaters + if not precs.is_empty then + v.local_property.need_super = true + else + v.error(self, "Error: No super method to call for {v.local_property}.") + return + end + end +end + +redef class AFullPropExternCall + redef fun target_class_name do return n_classid.to_symbol + redef fun target_method_name do return n_methid.name.as(not null) +end + +redef class AInitPropExternCall + redef fun target_class_name do return n_classid.to_symbol + redef fun target_method_name do return "init".to_symbol +end + +redef class ACastExternCall + fun from_type : MMType is abstract + fun to_type : MMType is abstract + + redef fun after_typing(v) + do + if from_type == to_type + then + v.error( self, "Attepting to cast from and to the same type." ) + end + + var cast = new MMImportedCast( from_type, to_type ) + var m = v.local_property + assert m isa MMMethod + m.explicit_casts.add( cast ) + end +end + +redef class ACastAsExternCall + redef fun from_type do return n_from_type.stype + redef fun to_type do return n_to_type.stype +end + +redef class AAsNullableExternCall + redef fun from_type do return n_type.stype + redef fun to_type do return n_type.stype.as_nullable +end + +redef class AAsNotNullableExternCall + redef fun from_type + do + var t = n_type.stype + if t.is_nullable + then + return t + else + return t.as_nullable + end + end + redef fun to_type do return n_type.stype.as_notnull +end + redef class AAttrFormExpr redef fun prop do return _prop.as(not null) var _prop: nullable MMAttribute @@ -1154,8 +1358,8 @@ redef class AAttrFormExpr return end var prop = lc.select_attribute(name) - if v.module.visibility_for(prop.global.local_class.module) < 3 then - v.error(self, "Error: Attribute {name} from {prop.global.local_class.module} is invisible in {v.module}") + if v.mmmodule.visibility_for(prop.global.local_class.mmmodule) < 3 then + v.error(self, "Error: Attribute {name} from {prop.global.local_class.mmmodule} is invisible in {v.mmmodule}") end _prop = prop var at = prop.signature_for(type_recv).return_type @@ -1244,7 +1448,7 @@ redef class AAbsAbsSendExpr var raw_arity: Int if raw_args == null then raw_arity = 0 else raw_arity = raw_args.length if par_arity > raw_arity or (par_arity != raw_arity and par_vararg == -1) then - v.error(self, "Error: arity missmatch; prototype is '{name}{psig}'.") + v.error(self, "Error: arity mismatch; prototype is '{name}{psig}'.") return false end var arg_idx = 0 @@ -1297,9 +1501,9 @@ redef class AAbsAbsSendExpr var csi = psig.closure_named(cni) if csi != null then var esc = new EscapableClosure(cdi, csi, break_list) - v.escapable_ctx.push(esc, n_label) + v.scope_ctx.push_escapable(esc, n_label) cdi.accept_typing2(v, esc) - v.escapable_ctx.pop + v.scope_ctx.pop else if cs.length == 1 then v.error(cdi.n_id, "Error: no closure named '!{cni}' in {name}; only closure is !{cs.first.name}.") else @@ -1378,7 +1582,7 @@ redef class AAbsSendExpr # Get the signature for a local property and a receiver private fun get_signature(v: TypingVisitor, type_recv: MMType, prop: MMMethod, recv_is_self: Bool): MMSignature do - prop.global.check_visibility(v, self, v.module, recv_is_self) + prop.global.check_visibility(v, self, v.mmmodule, recv_is_self) var psig = prop.signature_for(type_recv) if not recv_is_self then psig = psig.not_for_self return psig @@ -1400,7 +1604,7 @@ redef class ASuperInitCall if parent != v.top_block and self != v.top_block then v.error(self, "Error: Constructor invocation {property} must not be in nested block.") end - var cla = v.module[property.global.intro.local_class.global] + var cla = v.mmmodule[property.global.intro.local_class.global] var prev_class: nullable MMLocalClass = null var esic = v.explicit_super_init_calls.as(not null) if not esic.is_empty then @@ -1440,6 +1644,9 @@ redef class ANewExpr v.error(self, "Error: try to instantiate abstract class {t.local_class}.") return end + if t.is_nullable then + v.error(self, "Type error: cannot instantiate the nullable type {t}.") + end var name: Symbol if n_id == null then name = once "init".to_symbol @@ -1551,7 +1758,7 @@ redef class AEqExpr if n_expr.stype isa MMTypeNone then if n_expr2.stype isa MMTypeNone then - v.warning(self, "Warning: comparaison between 2 null values.") + v.warning(self, "Warning: comparaison between two null values.") else try_to_isa(v, n_expr2) end @@ -1582,7 +1789,7 @@ redef class ANeExpr if n_expr.stype isa MMTypeNone then if n_expr2.stype isa MMTypeNone then - v.warning(self, "Warning: comparaison between 2 null values.") + v.warning(self, "Warning: comparaison between two null values.") else try_to_isa(v, n_expr2) end @@ -1606,12 +1813,18 @@ end redef class ALeExpr redef fun name do return once "<=".to_symbol end +redef class ALlExpr + redef fun name do return once "<<".to_symbol +end redef class AGtExpr redef fun name do return once ">".to_symbol end redef class AGeExpr redef fun name do return once ">=".to_symbol end +redef class AGgExpr + redef fun name do return once ">>".to_symbol +end redef class APlusExpr redef fun name do return once "+".to_symbol end @@ -1648,7 +1861,7 @@ redef class ACallFormExpr n = new AClosureCallExpr.init_aclosurecallexpr(n_id, n_args, n_closure_defs) n._variable = variable else - if not n_args.is_empty then + if not n_args.n_exprs.is_empty or n_args isa AParExprs then v.error(self, "Error: {name} is variable, not a function.") return end @@ -1800,17 +2013,16 @@ redef class AClosureDef _closure = esc.closure - var old_scope_ctx = v.scope_ctx + v.scope_ctx.push(self) var old_flow_ctx = v.flow_ctx var old_base_flow_ctx = v.base_flow_ctx v.base_flow_ctx = v.flow_ctx - v.scope_ctx = v.scope_ctx.sub(self) variables = new Array[AutoVariable] for i in [0..n_ids.length[ do var va = new AutoVariable(n_ids[i].to_symbol, n_ids[i]) variables.add(va) va.stype = sig[i] - v.scope_ctx.add(va) + v.scope_ctx.add_variable(va) end _accept_typing2 = true @@ -1823,14 +2035,14 @@ redef class AClosureDef v.error(self, "Control error: Reached end of break block (a 'break' with a value was expected).") end end - v.scope_ctx = old_scope_ctx v.flow_ctx = old_flow_ctx v.base_flow_ctx = old_base_flow_ctx + v.scope_ctx.pop end end -class ATypeCheckExpr -special AExpr +abstract class ATypeCheckExpr + super AExpr private fun check_expr_cast(v: TypingVisitor, n_expr: AExpr, n_type: AType) do if not v.check_expr(n_expr) then return @@ -1861,7 +2073,7 @@ special AExpr end redef class AIsaExpr -special ATypeCheckExpr + super ATypeCheckExpr redef fun after_typing(v) do check_expr_cast(v, n_expr, n_type) @@ -1876,7 +2088,7 @@ special ATypeCheckExpr end redef class AAsCastExpr -special ATypeCheckExpr + super ATypeCheckExpr redef fun after_typing(v) do check_expr_cast(v, n_expr, n_type) @@ -1909,7 +2121,13 @@ redef class AProxyExpr _is_typed = true if n_expr.is_statement then return _stype = n_expr.stype + _if_true_flow_ctx = n_expr._if_true_flow_ctx + _if_false_flow_ctx = n_expr._if_false_flow_ctx end + + redef fun is_self do return n_expr.is_self + + redef fun its_variable do return n_expr.its_variable end redef class AOnceExpr @@ -1926,3 +2144,15 @@ redef class AOnceExpr end end +redef class ADebugTypeExpr + redef fun after_typing(v) + do + if not v.check_expr(n_expr) then return + if not n_type.is_typed then return + var etype = n_expr.stype + var ttype = n_type.stype + if etype != ttype then + v.warning(self, "Warning: Expression is a {etype}, expected {ttype}.") + end + end +end