X-Git-Url: http://nitlanguage.org diff --git a/src/syntax/typing.nit b/src/syntax/typing.nit index 77f9779..18fc645 100644 --- a/src/syntax/typing.nit +++ b/src/syntax/typing.nit @@ -40,7 +40,7 @@ private class TypingVisitor super AbsSyntaxVisitor redef fun visit(n) do - if n != null then n.accept_typing(self) + n.accept_typing(self) end # Current knowledge about scoped things (variable, labels, etc.) @@ -289,6 +289,15 @@ redef class AExternInitPropdef 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 @@ -403,6 +412,15 @@ redef class AParExpr 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 var _variable: nullable VarVariable redef fun variable do return _variable.as(not null) @@ -423,7 +441,13 @@ redef class AVardeclExpr end else if ne != null then if not v.check_expr(ne) then return - va.stype = ne.stype + var st = ne.stype + if st isa MMTypeNone then + va.stype = v.type_object.as_nullable + v.flow_ctx = v.flow_ctx.sub_with(self, va, st) + else + va.stype = st + end else va.stype = v.type_object.as_nullable end @@ -537,7 +561,7 @@ redef class AAbortExpr 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 @@ -970,6 +994,36 @@ redef class AOrExpr end end +redef class AImpliesExpr + redef fun accept_typing(v) + do + var old_flow_ctx = v.flow_ctx + var stype = v.type_bool + _stype = stype + + # Process left operand + v.enter_visit(n_expr) + + # Prepare right operand context + v.use_if_true_flow_ctx(n_expr) + + # Process right operand + v.enter_visit(n_expr2) + if n_expr2.if_false_flow_ctx != null then + _if_false_flow_ctx = n_expr2.if_false_flow_ctx + else + _if_false_flow_ctx = v.flow_ctx + end + + v.flow_ctx = old_flow_ctx + + v.check_conform_expr(n_expr, stype) + v.check_conform_expr(n_expr2, stype) + _stype = stype + _is_typed = true + end +end + redef class AAndExpr redef fun accept_typing(v) do @@ -1538,7 +1592,7 @@ redef class AAbsSendExpr var lc = type_recv.local_class var prop: nullable MMMethod = null if lc.has_global_property_by_name(name) then prop = lc.select_method(name) - if prop == null and v.local_property.global.is_init then + if prop == null then var props = lc.super_methods_named(name) if props.length > 1 then v.error(self, "Error: Ambigous method name '{name}' for {props.join(", ")}. Use explicit designation.") @@ -1604,9 +1658,6 @@ redef class ASuperInitCall 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 @@ -1626,6 +1677,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 @@ -1640,6 +1694,10 @@ redef class ANewExpr v.error(self, "Error: {prop} is not a constructor.") return end + if not prop.global.is_init_for(t.local_class) then + v.error(self, "Error: {prop} is not a constructor in {t.local_class}.") + return + end _stype = t _is_typed = true end @@ -1840,7 +1898,7 @@ redef class ACallFormExpr n = new AClosureCallExpr.init_aclosurecallexpr(n_id, n_args, n_closure_defs) n._variable = variable else - if not n_args.n_exprs.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 @@ -2020,7 +2078,7 @@ redef class AClosureDef end end -class ATypeCheckExpr +abstract class ATypeCheckExpr super AExpr private fun check_expr_cast(v: TypingVisitor, n_expr: AExpr, n_type: AType) do @@ -2031,7 +2089,10 @@ class ATypeCheckExpr 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.has_formal and not etype.has_formal 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}.") @@ -2123,3 +2184,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