Skip to content

Inconsistent compiler generated code when 'repition index' is used in 'repeat-until' expression #958

@transverberate

Description

@transverberate

Issue

I have a situation where there is a list of data types.
Before the list-entries (entries) are given, a maximum number of entries is given (max_num_entries) at the head of the list.

Additionally, any list entry may meet a condition which denotes it as the terminal entry - ending the list preemptively (before the max number of entries is reached).

Here is a minimal example of the phenomena
(Note that for this particular example there is a more elegant/proper solution; this is merely illustrating the problem).

seq:
  - id: first_list
    type: list_type
  - id: second_list
    type: list_type
types: 
  list_type:
    seq:
      - id: max_num_entries
        type: u1
      - id: entries
        type: u1  # in reality the entry is more complex than a 'u1'
        repeat: until
        # in reality the terminator is more complex than a value of '0xFF'
        repeat-until: _ == 0xFF or _index >= max_num_entries

Here, a repeat-until expression checks to see if either the
terminal condition _ == 0xFF is met or if the _index exceeds the max number of entries.

The behavior of the javascript compiler (and kaitai IDE) is as expected.
Here is the noteworthy piece of code generated:

ListType.prototype._read = function() {
  this.maxNumEntries = this._io.readU1();
  this.entries = []
  var i = 0;
  do {
    var _ = this._io.readU1();
    this.entries.push(_);
    i++;
  } while (!( ((_ == 255) || (i >= this.maxNumEntries)) ));
}

Compare this to the python output of the compiler

def _read(self):
    self.max_num_entries = self._io.read_u1()
    self.entries = []
    i = 0
    while True:
        _ = self._io.read_u1()
        self.entries.append(_)
        if  ((_ == 255) or (i >= self.max_num_entries)) :
            break
        i += 1

Hopefully the problem here is apparent - the value of i is incremented before the loop check in the javascript code,
while the value of i is incremented after the loop check in the python code.
In order to achieve the same behavior for python, the ksy must be modified to

repeat-until: _ == 0xFF or _index >= (max_num_entries - 1)

Proposed Fix

For each target language, ensure that the 'loop check' generated by a repeat-until expression is
the last thing to execute in its requisite repeat block.

I've searched the issues and haven't found anything similar,
however I may not have been using the appropriate keywords.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions