From af235badc247d515f8173c52a453316927f05e9f Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 18 Mar 2024 20:17:05 +0500 Subject: [PATCH 1/4] Lua: implement doByteArrayNonLiteral - create array from expression of `bytes` type Expressions of this type are created using: - omitting the `type:` field in attributes and parse instances - declaring parameters with `type: bytes` - using `.as` cast Fixes test ``` [info] - lua:[0 + 1, 5].as *** FAILED *** [info] scala.NotImplementedError: an implementation is missing [info] at scala.Predef$.$qmark$qmark$qmark(Predef.scala:344) [info] at io.kaitai.struct.translators.BaseTranslator.doByteArrayNonLiteral(BaseTranslator.scala:179) [info] at io.kaitai.struct.translators.BaseTranslator.doByteArrayNonLiteral(BaseTranslator.scala:28) [info] at io.kaitai.struct.translators.CommonArraysAndCast.doByteArray(CommonArraysAndCast.scala:85) [info] at io.kaitai.struct.translators.CommonArraysAndCast.doCastOrArray(CommonArraysAndCast.scala:62) [info] at io.kaitai.struct.translators.CommonArraysAndCast.doCastOrArray$(CommonArraysAndCast.scala:53) [info] at io.kaitai.struct.translators.BaseTranslator.doCastOrArray(BaseTranslator.scala:28) [info] at io.kaitai.struct.translators.BaseTranslator.translate(BaseTranslator.scala:147) [info] at io.kaitai.struct.translators.AbstractTranslator.translate(AbstractTranslator.scala:25) [info] at io.kaitai.struct.translators.AbstractTranslator.translate$(AbstractTranslator.scala:25) [info] ... ``` --- .../scala/io/kaitai/struct/translators/TranslatorSpec.scala | 2 +- .../scala/io/kaitai/struct/translators/LuaTranslator.scala | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/jvm/src/test/scala/io/kaitai/struct/translators/TranslatorSpec.scala b/jvm/src/test/scala/io/kaitai/struct/translators/TranslatorSpec.scala index 8db8d279a..6eda8e453 100644 --- a/jvm/src/test/scala/io/kaitai/struct/translators/TranslatorSpec.scala +++ b/jvm/src/test/scala/io/kaitai/struct/translators/TranslatorSpec.scala @@ -859,7 +859,7 @@ class TranslatorSpec extends AnyFunSpec { GoCompiler -> "[]uint8{0 + 1, 5}", JavaCompiler -> "new byte[] { 0 + 1, 5 }", JavaScriptCompiler -> "new Uint8Array([0 + 1, 5])", - LuaCompiler -> "???", + LuaCompiler -> "string.char(0 + 1, 5)", PerlCompiler -> "pack('C*', (0 + 1, 5))", PHPCompiler -> "pack('C*', 0 + 1, 5)", PythonCompiler -> "struct.pack('2B', 0 + 1, 5)", 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 5d45b0a3a..f2dcad1ec 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/LuaTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/LuaTranslator.scala @@ -67,10 +67,14 @@ class LuaTranslator(provider: TypeProvider, importList: ImportList) extends Base override def doBoolLiteral(n: Boolean): String = if (n) "true" else "false" + override def doArrayLiteral(t: DataType, value: Seq[Ast.expr]): String = "{" + value.map((v) => translate(v)).mkString(", ") + "}" override def doByteArrayLiteral(arr: Seq[Byte]): String = "\"" + decEscapeByteArray(arr) + "\"" + override def doByteArrayNonLiteral(values: Seq[Ast.expr]): String = + // It is assumed that every expression produces integer in the range [0; 255] + "string.char(" + values.map(translate).mkString(", ") + ")" override def doLocalName(s: String) = s match { case Identifier.ITERATOR => "_" From c8bd711fad2bb2ad84aa7c0f11ea6d7c5c65769b Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 18 Mar 2024 20:28:07 +0500 Subject: [PATCH 2/4] C++: implement doByteArrayNonLiteral - create array from expression of `bytes` type Expressions of this type are created using: - omitting the `type:` field in attributes and parse instances - declaring parameters with `type: bytes` - using `.as` cast Ghostly fixes test ``` [info] - cpp_stl:[0 + 1, 5].as *** FAILED *** [info] scala.NotImplementedError: an implementation is missing [info] at scala.Predef$.$qmark$qmark$qmark(Predef.scala:344) [info] at io.kaitai.struct.translators.BaseTranslator.doByteArrayNonLiteral(BaseTranslator.scala:179) [info] at io.kaitai.struct.translators.BaseTranslator.doByteArrayNonLiteral(BaseTranslator.scala:28) [info] at io.kaitai.struct.translators.CommonArraysAndCast.doByteArray(CommonArraysAndCast.scala:85) [info] at io.kaitai.struct.translators.CommonArraysAndCast.doCastOrArray(CommonArraysAndCast.scala:62) [info] at io.kaitai.struct.translators.CommonArraysAndCast.doCastOrArray$(CommonArraysAndCast.scala:53) [info] at io.kaitai.struct.translators.BaseTranslator.doCastOrArray(BaseTranslator.scala:28) [info] at io.kaitai.struct.translators.BaseTranslator.translate(BaseTranslator.scala:147) [info] at io.kaitai.struct.translators.AbstractTranslator.translate(AbstractTranslator.scala:25) [info] at io.kaitai.struct.translators.AbstractTranslator.translate$(AbstractTranslator.scala:25) [info] ... ``` (actually, test is failing because option `useListInitializers` in C++ backend is not set in tests and code generation without it is not unimplemented right now) --- .../kaitai/struct/translators/TranslatorSpec.scala | 2 +- .../io/kaitai/struct/translators/CppTranslator.scala | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/jvm/src/test/scala/io/kaitai/struct/translators/TranslatorSpec.scala b/jvm/src/test/scala/io/kaitai/struct/translators/TranslatorSpec.scala index 6eda8e453..768cbad04 100644 --- a/jvm/src/test/scala/io/kaitai/struct/translators/TranslatorSpec.scala +++ b/jvm/src/test/scala/io/kaitai/struct/translators/TranslatorSpec.scala @@ -854,7 +854,7 @@ class TranslatorSpec extends AnyFunSpec { describe("to do type enforcement") { // type enforcement: casting to non-literal byte array full("[0 + 1, 5].as", CalcIntType, CalcBytesType, ResultMap( - CppCompiler -> "???", + CppCompiler -> "std::string({static_cast(0 + 1), static_cast(5)})", CSharpCompiler -> "new byte[] { 0 + 1, 5 }", GoCompiler -> "[]uint8{0 + 1, 5}", JavaCompiler -> "new byte[] { 0 + 1, 5 }", 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 dccb1c0ab..da8edadfc 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala @@ -113,12 +113,22 @@ class CppTranslator(provider: TypeProvider, importListSrc: CppImportList, import // TODO: C++14 } } else { - throw new RuntimeException("C++ literal arrays are not implemented yet") + throw new RuntimeException("C++ literal arrays are not implemented yet without list initializers") } } override def doByteArrayLiteral(arr: Seq[Byte]): String = "std::string(\"" + Utils.hexEscapeByteArray(arr) + "\", " + arr.length + ")" + override def doByteArrayNonLiteral(values: Seq[Ast.expr]): String = { + // It is assumed that every expression produces integer in the range [0; 255] + if (config.cppConfig.useListInitializers) { + "std::string({" + values.map(value => s"static_cast(${translate(value)})").mkString(", ") + "})" + } else { + // TODO: We need to produce an expression, but this is possible only with initializer lists + // or variadic templates (if use a helper function) which both available only since C++11 + throw new RuntimeException("C++ non-literal arrays are not implemented yet without list initializers") + } + } override def genericBinOp(left: Ast.expr, op: Ast.operator, right: Ast.expr, extPrec: Int) = { (detectType(left), detectType(right), op) match { From 208cf53a8ae6d81e9591152998770fc466b7e2ae Mon Sep 17 00:00:00 2001 From: Petr Pucil Date: Thu, 3 Oct 2024 01:26:16 +0200 Subject: [PATCH 3/4] C++: improve "not yet implemented" error messages --- .../scala/io/kaitai/struct/translators/CppTranslator.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 da8edadfc..7821eabcc 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala @@ -113,7 +113,7 @@ class CppTranslator(provider: TypeProvider, importListSrc: CppImportList, import // TODO: C++14 } } else { - throw new RuntimeException("C++ literal arrays are not implemented yet without list initializers") + throw new RuntimeException("literal arrays are not yet implemented for C++98 (pass `--cpp-standard 11` to target C++11)") } } @@ -126,7 +126,7 @@ class CppTranslator(provider: TypeProvider, importListSrc: CppImportList, import } else { // TODO: We need to produce an expression, but this is possible only with initializer lists // or variadic templates (if use a helper function) which both available only since C++11 - throw new RuntimeException("C++ non-literal arrays are not implemented yet without list initializers") + throw new RuntimeException("non-literal byte arrays are not yet implemented for C++98 (pass `--cpp-standard 11` to target C++11)") } } From cd3c0e3e821677780fd0d4174100a699c47a864b Mon Sep 17 00:00:00 2001 From: Petr Pucil Date: Thu, 3 Oct 2024 01:34:42 +0200 Subject: [PATCH 4/4] CppTranslator: language fixes in code comment --- .../scala/io/kaitai/struct/translators/CppTranslator.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 7821eabcc..6d29c800e 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/CppTranslator.scala @@ -124,8 +124,9 @@ class CppTranslator(provider: TypeProvider, importListSrc: CppImportList, import if (config.cppConfig.useListInitializers) { "std::string({" + values.map(value => s"static_cast(${translate(value)})").mkString(", ") + "})" } else { - // TODO: We need to produce an expression, but this is possible only with initializer lists - // or variadic templates (if use a helper function) which both available only since C++11 + // TODO: We need to produce an expression, but this is only possible using + // initializer lists or variadic templates (if we use a helper function), + // both of which are only available since C++11 throw new RuntimeException("non-literal byte arrays are not yet implemented for C++98 (pass `--cpp-standard 11` to target C++11)") } }