Skip to content

compiler: Incorrect code gen for anon switch with default field #132

@extremeheat

Description

@extremeheat

https://github.com/PrismarineJS/minecraft-data/blob/c6a1e9af1a144d78d7d020ee55029aa1d3922a34/data/bedrock/1.18.0/protocol.json#L6571-L6617

above uses an anonymous switch field with a default condition, but the compiler generates code that repeatedly reads the default condition (minecart_entity_runtime_id):

packet_command_block_update: (buffer, offset) => {
  let { value: is_block, size: is_blockSize } = (ctx.bool)(buffer, offset)
  let { value: position, size: positionSize } = ((buffer, offset) => {
    switch (is_block) {
      case true: return (ctx.BlockCoordinates)(buffer, offset)
      default: return ((buffer, offset) => {
        let { value: minecart_entity_runtime_id, size: minecart_entity_runtime_idSize } = (ctx.varint64)(buffer, offset) // <==
        return { value: { minecart_entity_runtime_id }, size: minecart_entity_runtime_idSize}
      })(buffer, offset)
    }
  })(buffer, offset + is_blockSize)
  let { value: mode, size: modeSize } = ((buffer, offset) => {
    switch (is_block) {
      case true: return ((buffer, offset) => {
        const { value, size } = (ctx.varint)(buffer, offset)
        return { value: {"0":"impulse","1":"repeat","2":"chain"}[value] || value, size }
      })(buffer, offset)
      default: return ((buffer, offset) => {
        let { value: minecart_entity_runtime_id, size: minecart_entity_runtime_idSize } = (ctx.varint64)(buffer, offset)
        return { value: { minecart_entity_runtime_id }, size: minecart_entity_runtime_idSize}
      })(buffer, offset)
    }
  })(buffer, offset + is_blockSize + positionSize)
  let { value: needs_redstone, size: needs_redstoneSize } = ((buffer, offset) => {
    switch (is_block) {
      case true: return (ctx.bool)(buffer, offset)
      default: return ((buffer, offset) => {
        let { value: minecart_entity_runtime_id, size: minecart_entity_runtime_idSize } = (ctx.varint64)(buffer, offset)
        return { value: { minecart_entity_runtime_id }, size: minecart_entity_runtime_idSize}
      })(buffer, offset)
    }
  })(buffer, offset + is_blockSize + positionSize + modeSize)
  let { value: conditional, size: conditionalSize } = ((buffer, offset) => {
    switch (is_block) {
      case true: return (ctx.bool)(buffer, offset)
      default: return ((buffer, offset) => {
        let { value: minecart_entity_runtime_id, size: minecart_entity_runtime_idSize } = (ctx.varint64)(buffer, offset)
        return { value: { minecart_entity_runtime_id }, size: minecart_entity_runtime_idSize}
      })(buffer, offset)
    }
  })(buffer, offset + is_blockSize + positionSize + modeSize + needs_redstoneSize)
  let { value: minecart_entity_runtime_id, size: minecart_entity_runtime_idSize } = ((buffer, offset) => {
    switch (is_block) {
      default: return (ctx.varint64)(buffer, offset)
    }
  })(buffer, offset + is_blockSize + positionSize + modeSize + needs_redstoneSize + conditionalSize)

not using an anon field or not using default generates correct code, e.g.

  let { value: data, size: dataSize } = ((buffer, offset) => {
        switch (is_block) {
          case true: return ((buffer, offset) => {
            let { value: position1, size: position1Size } = (ctx.BlockCoordinates)(buffer, offset)
            let { value: mode1, size: mode1Size } = ((buffer, offset) => {
              const { value, size } = (ctx.varint)(buffer, offset)
              return { value: {"0":"impulse","1":"repeat","2":"chain"}[value] || value, size }
            })(buffer, offset + position1Size)
            let { value: needs_redstone, size: needs_redstoneSize } = (ctx.bool)(buffer, offset + position1Size + mode1Size)
            let { value: conditional, size: conditionalSize } = (ctx.bool)(buffer, offset + position1Size + mode1Size + needs_redstoneSize)
            return { value: { position: position1, mode: mode1, needs_redstone, conditional }, size: position1Size + mode1Size + needs_redstoneSize + conditionalSize}
          })(buffer, offset)
          default: return ((buffer, offset) => {
            let { value: minecart_entity_runtime_id, size: minecart_entity_runtime_idSize } = (ctx.varint64)(buffer, offset)
            return { value: { minecart_entity_runtime_id }, size: minecart_entity_runtime_idSize}
          })(buffer, offset)
        }
      })(buffer, offset + is_blockSize)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions