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
# 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
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
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
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
end
# An abstract control structure with feature escapable block
-class AAbsControl
+abstract class AAbsControl
super AExpr
# The corresponding escapable block
readable var _escapable: nullable EscapableBlock
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)
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)
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
# 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
# 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
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
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
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
if c == prev_class then
prev_class = null
else if c == cla then
- if prev_class != null then
- v.error(self, "Error: Constructor of {c} must be invoked before constructor of {prev_class}")
- end
esic.add(property)
break
end
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
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
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
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
end
end
-class ATypeCheckExpr
+abstract class ATypeCheckExpr
super AExpr
private fun check_expr_cast(v: TypingVisitor, n_expr: AExpr, n_type: AType)
do
if etype == ttype then
v.warning(self, "Warning: Expression is already a {ttype}.")
else if etype < ttype then
- v.warning(self, "Warning: Expression is already a {ttype} since it is a {etype}.")
+ if not ttype isa MMTypeFormal then
+ # the old metamodel is not that great with formal types
+ v.warning(self, "Warning: Expression is already a {ttype} since it is a {etype}.")
+ end
else if etype isa MMTypeNone then
# ttype is not nullable because of prevous test
v.warning(self, "Warning: Expression is null therefore cannot be a {ttype}.")
_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
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