diff --git a/sources/zweic/Analyzer.scala b/sources/zweic/Analyzer.scala index ead1998..2d97877 100755 --- a/sources/zweic/Analyzer.scala +++ b/sources/zweic/Analyzer.scala @@ -74,16 +74,11 @@ myVarScope = myVarScope + "this" -> VarSymbol(ownerClass.pos, "this", IClassType(ownerClass)); - // TODO: FieldSymbols can't be VarSymbols !!! - /*for ( val x <- ownerClass.allFields ) { - myVarScope = myVarScope + x.name -> x.asInstanceOf[VarSymbol]; - }*/ - val paramtypes = for ( val f <- args ) yield { //TODO: check that there isn't already a class field with the same name f.name.sym = VarSymbol(f.pos, f.name.name, analyzeType(f.typ)); myVarScope = myVarScope + f.name.name -> f.name.sym.asInstanceOf[VarSymbol]; - analyzeType(f.typ); + analyzeType(f.typ) } val rt = analyzeType(rtype); @@ -91,9 +86,17 @@ ownerClass.lookupMethod(name.name) match { case Some(m) => - ownerClass.enterMethod(name.sym.asInstanceOf[MethodSymbol]); + //TODO: check that returntype is subtype of old returntype and args are subtypes of old args + checkSubtype(tree.pos, "redefinition of class method '"+name+"' has incompatible returntype", m.restype, rt); + + if ( !m.paramtypes.zip(paramtypes).forall(x:Pair[Type,Type] => x._1.isSubtype(x._2)) ) { + Report.error(tree.pos, "incompatible argument types for class method redefinition: \nrequired:" + paramtypes.foldLeft(" ")((a,b)=>a + b) + + "\nfound:" + m.paramtypes.foldLeft(" ")((a,b)=>a + b) ); + } + + ownerClass.enterMethod(name.sym.asInstanceOf[MethodSymbol]); case None => - ownerClass.enterNewMethod(name.sym.asInstanceOf[MethodSymbol]); + ownerClass.enterNewMethod(name.sym.asInstanceOf[MethodSymbol]); } checkSubtype(tree.pos, "returntype mismatch", analyzeExpr(myVarScope, expr), rt); @@ -182,7 +185,7 @@ name.sym = v; v.fieldtype case None => - Report.error(tree.pos, "unknown class variable '" + name + "' in " + ct); + Report.error(tree.pos, "unknown class variable '" + name + "' in " + c); IBadType; } case _ => @@ -198,7 +201,7 @@ c.lookupMethod(name.name) match { case Some(v) => if (args.length != v.paramtypes.length) { - Report.error(tree.pos, "wrong number of arguments for class method '" + name + "' in " + ct); + Report.error(tree.pos, "wrong number of arguments for method '" + name + "' of " + c); IBadType } val argtypes = args.map(x => analyzeExpr(varScope, x)); @@ -211,7 +214,7 @@ v.restype case None => - Report.error(tree.pos, "unknown class method '" + name + "' in " + ct); + Report.error(tree.pos, "unknown method '" + name + "' in " + c); IBadType } case _ => @@ -220,11 +223,10 @@ } case New(name, args) => - val ct = classScope.get(name.name); - ct match { + classScope.get(name.name) match { case Some(v) => if (args.length != v.allFields.length) { - Report.error(tree.pos, "wrong number of arguments for class constructor in " + ct); + Report.error(tree.pos, "wrong number of arguments for constructor of " + v); IBadType } val argtypes = args.map(x => analyzeExpr(varScope, x)); @@ -256,8 +258,13 @@ val t1 = analyzeExpr(varScope, left); val t2 = analyzeExpr(varScope, right); if ( op == EQ || op == NE ) { - if ( !(t1.isSubtype(t2) || t2.isSubtype(t1)) ) - Report.error(tree.pos, "incompatible types: '" + t1 + "' <=> '" + t2 + "'"); + t1.lub(t2) match { + case None => + Report.error(tree.pos, "incompatible types: '" + t1 + "' <=> '" + t2 + "'"); + case _ => () + } + //if ( !(t1.isSubtype(t2) || t2.isSubtype(t1)) ) + // Report.error(tree.pos, "incompatible types: '" + t1 + "' <=> '" + t2 + "'"); } else { checkIntType(left.pos, t1); checkIntType(right.pos, t2); @@ -272,9 +279,13 @@ case If(cond, stata, statb) => checkIntType(cond.pos, analyzeExpr(varScope, cond)); - analyzeExpr(varScope, stata).lub(analyzeExpr(varScope, statb)) match { + val ta = analyzeExpr(varScope, stata); + val tb = analyzeExpr(varScope, statb); + ta.lub(tb) match { case Some(v) => v - case None => IBadType + case None => + Report.error(tree.pos, "'if/else' block common has incompatible return types: '" + ta + "' <=> '" + tb + "'"); + IBadType } case Block(stats, expr) => diff --git a/sources/zweic/Parser.scala b/sources/zweic/Parser.scala index 8ea4e18..6ac090e 100755 --- a/sources/zweic/Parser.scala +++ b/sources/zweic/Parser.scala @@ -375,10 +375,21 @@ private def _string(str: String): New = { val pos = start; - if ( str.length() > 1 ) { + /*if ( str.length() > 1 ) { return New(Name("Cons"), IntLit(str.charAt(0).asInstanceOf[Int]).setPos(pos)::_string(str.substring(1))::Nil).setPos(pos); } else { return New(Name("Cons"), New(Name("Nil"), Nil).setPos(pos)::Nil).setPos(pos); + }*/ + if ( str.length() > 0 ) { + val il = IntLit(str.charAt(0).asInstanceOf[Int]); + il.setPos(pos); + val n = New(Name("Cons"), il::_string(str.substring(1))::Nil); + n.setPos(pos); + return n; + } else { + val nl = New(Name("Nil"), Nil); + nl.setPos(pos); + return nl; } } diff --git a/sources/zweic/Type.scala b/sources/zweic/Type.scala index e008145..29f45c2 100755 --- a/sources/zweic/Type.scala +++ b/sources/zweic/Type.scala @@ -38,6 +38,9 @@ def lub(that: Type): Option[Type] = Pair(this, that) match { case Pair(IIntType, IIntType) => Some(IIntType) + case Pair(INullType, INullType) => Some(INullType) + case Pair(IIntType, INullType) => Some(IIntType) + case Pair(INullType, IIntType) => Some(IIntType) case Pair(c@IClassType(x), INullType) => Some(c) case Pair(INullType, c@IClassType(x)) => Some(c) case Pair(IClassType(c1), IClassType(c2)) => @@ -45,7 +48,7 @@ case t :: ts => Some(IClassType(t)) case List() => None } - case x => None + case _ => None } }