Newer
Older
zweic / sources / zweic / Symbol.scala
/*  zweic -- a compiler for zwei
 *
 *  Stephane Micheloud & LAMP
 *
 *  $Id$
 */

package zweic;

import scala.collection.immutable.{Map, ListMap};

/**
 * This class provides a representation for symbol table entries.
 */
abstract class Symbol {

  def pos: Int;

  def name: String;

  /**
   * Offset of the symbol. For variables, that's the offset
   * relative to the frame pointer; for functions that's the PC of
   * the first instruction.
   */
  var offset: Int = -1;

}

case class ClassSymbol(pos: Int, name: String, superclass: Option[ClassSymbol])
     extends Symbol
{
  private var fields: Map[String,FieldSymbol] =
    superclass match {
      case None => ListMap.Empty[String,FieldSymbol]
      case Some(s) => s.fields
    }

  private var methods: Map[String,MethodSymbol] =
    superclass match {
      case None => ListMap.Empty[String,MethodSymbol]
      case Some(s) => s.methods
    }

  def superclasses: List[ClassSymbol] =
    this :: (superclass match {
      case None => Nil
      case Some(c) => c.superclasses
    });

  def isSubclassOf(that: ClassSymbol): Boolean =
    superclasses.contains(that);

  def enterField(f: FieldSymbol): Unit = {
    f.offset = fields.size * 4;
    fields = fields + f.name -> f;
  }

  def lookupField(name: String): Option[FieldSymbol] =
    fields.get(name);

  def enterNewMethod(m: MethodSymbol): Unit = {
    m.offset = methods.size * 4;
    methods = methods + m.name -> m;
  }

  def enterMethod(m: MethodSymbol): Unit = {
    m.offset = methods(m.name).offset;
    methods = methods + m.name -> m;
  }

  def lookupMethod(name: String): Option[MethodSymbol] =
    methods.get(name);

  def allFields: List[FieldSymbol] =
    fields.values.toList;

  def allMethods: List[MethodSymbol] =
    methods.values.toList;
    
  override def toString() = "class " + name;
}

case class FieldSymbol(pos: Int, name: String, fieldtype: Type)
  extends Symbol
{
  override def toString() = "field " + name + ": " + fieldtype;
}

case class MethodSymbol(pos: Int, name: String, paramtypes: List[Type], restype: Type)
  extends Symbol
{
  var address: Int = _;
  override def toString() = "method " + name +
    paramtypes.mkString("(", ",", ")") + ": " + restype;
}

case class VarSymbol(pos: Int, name: String, vartype: Type)
  extends Symbol
{
  override def toString() = "variable " + name + ": " + vartype;
}