Simplistic type hierarchy for ASTs
parent
7bc91c8402
commit
f1a5fa4cc8
|
@ -0,0 +1,15 @@
|
|||
package com.astraldb.spec
|
||||
|
||||
case class ASTDefinition(
|
||||
family: Type.AST,
|
||||
nodes: Set[Node]
|
||||
)
|
||||
{
|
||||
val subtypes:Map[Type.ASTSubtype, Set[Node]] =
|
||||
nodes.flatMap { node =>
|
||||
node.supertypes.map { st =>
|
||||
st -> node
|
||||
}
|
||||
}
|
||||
.groupMap { _._1 } { _._2 }
|
||||
}
|
|
@ -4,10 +4,14 @@ import scala.collection.mutable
|
|||
import com.astraldb.expression._
|
||||
|
||||
case class Definition(
|
||||
nodes:Map[String, Seq[Node]],
|
||||
asts: Map[String, ASTDefinition],
|
||||
rules:Seq[Rule],
|
||||
globals: Map[String, Type],
|
||||
) {
|
||||
|
||||
def nodes =
|
||||
asts.mapValues { _.nodes }
|
||||
|
||||
override def toString =
|
||||
s"""/////// ASTs //////
|
||||
|${nodes.map { case (family, nodeTypes) => s"Ast(${family})(\n ${nodeTypes.mkString(",\n ")}\n)" }.mkString("\n\n")}
|
||||
|
@ -15,6 +19,7 @@ case class Definition(
|
|||
|/////// Rules /////
|
||||
|${rules.mkString("\n\n")}
|
||||
""".stripMargin
|
||||
|
||||
val familyOfNode: Map[String, String] =
|
||||
nodes.flatMap { case (family, elements) => elements.map { _.name -> family } }
|
||||
.toMap
|
||||
|
@ -32,7 +37,12 @@ class HardcodedDefinition
|
|||
{
|
||||
lazy val definition: Definition =
|
||||
Definition(
|
||||
nodes = nodes.mapValues { _.toSeq }.toMap,
|
||||
asts = nodes.map { case (f, n) =>
|
||||
val family = Type.AST(f)
|
||||
f -> ASTDefinition(
|
||||
family = family,
|
||||
nodes = n.map { _.copy(family = family) }.toSet
|
||||
)}.toMap,
|
||||
rules = rules.toSeq,
|
||||
globals = globals.toMap
|
||||
)
|
||||
|
@ -43,13 +53,12 @@ class HardcodedDefinition
|
|||
|
||||
import FieldConversions._
|
||||
|
||||
|
||||
def Ast(label: String)(newNodes: Node*): Unit =
|
||||
def Ast(label: String)(newNodes: => Node*): Unit =
|
||||
nodes.getOrElseUpdate(label, mutable.Buffer.empty)
|
||||
.appendAll(newNodes)
|
||||
|
||||
def Node(label: String)(fields: (String, Type)*): Node =
|
||||
com.astraldb.spec.Node(label, fields)
|
||||
com.astraldb.spec.Node(label, fields, supertypes = Set.empty, family = null)
|
||||
|
||||
def Rule(label: String, family: String)(pattern: Match)(replacement: Expression): Unit =
|
||||
rules.append(
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
package com.astraldb.spec;
|
||||
|
||||
case class Node(val name:String, val fields:Seq[Field])
|
||||
case class Node(
|
||||
val name: String,
|
||||
val fields: Seq[Field],
|
||||
val family: Type.AST,
|
||||
val supertypes: Set[Type.ASTSubtype]
|
||||
)
|
||||
{
|
||||
def renderName = name+"Node"
|
||||
def enumName = "JITD_NODE_"+name
|
||||
|
@ -9,4 +14,9 @@ case class Node(val name:String, val fields:Seq[Field])
|
|||
override def toString =
|
||||
name + "(" + fields.map { _.toString }.mkString(", ") + ")"
|
||||
|
||||
def withSupertypes(supertypes: String*): Node =
|
||||
copy(supertypes = this.supertypes ++ supertypes.map { Type.ASTSubtype(_) })
|
||||
|
||||
def allSupertypes: Set[Type.ASTType] = supertypes ++ Set(family)
|
||||
|
||||
}
|
|
@ -19,12 +19,20 @@ object Type
|
|||
override def toString: String = s"Native[${name}]"
|
||||
def scalaType: String = name
|
||||
}
|
||||
case class AST(family: String) extends Type
|
||||
|
||||
sealed trait ASTType extends Type
|
||||
|
||||
case class AST(family: String) extends ASTType
|
||||
{
|
||||
override def toString: String = s"Ast[${family}]"
|
||||
def scalaType: String = family
|
||||
}
|
||||
case class Node(nodeType: String) extends Type
|
||||
case class ASTSubtype(typeName: String) extends ASTType
|
||||
{
|
||||
override def toString: String = s"ASTSubtype[${typeName}]"
|
||||
def scalaType: String = typeName
|
||||
}
|
||||
case class Node(nodeType: String) extends ASTType
|
||||
{
|
||||
override def toString: String = s"Node[${nodeType}]"
|
||||
def scalaType: String = nodeType
|
||||
|
|
|
@ -12,10 +12,8 @@ object Typecheck
|
|||
{
|
||||
(source, target) match {
|
||||
case (a, b) if a == b => true
|
||||
case (Type.Node(label), Type.AST(family)) =>
|
||||
schema.nodes.get(family)
|
||||
.map { _.exists { _.name == label } }
|
||||
.getOrElse { false }
|
||||
case (Type.Node(label), o:Type.ASTType) =>
|
||||
schema.nodesByName(label).allSupertypes contains o
|
||||
case (Type.Union(elems), a) =>
|
||||
elems.forall { escalatesTo(_, a, schema) }
|
||||
case (a, Type.Union(elems)) =>
|
||||
|
@ -30,14 +28,16 @@ object Typecheck
|
|||
{
|
||||
if(a == b){ return a }
|
||||
(a, b) match {
|
||||
case (Type.Node(label), Type.AST(family)) if
|
||||
schema.nodes.get(family)
|
||||
.map { _.exists { _.name == label } }
|
||||
.getOrElse { false } => a
|
||||
case (Type.AST(family), Type.Node(label)) if
|
||||
schema.nodes.get(family)
|
||||
.map { _.exists { _.name == label } }
|
||||
.getOrElse { false } => b
|
||||
case (n@Type.Node(label), o:Type.ASTType) if
|
||||
schema.nodesByName(label)
|
||||
.allSupertypes contains o => n
|
||||
case (o:Type.ASTType, n@Type.Node(label)) if
|
||||
schema.nodesByName(label)
|
||||
.allSupertypes contains o => n
|
||||
case (n:Type.ASTSubtype, a:Type.AST) if
|
||||
schema.asts(a.family).subtypes contains n => n
|
||||
case (a:Type.AST, n:Type.ASTSubtype) if
|
||||
schema.asts(a.family).subtypes contains n => n
|
||||
case (Type.Union(elems), _) if elems contains b => a
|
||||
case (_, Type.Union(elems)) if elems contains a => b
|
||||
case (_, Type.Any) => a
|
||||
|
@ -53,14 +53,29 @@ object Typecheck
|
|||
{
|
||||
if(a == b){ return a }
|
||||
(a, b) match {
|
||||
case (Type.Node(label), Type.AST(family)) if
|
||||
schema.nodes.get(family)
|
||||
.map { _.exists { _.name == label } }
|
||||
.getOrElse { false } => b
|
||||
case (Type.AST(family), Type.Node(label)) if
|
||||
schema.nodes.get(family)
|
||||
.map { _.exists { _.name == label } }
|
||||
.getOrElse { false } => a
|
||||
case (n:Type.Node, o:Type.ASTType) if
|
||||
schema.nodesByName(n.nodeType)
|
||||
.allSupertypes contains o => o
|
||||
case (o:Type.ASTType, n@Type.Node(label)) if
|
||||
schema.nodesByName(label)
|
||||
.allSupertypes contains o => o
|
||||
case (n:Type.ASTSubtype, o:Type.AST) if
|
||||
schema.asts(o.family).subtypes contains n => o
|
||||
case (o:Type.AST, n:Type.ASTSubtype) if
|
||||
schema.asts(o.family).subtypes contains n => o
|
||||
case (a:Type.Node, b:Type.Node) =>
|
||||
val sharedSuperTypes =
|
||||
schema.nodesByName(a.nodeType).allSupertypes &
|
||||
schema.nodesByName(b.nodeType).allSupertypes
|
||||
if(sharedSuperTypes.isEmpty){
|
||||
assert(false, s"Node types $a and $b have nothing in common")
|
||||
} else {
|
||||
sharedSuperTypes.find { _.isInstanceOf[Type.ASTSubtype] }
|
||||
.orElse { sharedSuperTypes.find { _.isInstanceOf[Type.AST] }}
|
||||
.getOrElse {
|
||||
assert(false, "A node can't inherit from another node")
|
||||
}
|
||||
}
|
||||
case (Type.Union(elems), _) if elems contains b => a
|
||||
case (_, Type.Union(elems)) if elems contains a => b
|
||||
case (_, Type.Any) => Type.Any
|
||||
|
|
Loading…
Reference in New Issue