Paste number 37746: scala object database

Paste number 37746: scala object database
Pasted by: yang
1 year, 10 months ago
None
Paste contents:
Raw Source | XML | Display As
import scala.collection.mutable._

/*object Uniq {
  var x = 0
  def next = {
    x = x + 1
    x - 1
  }
}*/

case class Prop(typ: Type, default: Val, inv: Option[String])

abstract class Type
case class AnyT(t: Iterable[Type]) extends Type
case class SetT(t: Type) extends Type
case class StrT extends Type
case class ObjT(o: Obj) extends Type

// TODO clean up
object ValUtil {
  def print(v: Val): String = v match {
    case NilV() => "(nil)"
    case SetV(s) => s map { x => print(x) } mkString("{ ", ", ", " }")
    case StrV(s) => "\"" + s + "\""
    case o@Obj() =>
      "Obj( " + (o.parents map (.summary) mkString("parents{ ", "; ", " }")) + ";; " + (o.props map { case {name,prop} => name + " = " + printProp(prop) } mkString("props{ ", "; ", " }")) + ";; " + (o.vals map { case {name,value} => name + " = " + printSumm(value) } mkString("vals{ ", "; ", " }")) + " )"
  }
  def printSumm(v: Val): String = v match {
    case NilV() => "(nil)"
    case SetV(s) => s map { x => printSumm(x) } mkString("{ ", ", ", " }")
    case StrV(s) => "\"" + s + "\""
    case o@Obj() => o.summary
  }
  def printProp(p: Prop) = p match {
    case Prop(typ, default, inv) => "Prop(typ: " + typ + ", default: " + printSumm(default) + ", inv: " + inv + ")"
  }
}
import ValUtil._

class BadPropException(prop: String) extends Exception

abstract class Val
case class NilV extends Val
case class SetV(s: Set[Val]) extends Val
case class StrV(s: String) extends Val
case class Obj extends Val {
  val parents: Set[Obj] = new HashSet()
  val children: Set[Obj] = new HashSet()
  val props: Map[String,Prop] = new HashMap()
  val vals: Map[String,Val] = new HashMap()
//  val id = Uniq.next
  var isInst = false

  override def hashCode = parents.hashCode
  override def equals(any: Any) = any match {
    case o@Obj() => this eq o
    case _ => false
  }

  def summary = vals("names") match {
    case SetV(s) => (s.toList)(0) match {
      case StrV(s) => s
    }
  }
  def derives(o: Obj): Boolean = o == this ||
    parents.exists { p => o derives p }

  //@ modifies: props
  def addProp(name: String, typ: Type, default: Val): Unit =
    props.update(name, Prop(typ, default, None))
  //@ modifies: vals
  def setProp(name: String, value: Val): Unit =
    vals.update(name, value)
  private def getRecur[A](name: String, acc: Obj => Map[String,A]): Option[A] =
    acc(this) get name match {
      case x@Some(_) => x
      case None => {
        val x = parents map ( .getRecur(name, acc) ) find { None != }
        x match {
          case Some(x) => x
          case None => None
        }
      }
    }
  // gets the value, searching parents for the value or a default value
  def getProp(name: String) = {
    try { getRecur(name, .vals).get }
    catch { case _ => throw new BadPropException(name) }
  }
  def infoProp(name: String) = {
    try { getRecur(name, .props).get }
    catch { case _ => throw new BadPropException(name) }
  }

  //@ invariants
  def validate = {
    Console.println("validating " + print(this)) // vals("names")))
    val check: (Boolean, Any) => Unit = assert
    def checkType(value: Val, typ: Type): Boolean =
      {value, typ} match {
        case {NilV(), _} => true
        case {SetV(xs), SetT(t)} => xs forall { x => checkType(x,t) }
        case {StrV(s), StrT()} => true
        case {o@Obj(), ObjT(p)} => o derives p
        case {x, AnyT(ts)} => ts exists { t => checkType(x,t) }
        case _ => false
      }
    def checkRefShapes(value: Val, typ: Type, inv: Option[String]): Boolean =
      {value, typ, inv} match {
        // TODO hairy - should either restrict the shapes in the Type
        // types, or think of changes to the system to allow for more
        // expressive types
        case {SetV(xs), SetT(ObjT(t)), Some(inv)} => xs forall {
          case o@Obj() => o.vals(inv) match {
            case SetV(refs) => refs contains this
            case _ => false
          }
          case _ => false
        }
        case _ => true
      }
    // instances
    check(children.size == 0 || !isInst, "failed instance-test")
    // properties: types (for default and set values), bi-directionality
    check(props forall {
      case {name, prop@Prop(typ, default, inv)} =>
        checkType(default, typ) && checkRefShapes(default, typ, inv) && {
          // TODO the following is redundant with the value-check further down
          // (should keep latter because all values have a prop but not all props have a value)
          val optVal = vals get name
          optVal == None || {
            val value = optVal.get
            checkType(value, typ) && checkRefShapes(value, typ, inv)
          }}}, "properties don't hold")
    // values: check that all the values exist in the props
    def checkVal(value: Val, name: String, src: Obj): Boolean = {
      Console println("resolving: value " + print(value) + " name " + name + " src " + print(src))
      src.props get name match {
        // TODO hairy, this is DFS; need to figure out a better way to
        // resolve with parent(s), i.e. need to figure out where we're
        // inheriting a certain property from
        case None => src.parents exists { p => checkVal(value, name, p) }
        case Some(Prop(typ, _, _)) => checkType(value, typ)
      }
    }
    check(
      vals forall { case {name, value} => checkVal(value, name, this) },
      "values inconsistent")
    // parent-child
    check(children forall (.parents.contains(this)),
          "not all children have me as parent")
    check(parents forall (.children.contains(this)),
          "not all parents have me as child")
  }
}

object ObjUtils {
  val objs = new HashSet[Obj]
  def addRelProp(left: Obj, lname: String, ltyp: Type,
             right: Obj, rname: String, rtyp: Type) = {
               left.props.update(rname, Prop(SetT(rtyp), mkSetV(), Some(lname)))
               right.props.update(lname, Prop(SetT(ltyp), mkSetV(), Some(rname)))
             }
  def addRel(lname: String, left: Obj, rname: String, right: Obj) = {
    def addOneSide(o: Obj, name: String, other: Obj) = {
      def getDef(o: Obj): Option[Val] = o.props get name match {
        case Some(prop) => Some(prop.default)
        case None => getDef( (o.parents find { p => getDef(p) != None }).get )
      }
      o.vals get name match {
        case None => getDef(o).get match {
          case SetV(s) => o.vals(name) = mkSetV(s)
          case _ => assert(false)
        }
      }
      o.vals get name match {
        case Some(x) => x match {
          case SetV(s) => s + other
          case _ => assert(false)
        }
        case _ => assert(false)
      }
    }
    addOneSide(left, rname, right)
    if (left ne right) addOneSide(right, lname, left)
  }
  def mkObj(parents: Iterable[Obj]) = {
    val obj = Obj

    // parent-child
    obj.parents ++= parents
    parents foreach { p => p.children += obj }

    // global set
    objs += obj

    // return
    obj
  }
  def validateAll = objs foreach (.validate)
  def mkSetV(xs: Val*): SetV = mkSetV(xs)
  def mkSetV(xs: Iterable[Val]) = {
    val set = new HashSet[Val]()
    set ++= xs
    SetV(set)
  }
  def getObj(name: String) = objs.find( .getProp("names").asInstanceOf[SetV].s.contains(StrV(name)) ).get
/*
  def query(name: String, names: String*): Val = {
    val init = objs.find(name==).get
    (names foldLeft init) {
      value, name => value match {
        case obj@Obj() => obj.getProp(name)
        case SetV(s) => throw new BadQueryException(
          "property " + name + " not found"
        )
      }
    }
  }
*/
  def dump(any: Any): String = any match {
    case NilV() = "NilV()"
    case SetV(s) = "SetV(" + dump(s) + ")"
    case StrV(s) = "StrV(" + dump(s) + ")"
    case s:Set(xs: _*) =
  }
/*
  def dump(v: Val) = v match {
    
  }
*/
/*  def pickleNilV: SPU[NilV] = wrap(
    NilV,
    (v: Val) => v match { case NilV() => () },
    string
  )
  def pickleSetV: SPU[SetV] = wrap(
    SetV,
    (v: Val) => v match { case SetV(s) => s },
    string
  )
  def pickleVal: SPU[Val] = data(
    (v: Val) => v match {
      case NilV() => 0
      case SetV(_) => 1
      case StrV(_) => 2
      case Obj() => 3
    },
    List(() => pickleNilV,
         () => pickleSetV,
         () => pickleStrV,
         () => pickleObj)
  )*/
}
import ObjUtils._

class BadTypeException extends Exception
class BadValueException extends Exception

object ObjUser {
  def mkInst(newNames: String*)(srcNames: String*) = {
    val obj = mkObj(Set(srcNames map getObj: _*))
    obj.setProp("names",  mkSetV(newNames map StrV))
    obj.isInst = true
    obj
  }
  def prop(objName: String, propName: String, propType: String, default: Option[String]) = {
    val obj = getObj(objName)
    propType match {
      case "string set" => obj.addProp(
        propName, SetT(StrT),
        default match {
          case None => NilV
          case Some(s) => SetV(Set(StrV(s)))
        }
      )
      case "string" => obj.addProp(
        propName, StrT,
        default match {
          case None => NilV
          case Some(s) => StrV(s)
        }
      )
      case _ => throw new BadTypeException()
    }
  }
  def set(objName: String, propName: String, value: String) = {
    val obj = getObj(objName)
    val v = obj.infoProp(propName).typ match {
      case StrT() => StrV(value)
      case SetT(StrT()) => mkSetV(StrV(value))
      case _ => throw new BadValueException()
    }
    obj.setProp(propName, v)
  }
  def mirror(objName: String, relName: String) = {
    val obj = getObj(objName)
    addRelProp(obj, relName, ObjT(obj),
               obj, relName, ObjT(obj))
  }
  def setMirror(objName1: String, relName: String, objName2: String) = {
    val {obj1, obj2} = {getObj(objName1), getObj(objName2)}
    addRel(relName, obj1, relName, obj2)
  }
  def get(objName: String) = getObj(objName)
  def get(objName: String, propName: String) =
    getObj(objName).getProp(propName)
}
import ObjUser._

object Main {
  def fakeUser = {
    mkInst("Yang Zhang")("person")
    prop("person", "mobile phones", "string set", None)
    prop("person", "websites", "string set", None)
    set("Yang Zhang", "mobile phones", "123 456 7890")
    set("Yang Zhang", "websites", "http://mysite/")
    mkInst("Pawan Deshpande")("person")
//    set("Pawan Deshpande", "mobile phone", "234 456 6789")
//    set("Pawan Deshpande", "website", "234 456 6789")
    mirror("person", "roommates")
    setMirror("Yang Zhang", "roommates", "Pawan Deshpande")
    Console println printSumm(get("Yang Zhang", "roommates"))
    Console println printSumm(get("Yang Zhang", "mobile phones"))
    Console println printSumm(get("Yang Zhang", "websites"))
    Console println print(get("Yang Zhang"))
  }
  def main(args: Array[String]): Unit = {
    val concept = mkObj(Set())
    concept.addProp("names", SetT(StrT), NilV)
    concept.setProp("names", mkSetV(StrV("concept")))

    val sw = mkObj(Set(concept))
    sw setProp("names", mkSetV(StrV("software")))
    addRelProp(sw, "platforms", ObjT(sw),
               sw, "hosted software", ObjT(sw))

    val lisp = mkObj(Set(sw))
    lisp.isInst = true
    lisp.setProp("names", mkSetV(StrV("Common Lisp")))

    val person = mkObj(Set(concept))
    person.setProp("names", mkSetV(StrV("person")))

    val mccarthy = mkObj(Set(person))
    mccarthy.isInst = true
    mccarthy.setProp("names", mkSetV(StrV("mccarthy")))

    addRelProp(sw, "software", ObjT(sw),
               person, "people", ObjT(person))
    addRel("software", lisp, "people", mccarthy)

//    query("mccarthy", "software", "lisp", "people")

    fakeUser

    validateAll
    Console println "done!"
  }
}

This paste has no annotations.

Colorize as:
Show Line Numbers

Lisppaste pastes can be made by anyone at any time. Imagine a fearsomely comprehensive disclaimer of liability. Now fear, comprehensively.