Skip to content
Snippets Groups Projects
Commit ed632f4d authored by Philippe Suter's avatar Philippe Suter
Browse files

still in the...

still in the "breaking-before-I'll-fix-it-all-again-and-like-will-be-wonderful-with-rainbows-and-unicorns" phase.


parent 629343e2
Branches
Tags
No related merge requests found
...@@ -19,7 +19,7 @@ trait CodeExtraction extends Extractors { ...@@ -19,7 +19,7 @@ trait CodeExtraction extends Extractors {
import scala.collection.mutable.HashMap import scala.collection.mutable.HashMap
// register where the symbols where extracted from // register where the symbols where extracted from
val symbolDefMap = new HashMap[purescala.Symbols.Symbol,Tree] // val symbolDefMap = new HashMap[purescala.Symbols.Symbol,Tree]
def s2ps(tree: Tree): Expr = toPureScala(unit)(tree) match { def s2ps(tree: Tree): Expr = toPureScala(unit)(tree) match {
case Some(ex) => ex case Some(ex) => ex
...@@ -28,7 +28,7 @@ trait CodeExtraction extends Extractors { ...@@ -28,7 +28,7 @@ trait CodeExtraction extends Extractors {
/** Populates the symbolDefMap with object and class symbols, and returns /** Populates the symbolDefMap with object and class symbols, and returns
* the symbol corresponding to the expected single top-level object. */ * the symbol corresponding to the expected single top-level object. */
def extractClassSymbols: purescala.Symbols.ObjectSymbol = { def extractClassSymbols: ObjectDef = {
val top = unit.body match { val top = unit.body match {
case p @ PackageDef(name, lst) if lst.size == 0 => { case p @ PackageDef(name, lst) if lst.size == 0 => {
unit.error(p.pos, "No top-level definition found.") unit.error(p.pos, "No top-level definition found.")
...@@ -54,13 +54,13 @@ trait CodeExtraction extends Extractors { ...@@ -54,13 +54,13 @@ trait CodeExtraction extends Extractors {
top.get top.get
} }
def extractObjectSym(name: Identifier, tmpl: Template): purescala.Symbols.ObjectSymbol = { def extractObjectSym(name: Identifier, tmpl: Template): ObjectDef = {
// we assume that the template actually corresponds to an object // we assume that the template actually corresponds to an object
// definition. Typically it should have been obtained from the proper // definition. Typically it should have been obtained from the proper
// extractor (ExObjectDef) // extractor (ExObjectDef)
var classSyms: List[purescala.Symbols.ClassSymbol] = Nil var classDefs: List[ClassTypeDef] = Nil
var objectSyms: List[purescala.Symbols.ObjectSymbol] = Nil var objectDefs: List[purescala.Symbols.ObjectSymbol] = Nil
tmpl.body.foreach(tree => tree match { tmpl.body.foreach(tree => tree match {
case ExObjectDef(o2, t2) => { objectSyms = extractObjectSym(o2, t2) :: objectSyms } case ExObjectDef(o2, t2) => { objectSyms = extractObjectSym(o2, t2) :: objectSyms }
...@@ -68,10 +68,10 @@ trait CodeExtraction extends Extractors { ...@@ -68,10 +68,10 @@ trait CodeExtraction extends Extractors {
case _ => ; case _ => ;
}) })
val theSym = new purescala.Symbols.ObjectSymbol(name, classSyms.reverse, objectSyms.reverse) // val theSym = new purescala.Symbols.ObjectSymbol(name, classSyms.reverse, objectSyms.reverse)
// we register the tree associated to the symbol to be able to fill in // we register the tree associated to the symbol to be able to fill in
// the rest later // the rest later
symbolDefMap(theSym) = tmpl // symbolDefMap(theSym) = tmpl
theSym theSym
} }
......
...@@ -39,20 +39,25 @@ object Definitions { ...@@ -39,20 +39,25 @@ object Definitions {
} }
/** A VarDecl declares a new identifier to be of a certain type. */ /** A VarDecl declares a new identifier to be of a certain type. */
final case class VarDecl(id: Identifier, tpe: TypeTree) { case class VarDecl(id: Identifier, tpe: TypeTree) extends Typed {
val uniqueID: Int = UniqueID(id.toString) val uniqueID: Int = UniqueID(id.toString)
override val toString: String = id + uniqueID override val toString: String = id + uniqueID
override def equals(other: Any) = other match { override def equals(other: Any) = other match {
case v: VarDecl => this.equals(v) && uniqueID == v.uniqueID case v: VarDecl => this.equals(v) && uniqueID == v.uniqueID
case _ => false case _ => false
} }
override def getType = tpe
override def setType(tt: TypeTree) = scala.Predef.error("Can't set type of VarDecl.")
} }
type VarDecls = Seq[VarDecl] type VarDecls = Seq[VarDecl]
/** A wrapper for a program. For now a program is simply a single object. The /** A wrapper for a program. For now a program is simply a single object. The
* name is meaningless and we just use the package name. */ * name is meaningless and we just use the package name as id. */
final case class Program(id: Identifier, mainObject: ObjectDef) extends Definition { case class Program(id: Identifier, mainObject: ObjectDef) extends Definition {
override val parentScope = None override val parentScope = None
override def lookupObject(id: Identifier) = { override def lookupObject(id: Identifier) = {
......
...@@ -3,99 +3,101 @@ package funcheck.purescala ...@@ -3,99 +3,101 @@ package funcheck.purescala
import Common._ import Common._
import TypeTrees._ import TypeTrees._
object Symbols { /* dummy */ }
/** There's a need for symbols, as we have purely functional trees with /** There's a need for symbols, as we have purely functional trees with
* potential recursive calls, and we want references to be resolved once and * potential recursive calls, and we want references to be resolved once and
* for all. */ * for all. */
object Symbols { // object Symbols {
trait Symbolic { // trait Symbolic {
self => // self =>
//
private var __s: Option[Symbol] = None // private var __s: Option[Symbol] = None
//
def symbol: Symbol = __s.getOrElse(throw new Exception("Undefined symbol.")) // def symbol: Symbol = __s.getOrElse(throw new Exception("Undefined symbol."))
//
def setSymbol(s: Symbol): self.type = __s match { // def setSymbol(s: Symbol): self.type = __s match {
case Some(_) => throw new Exception("Symbol already set.") // case Some(_) => throw new Exception("Symbol already set.")
case None => { __s = Some(s); this } // case None => { __s = Some(s); this }
} // }
} // }
//
sealed abstract class Symbol { // sealed abstract class Symbol {
val id: Identifier // val id: Identifier
} // }
//
class VariableSymbol(val id: Identifier, val tpe: TypeTree) extends Typed { // class VariableSymbol(val id: Identifier, val tpe: TypeTree) extends Typed {
def getType = tpe // def getType = tpe
} // }
//
// The object and class members have to be known at construction time. The // // The object and class members have to be known at construction time. The
// typed members can be added anytime. // // typed members can be added anytime.
class ObjectSymbol( // class ObjectSymbol(
val id: Identifier, // val id: Identifier,
val classes: Seq[ClassSymbol], // val classes: Seq[ClassSymbol],
val objects: Seq[ObjectSymbol]) extends Symbol { // val objects: Seq[ObjectSymbol]) extends Symbol {
//
private var _fields: List[VariableSymbol] = Nil // private var _fields: List[VariableSymbol] = Nil
private var _functions: List[FunctionSymbol] = Nil // private var _functions: List[FunctionSymbol] = Nil
//
def fields: Seq[VariableSymbol] = _fields // def fields: Seq[VariableSymbol] = _fields
def functions: Seq[FunctionSymbol] = _functions // def functions: Seq[FunctionSymbol] = _functions
//
def registerField(f: VariableSymbol): ObjectSymbol = { // def registerField(f: VariableSymbol): ObjectSymbol = {
_fields = _fields ::: List(f) // _fields = _fields ::: List(f)
this // this
} // }
//
def registerFunction(f: FunctionSymbol): ObjectSymbol = { // def registerFunction(f: FunctionSymbol): ObjectSymbol = {
_functions = _functions ::: List(f) // _functions = _functions ::: List(f)
this // this
} // }
//
override def toString: String = withInc(0) // override def toString: String = withInc(0)
//
private def withInc(inc: Int): String = { // private def withInc(inc: Int): String = {
val ii: String = " " * inc // val ii: String = " " * inc
ii + "[object: " + id + "\n" + // ii + "[object: " + id + "\n" +
(if(!fields.isEmpty) { // (if(!fields.isEmpty) {
ii + " fields: " + fields.map(_.toString).mkString("{ ", ", ", " }") + "\n" // ii + " fields: " + fields.map(_.toString).mkString("{ ", ", ", " }") + "\n"
} else { "" }) + // } else { "" }) +
(if(!functions.isEmpty) { // (if(!functions.isEmpty) {
ii + " functions: " + functions.map(_.toString).mkString("{ ", ", ", " }") + "\n" // ii + " functions: " + functions.map(_.toString).mkString("{ ", ", ", " }") + "\n"
} else { "" }) + // } else { "" }) +
(if(!classes.isEmpty) { // (if(!classes.isEmpty) {
ii + " classes: " + classes.map(_.toString).mkString("{ ", ", ", " }") + "\n" // ii + " classes: " + classes.map(_.toString).mkString("{ ", ", ", " }") + "\n"
} else { "" }) + // } else { "" }) +
(if(!objects.isEmpty) { // (if(!objects.isEmpty) {
ii + " objects: " + objects.map(_.withInc(inc+1)).mkString("{\n", ",\n", "\n" + ii + " }") + "\n" // ii + " objects: " + objects.map(_.withInc(inc+1)).mkString("{\n", ",\n", "\n" + ii + " }") + "\n"
} else { "" }) + // } else { "" }) +
ii + "]" // ii + "]"
} // }
} // }
//
sealed abstract class ClassSymbol extends Symbol { // sealed abstract class ClassSymbol extends Symbol {
val parents: Seq[AbstractClassSymbol] // val parents: Seq[AbstractClassSymbol]
//
protected val _pfx: String // protected val _pfx: String
//
override def toString = "[" + _pfx + ": " + id + (if (!parents.isEmpty) { " extends " + parents.mkString(", ") } else { "" }) + "]" // override def toString = "[" + _pfx + ": " + id + (if (!parents.isEmpty) { " extends " + parents.mkString(", ") } else { "" }) + "]"
} // }
//
/** Symbols for abstract classes (or traits) */ // /** Symbols for abstract classes (or traits) */
class AbstractClassSymbol(val id: Identifier, val parents: Seq[AbstractClassSymbol]) extends ClassSymbol { // class AbstractClassSymbol(val id: Identifier, val parents: Seq[AbstractClassSymbol]) extends ClassSymbol {
override protected val _pfx = "abstract class" // override protected val _pfx = "abstract class"
} // }
//
/** Symbols for "regular" (= non-abstract, non-case) classes */ // /** Symbols for "regular" (= non-abstract, non-case) classes */
class RefClassSymbol(val id: Identifier, val parents: Seq[AbstractClassSymbol]) extends ClassSymbol { // class RefClassSymbol(val id: Identifier, val parents: Seq[AbstractClassSymbol]) extends ClassSymbol {
override protected val _pfx = "class" // override protected val _pfx = "class"
} // }
//
/** Symbols for case classes. */ // /** Symbols for case classes. */
class CaseClassSymbol(val id: Identifier, val parents: Seq[AbstractClassSymbol]) extends ClassSymbol { // class CaseClassSymbol(val id: Identifier, val parents: Seq[AbstractClassSymbol]) extends ClassSymbol {
override protected val _pfx = "case class" // override protected val _pfx = "case class"
} // }
//
class FunctionSymbol(val id: Identifier, val params: Seq[VariableSymbol], val returnType: TypeTree) extends Typed { // class FunctionSymbol(val id: Identifier, val params: Seq[VariableSymbol], val returnType: TypeTree) extends Typed {
def getType = returnType // def getType = returnType
} // }
} // }
...@@ -9,66 +9,30 @@ object Trees { ...@@ -9,66 +9,30 @@ object Trees {
/* EXPRESSIONS */ /* EXPRESSIONS */
/** There's no such thing as a typing phase for these trees, they need to be
* correctly typed at construction time. Each AST node checks that the
* children provided satisfy whatever typing constraints are required by the
* node, and each node is then responsible for communicating its type. */
sealed abstract class Expr extends Typed { sealed abstract class Expr extends Typed {
override def toString: String = PrettyPrinter(this) override def toString: String = PrettyPrinter(this)
private var _scope: Option[Scope] = None // private var _scope: Option[Scope] = None
//
// def scope: Scope =
// if(_scope.isEmpty)
// throw new Exception("Undefined scope.")
// else
// _scope.get
def scope: Scope = // def scope_=(s: Scope): Unit = {
if(_scope.isEmpty) // if(_scope.isEmpty) {
throw new Exception("Undefined scope.") // _scope = Some(s)
else // } else {
_scope.get // throw new Exception("Redefining scope.")
// }
def scope_=(s: Scope): Unit = { // }
if(_scope.isEmpty) {
_scope = Some(s)
} else {
throw new Exception("Redefining scope.")
}
}
} }
/**
equality on sets, ADTs etc. (equality on function types?!)
forall, exists - optionally bounded quantifiers
* comes with type A of bound variable
* also comes with an optional Set[A] that gives more precise description of the range of this variable
Without Set[A] bound, the variable ranges over all constructible (not only allocated) objects.
see examples in:
http://code.google.com/p/scalacheck/wiki/UserGuide
*/
/* Control flow */ /* Control flow */
case class FunctionInvocation(funDef: FunDef, args: Seq[Expr]) extends Expr { case class FunctionInvocation(funDef: FunDef, args: Seq[Expr]) extends Expr
assert(args.map(_.getType).corresponds(funDef.argTypes)(_ == _)) case class IfExpr(cond: Expr, then: Expr, elze: Expr) extends Expr
lazy val getType = funDef.returnType case class MatchExpr(scrutinee: Expr, cases: Seq[MatchCase]) extends Expr
}
case class IfExpr(cond: Expr, then: Expr, elze: Expr) extends Expr {
assert(cond.getType == BooleanType)
assert(then.getType == elze.getType)
def getType = then.getType
}
case class MatchExpr(scrutinee: Expr, cases: Seq[MatchCase]) extends Expr {
// there can be no assumption about the type of the scrutinee.. Scala
// gives nice errors "constructor cannot be instantiated to expected type"
// but that seems relatively hard to check at construction for now...
// Actually it only gives that error when the pattern is unapply (ie. not
// an "instanceOf" one), so there's hope.
// we should assert that the rhs types of all MatchCases match !
lazy val getType = cases(0).rhs.getType
}
sealed abstract class MatchCase { sealed abstract class MatchCase {
val pattern: Pattern val pattern: Pattern
...@@ -76,9 +40,7 @@ see examples in: ...@@ -76,9 +40,7 @@ see examples in:
} }
case class SimpleCase(pattern: Pattern, rhs: Expr) extends MatchCase case class SimpleCase(pattern: Pattern, rhs: Expr) extends MatchCase
case class GuardedCase(pattern: Pattern, guard: Expr, rhs: Expr) extends MatchCase { case class GuardedCase(pattern: Pattern, guard: Expr, rhs: Expr) extends MatchCase
assert(guard.getType == BooleanType)
}
sealed abstract class Pattern sealed abstract class Pattern
case class InstanceOfPattern(binder: Option[Identifier], classTypeDef: ClassTypeDef) extends Pattern // c: Class case class InstanceOfPattern(binder: Option[Identifier], classTypeDef: ClassTypeDef) extends Pattern // c: Class
...@@ -86,257 +48,82 @@ see examples in: ...@@ -86,257 +48,82 @@ see examples in:
case class ExtractorPattern(binder: Option[Identifier], case class ExtractorPattern(binder: Option[Identifier],
extractor : ExtractorTypeDef, extractor : ExtractorTypeDef,
subPatterns: Seq[Pattern]) extends Pattern // c @ Extractor(...,...) subPatterns: Seq[Pattern]) extends Pattern // c @ Extractor(...,...)
// I suggest we skip Seq stars for now. // We don't handle Seq stars for now.
/* Propositional logic */ /* Propositional logic */
case class And(exprs: Seq[Expr]) extends Expr { case class And(exprs: Seq[Expr]) extends Expr
assert(exprs.forall(_.getType == BooleanType)) case class Or(exprs: Seq[Expr]) extends Expr
def getType = BooleanType case class Not(expr: Expr) extends Expr
}
case class Or(exprs: Seq[Expr]) extends Expr {
assert(exprs.forall(_.getType == BooleanType))
def getType = BooleanType
}
case class Not(expr: Expr) extends Expr {
assert(expr.getType == BooleanType)
def getType = BooleanType
}
/* Not sure if we should really have these.. I suppose they could be of some
* help to some theorem provers? *
case class Implies(lhs: Expr, rhs: Expr) extends Expr {
assert(lhs.getType == BooleanType && rhs.getType == BooleanType)
def getType = BooleanType
}
case class Iff(lhs: Expr, rhs: Expr) extends Expr {
assert(lhs.getType == BooleanType && rhs.getType == BooleanType)
def getType = BooleanType
} */
/* Maybe we should split this one depending on types? */ /* Maybe we should split this one depending on types? */
case class Equals(left: Expr, right: Expr) extends Expr { case class Equals(left: Expr, right: Expr) extends Expr
assert(left.getType == right.getType)
val getType = BooleanType
}
/* Literals */ /* Literals */
// to be fixed! Should contain a reference to the definition of that // to be fixed! Should contain a reference to the definition of that
// variable, which would also give us its type. // variable, which would also give us its type.
case class Variable(id: Identifier) extends Expr { case class Variable(id: Identifier) extends Expr
val getType = AnyType
}
case class IntLiteral(value: Int) extends Expr { sealed abstract class Literal[T] extends Expr {
val getType = Int32Type val value: T
} }
case class BooleanLiteral(value: Boolean) extends Expr { case class IntLiteral(value: Int) extends Literal[Int]
val getType = BooleanType case class BooleanLiteral(value: Boolean) extends Literal[Boolean]
}
/* Arithmetic */ /* Arithmetic */
case class Plus(lhs: Expr, rhs: Expr) extends Expr { case class Plus(lhs: Expr, rhs: Expr) extends Expr
assert(lhs.getType == Int32Type && rhs.getType == Int32Type) case class Minus(lhs: Expr, rhs: Expr) extends Expr
val getType = Int32Type case class UMinus(expr: Expr) extends Expr
} case class Times(lhs: Expr, rhs: Expr) extends Expr
case class Division(lhs: Expr, rhs: Expr) extends Expr
case class Minus(lhs: Expr, rhs: Expr) extends Expr { case class LessThan(lhs: Expr, rhs: Expr) extends Expr
assert(lhs.getType == Int32Type && rhs.getType == Int32Type) case class GreaterThan(lhs: Expr, rhs: Expr) extends Expr
val getType = Int32Type case class LessEquals(lhs: Expr, rhs: Expr) extends Expr
} case class GreaterEquals(lhs: Expr, rhs: Expr) extends Expr
case class UMinus(expr: Expr) extends Expr {
assert(expr.getType == Int32Type)
val getType = Int32Type
}
case class Times(lhs: Expr, rhs: Expr) extends Expr {
assert(lhs.getType == Int32Type && rhs.getType == Int32Type)
val getType = Int32Type
}
case class Division(lhs: Expr, rhs: Expr) extends Expr {
assert(lhs.getType == Int32Type && rhs.getType == Int32Type)
val getType = Int32Type
}
case class LessThan(lhs: Expr, rhs: Expr) extends Expr {
assert(lhs.getType == Int32Type && rhs.getType == Int32Type)
val getType = BooleanType
}
case class GreaterThan(lhs: Expr, rhs: Expr) extends Expr {
assert(lhs.getType == Int32Type && rhs.getType == Int32Type)
val getType = BooleanType
}
case class LessEquals(lhs: Expr, rhs: Expr) extends Expr {
assert(lhs.getType == Int32Type && rhs.getType == Int32Type)
val getType = BooleanType
}
case class GreaterEquals(lhs: Expr, rhs: Expr) extends Expr {
assert(lhs.getType == Int32Type && rhs.getType == Int32Type)
val getType = BooleanType
}
/* Option expressions */ /* Option expressions */
case class OptionSome(value: Expr) extends Expr { case class OptionSome(value: Expr) extends Expr
lazy val getType = OptionType(value.getType) case class OptionNone(baseType: TypeTree) extends Expr
}
case class OptionNone(baseType: TypeTree) extends Expr {
lazy val getType = OptionType(baseType)
}
/* Set expressions */ /* Set expressions */
case class EmptySet(baseType: TypeTree) extends Expr { case class EmptySet(baseType: TypeTree) extends Expr
lazy val getType = SetType(baseType) case class FiniteSet(elements: Seq[Expr]) extends Expr
} case class ElementOfSet(element: Expr, set: Expr) extends Expr
case class FiniteSet(elements: Seq[Expr]) extends Expr { case class IsEmptySet(set: Expr) extends Expr
assert(elements.size > 0) case class SetEquals(set1: Expr, set2: Expr) extends Expr
assert(elements.drop(1).forall(_.getType == elements(0).getType)) case class SetCardinality(set: Expr) extends Expr
lazy val getType = SetType(elements(0).getType) case class SubsetOf(set1: Expr, set2: Expr) extends Expr
} case class SetIntersection(set1: Expr, set2: Expr) extends Expr
case class ElementOfSet(element: Expr, set: Expr) extends Expr { case class SetUnion(set1: Expr, set2: Expr) extends Expr
assert(set.getType == SetType(element.getType)) case class SetDifference(set1: Expr, set2: Expr) extends Expr
val getType = BooleanType
}
case class IsEmptySet(set: Expr) extends Expr {
assert(set.getType.isInstanceOf[SetType])
val getType = BooleanType
}
case class SetEquals(set1: Expr, set2: Expr) extends Expr {
assert(set1.getType == set2.getType && set1.getType.isInstanceOf[SetType])
val getType = BooleanType
}
case class SetCardinality(set: Expr) extends Expr {
assert(set.getType.isInstanceOf[SetType])
val getType = Int32Type
}
case class SubsetOf(set1: Expr, set2: Expr) extends Expr {
assert(set1.getType == set2.getType && set1.getType.isInstanceOf[SetType])
val getType = BooleanType
}
case class SetIntersection(set1: Expr, set2: Expr) extends Expr {
assert(set1.getType == set2.getType && set1.getType.isInstanceOf[SetType])
lazy val getType = set1.getType
}
case class SetUnion(set1: Expr, set2: Expr) extends Expr {
assert(set1.getType == set2.getType && set1.getType.isInstanceOf[SetType])
lazy val getType = set1.getType
}
case class SetDifference(set1: Expr, set2: Expr) extends Expr {
assert(set1.getType == set2.getType && set1.getType.isInstanceOf[SetType])
lazy val getType = set1.getType
}
/* Multiset expressions */ /* Multiset expressions */
case class EmptyMultiset(baseType: TypeTree) extends Expr { // case class EmptyMultiset(baseType: TypeTree) extends Expr
lazy val getType = MultisetType(baseType) // case class FiniteMultiset(elements: Seq[Expr]) extends Expr
} // case class Multiplicity(element: Expr, multiset: Expr) extends Expr
case class FiniteMultiset(elements: Seq[Expr]) extends Expr { // case class IsEmptyMultiset(multiset: Expr) extends Expr
assert(elements.size > 0) // case class MultisetEquals(multiset1: Expr, multiset2: Expr) extends Expr
assert(elements.drop(1).forall(_.getType == elements(0).getType)) // case class MultisetCardinality(multiset: Expr) extends Expr
lazy val getType = MultisetType(elements(0).getType) // case class SubmultisetOf(multiset1: Expr, multiset2: Expr) extends Expr
} // case class MultisetIntersection(multiset1: Expr, multiset2: Expr) extends Expr
case class Multiplicity(element: Expr, multiset: Expr) extends Expr { // case class MultisetUnion(multiset1: Expr, multiset2: Expr) extends Expr
assert(multiset.getType == MultisetType(element.getType)) // case class MultisetPlus(multiset1: Expr, multiset2: Expr) extends Expr // disjoint union
val getType = Int32Type // case class MultisetDifference(multiset1: Expr, multiset2: Expr) extends Expr
}
case class IsEmptyMultiset(multiset: Expr) extends Expr {
assert(multiset.getType.isInstanceOf[MultisetType])
val getType = BooleanType
}
case class MultisetEquals(multiset1: Expr, multiset2: Expr) extends Expr {
assert(multiset1.getType == multiset2.getType && multiset1.getType.isInstanceOf[MultisetType])
val getType = BooleanType
}
case class MultisetCardinality(multiset: Expr) extends Expr {
assert(multiset.getType.isInstanceOf[MultisetType])
val getType = Int32Type
}
case class SubmultisetOf(multiset1: Expr, multiset2: Expr) extends Expr {
assert(multiset1.getType == multiset2.getType && multiset1.getType.isInstanceOf[MultisetType])
val getType = BooleanType
}
case class MultisetIntersection(multiset1: Expr, multiset2: Expr) extends Expr {
assert(multiset1.getType == multiset2.getType && multiset1.getType.isInstanceOf[MultisetType])
lazy val getType = multiset1.getType
}
case class MultisetUnion(multiset1: Expr, multiset2: Expr) extends Expr {
assert(multiset1.getType == multiset2.getType && multiset1.getType.isInstanceOf[MultisetType])
lazy val getType = multiset1.getType
}
case class MultisetPlus(multiset1: Expr, multiset2: Expr) extends Expr { // disjoint union
assert(multiset1.getType == multiset2.getType && multiset1.getType.isInstanceOf[MultisetType])
lazy val getType = multiset1.getType
}
case class MultisetDifference(multiset1: Expr, multiset2: Expr) extends Expr {
assert(multiset1.getType == multiset2.getType && multiset1.getType.isInstanceOf[MultisetType])
lazy val getType = multiset1.getType
}
/* Map operations. */ /* Map operations. */
case class EmptyMap(fromType: TypeTree, toType: TypeTree) extends Expr { case class EmptyMap(fromType: TypeTree, toType: TypeTree) extends Expr
lazy val getType = MapType(fromType, toType) case class SingletonMap(from: Expr, to: Expr) extends Expr
} case class FiniteMap(singletons: Seq[SingletonMap]) extends Expr
case class SingletonMap(from: Expr, to: Expr) extends Expr {
lazy val getType = MapType(from.getType, to.getType)
}
case class FiniteMap(singletons: Seq[SingletonMap]) extends Expr { case class MapGet(map: Expr, key: Expr) extends Expr
assert(singletons.size > 0 case class MapUnion(map1: Expr, map2: Expr) extends Expr
&& singletons.drop(1).forall(_.getType == singletons(0).getType)) case class MapDiffrence(map: Expr, keys: Expr) extends Expr
lazy val getType = singletons(0).getType
}
case class MapGet(map: Expr, key: Expr) extends Expr {
assert(map.getType.isInstanceOf[MapType] && key.getType == map.getType.asInstanceOf[MapType].from)
lazy val getType = OptionType(map.getType.asInstanceOf[MapType].to)
}
case class MapUnion(map1: Expr, map2: Expr) extends Expr {
assert(map1.getType.isInstanceOf[MapType] && map1.getType == map2.getType)
lazy val getType = map1.getType
}
case class MapDiffrence(map: Expr, keys: Expr) extends Expr {
assert(map.getType.isInstanceOf[MapType] && keys.isInstanceOf[SetType] && map.getType.asInstanceOf[MapType].from == keys.getType.asInstanceOf[SetType].base)
lazy val getType = map.getType
}
/* List operations */ /* List operations */
case class NilList(baseType: TypeTree) extends Expr { case class NilList(baseType: TypeTree) extends Expr
lazy val getType = ListType(baseType) case class Cons(head: Expr, tail: Expr) extends Expr
} case class Car(list: Expr) extends Expr
case class Cdr(list: Expr) extends Expr
case class Cons(head: Expr, tail: Expr) extends Expr { case class Concat(list1: Expr, list2: Expr) extends Expr
assert(tail.isInstanceOf[ListType] && tail.getType.asInstanceOf[ListType].base == head.getType) case class ListAt(list: Expr, index: Expr) extends Expr
lazy val getType = tail.getType
}
case class Car(list: Expr) extends Expr {
assert(list.getType.isInstanceOf[ListType])
lazy val getType = list.getType.asInstanceOf[ListType].base
}
case class Cdr(list: Expr) extends Expr {
assert(list.getType.isInstanceOf[ListType])
lazy val getType = list.getType
}
case class Concat(list1: Expr, list2: Expr) extends Expr {
assert(list1.getType.isInstanceOf[ListType] && list1.getType == list2.getType)
lazy val getType = list1.getType
}
case class ListAt(list: Expr, index: Expr) extends Expr {
assert(list.getType.isInstanceOf[ListType] && index.getType == Int32Type)
lazy val getType = OptionType(list.getType.asInstanceOf[ListType].base)
}
} }
...@@ -6,13 +6,27 @@ object TypeTrees { ...@@ -6,13 +6,27 @@ object TypeTrees {
import Definitions._ import Definitions._
trait Typed { trait Typed {
def getType: TypeTree self =>
var _type: Option[TypeTree] = None
def getType: TypeTree = _type match {
case None => NoType
case Some(t) => t
}
def setType(tt: TypeTree): self.type = _type match {
case None => _type = Some(tt); this
case Some(_) => scala.Predef.error("Resetting type information.")
}
} }
sealed abstract class TypeTree { sealed abstract class TypeTree {
override def toString: String = PrettyPrinter(this) override def toString: String = PrettyPrinter(this)
} }
case object NoType extends TypeTree
case object AnyType extends TypeTree case object AnyType extends TypeTree
case object BooleanType extends TypeTree case object BooleanType extends TypeTree
case object Int32Type extends TypeTree case object Int32Type extends TypeTree
...@@ -21,7 +35,7 @@ object TypeTrees { ...@@ -21,7 +35,7 @@ object TypeTrees {
case class TupleType(bases: Seq[TypeTree]) extends TypeTree { lazy val dimension: Int = bases.length } case class TupleType(bases: Seq[TypeTree]) extends TypeTree { lazy val dimension: Int = bases.length }
case class FunctionType(arg: TypeTree, res: TypeTree) extends TypeTree case class FunctionType(arg: TypeTree, res: TypeTree) extends TypeTree
case class SetType(base: TypeTree) extends TypeTree case class SetType(base: TypeTree) extends TypeTree
case class MultisetType(base: TypeTree) extends TypeTree // case class MultisetType(base: TypeTree) extends TypeTree
case class MapType(from: TypeTree, to: TypeTree) extends TypeTree case class MapType(from: TypeTree, to: TypeTree) extends TypeTree
case class ClassType(id: Identifier) extends TypeTree case class ClassType(id: Identifier) extends TypeTree
case class CaseClassType(id: Identifier) extends TypeTree case class CaseClassType(id: Identifier) extends TypeTree
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment