Skip to content

Commit

Permalink
Rename EnumById & Co to EnumCast and document them
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingun committed Nov 27, 2020
1 parent c290e26 commit 0a371ac
Show file tree
Hide file tree
Showing 20 changed files with 53 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,8 @@ class GraphvizClassCompiler(classSpecs: ClassSpecs, topClass: ClassSpec) extends
List()
case _: Ast.expr.EnumVariant =>
List()
case Ast.expr.EnumById(_, id, _) =>
affectedVars(id)
case Ast.expr.EnumCast(_, value, _) =>
affectedVars(value)
case Ast.expr.Attribute(value, attr) =>
val targetClass = translator.detectType(value)
targetClass match {
Expand Down
8 changes: 7 additions & 1 deletion shared/src/main/scala/io/kaitai/struct/exprlang/Ast.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,13 @@ object Ast {
* KSY file.
*/
case class EnumVariant(enumName: identifier, variant: identifier, inType: typeId = EmptyTypeId) extends expr
case class EnumById(enumName: identifier, id: expr, inType: typeId = EmptyTypeId) extends expr
/**
* Transformation of the `value` expression into the `enumName` type,
* defined in the type `inType`. Unlike other nodes this node never
* parsed from the expression language, because at parse time any
* identifier can represent an enum and actual resolution performed later
*/
case class EnumCast(enumName: identifier, value: expr, inType: typeId = EmptyTypeId) extends expr

case class Attribute(value: expr, attr: identifier) extends expr
case class CastToType(value: expr, typeName: typeId) extends expr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ object InstanceSpec {
// value instance
ParseUtils.ensureLegalKeys(srcMap, LEGAL_KEYS_VALUE_INST, path, Some("value instance"))

// Wrap everything in EnumById if "enum" is used
// Wrap everything in EnumCast if "enum" is used
val value2 = ParseUtils.getOptValueStr(srcMap, "enum", path) match {
case None =>
value
case Some(enumName) =>
Ast.expr.EnumById(Ast.identifier(enumName), value)
Ast.expr.EnumCast(Ast.identifier(enumName), value)
}

val ifExpr = ParseUtils.getOptValueExpression(srcMap, "if", path)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ trait EveryReadIsExpression
val expr = translator.bytesToStr(parseExprBytes(t.bytes, io), Ast.expr.Str(t.encoding))
handleAssignment(id, expr, rep, isRaw)
case t: EnumType =>
val expr = translator.doEnumById(t.enumSpec.get.name, parseExpr(t.basedOn, t.basedOn, io, defEndian))
val expr = translator.doEnumCast(t.enumSpec.get.name, parseExpr(t.basedOn, t.basedOn, io, defEndian))
handleAssignment(id, expr, rep, isRaw)
case _ =>
val expr = parseExpr(dataType, assignType, io, defEndian)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ trait GoReads extends CommonReads with ObjectOrientedLanguage with GoSwitchOps {
case t: EnumType =>
val r1 = translator.outVarCheckRes(parseExpr(t.basedOn, io, defEndian))
val enumSpec = t.enumSpec.get
val expr = translator.trEnumById(enumSpec.name, translator.resToStr(r1))
val expr = translator.trEnumCast(enumSpec.name, translator.resToStr(r1))
handleAssignment(id, expr, rep, isRaw)
case _: BitsType1 =>
val expr = parseExpr(dataType, io, defEndian)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ abstract class BaseTranslator(val provider: TypeProvider)
doStringLiteral(s)
case Ast.expr.Bool(n) =>
doBoolLiteral(n)
case Ast.expr.EnumById(enumType, id, inType) =>
case Ast.expr.EnumCast(enumType, value, inType) =>
val enumSpec = provider.resolveEnum(inType, enumType.name)
doEnumById(enumSpec.name, translate(id))
doEnumCast(enumSpec.name, translate(value))
case Ast.expr.EnumVariant(enumType, variant, inType) =>
val enumSpec = provider.resolveEnum(inType, enumType.name)
doEnumVariant(enumSpec.name, variant.name)
Expand Down Expand Up @@ -187,7 +187,16 @@ abstract class BaseTranslator(val provider: TypeProvider)
* @return String in the target language with reference to the enum variant
*/
def doEnumVariant(enumTypeAbs: List[String], variant: String): String
def doEnumById(enumTypeAbs: List[String], id: String): String
/**
* Translates cast of expression to the enumeration type.
*
* @param enumTypeAbs Absolute path to the enum definition. Contains at least one element.
* The last element in the path is the enum name itself, other -- types in which it is defined
* @param value Translated expression which should have enum type
*
* @return String in the target language transformation of the expression result into enumeration type
*/
def doEnumCast(enumTypeAbs: List[String], value: String): String

// Predefined methods of various types
def strConcat(left: Ast.expr, right: Ast.expr): String = s"${translate(left)} + ${translate(right)}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ class CSharpTranslator(provider: TypeProvider, importList: ImportList) extends B

override def doEnumVariant(enumTypeAbs: List[String], variant: String): String =
s"${enumClass(enumTypeAbs)}.${Utils.upperCamelCase(variant)}"
override def doEnumById(enumTypeAbs: List[String], id: String): String =
s"((${enumClass(enumTypeAbs)}) $id)"
override def doEnumCast(enumTypeAbs: List[String], value: String): String =
s"((${enumClass(enumTypeAbs)}) $value)"

def enumClass(enumTypeAbs: List[String]): String = {
val enumTypeRel = Utils.relClass(enumTypeAbs, provider.nowClass.name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ class CppTranslator(provider: TypeProvider, importListSrc: CppImportList, import
override def doEnumVariant(enumType: List[String], variant: String): String =
CppCompiler.types2class(enumType.dropRight(1)) + "::" +
Utils.upperUnderscoreCase(enumType.last + "_" + variant)
override def doEnumById(enumType: List[String], id: String): String =
s"static_cast<${CppCompiler.types2class(enumType)}>($id)"
override def doEnumCast(enumType: List[String], value: String): String =
s"static_cast<${CppCompiler.types2class(enumType)}>($value)"

override def doStrCompareOp(left: Ast.expr, op: Ast.cmpop, right: Ast.expr) = {
if (op == Ast.cmpop.Eq) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ class ExpressionValidator(val provider: TypeProvider)
_: Ast.expr.FloatNum |
_: Ast.expr.Str |
_: Ast.expr.Bool => // all simple literals are good and valid
case Ast.expr.EnumById(enumType, id, inType) =>
case Ast.expr.EnumCast(enumType, value, inType) =>
provider.resolveEnum(inType, enumType.name)
validate(id)
validate(value)
case Ast.expr.EnumVariant(enumType, variant, inType) =>
provider.resolveEnum(inType, enumType.name)
// TODO: check that variant belongs to that enum
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ class GoTranslator(out: StringLanguageOutputWriter, provider: TypeProvider, impo
trStringLiteral(s)
case Ast.expr.Bool(n) =>
trBoolLiteral(n)
case Ast.expr.EnumById(enumType, id, inType) =>
case Ast.expr.EnumCast(enumType, value, inType) =>
val enumSpec = provider.resolveEnum(inType, enumType.name)
trEnumById(enumSpec.name, translate(id))
trEnumCast(enumSpec.name, translate(value))
case Ast.expr.EnumVariant(enumType, variant, inType) =>
val enumSpec = provider.resolveEnum(inType, enumType.name)
trEnumVariant(enumSpec.name, variant.name)
Expand Down Expand Up @@ -240,8 +240,8 @@ class GoTranslator(out: StringLanguageOutputWriter, provider: TypeProvider, impo

def trEnumVariant(enumTypeAbs: List[String], variant: String) =
ResultString(GoCompiler.enumToStr(enumTypeAbs, variant))
def trEnumById(enumTypeAbs: List[String], id: String) =
ResultString(s"${types2class(enumTypeAbs)}($id)")
def trEnumCast(enumTypeAbs: List[String], value: String) =
ResultString(s"${types2class(enumTypeAbs)}($value)")

override def doBytesCompareOp(left: Ast.expr, op: Ast.cmpop, right: Ast.expr): String = {
op match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ class JavaScriptTranslator(provider: TypeProvider) extends BaseTranslator(provid

override def doEnumVariant(enumType: List[String], variant: String): String =
s"${JavaScriptCompiler.types2class(enumType)}.${Utils.upperUnderscoreCase(variant)}"
override def doEnumById(enumTypeAbs: List[String], id: String): String =
override def doEnumCast(enumTypeAbs: List[String], value: String): String =
// Just an integer, without any casts / resolutions - one would have to look up constants manually
id
value

override def doBytesCompareOp(left: Ast.expr, op: Ast.cmpop, right: Ast.expr): String =
s"(${JavaScriptCompiler.kstreamName}.byteArrayCompare(${translate(left)}, ${translate(right)}) ${cmpOp(op)} 0)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ class JavaTranslator(provider: TypeProvider, importList: ImportList) extends Bas

override def doEnumVariant(enumTypeAbs: List[String], variant: String): String =
s"${enumClass(enumTypeAbs)}.${Utils.upperUnderscoreCase(variant)}"
override def doEnumById(enumTypeAbs: List[String], id: String): String =
s"${enumClass(enumTypeAbs)}.byId($id)"
override def doEnumCast(enumTypeAbs: List[String], value: String): String =
s"${enumClass(enumTypeAbs)}.byId($value)"

def enumClass(enumTypeAbs: List[String]): String = {
val enumTypeRel = Utils.relClass(enumTypeAbs, provider.nowClass.name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ class LuaTranslator(provider: TypeProvider, importList: ImportList) extends Base
s
override def doEnumVariant(enumTypeAbs: List[String], variant: String): String =
s"${LuaCompiler.types2class(enumTypeAbs)}.$variant"
override def doEnumById(enumTypeAbs: List[String], id: String): String =
s"${LuaCompiler.types2class(enumTypeAbs)}($id)"
override def doEnumCast(enumTypeAbs: List[String], value: String): String =
s"${LuaCompiler.types2class(enumTypeAbs)}($value)"

// This is very hacky because integers and booleans cannot be compared
override def doNumericCompareOp(left: Ast.expr, op: Ast.cmpop, right: Ast.expr): String = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class NimTranslator(provider: TypeProvider, importList: ImportList) extends Base
override def bytesToStr(bytesExpr: String, encoding: Ast.expr): String = {
s"encode($bytesExpr, ${translate(encoding)})"
}
override def doEnumById(enumTypeAbs: List[String], id: String): String = s"${namespaced(enumTypeAbs)}($id)"
override def doEnumCast(enumTypeAbs: List[String], value: String): String = s"${namespaced(enumTypeAbs)}($value)"
// override def doEnumVariant(enumTypeAbs: List[String], variant: String): String = s"${namespaced(enumTypeAbs)}($variant)"
override def doEnumVariant(enumTypeAbs: List[String], variant: String): String = s"${enumTypeAbs.head}.$variant"
override def doName(s: String): String =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ class PHPTranslator(provider: TypeProvider, config: RuntimeConfig) extends BaseT
val enumClass = types2classAbs(enumTypeAbs)
s"$enumClass::${Utils.upperUnderscoreCase(variant)}"
}
override def doEnumById(enumTypeAbs: List[String], id: String) =
override def doEnumCast(enumTypeAbs: List[String], value: String) =
// Just an integer, without any casts / resolutions - one would have to look up constants manually
id
value

override def arraySubscript(container: expr, idx: expr): String =
s"${translate(container)}[${translate(idx)}]"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ class PerlTranslator(provider: TypeProvider, importList: ImportList) extends Bas
val enumName = Utils.upperUnderscoreCase(enumType.last)
s"$$$enumClassWithScope${enumName}_${Utils.upperUnderscoreCase(variant)}"
}
override def doEnumById(enumTypeAbs: List[String], id: String): String =
override def doEnumCast(enumTypeAbs: List[String], value: String): String =
// Just an integer, without any casts / resolutions - one would have to look up constants manually
id
value

def enumClass(enumTypeAbs: List[String]): String = {
val enumTypeRel = Utils.relClass(enumTypeAbs, provider.nowClass.name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ class PythonTranslator(provider: TypeProvider, importList: ImportList) extends B

override def doEnumVariant(enumTypeAbs: List[String], variant: String): String =
s"${PythonCompiler.types2class(enumTypeAbs)}.$variant"
override def doEnumById(enumTypeAbs: List[String], id: String): String =
s"${PythonCompiler.kstreamName}.resolve_enum(${PythonCompiler.types2class(enumTypeAbs)}, $id)"
override def doEnumCast(enumTypeAbs: List[String], value: String): String =
s"${PythonCompiler.kstreamName}.resolve_enum(${PythonCompiler.types2class(enumTypeAbs)}, $value)"

override def booleanOp(op: Ast.boolop) = op match {
case Ast.boolop.Or => "or"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ class RubyTranslator(provider: TypeProvider) extends BaseTranslator(provider)

override def doEnumVariant(enumTypeAbs: List[String], variant: String): String =
s":${enumTypeAbs.last}_$variant"
override def doEnumById(enumType: List[String], id: String): String =
s"${RubyCompiler.kstreamName}::resolve_enum(${enumDirectMap(enumType)}, $id)"
override def doEnumCast(enumType: List[String], value: String): String =
s"${RubyCompiler.kstreamName}::resolve_enum(${enumDirectMap(enumType)}, $value)"

def enumDirectMap(enumTypeAndName: List[String]): String = {
val enumTypeAbs = enumTypeAndName.dropRight(1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ class RustTranslator(provider: TypeProvider, config: RuntimeConfig) extends Base
val enumClass = types2classAbs(enumTypeAbs)
s"$enumClass::${Utils.upperUnderscoreCase(variant)}"
}
override def doEnumById(enumTypeAbs: List[String], id: String) =
override def doEnumCast(enumTypeAbs: List[String], value: String) =
// Just an integer, without any casts / resolutions - one would have to look up constants manually
id
value

override def arraySubscript(container: expr, idx: expr): String =
s"${translate(container)}[${translate(idx)}]"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class TypeDetector(provider: TypeProvider) {
val t = EnumType(List(enumType.name), CalcIntType)
t.enumSpec = Some(provider.resolveEnum(inType, enumType.name))
t
case Ast.expr.EnumById(enumType, _, inType) =>
case Ast.expr.EnumCast(enumType, _, inType) =>
val t = EnumType(List(enumType.name), CalcIntType)
t.enumSpec = Some(provider.resolveEnum(inType, enumType.name))
t
Expand Down

0 comments on commit 0a371ac

Please sign in to comment.