All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.kaitai.struct.translators.NimTranslator.scala Maven / Gradle / Ivy

package io.kaitai.struct.translators

import io.kaitai.struct.{ImportList, Utils}
import io.kaitai.struct.exprlang.Ast
import io.kaitai.struct.exprlang.Ast._
import io.kaitai.struct.datatype._
import io.kaitai.struct.datatype.DataType
import io.kaitai.struct.datatype.DataType._
import io.kaitai.struct.format.Identifier
import io.kaitai.struct.languages.NimCompiler.{ksToNim, namespaced, camelCase}

class NimTranslator(provider: TypeProvider, importList: ImportList) extends BaseTranslator(provider) {
  // Members declared in io.kaitai.struct.translators.BaseTranslator
  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 doEnumByLabel(enumTypeAbs: List[String], label: String): String = s"${namespaced(enumTypeAbs)}($label)"
  override def doEnumByLabel(enumTypeAbs: List[String], label: String): String = s"${enumTypeAbs.head}.$label"
  override def doName(s: String): String =
    s match {
      case Identifier.ROOT => "root"
      case Identifier.PARENT => "parent"
      case Identifier.IO => "io"
      case Identifier.ITERATOR => "it"
      case Identifier.ITERATOR2 => "buf"
      case Identifier.INDEX => "i"
      case Identifier.SWITCH_ON => "on"
      case Identifier.IS_LE => "isLe"
      case Identifier.SIZEOF => "size"
      case _ => s"${camelCase(s, false)}"
    }
  override def doLocalName(s: String): String =
    s match {
      case Identifier.ITERATOR => doName(s)
      case Identifier.INDEX => doName(s)
      case Identifier.ROOT => s"${ksToNim(provider.determineType(Identifier.ROOT))}(this.${doName(s)})"
      case _ => s"this.${doName(s)}"
    }
  override def doIfExp(condition: expr, ifTrue: expr, ifFalse: expr): String =
    s"(if ${translate(condition)}: ${translate(ifTrue)} else: ${translate(ifFalse)})"
  override def arraySubscript(container: expr, idx: expr): String =
    s"${translate(container)}[${translate(idx)}]"

  override def strConcat(left: Ast.expr, right: Ast.expr): String = "($" + s"${translate(left)} & " + "$" + s"${translate(right)})"

  // Members declared in io.kaitai.struct.translators.CommonMethods

  override def unaryOp(op: Ast.unaryop): String = op match {
    case Ast.unaryop.Invert => "not"
    case Ast.unaryop.Minus => "-"
    case Ast.unaryop.Not => "not"
  }

  override def booleanOp(op: Ast.boolop): String = op match {
      case Ast.boolop.And => "and"
      case Ast.boolop.Or => "or"
  }

  override def binOp(op: Ast.operator): String = {
    op match {
      case Ast.operator.Add => "+"
      case Ast.operator.Sub => "-"
      case Ast.operator.Mult => "*"
      case Ast.operator.Div => "div"
      case Ast.operator.Mod => "%%%"
      case Ast.operator.BitAnd => "and"
      case Ast.operator.BitOr => "or"
      case Ast.operator.BitXor => "xor"
      case Ast.operator.LShift => "shl"
      case Ast.operator.RShift => "shr"
    }
  }
  override def doCast(value: Ast.expr, typeName: DataType): String =
    typeName match {
      case at: ArrayType => {
        importList.add("sequtils")
        s"${translate(value)}.mapIt(it.${ksToNim(at.elType)})"
      }
      case _ => s"(${ksToNim(typeName)}(${translate(value)}))"
    }
  override def doIntLiteral(n: BigInt): String = {
    if (n <= -2147483649L) { // -9223372036854775808..-2147483649
      s"$n'i64"
    } else if (n <= 2147483647L) { // -2147483648..2147483647
      s"$n"
    } else if (n <= 9223372036854775807L) { // 2147483648..9223372036854775807
      s"$n'i64"
    } else if (n <= Utils.MAX_UINT64) { // 9223372036854775807..18446744073709551615
      s"$n'u64"
    } else {
      s"$n"
    }
  }
  override def doArrayLiteral(t: DataType, value: Seq[expr]): String = {
    val contents = value.map(v => s"${ksToNim(t)}(${translate(v)})").mkString(", ")
    s"@[$contents]"
  }
  override def doByteArrayLiteral(arr: Seq[Byte]): String = {
    if (arr.size == 0)
      s"@[]"
    else
      "@[" + arr.map(b => {
        val ub: Int = b & 0xff
        ub
      }).mkString("'u8, ") + "'u8]"
  }
  override def doByteArrayNonLiteral(elts: Seq[expr]): String =
    s"@[${elts.map(translate).mkString(", ")}]"
  override def arrayFirst(a: expr): String = s"${translate(a)}[0]"
  override def arrayLast(a: expr): String = s"${translate(a)}[^1]"
  override def arrayMax(a: expr): String = s"max(${translate(a)})"
  override def arrayMin(a: expr): String = s"min(${translate(a)})"
  override def arraySize(a: expr): String = s"len(${translate(a)})"
  override def enumToInt(v: expr, et: EnumType): String = s"ord(${translate(v)})"
  override def floatToInt(v: expr): String = s"int(${translate(v)})"
  override def intToStr(v: expr, base: expr): String = {
    importList.add("strutils")
    s"intToStr(int(${translate(v)}))"
  }
  override def strLength(s: expr): String = s"len(${translate(s)})"
  override def strReverse(s: expr): String = {
    importList.add("unicode")
    s"reversed(${translate(s)})"
  }
  override def strSubstring(s: expr, from: expr, to: expr): String =
    s"${translate(s)}.substr(${translate(from)}, ${translate(to)} - 1)"
  override def strToInt(s: expr, base: expr): String =
    s"${translate(s)}.parseInt(${translate(base)})"
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy