Newer
Older
zweic / sources / zweic / Analyzer.scala
@ajaggi ajaggi on 20 Dec 2005 3 KB Sync with sun.
/*  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);

}