diff --git a/sources/zweic/Analyzer.scala b/sources/zweic/Analyzer.scala index 86deb1e..89c0427 100755 --- a/sources/zweic/Analyzer.scala +++ b/sources/zweic/Analyzer.scala @@ -88,12 +88,12 @@ case None => val mt = analyzeType(typ); checkSubtype(tree.pos, "Incompatible types", analyzeExpr(varScope, expr), mt); - varScope + name.name -> VarSymbol(tree.pos, name.name, mt); + val ms = VarSymbol(tree.pos, name.name, mt); + ident.sym = ms; + varScope + name.name -> ms; } - // ... � compl�ter ... case Set(ident, expr) => - //TODO: this method is copied from lecture script, check if it's correct varScope.get(ident.name) match { case Some(v) => ident.sym = v; @@ -102,6 +102,18 @@ Report.error(tree.pos, "Unknown variable " + ident.name); } varScope + + case Do(expr) => + analyzeExpr(varScope, expr); + varScope + + case PrintInt(expr) => + checkIntType(tree.pos, analyzeExpr(varScope, expr)); + varScope + + case PrintChar(expr) => + checkIntType(tree.pos, analyzeExpr(varScope, expr)); + varScope } // Analyze a type @@ -123,22 +135,70 @@ // Analyze an expression private def analyzeExpr(varScope: VarScope, tree: Expr): Type = tree match { - // ... � compl�ter ... - case NullLit() => - INullType + // ... � compl�ter ... + case Ident(name) => + varScope.get(name.name) match { + case Some(v) => + name.sym = v; + v.vartype + case None => + Report.error(tree.pos, "Unknown variable " + name); + IBadType + } - case IntLit(_) => - IIntType - // ... � compl�ter ... - case Ident(name) => - varScope.get(name.name) match { - case Some(v) => - name.sym = v; - v.vartype - case None => - Report.error(tree.pos, "Unknown variable " + name); - IBadType - } + case Select(expr, name) => + val ct = analyzeExpr(varScope, expr); + ct.c.lookupField(name.name) match { + case Some(v) => + name.sym = v; + v.fieldtype + case None => + Report.error(tree.pos, "Unknown class variable " + name + " in " + ct); + IBadType + } + + case Call(expr, name, args) => + val ct = analyzeExpr(varScope, expr); //XXX: this implies checking if class exists + ct.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); + IBadType + } + if ( !args.map(x => analyzeExpr(varScope, x)).zip(v.paramtypes).forall(Tuple(a,b) => checkSubtype(tree.pos, "Incompatible types", a, b)) ) + IBadType + name.sym = v; + v.restype + case None => + Report.error(tree.pos, "Unknown class method " + name + " in " + ct); + IBadType + } + + case New(name, args) => + 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); + IBadType + } + if ( args.map(x => analyzeExpr(varScope, x)).zip(v.allFields).forall(Tuple(a,b) => checkSubtype(tree.pos, "Incompatible types", a, b)) ) + IBadType + name.sym = v; + IClassType(v) + case None => + Report.error(tree.pos, "Class " + name + " is unknown"); + IBadType + } + + case NullLit() => + INullType + + case IntLit(_) => + IIntType + + case Unop(op, expr) => + checkIntType(tree.pos, analyzeExpr(varScope, expr)) + IIntType case Binop(op, left, right) => val t1 = analyzeExpr(varScope, left); @@ -151,6 +211,19 @@ checkIntType(right.pos, t2); } IIntType + + case ReadInt => + IIntType + + case ReadChar => + IIntType + + case If(cond, stata, statb) => + checkIntType(analyzeExpr(varScope, cond)) + analyzeExpr(varScope, stata).lub(analyzeExpr(varScope, statb)) + + case Block(stats, expr) => + analyzeExpr(stats.foldLeft(varScope)(analyzeStat), expr) } /**