/* zweic -- a compiler for Zwei * * Stephane Micheloud & LAMP * * $Id$ */ package zweic; /** * This class implements the semantic analyzer of zweic. */ class Analyzer { import Operators._; import scala.collection.immutable.{Map, ListMap}; // Global scope of classes type ClassScope = Map[String, ClassSymbol]; var classScope: ClassScope = ListMap.Empty; // For local scopes of variables type VarScope = Map[String, VarSymbol]; val emptyVarScope: VarScope = ListMap.Empty; // Analyze a program def analyzeProgram(tree: Program): Unit = tree match { case Program(classes, main) => classes.foreach(analyzeClass); analyzeExpr(emptyVarScope, main); () } // Analyze a class private def analyzeClass(tree: ClassDef): Unit = tree match { case ClassDef(name, extend, members) => } // ... à compléter ... // Analyze a member private def analyzeMember(ownerClass: ClassSymbol, tree: Member): Unit = tree.match { case FieldDecl(Formal(name, typ)) => // TODO check that field does not yet exist! ownerClass.enterField(FieldSymbol(tree.pos, name, analyzeType(typ))) case MethodDef(name, args, rtype, expr) => lookupMethod(name) match { case Some ownerClass.enterMethod } } // ... à compléter ... // Analyze a statement private def analyzeStat(varScope: VarScope, tree: Stat): VarScope = tree match { case While(cond, stats) => checkIntType(cond.pos, analyzeExpr(varScope, cond)); stats.foldLeft(varScope)(analyzeStat); varScope // ... à compléter ... } // Analyze a type private def analyzeType(tree: TypeTree): Type = tree match { case IntType() => IIntType case NullType() => INullType case ClassType(name) => classScope.get(name.name) match { case Some(c) => name.sym = c; IClassType(c) case None => Report.error(tree.pos, "Class " + name + " is unknown"); IBadType } } // Analyze an expression private def analyzeExpr(varScope: VarScope, tree: Expr): Type = tree match { // ... à compléter ... case NullLit() => INullType case IntLit(_) => IIntType // ... à compléter ... } /** * Generates an error if the expected type is not equal * to the found type. */ private def checkSametype(pos: Int, found: Type, expected: Type): Unit = if (!found.isSametype(expected)) error(pos, "Type mismatch", found, expected); /** * Generates an error if the found type is not equal to IIntType. */ private def checkIntType(pos: Int, found: Type): Unit = checkSametype(pos, found, IIntType); /** * Generates an error if the expected type is not a super type * of the found type. */ private def checkSubtype(pos: Int, header: String, found: Type, expected: Type) = if (!found.isSubtype(expected)) error(pos, header, found, expected); /** * Generates an error message for unexpected types. */ private def error(pos: Int, header: String, found: Type, expected: Type) = Report.error(pos, header + "\nexpected type: " + expected + "\n" + "actual type : " + found); }