diff --git a/shared/src/main/scala/io/kaitai/struct/GraphvizClassCompiler.scala b/shared/src/main/scala/io/kaitai/struct/GraphvizClassCompiler.scala index 6f1fac354..f6f5209d5 100644 --- a/shared/src/main/scala/io/kaitai/struct/GraphvizClassCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/GraphvizClassCompiler.scala @@ -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 { diff --git a/shared/src/main/scala/io/kaitai/struct/exprlang/Ast.scala b/shared/src/main/scala/io/kaitai/struct/exprlang/Ast.scala index 667ccb64b..1b4bf0d25 100644 --- a/shared/src/main/scala/io/kaitai/struct/exprlang/Ast.scala +++ b/shared/src/main/scala/io/kaitai/struct/exprlang/Ast.scala @@ -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 diff --git a/shared/src/main/scala/io/kaitai/struct/format/InstanceSpec.scala b/shared/src/main/scala/io/kaitai/struct/format/InstanceSpec.scala index f833f637f..8fe5ccff8 100644 --- a/shared/src/main/scala/io/kaitai/struct/format/InstanceSpec.scala +++ b/shared/src/main/scala/io/kaitai/struct/format/InstanceSpec.scala @@ -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) diff --git a/shared/src/main/scala/io/kaitai/struct/languages/components/EveryReadIsExpression.scala b/shared/src/main/scala/io/kaitai/struct/languages/components/EveryReadIsExpression.scala index 7f803a816..762294df2 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/components/EveryReadIsExpression.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/components/EveryReadIsExpression.scala @@ -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) diff --git a/shared/src/main/scala/io/kaitai/struct/languages/components/GoReads.scala b/shared/src/main/scala/io/kaitai/struct/languages/components/GoReads.scala index 17f1d99ae..c691d15f8 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/components/GoReads.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/components/GoReads.scala @@ -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) diff --git a/shared/src/main/scala/io/kaitai/struct/translators/BaseTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/BaseTranslator.scala index b339223d9..084b1b250 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/BaseTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/BaseTranslator.scala @@ -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) @@ -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)}" diff --git a/shared/src/main/scala/io/kaitai/struct/translators/CSharpTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/CSharpTranslator.scala index 6aefa3b77..0103f72aa 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/CSharpTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/CSharpTranslator.scala @@ -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) diff --git a/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala index 2bf4e851f..d391ea686 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala @@ -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) { diff --git a/shared/src/main/scala/io/kaitai/struct/translators/ExpressionValidator.scala b/shared/src/main/scala/io/kaitai/struct/translators/ExpressionValidator.scala index 70c686135..d749ef93d 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/ExpressionValidator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/ExpressionValidator.scala @@ -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 diff --git a/shared/src/main/scala/io/kaitai/struct/translators/GoTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/GoTranslator.scala index fb3d39940..233c77656 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/GoTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/GoTranslator.scala @@ -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) @@ -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 { diff --git a/shared/src/main/scala/io/kaitai/struct/translators/JavaScriptTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/JavaScriptTranslator.scala index 9be19779f..9538cf8dc 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/JavaScriptTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/JavaScriptTranslator.scala @@ -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)" diff --git a/shared/src/main/scala/io/kaitai/struct/translators/JavaTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/JavaTranslator.scala index db4e5ef36..0ce4fea6d 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/JavaTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/JavaTranslator.scala @@ -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) diff --git a/shared/src/main/scala/io/kaitai/struct/translators/LuaTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/LuaTranslator.scala index 65f294bb0..621cb6bb5 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/LuaTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/LuaTranslator.scala @@ -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 = { diff --git a/shared/src/main/scala/io/kaitai/struct/translators/NimTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/NimTranslator.scala index 0dd19424d..2ae60c53c 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/NimTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/NimTranslator.scala @@ -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 = diff --git a/shared/src/main/scala/io/kaitai/struct/translators/PHPTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/PHPTranslator.scala index b8bd88f1e..69340cc57 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/PHPTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/PHPTranslator.scala @@ -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)}]" diff --git a/shared/src/main/scala/io/kaitai/struct/translators/PerlTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/PerlTranslator.scala index 12e108b71..092a71935 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/PerlTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/PerlTranslator.scala @@ -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) diff --git a/shared/src/main/scala/io/kaitai/struct/translators/PythonTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/PythonTranslator.scala index 3e5bdce36..78d3c145e 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/PythonTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/PythonTranslator.scala @@ -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" diff --git a/shared/src/main/scala/io/kaitai/struct/translators/RubyTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/RubyTranslator.scala index 63f68f5d3..58395bf79 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/RubyTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/RubyTranslator.scala @@ -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) diff --git a/shared/src/main/scala/io/kaitai/struct/translators/RustTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/RustTranslator.scala index f691d2847..6d0923959 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/RustTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/RustTranslator.scala @@ -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)}]" diff --git a/shared/src/main/scala/io/kaitai/struct/translators/TypeDetector.scala b/shared/src/main/scala/io/kaitai/struct/translators/TypeDetector.scala index f5b7f36dc..0d30f4501 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/TypeDetector.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/TypeDetector.scala @@ -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