Skip to content

Commit

Permalink
AST representation of external types
Browse files Browse the repository at this point in the history
  • Loading branch information
mknejp committed Jul 13, 2015
1 parent 18b3772 commit 730f745
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 13 deletions.
9 changes: 8 additions & 1 deletion src/source/ast.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,14 @@ case class TypeParam(ident: Ident)

case class Doc(lines: Seq[String])

case class TypeDecl(ident: Ident, params: Seq[TypeParam], body: TypeDef, doc: Doc, origin: String)
sealed abstract class TypeDecl {
val ident: Ident
val params: Seq[TypeParam]
val body: TypeDef
val origin: String
}
case class InternTypeDecl(override val ident: Ident, override val params: Seq[TypeParam], override val body: TypeDef, doc: Doc, override val origin: String) extends TypeDecl
case class ExternTypeDecl(override val ident: Ident, override val params: Seq[TypeParam], override val body: TypeDef, properties: Map[String, Any], override val origin: String) extends TypeDecl

case class Ext(java: Boolean, cpp: Boolean, objc: Boolean) {
def any(): Boolean = {
Expand Down
14 changes: 6 additions & 8 deletions src/source/generator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -298,14 +298,12 @@ abstract class Generator(spec: Spec)
}

def generate(idl: Seq[TypeDecl]) {
for (td <- idl) {
td.body match {
case e: Enum =>
assert(td.params.isEmpty)
generateEnum(td.origin, td.ident, td.doc, e)
case r: Record => generateRecord(td.origin, td.ident, td.doc, td.params, r)
case i: Interface => generateInterface(td.origin, td.ident, td.doc, td.params, i)
}
for (td <- idl.collect { case itd: InternTypeDecl => itd }) td.body match {
case e: Enum =>
assert(td.params.isEmpty)
generateEnum(td.origin, td.ident, td.doc, e)
case r: Record => generateRecord(td.origin, td.ident, td.doc, td.params, r)
case i: Interface => generateInterface(td.origin, td.ident, td.doc, td.params, i)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/source/parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private object IdlParser extends RegexParsers {
def externDirective = "extern".r

def typeDecl(origin: String): Parser[TypeDecl] = doc ~ ident ~ typeList(ident ^^ TypeParam) ~ "=" ~ typeDef ^^ {
case doc~ident~typeParams~_~body => TypeDecl(ident, typeParams, body, doc, origin)
case doc~ident~typeParams~_~body => InternTypeDecl(ident, typeParams, body, doc, origin)
}

def ext(default: Ext) = (rep1("+" ~> ident) >> checkExts) | success(default)
Expand Down
18 changes: 15 additions & 3 deletions src/source/resolver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def resolve(metas: Scope, idl: Seq[TypeDecl]): Option[Error] = {
for (typeDecl <- idl) {
topLevelDupeChecker.check(typeDecl.ident)

val defType = typeDecl.body match {
def defType = typeDecl.body match {
case e: Enum =>
if (!typeDecl.params.isEmpty) {
throw Error(typeDecl.ident.loc, "enums can't have type parameters").toException
Expand All @@ -51,8 +51,10 @@ def resolve(metas: Scope, idl: Seq[TypeDecl]): Option[Error] = {
case r: Record => DRecord
case i: Interface => DInterface
}
val mdef = MDef(typeDecl.ident.name, typeDecl.params.length, defType, typeDecl.body)
topScope = topScope.updated(typeDecl.ident.name, mdef)
topScope = topScope.updated(typeDecl.ident.name, typeDecl match {
case td: InternTypeDecl => MDef(typeDecl.ident.name, typeDecl.params.length, defType, typeDecl.body)
case td: ExternTypeDecl => throw new AssertionError("not implemented")
})
}

// Resolve everything
Expand Down Expand Up @@ -201,6 +203,7 @@ private def constTypeCheck(ty: MExpr, value: Any, resolvedConsts: Seq[Const]) {
throw new AssertionError(s"Const type mismatch: enum ${d.name} does not have option ${opt.name}")
}
}
case e: MExtern => throw new AssertionError("Extern type not allowed for constant")
case _ => throw new AssertionError("Const type cannot be resolved")
}
}
Expand Down Expand Up @@ -241,6 +244,15 @@ private def resolveRecord(scope: Scope, r: Record) {
throw new Error(f.ident.loc, s"Some deriving required is not implemented in record ${f.ident.name}").toException
case DEnum =>
}
case e: MExtern => e.defType match {
case DInterface =>
throw new Error(f.ident.loc, "Interface reference cannot live in a record").toException
case DRecord =>
val record = e.body.asInstanceOf[Record]
if (!r.derivingTypes.subsetOf(record.derivingTypes))
throw new Error(f.ident.loc, s"Some deriving required is not implemented in record ${f.ident.name}").toException
case DEnum =>
}
case _ => throw new AssertionError("Type cannot be resolved")
}
}
Expand Down

0 comments on commit 730f745

Please sign in to comment.