From ae16deed271620bf8f06b29894e67a6c7350a969 Mon Sep 17 00:00:00 2001 From: Petr Pucil Date: Sun, 15 Oct 2023 23:19:38 +0200 Subject: [PATCH] Fix inconsistencies in defined vs. initialized "extra attrs" In particular, this commit fixes build errors of generated Java parsers for these 5 tests: - InstanceUserArray - RepeatUntilCalcArrayType - RepeatUntilSized - SwitchRepeatExpr - SwitchRepeatExprInvalid The build error in all these parsers was caused by trying to initialize a `_raw_*` field (like `this._raw_userEntries = new ArrayList();`), which wasn't actually declared, though. This inconsistency was possible because until now, we've had different code deciding what fields to declare to code deciding what fields to initialize. Since this commit, we're simply initializing all "extra attrs" + the attribute itself (in case the attribute is repeated; otherwise no init is needed), which avoids all discrepancies and also results in simpler code. --- .../io/kaitai/struct/languages/CSharpCompiler.scala | 6 +----- .../io/kaitai/struct/languages/CppCompiler.scala | 11 +---------- .../scala/io/kaitai/struct/languages/GoCompiler.scala | 2 +- .../io/kaitai/struct/languages/JavaCompiler.scala | 7 +------ .../kaitai/struct/languages/JavaScriptCompiler.scala | 7 +------ .../io/kaitai/struct/languages/LuaCompiler.scala | 8 ++------ .../io/kaitai/struct/languages/NimCompiler.scala | 2 +- .../io/kaitai/struct/languages/PHPCompiler.scala | 9 ++------- .../io/kaitai/struct/languages/PerlCompiler.scala | 9 ++------- .../io/kaitai/struct/languages/PythonCompiler.scala | 7 +------ .../io/kaitai/struct/languages/RubyCompiler.scala | 7 +------ .../io/kaitai/struct/languages/RustCompiler.scala | 9 ++------- .../languages/components/AllocateAndStoreIO.scala | 10 ++-------- .../struct/languages/components/CommonReads.scala | 2 +- .../languages/components/LanguageCompiler.scala | 4 ++-- 15 files changed, 21 insertions(+), 79 deletions(-) diff --git a/shared/src/main/scala/io/kaitai/struct/languages/CSharpCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/CSharpCompiler.scala index d70752b14..991b0e7d4 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/CSharpCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/CSharpCompiler.scala @@ -274,13 +274,9 @@ class CSharpCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) override def condIfFooter(expr: expr): Unit = fileFooter(null) - override def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit = { + override def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit = { importList.add("System.Collections.Generic") - if (needRaw.level >= 1) - out.puts(s"${privateMemberName(RawIdentifier(id))} = new List();") - if (needRaw.level >= 2) - out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = new List();") out.puts(s"${privateMemberName(id)} = new ${kaitaiType2NativeType(ArrayTypeInStream(dataType))}();") } diff --git a/shared/src/main/scala/io/kaitai/struct/languages/CppCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/CppCompiler.scala index 09be52792..41cda7309 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/CppCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/CppCompiler.scala @@ -619,18 +619,9 @@ class CppCompiler( outSrc.puts("}") } - override def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit = { + override def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit = { importListHdr.addSystem("vector") - if (needRaw.level >= 1) { - outSrc.puts(s"${privateMemberName(RawIdentifier(id))} = ${newVector(CalcBytesType)};") - if (needRaw.hasIO) { - outSrc.puts(s"${privateMemberName(IoStorageIdentifier(RawIdentifier(id)))} = ${newVector(OwnedKaitaiStreamType)};") - } - } - if (needRaw.level >= 2) { - outSrc.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = ${newVector(CalcBytesType)};") - } outSrc.puts(s"${privateMemberName(id)} = ${newVector(dataType)};") } diff --git a/shared/src/main/scala/io/kaitai/struct/languages/GoCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/GoCompiler.scala index fbeac77c7..4afa8dae4 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/GoCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/GoCompiler.scala @@ -293,7 +293,7 @@ class GoCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit = { + override def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit = { // slices don't have to be manually initialized in Go: the built-in append() // function works even on `nil` slices (https://go.dev/tour/moretypes/15) } diff --git a/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala index 6fadb5d0f..231b4aeab 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala @@ -352,13 +352,8 @@ class JavaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit = { - if (needRaw.level >= 1) - out.puts(s"${privateMemberName(RawIdentifier(id))} = new ArrayList();") - if (needRaw.level >= 2) - out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = new ArrayList();") + override def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit = out.puts(s"${privateMemberName(id)} = new ${kaitaiType2JavaType(ArrayTypeInStream(dataType))}();") - } override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType): Unit = { out.puts("{") diff --git a/shared/src/main/scala/io/kaitai/struct/languages/JavaScriptCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/JavaScriptCompiler.scala index ded1ba36c..17d6db711 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/JavaScriptCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/JavaScriptCompiler.scala @@ -295,13 +295,8 @@ class JavaScriptCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts("}") } - override def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit = { - if (needRaw.level >= 1) - out.puts(s"${privateMemberName(RawIdentifier(id))} = [];") - if (needRaw.level >= 2) - out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = [];") + override def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit = out.puts(s"${privateMemberName(id)} = [];") - } override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType): Unit = { out.puts("var i = 0;") diff --git a/shared/src/main/scala/io/kaitai/struct/languages/LuaCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/LuaCompiler.scala index ec17a8949..45e9464c8 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/LuaCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/LuaCompiler.scala @@ -1,7 +1,7 @@ package io.kaitai.struct.languages import io.kaitai.struct.{ClassTypeProvider, RuntimeConfig, Utils} -import io.kaitai.struct.datatype.{DataType, FixedEndian, InheritedEndian, KSError, ValidationNotEqualError, NeedRaw} +import io.kaitai.struct.datatype.{DataType, FixedEndian, InheritedEndian, KSError, ValidationNotEqualError} import io.kaitai.struct.datatype.DataType._ import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.format._ @@ -162,11 +162,7 @@ class LuaCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.puts("end") } - override def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit = { - if (needRaw.level >= 1) - out.puts(s"${privateMemberName(RawIdentifier(id))} = {}") - if (needRaw.level >= 2) - out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = {}") + override def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit = { out.puts(s"${privateMemberName(id)} = {}") } diff --git a/shared/src/main/scala/io/kaitai/struct/languages/NimCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/NimCompiler.scala index f3f3e2bc3..565ef2700 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/NimCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/NimCompiler.scala @@ -153,7 +153,7 @@ class NimCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) universalFooter } - override def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit = { + override def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit = { // sequences don't have to be manually initialized in Nim - they're automatically initialized as // empty sequences (see https://narimiran.github.io/nim-basics/#_result_variable) } diff --git a/shared/src/main/scala/io/kaitai/struct/languages/PHPCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/PHPCompiler.scala index 66bc53e7f..672fcab3b 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/PHPCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/PHPCompiler.scala @@ -1,7 +1,7 @@ package io.kaitai.struct.languages import io.kaitai.struct.datatype.DataType._ -import io.kaitai.struct.datatype.{CalcEndian, DataType, FixedEndian, InheritedEndian, KSError, NeedRaw, UndecidedEndiannessError} +import io.kaitai.struct.datatype.{CalcEndian, DataType, FixedEndian, InheritedEndian, KSError, UndecidedEndiannessError} import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.format.{NoRepeat, RepeatEos, RepeatExpr, RepeatSpec, _} import io.kaitai.struct.languages.components._ @@ -267,13 +267,8 @@ class PHPCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit = { - if (needRaw.level >= 1) - out.puts(s"${privateMemberName(RawIdentifier(id))} = [];") - if (needRaw.level >= 2) - out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = [];") + override def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit = out.puts(s"${privateMemberName(id)} = [];") - } override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType): Unit = { out.puts("$i = 0;") diff --git a/shared/src/main/scala/io/kaitai/struct/languages/PerlCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/PerlCompiler.scala index bdf5d962b..732da5622 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/PerlCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/PerlCompiler.scala @@ -1,6 +1,6 @@ package io.kaitai.struct.languages -import io.kaitai.struct.datatype.{DataType, FixedEndian, InheritedEndian, KSError, NeedRaw} +import io.kaitai.struct.datatype.{DataType, FixedEndian, InheritedEndian, KSError} import io.kaitai.struct.datatype.DataType._ import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.exprlang.Ast.expr @@ -236,13 +236,8 @@ class PerlCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit = { - if (needRaw.level >= 1) - out.puts(s"${privateMemberName(RawIdentifier(id))} = [];") - if (needRaw.level >= 2) - out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = [];") + override def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit = out.puts(s"${privateMemberName(id)} = [];") - } override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType): Unit = { out.puts(s"while (!$io->is_eof()) {") diff --git a/shared/src/main/scala/io/kaitai/struct/languages/PythonCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/PythonCompiler.scala index b828eb6d2..abfda41bb 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/PythonCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/PythonCompiler.scala @@ -301,13 +301,8 @@ class PythonCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit = { - if (needRaw.level >= 1) - out.puts(s"${privateMemberName(RawIdentifier(id))} = []") - if (needRaw.level >= 2) - out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = []") + override def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit = out.puts(s"${privateMemberName(id)} = []") - } override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType): Unit = { out.puts("i = 0") diff --git a/shared/src/main/scala/io/kaitai/struct/languages/RubyCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/RubyCompiler.scala index 12382b879..6ce5d98e9 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/RubyCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/RubyCompiler.scala @@ -275,13 +275,8 @@ class RubyCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit = { - if (needRaw.level >= 1) - out.puts(s"${privateMemberName(RawIdentifier(id))} = []") - if (needRaw.level >= 2) - out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = []") + override def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit = out.puts(s"${privateMemberName(id)} = []") - } override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType): Unit = { out.puts("i = 0") diff --git a/shared/src/main/scala/io/kaitai/struct/languages/RustCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/RustCompiler.scala index 0247113e0..0e55cb402 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/RustCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/RustCompiler.scala @@ -1,7 +1,7 @@ package io.kaitai.struct.languages import io.kaitai.struct.datatype.DataType._ -import io.kaitai.struct.datatype.{DataType, FixedEndian, InheritedEndian, KSError, NeedRaw} +import io.kaitai.struct.datatype.{DataType, FixedEndian, InheritedEndian, KSError} import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.format.{NoRepeat, RepeatEos, RepeatExpr, RepeatSpec, _} import io.kaitai.struct.languages.components._ @@ -253,13 +253,8 @@ class RustCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) out.inc } - override def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit = { - if (needRaw.level >= 1) - out.puts(s"${privateMemberName(RawIdentifier(id))} = vec!();") - if (needRaw.level >= 2) - out.puts(s"${privateMemberName(RawIdentifier(RawIdentifier(id)))} = vec!();") + override def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit = out.puts(s"${privateMemberName(id)} = vec!();") - } override def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType): Unit = { out.puts(s"while !$io.isEof() {") diff --git a/shared/src/main/scala/io/kaitai/struct/languages/components/AllocateAndStoreIO.scala b/shared/src/main/scala/io/kaitai/struct/languages/components/AllocateAndStoreIO.scala index 2166071dc..33fe36608 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/components/AllocateAndStoreIO.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/components/AllocateAndStoreIO.scala @@ -11,12 +11,6 @@ import io.kaitai.struct.format._ trait AllocateAndStoreIO extends ExtraAttrs { def allocateIO(id: Identifier, rep: RepeatSpec): String - override def extraAttrForIO(id: Identifier, rep: RepeatSpec): List[AttrSpec] = { - val ioId = IoStorageIdentifier(id) - val ioType = rep match { - case NoRepeat => OwnedKaitaiStreamType - case _ => ArrayTypeInStream(OwnedKaitaiStreamType) - } - List(AttrSpec(List(), ioId, ioType)) - } + override def extraAttrForIO(id: Identifier, rep: RepeatSpec): List[AttrSpec] = + List(AttrSpec(List(), IoStorageIdentifier(id), OwnedKaitaiStreamType, ConditionalSpec(None, rep))) } diff --git a/shared/src/main/scala/io/kaitai/struct/languages/components/CommonReads.scala b/shared/src/main/scala/io/kaitai/struct/languages/components/CommonReads.scala index 2a73c3d1d..13e79fabb 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/components/CommonReads.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/components/CommonReads.scala @@ -67,7 +67,7 @@ trait CommonReads extends LanguageCompiler { def attrParse0(id: Identifier, attr: AttrLikeSpec, io: String, defEndian: Option[FixedEndian]): Unit = { if (attr.cond.repeat != NoRepeat) - condRepeatCommonInit(id, attr.dataType, needRaw(attr.dataType)) + (ExtraAttrs.forAttr(attr, this) ++ List(attr)).foreach(a => condRepeatInitAttr(a.id, a.dataType)) attr.cond.repeat match { case RepeatEos => condRepeatEosHeader(id, io, attr.dataType) diff --git a/shared/src/main/scala/io/kaitai/struct/languages/components/LanguageCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/components/LanguageCompiler.scala index 038a3d688..76fc21a3c 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/components/LanguageCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/components/LanguageCompiler.scala @@ -1,6 +1,6 @@ package io.kaitai.struct.languages.components -import io.kaitai.struct.datatype.{DataType, Endianness, FixedEndian, InheritedEndian, NeedRaw} +import io.kaitai.struct.datatype.{DataType, Endianness, FixedEndian, InheritedEndian} import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.format._ import io.kaitai.struct.translators.AbstractTranslator @@ -131,7 +131,7 @@ abstract class LanguageCompiler( def condIfHeader(expr: Ast.expr): Unit def condIfFooter(expr: Ast.expr): Unit - def condRepeatCommonInit(id: Identifier, dataType: DataType, needRaw: NeedRaw): Unit + def condRepeatInitAttr(id: Identifier, dataType: DataType): Unit def condRepeatEosHeader(id: Identifier, io: String, dataType: DataType): Unit def condRepeatEosFooter: Unit