| | /* 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 = |
---|
| | // ... à compléter ... |
---|
| | |
---|
| | // Analyze a member |
---|
| | private def analyzeMember(ownerClass: ClassSymbol, tree: Member): Unit = |
---|
| | // ... à 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); |
---|
| | |
---|
| | } |
---|
| | |
---|
| | |