Merge
This commit is contained in:
commit
72f23c23a6
15
astral/compiler/src/com/astraldb/spec/ASTDefinition.scala
Normal file
15
astral/compiler/src/com/astraldb/spec/ASTDefinition.scala
Normal file
|
@ -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._
|
import com.astraldb.expression._
|
||||||
|
|
||||||
case class Definition(
|
case class Definition(
|
||||||
nodes:Map[Type.AST, Seq[Node]],
|
asts: Map[Type.AST, ASTDefinition],
|
||||||
rules:Seq[Rule],
|
rules:Seq[Rule],
|
||||||
globals: Map[String, Type],
|
globals: Map[String, Type],
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
def nodes =
|
||||||
|
asts.mapValues { _.nodes }
|
||||||
|
|
||||||
override def toString =
|
override def toString =
|
||||||
s"""/////// ASTs //////
|
s"""/////// ASTs //////
|
||||||
|${nodes.map { case (family, nodeTypes) => s"Ast(${family})(\n ${nodeTypes.mkString(",\n ")}\n)" }.mkString("\n\n")}
|
|${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 /////
|
||||||
|${rules.mkString("\n\n")}
|
|${rules.mkString("\n\n")}
|
||||||
""".stripMargin
|
""".stripMargin
|
||||||
|
|
||||||
val familyOfNode: Map[String, Type.AST] =
|
val familyOfNode: Map[String, Type.AST] =
|
||||||
nodes.flatMap { case (family, elements) => elements.map { _.name -> family } }
|
nodes.flatMap { case (family, elements) => elements.map { _.name -> family } }
|
||||||
.toMap
|
.toMap
|
||||||
|
@ -32,7 +37,12 @@ class HardcodedDefinition
|
||||||
{
|
{
|
||||||
lazy val definition: Definition =
|
lazy val definition: Definition =
|
||||||
Definition(
|
Definition(
|
||||||
nodes = nodes.map { case (f, r) => Type.AST(f) -> r.toSeq }.toMap,
|
asts = nodes.map { case (f, n) =>
|
||||||
|
val family = Type.AST(f)
|
||||||
|
family -> ASTDefinition(
|
||||||
|
family = family,
|
||||||
|
nodes = n.map { _.copy(family = family) }.toSet
|
||||||
|
)}.toMap,
|
||||||
rules = rules.toSeq,
|
rules = rules.toSeq,
|
||||||
globals = globals.toMap
|
globals = globals.toMap
|
||||||
)
|
)
|
||||||
|
@ -43,13 +53,12 @@ class HardcodedDefinition
|
||||||
|
|
||||||
import FieldConversions._
|
import FieldConversions._
|
||||||
|
|
||||||
|
def Ast(label: String)(newNodes: => Node*): Unit =
|
||||||
def Ast(label: String)(newNodes: Node*): Unit =
|
|
||||||
nodes.getOrElseUpdate(label, mutable.Buffer.empty)
|
nodes.getOrElseUpdate(label, mutable.Buffer.empty)
|
||||||
.appendAll(newNodes)
|
.appendAll(newNodes)
|
||||||
|
|
||||||
def Node(label: String)(fields: (String, Type)*): Node =
|
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 =
|
def Rule(label: String, family: String)(pattern: Match)(replacement: Expression): Unit =
|
||||||
rules.append(
|
rules.append(
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
package com.astraldb.spec;
|
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 renderName = name+"Node"
|
||||||
def enumName = "JITD_NODE_"+name
|
def enumName = "JITD_NODE_"+name
|
||||||
|
@ -9,4 +14,9 @@ case class Node(val name:String, val fields:Seq[Field])
|
||||||
override def toString =
|
override def toString =
|
||||||
name + "(" + fields.map { _.toString }.mkString(", ") + ")"
|
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}]"
|
override def toString: String = s"Native[${name}]"
|
||||||
def scalaType: String = 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}]"
|
override def toString: String = s"Ast[${family}]"
|
||||||
def scalaType: String = 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}]"
|
override def toString: String = s"Node[${nodeType}]"
|
||||||
def scalaType: String = nodeType
|
def scalaType: String = nodeType
|
||||||
|
|
|
@ -12,10 +12,8 @@ object Typecheck
|
||||||
{
|
{
|
||||||
(source, target) match {
|
(source, target) match {
|
||||||
case (a, b) if a == b => true
|
case (a, b) if a == b => true
|
||||||
case (Type.Node(label), family:Type.AST) =>
|
case (Type.Node(label), o:Type.ASTType) =>
|
||||||
schema.nodes.get(family)
|
schema.nodesByName(label).allSupertypes contains o
|
||||||
.map { _.exists { _.name == label } }
|
|
||||||
.getOrElse { false }
|
|
||||||
case (Type.Union(elems), a) =>
|
case (Type.Union(elems), a) =>
|
||||||
elems.forall { escalatesTo(_, a, schema) }
|
elems.forall { escalatesTo(_, a, schema) }
|
||||||
case (a, Type.Union(elems)) =>
|
case (a, Type.Union(elems)) =>
|
||||||
|
@ -37,14 +35,16 @@ object Typecheck
|
||||||
{
|
{
|
||||||
if(a == b){ return a }
|
if(a == b){ return a }
|
||||||
(a, b) match {
|
(a, b) match {
|
||||||
case (Type.Node(label), family:Type.AST) if
|
case (n@Type.Node(label), o:Type.ASTType) if
|
||||||
schema.nodes.get(family)
|
schema.nodesByName(label)
|
||||||
.map { _.exists { _.name == label } }
|
.allSupertypes contains o => n
|
||||||
.getOrElse { false } => a
|
case (o:Type.ASTType, n@Type.Node(label)) if
|
||||||
case (family:Type.AST, Type.Node(label)) if
|
schema.nodesByName(label)
|
||||||
schema.nodes.get(family)
|
.allSupertypes contains o => n
|
||||||
.map { _.exists { _.name == label } }
|
case (n:Type.ASTSubtype, a:Type.AST) if
|
||||||
.getOrElse { false } => b
|
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 b => a
|
||||||
case (_, Type.Union(elems)) if elems contains a => b
|
case (_, Type.Union(elems)) if elems contains a => b
|
||||||
case (_, Type.Any) => a
|
case (_, Type.Any) => a
|
||||||
|
@ -79,22 +79,34 @@ object Typecheck
|
||||||
{
|
{
|
||||||
if(a == b){ return Some(a) }
|
if(a == b){ return Some(a) }
|
||||||
(a, b) match {
|
(a, b) match {
|
||||||
case (Type.Node(label), family:Type.AST) if
|
case (n:Type.Node, o:Type.ASTType) if
|
||||||
schema.nodes.get(family)
|
schema.nodesByName(n.nodeType)
|
||||||
.map { _.exists { _.name == label } }
|
.allSupertypes contains o => o
|
||||||
.getOrElse { false } => Some(b)
|
case (o:Type.ASTType, n@Type.Node(label)) if
|
||||||
case (family:Type.AST, Type.Node(label)) if
|
schema.nodesByName(label)
|
||||||
schema.nodes.get(family)
|
.allSupertypes contains o => o
|
||||||
.map { _.exists { _.name == label } }
|
case (n:Type.ASTSubtype, o:Type.AST) if
|
||||||
.getOrElse { false } => Some(a)
|
schema.asts(o.family).subtypes contains n => o
|
||||||
case (Type.Node(a), Type.Node(b)) if
|
case (o:Type.AST, n:Type.ASTSubtype) if
|
||||||
schema.familyOfNode(a) ==
|
schema.asts(o.family).subtypes contains n => o
|
||||||
schema.familyOfNode(b) => Some(schema.familyOfNode(a))
|
case (a:Type.Node, b:Type.Node) =>
|
||||||
case (Type.Union(elems), _) if elems contains b => Some(a)
|
val sharedSuperTypes =
|
||||||
case (_, Type.Union(elems)) if elems contains a => Some(b)
|
schema.nodesByName(a.nodeType).allSupertypes &
|
||||||
case (_, Type.Any) => Some(Type.Any)
|
schema.nodesByName(b.nodeType).allSupertypes
|
||||||
case (Type.Any, _) => Some(Type.Any)
|
if(sharedSuperTypes.isEmpty){
|
||||||
case _ => None
|
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
|
||||||
|
case (Type.Any, _) => Type.Any
|
||||||
|
case _ => assert(false, s"Types $a and $b don't unify")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue