Add LEB128 integer support v0.4.0
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 29 Sep 2023 17:10:59 +0000 (13:10 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 29 Sep 2023 17:26:42 +0000 (13:26 -0400)
This patch adds unsigned and signed LEB128 [1] integer support with the
following Normand format:

    {my_val : uleb128}
    {my_val : sleb128}

LEB128 is a popular variable-length integer encoding which has
CTF 2 [2], Android, HP, DWARF, WebAssembly, the xz format, and many more
as its users.

To avoid any confusion, the term "value" in the Normand project is
renamed to "fixed-length integer" (`README.adoc`, test names, and the
code itself).

The challenge for a LEB128 item is similar to a repetition with an
expression: you don't know the final length when parsing because it can
depend on preceding labels and variables. Therefore the repetition item
validation and handling code is reused.

The new test files with names containing `-byte` were randomly generated
using the `leb128` package, therefore Normand agrees with another LEB128
implementation.

[1]: https://en.wikipedia.org/wiki/LEB128
[2]: https://diamon.org/ctf/

Change-Id: Ieac783dcdd093e1b5c70396a12fc2b568c9885bb
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
110 files changed:
README.adoc
normand/normand.py
pyproject.toml
tests/fail-fl-int-32b-out-of-range-neg.nt [new file with mode: 0644]
tests/fail-fl-int-32b-out-of-range-pos.nt [new file with mode: 0644]
tests/fail-fl-int-8b-out-of-range-neg.nt [new file with mode: 0644]
tests/fail-fl-int-8b-out-of-range-pos.nt [new file with mode: 0644]
tests/fail-fl-int-empty-expr.nt [new file with mode: 0644]
tests/fail-fl-int-eval-type.nt [new file with mode: 0644]
tests/fail-fl-int-eval.nt [new file with mode: 0644]
tests/fail-fl-int-inval-len.nt [new file with mode: 0644]
tests/fail-fl-int-inval-syntax.nt [new file with mode: 0644]
tests/fail-fl-int-missing-bo.nt [new file with mode: 0644]
tests/fail-fl-int-missing-len.nt [new file with mode: 0644]
tests/fail-fl-int-unknown-name-1.nt [new file with mode: 0644]
tests/fail-fl-int-unknown-name-2.nt [new file with mode: 0644]
tests/fail-sleb128-empty-expr.nt [new file with mode: 0644]
tests/fail-uleb128-empty-expr.nt [new file with mode: 0644]
tests/fail-uleb128-eval-type.nt [new file with mode: 0644]
tests/fail-uleb128-eval.nt [new file with mode: 0644]
tests/fail-uleb128-inval-syntax.nt [new file with mode: 0644]
tests/fail-uleb128-unknown-name-1.nt [new file with mode: 0644]
tests/fail-uleb128-unknown-name-2.nt [new file with mode: 0644]
tests/fail-uleb128-unreachable-label-1.nt [new file with mode: 0644]
tests/fail-uleb128-unreachable-label-2.nt [new file with mode: 0644]
tests/fail-uleb128-unreachable-label-3.nt [new file with mode: 0644]
tests/fail-val-32b-out-of-range-neg.nt [deleted file]
tests/fail-val-32b-out-of-range-pos.nt [deleted file]
tests/fail-val-8b-out-of-range-neg.nt [deleted file]
tests/fail-val-8b-out-of-range-pos.nt [deleted file]
tests/fail-val-empty-expr.nt [deleted file]
tests/fail-val-eval-type.nt [deleted file]
tests/fail-val-eval.nt [deleted file]
tests/fail-val-inval-len.nt [deleted file]
tests/fail-val-inval-syntax.nt [deleted file]
tests/fail-val-missing-bo.nt [deleted file]
tests/fail-val-missing-len.nt [deleted file]
tests/fail-val-unknown-name-1.nt [deleted file]
tests/fail-val-unknown-name-2.nt [deleted file]
tests/fail-var-label-bo-none.nt
tests/pass-fl-int-16b-be.nt [new file with mode: 0644]
tests/pass-fl-int-16b-le.nt [new file with mode: 0644]
tests/pass-fl-int-24b-be.nt [new file with mode: 0644]
tests/pass-fl-int-24b-le.nt [new file with mode: 0644]
tests/pass-fl-int-32b-be.nt [new file with mode: 0644]
tests/pass-fl-int-32b-le.nt [new file with mode: 0644]
tests/pass-fl-int-40b-be.nt [new file with mode: 0644]
tests/pass-fl-int-40b-le.nt [new file with mode: 0644]
tests/pass-fl-int-48b-be.nt [new file with mode: 0644]
tests/pass-fl-int-48b-le.nt [new file with mode: 0644]
tests/pass-fl-int-56b-be.nt [new file with mode: 0644]
tests/pass-fl-int-56b-le.nt [new file with mode: 0644]
tests/pass-fl-int-64b-be.nt [new file with mode: 0644]
tests/pass-fl-int-64b-le.nt [new file with mode: 0644]
tests/pass-fl-int-8b.nt [new file with mode: 0644]
tests/pass-fl-int-icitte.nt [new file with mode: 0644]
tests/pass-readme-intro-leb128.nt [new file with mode: 0644]
tests/pass-readme-learn-fl-int-1.nt [new file with mode: 0644]
tests/pass-readme-learn-fl-int-2.nt [new file with mode: 0644]
tests/pass-readme-learn-fl-int-3.nt [new file with mode: 0644]
tests/pass-readme-learn-leb128-1.nt [new file with mode: 0644]
tests/pass-readme-learn-leb128-2.nt [new file with mode: 0644]
tests/pass-readme-learn-val-1.nt [deleted file]
tests/pass-readme-learn-val-2.nt [deleted file]
tests/pass-readme-learn-val-3.nt [deleted file]
tests/pass-sleb128-1-byte.nt [new file with mode: 0644]
tests/pass-sleb128-10-bytes.nt [new file with mode: 0644]
tests/pass-sleb128-2-bytes.nt [new file with mode: 0644]
tests/pass-sleb128-3-bytes.nt [new file with mode: 0644]
tests/pass-sleb128-4-bytes.nt [new file with mode: 0644]
tests/pass-sleb128-5-bytes.nt [new file with mode: 0644]
tests/pass-sleb128-6-bytes.nt [new file with mode: 0644]
tests/pass-sleb128-7-bytes.nt [new file with mode: 0644]
tests/pass-sleb128-8-bytes.nt [new file with mode: 0644]
tests/pass-sleb128-9-bytes.nt [new file with mode: 0644]
tests/pass-sleb128-limits.nt [new file with mode: 0644]
tests/pass-sleb128-minus-one.nt [new file with mode: 0644]
tests/pass-sleb128-zero.nt [new file with mode: 0644]
tests/pass-uleb128-1-byte.nt [new file with mode: 0644]
tests/pass-uleb128-10-bytes.nt [new file with mode: 0644]
tests/pass-uleb128-2-bytes.nt [new file with mode: 0644]
tests/pass-uleb128-3-bytes.nt [new file with mode: 0644]
tests/pass-uleb128-4-bytes.nt [new file with mode: 0644]
tests/pass-uleb128-5-bytes.nt [new file with mode: 0644]
tests/pass-uleb128-6-bytes.nt [new file with mode: 0644]
tests/pass-uleb128-7-bytes.nt [new file with mode: 0644]
tests/pass-uleb128-8-bytes.nt [new file with mode: 0644]
tests/pass-uleb128-9-bytes.nt [new file with mode: 0644]
tests/pass-uleb128-expr-label-inner.nt [new file with mode: 0644]
tests/pass-uleb128-expr-label.nt [new file with mode: 0644]
tests/pass-uleb128-expr-var-1.nt [new file with mode: 0644]
tests/pass-uleb128-expr-var-2.nt [new file with mode: 0644]
tests/pass-uleb128-limits.nt [new file with mode: 0644]
tests/pass-uleb128-zero.nt [new file with mode: 0644]
tests/pass-val-16b-be.nt [deleted file]
tests/pass-val-16b-le.nt [deleted file]
tests/pass-val-24b-be.nt [deleted file]
tests/pass-val-24b-le.nt [deleted file]
tests/pass-val-32b-be.nt [deleted file]
tests/pass-val-32b-le.nt [deleted file]
tests/pass-val-40b-be.nt [deleted file]
tests/pass-val-40b-le.nt [deleted file]
tests/pass-val-48b-be.nt [deleted file]
tests/pass-val-48b-le.nt [deleted file]
tests/pass-val-56b-be.nt [deleted file]
tests/pass-val-56b-le.nt [deleted file]
tests/pass-val-64b-be.nt [deleted file]
tests/pass-val-64b-le.nt [deleted file]
tests/pass-val-8b.nt [deleted file]
tests/pass-val-icitte.nt [deleted file]

index 1323570912776e7ef2d1948400bbe34091b4b4f1..e350be56c02d75b1861b2901577a90202bf560fc 100644 (file)
@@ -29,7 +29,7 @@ _**Normand**_ is a text-to-binary processor with its own language.
 This package offers both a portable {py3} module and a command-line
 tool.
 
-WARNING: This version of Normand is 0.1, meaning both the Normand
+WARNING: This version of Normand is 0.4, meaning both the Normand
 language and the module/CLI interface aren't stable.
 
 ifdef::env-github[]
@@ -133,7 +133,7 @@ Variables::
 The value of a variable assignment is the evaluation of a valid {py3}
 expression which may include label and variable names.
 
-Value encoding with a specific length (8{nbsp}bits to 64{nbsp}bits) and byte order::
+Fixed-length integer with a given length (8{nbsp}bits to 64{nbsp}bits) and byte order::
 +
 Input:
 +
@@ -149,7 +149,25 @@ Output:
 67 44 b2 00 2c 63 37 f8  ff ff
 ----
 +
-The encoded value is the evaluation of a valid {py3} expression which
+The encoded integer is the evaluation of a valid {py3} expression which
+may include label and variable names.
+
+https://en.wikipedia.org/wiki/LEB128[LEB128] integer::
++
+Input:
++
+----
+aa bb cc {-1993 : sleb128} <meow> dd ee ff
+{meow * 199 : uleb128}
+----
++
+Output:
++
+----
+aa bb cc b7 70 dd ee ff e3 07
+----
++
+The encoded integer is the evaluation of a valid {py3} expression which
 may include label and variable names.
 
 Repetition::
@@ -257,8 +275,9 @@ current state:
 
 |[[cur-offset]] Current offset
 |
-The current offset has an effect on the value of
-<<label,labels>> and of the special `ICITTE` name in <<value,value>> and
+The current offset has an effect on the value of <<label,labels>> and of
+the special `ICITTE` name in <<fixed-length-integer,fixed-length
+integer>>, <<leb-128-integer,LEB128 integer>>, and
 <<variable-assignment,variable assignment>> expression evaluation.
 
 Each generated byte increments the current offset.
@@ -270,7 +289,8 @@ current offset.
 
 |[[cur-bo]] Current byte order
 |
-The current byte order has an effect on the encoding of <<value,values>>.
+The current byte order has an effect on the encoding of
+<<fixed-length-integer,fixed-length integers>>.
 
 A <<current-byte-order-setting,current byte order setting>> may change
 the current byte order.
@@ -298,9 +318,12 @@ The available items are:
 * A <<current-byte-order-setting,current byte order setting>> (big or
   little endian).
 
-* A <<value,{py3} expression to be evaluated>> as an unsigned or signed
-  integer to be encoded on one or more bytes using the current byte
-  order.
+* A <<fixed-length-integer,fixed-length integer>> using the
+  <<cur-bo,current byte order>> and of which the value is the result of
+  a {py3} expression.
+
+* An <<leb128-integer,LEB128 integer>> of which the value is the result
+  of a {py3} expression.
 
 * A <<current-offset-setting,current offset setting>>.
 
@@ -533,31 +556,26 @@ The two accepted forms are:
 ``pass:[{be}]``:: Set the current byte order to big endian.
 ``pass:[{le}]``:: Set the current byte order to little endian.
 
-=== Value
-
-A _value_ represents a fixed number of bytes encoding an unsigned or
-signed integer which is the result of evaluating a {py3} expression
-using the <<cur-bo,current byte order>>.
-
-For a value at some source location{nbsp}__**L**__, its {py3} expression
-may contain the name of any accessible <<label,label>>, including the
-name of a label defined after{nbsp}__**L**__, as well as the name of any
-<<variable-assignment,variable>> known at{nbsp}__**L**__.
-
-An accessible label is either:
-
-* Outside of the current <<group,group>>.
-* Within the same immediate group (not within a nested group).
+=== Fixed-length integer
 
-In the {py3} expression of a value, the value of the special name
-`ICITTE` is the <<cur-offset,current offset>> (before encoding the
-value).
+A _fixed-length integer_ represents a fixed number of bytes encoding an
+unsigned or signed integer which is the result of evaluating a {py3}
+expression using the <<cur-bo,current byte order>>.
 
-A value is:
+A fixed-length integer is:
 
 . The ``pass:[{]`` prefix.
 
 . A valid {py3} expression.
++
+For a fixed-length integer at some source location{nbsp}__**L**__, this
+expression may contain the name of any accessible <<label,label>> (not
+within a nested group), including the name of a label defined
+after{nbsp}__**L**__, as well as the name of any
+<<variable-assignment,variable>> known at{nbsp}__**L**__.
++
+The value of the special name `ICITTE` in this expression is the
+<<cur-offset,current offset>> (before encoding the integer).
 
 . The `:` character.
 
@@ -617,6 +635,74 @@ Output:
 ----
 ====
 
+=== LEB128 integer
+
+An _LEB128 integer_ represents a variable number of bytes encoding an
+unsigned or signed integer which is the result of evaluating a {py3}
+expression following the https://en.wikipedia.org/wiki/LEB128[LEB128]
+format.
+
+An LEB128 integer is:
+
+. The ``pass:[{]`` prefix.
+
+. A valid {py3} expression.
++
+For an LEB128 integer at some source location{nbsp}__**L**__, this
+expression may contain:
++
+--
+* The name of any <<label,label>> defined before{nbsp}__**L**__.
+* The name of any <<variable-assignment,variable>> known at{nbsp}__**L**__
+  which doesn't, directly or indirectly, refer to a label
+  defined after{nbsp}__**L**__.
+--
++
+The value of the special name `ICITTE` in this expression is the
+<<cur-offset,current offset>> (before encoding the integer).
+
+. The `:` character.
+
+. One of:
++
+--
+[horizontal]
+`uleb128`:: Use the unsigned LEB128 format.
+`sleb128`:: Use the signed LEB128 format.
+--
+
+. The `}` suffix.
+
+====
+Input:
+
+----
+{624485 : uleb128}
+----
+
+Output:
+
+----
+e5 8e 26
+----
+====
+
+====
+Input:
+
+----
+aa bb cc dd
+<meow>
+ee ff
+{-981238311 + (meow * -23) : sleb128}
+"hello"
+----
+
+----
+aa bb cc dd ee ff fd fa  8d ac 7c 68 65 6c 6c 6f  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢|hello
+----
+====
+
 === Current offset setting
 
 This special item sets the <<cur-offset,_current offset_>>.
@@ -667,17 +753,16 @@ A _label_ associates a name to the <<cur-offset,current offset>>.
 
 All the labels of a whole Normand input must have unique names.
 
-A label may not share the name of a <<variable-assignment,variable>>
+A label must not share the name of a <<variable-assignment,variable>>
 name.
 
-A label name may not be `ICITTE` (see <<value>> and
-<<variable-assignment>> to learn more).
-
 A label is:
 
 . The `<` prefix.
 
-. A valid {py3} name which is not `ICITTE`.
+. A valid {py3} name which is not `ICITTE` (see
+  <<fixed-length-integer>>, <<leb128-integer>>, and
+  <<variable-assignment>> to learn more).
 
 . The `>` suffix.
 
@@ -686,30 +771,26 @@ A label is:
 A _variable assignment_ associates a name to the integral result of an
 evaluated {py3} expression.
 
-For a variable assignment at some source location{nbsp}__**L**__, its
-{py3} expression may contain the name of any accessible <<label,label>>,
-including the name of a label defined after{nbsp}__**L**__, as well as
-the name of any variable known at{nbsp}__**L**__.
-
-An accessible label is either:
-
-* Outside of the current <<group,group>>.
-* Within the same immediate group (not within a nested group).
-
-A variable name may not be `ICITTE`.
-
-In the {py3} expression of a variable assignment, the special name
-`ICITTE` is the <<cur-offset,current offset>>.
-
-A variable is:
+A variable assignment is:
 
 . The ``pass:[{]`` prefix.
 
-. A valid {py3} name which is not `ICITTE`.
+. A valid {py3} name which is not `ICITTE` (see
+  <<fixed-length-integer>>, <<leb128-integer>>, and
+  <<variable-assignment>> to learn more).
 
 . The `=` character.
 
 . A valid {py3} expression.
++
+For a variable assignment at some source location{nbsp}__**L**__, this
+expression may contain the name of any accessible <<label,label>> (not
+within a nested group), including the name of a label defined
+after{nbsp}__**L**__, as well as the name of any
+<<variable-assignment,variable>> known at{nbsp}__**L**__.
++
+The value of the special name `ICITTE` in this expression is the
+<<cur-offset,current offset>>.
 
 . The `}` suffix.
 
@@ -820,9 +901,20 @@ A repetition is:
 
 ** The ``pass:[{]`` prefix, a valid {py3} expression, and the
    ``pass:[}]`` suffix.
-
-When using an expression, it can't refer, directly or indirectly, to a
-subsequent label name and to the reserved `ICITTE` name.
++
+For a repetition at some source location{nbsp}__**L**__, this expression
+may contain:
++
+--
+* The name of any <<label,label>> defined before{nbsp}__**L**__ and
+  which isn't part of its repeated item.
+* The name of any <<variable-assignment,variable>> known
+  at{nbsp}__**L**__, which isn't part of its repeated item, and which
+  doesn't, directly or indirectly, refer to a label defined
+  after{nbsp}__**L**__.
+--
++
+This expression must not contain the special name `ICITTE`.
 
 ====
 Input:
index b6c470baf5e448e5823767ef1c51c92e4347d088..35c2330662ccb40ba67a1ab030e054408615a334 100644 (file)
@@ -30,7 +30,7 @@
 # Upstream repository: <https://github.com/efficios/normand>.
 
 __author__ = "Philippe Proulx"
-__version__ = "0.3.0"
+__version__ = "0.4.0"
 __all__ = [
     "ByteOrder",
     "parse",
@@ -47,6 +47,7 @@ import abc
 import ast
 import sys
 import enum
+import math
 import struct
 from typing import (
     Any,
@@ -245,8 +246,8 @@ class _VarAssign(_Item, _ExprMixin):
         )
 
 
-# Value, possibly needing more than one byte.
-class _Val(_ScalarItem, _RepableItem, _ExprMixin):
+# Fixed-length integer, possibly needing more than one byte.
+class _FlInt(_ScalarItem, _RepableItem, _ExprMixin):
     def __init__(
         self, expr_str: str, expr: ast.Expression, len: int, text_loc: TextLoc
     ):
@@ -264,11 +265,36 @@ class _Val(_ScalarItem, _RepableItem, _ExprMixin):
         return self._len // 8
 
     def __repr__(self):
-        return "_Val({}, {}, {}, {})".format(
+        return "_FlInt({}, {}, {}, {})".format(
             repr(self._expr_str), repr(self._expr), repr(self._len), self._text_loc
         )
 
 
+# LEB128 integer.
+class _Leb128Int(_Item, _RepableItem, _ExprMixin):
+    def __init__(self, expr_str: str, expr: ast.Expression, text_loc: TextLoc):
+        super().__init__(text_loc)
+        _ExprMixin.__init__(self, expr_str, expr)
+
+    def __repr__(self):
+        return "{}({}, {}, {})".format(
+            self.__class__.__name__,
+            repr(self._expr_str),
+            repr(self._expr),
+            self._text_loc,
+        )
+
+
+# Unsigned LEB128 integer.
+class _ULeb128Int(_Leb128Int, _RepableItem, _ExprMixin):
+    pass
+
+
+# Signed LEB128 integer.
+class _SLeb128Int(_Leb128Int, _RepableItem, _ExprMixin):
+    pass
+
+
 # Group of items.
 class _Group(_Item, _RepableItem):
     def __init__(self, items: List[_Item], text_loc: TextLoc):
@@ -305,7 +331,7 @@ class _Rep(_Item, _ExprMixin):
 
 
 # Expression item type.
-_ExprItemT = Union[_Val, _VarAssign, _Rep]
+_ExprItemT = Union[_FlInt, _Leb128Int, _VarAssign, _Rep]
 
 
 # A parsing error containing a message and a text location.
@@ -508,7 +534,7 @@ class _Parser:
             _raise_error("Invalid decimal byte value {}".format(val), begin_text_loc)
 
         # Two's complement
-        val = val % 256
+        val %= 256
 
         # Return item
         return _Byte(val, begin_text_loc)
@@ -629,13 +655,14 @@ class _Parser:
 
         return expr_str, expr
 
-    # Patterns for _try_parse_val_and_len()
-    _val_expr_pat = re.compile(r"([^}:]+):")
-    _val_len_pat = re.compile(r"\s*(8|16|24|32|40|48|56|64)")
+    # Patterns for _try_parse_val_and_attr()
+    _val_expr_pat = re.compile(r"([^}:]+):\s*")
+    _fl_int_len_attr_pat = re.compile(r"8|16|24|32|40|48|56|64")
+    _leb128_int_attr_pat = re.compile(r"(u|s)leb128")
 
-    # Tries to parse a value and length, returning a value item on
-    # success.
-    def _try_parse_val_and_len(self):
+    # Tries to parse a value and attribute (fixed length in bits or
+    # `leb128`), returning a value item on success.
+    def _try_parse_val_and_attr(self):
         begin_text_loc = self._text_loc
 
         # Match
@@ -645,23 +672,35 @@ class _Parser:
             # No match
             return
 
-        # Expect a length
-        m_len = self._expect_pat(
-            self._val_len_pat, "Expecting a length (multiple of eight bits)"
-        )
-
         # Create an expression node from the expression string
         expr_str, expr = self._ast_expr_from_str(m_expr.group(1), begin_text_loc)
 
-        # Return item
-        return _Val(
-            expr_str,
-            expr,
-            int(m_len.group(1)),
-            begin_text_loc,
-        )
+        # Length?
+        m_attr = self._try_parse_pat(self._fl_int_len_attr_pat)
+
+        if m_attr is None:
+            # LEB128?
+            m_attr = self._try_parse_pat(self._leb128_int_attr_pat)
+
+            if m_attr is None:
+                # At this point it's invalid
+                self._raise_error(
+                    "Expecting a length (multiple of eight bits), `uleb128`, or `sleb128`"
+                )
+
+            # Return LEB128 integer item
+            cls = _ULeb128Int if m_attr.group(1) == "u" else _SLeb128Int
+            return cls(expr_str, expr, begin_text_loc)
+        else:
+            # Return fixed-length integer item
+            return _FlInt(
+                expr_str,
+                expr,
+                int(m_attr.group(0)),
+                begin_text_loc,
+            )
 
-    # Patterns for _try_parse_val_and_len()
+    # Patterns for _try_parse_val_and_attr()
     _var_assign_pat = re.compile(
         r"(?P<name>{})\s*=\s*(?P<expr>[^}}]+)".format(_py_name_pat.pattern)
     )
@@ -741,8 +780,8 @@ class _Parser:
         item = self._try_parse_var_assign()
 
         if item is None:
-            # Value item?
-            item = self._try_parse_val_and_len()
+            # Fixed-length value item?
+            item = self._try_parse_val_and_attr()
 
             if item is None:
                 # Byte order setting item?
@@ -751,7 +790,7 @@ class _Parser:
                 if item is None:
                     # At this point it's invalid
                     self._raise_error(
-                        "Expecting a value, a variable assignment, or a byte order setting"
+                        "Expecting a fixed-length integer, a variable assignment, or a byte order setting"
                     )
 
         # Expect suffix
@@ -1086,12 +1125,12 @@ class _ExprValidator(_NodeVisitor):
                 name, self._item.expr_str
             )
 
-            if len(self._allowed_names) > 0:
-                allowed_names = self._allowed_names.copy()
+            allowed_names = self._allowed_names.copy()
 
-                if self._icitte_allowed:
-                    allowed_names.add(_icitte_name)
+            if self._icitte_allowed:
+                allowed_names.add(_icitte_name)
 
+            if len(allowed_names) > 0:
                 allowed_names_str = ", ".join(
                     sorted(["`{}`".format(name) for name in allowed_names])
                 )
@@ -1136,17 +1175,18 @@ class _GenState:
 #
 # The steps of generation are:
 #
-# 1. Validate that each repetition expression uses only reachable names
-#    and not `ICITTE`.
+# 1. Validate that each repetition and LEB128 integer expression uses
+#    only reachable names and not `ICITTE`.
 #
-# 2. Compute and keep the effective repetition count for each repetition
-#    instance.
+# 2. Compute and keep the effective repetition count and LEB128 integer
+#    value for each repetition and LEB128 integer instance.
 #
 # 3. Generate bytes, updating the initial state as it goes which becomes
 #    the final state after the operation.
 #
-#    During the generation, when handling a `_Rep` item, we already have
-#    the effective repetition count of the instance.
+#    During the generation, when handling a `_Rep` or `_Leb128Int` item,
+#    we already have the effective repetition count or value of the
+#    instance.
 #
 #    When handling a `_Group` item, first update the current labels with
 #    all the immediate (not nested) labels, and then handle each
@@ -1162,8 +1202,8 @@ class _Gen:
         offset: int,
         bo: Optional[ByteOrder],
     ):
-        self._validate_rep_exprs(group, set(variables.keys()), set(labels.keys()))
-        self._rep_instance_vals = self._compute_rep_instance_vals(
+        self._validate_vl_exprs(group, set(variables.keys()), set(labels.keys()))
+        self._vl_instance_vals = self._compute_vl_instance_vals(
             group, _GenState(variables, labels, offset, bo)
         )
         self._gen(group, _GenState(variables, labels, offset, bo))
@@ -1201,8 +1241,9 @@ class _Gen:
         visitor.visit(expr)
         return visitor.names
 
-    # Validates that all the repetition expressions within `group` don't
-    # refer, directly or indirectly, to subsequent labels.
+    # Validates that all the repetition and LEB128 integer expressions
+    # within `group` don't refer, directly or indirectly, to subsequent
+    # labels.
     #
     # The strategy here is to keep a set of allowed label names, per
     # group, initialized to `allowed_label_names`, and a set of allowed
@@ -1223,7 +1264,7 @@ class _Gen:
     #     it's in there): a variable which refers to an unreachable name
     #     is unreachable itself.
     #
-    # `_Rep`:
+    # `_Rep` and `_Leb128`:
     #     Make sure all the names within its expression are allowed.
     #
     # `_Group`:
@@ -1231,7 +1272,7 @@ class _Gen:
     #     the current allowed label names and the same current allowed
     #     variable names.
     @staticmethod
-    def _validate_rep_exprs(
+    def _validate_vl_exprs(
         item: _Item, allowed_variable_names: Set[str], allowed_label_names: Set[str]
     ):
         if type(item) is _Label:
@@ -1252,14 +1293,19 @@ class _Gen:
                 allowed_variable_names.add(item.name)
             elif item.name in allowed_variable_names:
                 allowed_variable_names.remove(item.name)
+        elif isinstance(item, _Leb128Int):
+            # Validate the expression (`ICITTE` allowed)
+            _ExprValidator(
+                item, allowed_label_names | allowed_variable_names, True
+            ).visit(item.expr)
         elif type(item) is _Rep:
-            # Validate the expression first
+            # Validate the expression first (`ICITTE` not allowed)
             _ExprValidator(
                 item, allowed_label_names | allowed_variable_names, False
             ).visit(item.expr)
 
             # Validate inner item
-            _Gen._validate_rep_exprs(
+            _Gen._validate_vl_exprs(
                 item.item, allowed_variable_names, allowed_label_names
             )
         elif type(item) is _Group:
@@ -1268,7 +1314,7 @@ class _Gen:
             group_allowed_label_names = allowed_label_names.copy()
 
             for subitem in item.items:
-                _Gen._validate_rep_exprs(
+                _Gen._validate_vl_exprs(
                     subitem, allowed_variable_names, group_allowed_label_names
                 )
 
@@ -1311,20 +1357,40 @@ class _Gen:
 
         return val
 
-    # Computes the effective value (multiplier) for each repetition
-    # instance, filling `instance_vals` (if not `None`) and returning
-    # `instance_vals`.
+    # Returns the size, in bytes, required to encode the value `val`
+    # with LEB128 (signed version if `is_signed` is `True`).
+    @staticmethod
+    def _leb128_size_for_val(val: int, is_signed: bool):
+        if val < 0:
+            # Equivalent upper bound.
+            #
+            # For example, if `val` is -128, then the full integer for
+            # this number of bits would be [-128, 127].
+            val = -val - 1
+
+        # Number of bits (add one for the sign if needed)
+        bits = val.bit_length() + int(is_signed)
+
+        if bits == 0:
+            bits = 1
+
+        # Seven bits per byte
+        return math.ceil(bits / 7)
+
+    # Computes the effective value for each repetition and LEB128
+    # integer instance, filling `instance_vals` (if not `None`) and
+    # returning `instance_vals`.
     #
-    # At this point it must be known that, for a given repetition, its
-    # expression only contains reachable names.
+    # At this point it must be known that, for a given variable-length
+    # item, its expression only contains reachable names.
     #
     # When handling a `_Rep` item, this function appends its effective
     # multiplier to `instance_vals` _before_ handling its repeated item.
     #
-    # When handling a `_VarAssign` item, this function only evaluates it if
-    # all its names are reachable.
+    # When handling a `_VarAssign` item, this function only evaluates it
+    # if all its names are reachable.
     @staticmethod
-    def _compute_rep_instance_vals(
+    def _compute_vl_instance_vals(
         item: _Item, state: _GenState, instance_vals: Optional[List[int]] = None
     ):
         if instance_vals is None:
@@ -1353,6 +1419,25 @@ class _Gen:
                 state.variables[item.name] = _Gen._eval_item_expr(item, state, True)
         elif type(item) is _SetOffset:
             state.offset = item.val
+        elif isinstance(item, _Leb128Int):
+            # Evaluate the expression
+            val = _Gen._eval_item_expr(item, state, True)
+
+            # Validate result
+            if type(item) is _ULeb128Int and val < 0:
+                _raise_error_for_item(
+                    "Invalid expression `{}`: unexpected negative result {:,} for a ULEB128 encoding".format(
+                        item.expr_str, val
+                    ),
+                    item,
+                )
+
+            # Add the evaluation result to the to variable-length item
+            # instance values.
+            instance_vals.append(val)
+
+            # Update offset
+            state.offset += _Gen._leb128_size_for_val(val, type(item) is _SLeb128Int)
         elif type(item) is _Rep:
             # Evaluate the expression and keep the result
             val = _Gen._eval_item_expr(item, state, False)
@@ -1371,83 +1456,94 @@ class _Gen:
 
             # Process the repeated item `val` times
             for _ in range(val):
-                _Gen._compute_rep_instance_vals(item.item, state, instance_vals)
+                _Gen._compute_vl_instance_vals(item.item, state, instance_vals)
         elif type(item) is _Group:
             prev_labels = state.labels.copy()
 
             # Process each item
             for subitem in item.items:
-                _Gen._compute_rep_instance_vals(subitem, state, instance_vals)
+                _Gen._compute_vl_instance_vals(subitem, state, instance_vals)
 
             state.labels = prev_labels
 
         return instance_vals
 
-    def _zero_item_size(self, item: _Item, next_rep_instance: int):
-        return 0, next_rep_instance
+    def _zero_item_size(self, item: _Item, next_vl_instance: int):
+        return 0, next_vl_instance
+
+    def _scalar_item_size(self, item: _ScalarItem, next_vl_instance: int):
+        return item.size, next_vl_instance
 
-    def _scalar_item_size(self, item: _ScalarItem, next_rep_instance: int):
-        return item.size, next_rep_instance
+    def _leb128_int_item_size(self, item: _Leb128Int, next_vl_instance: int):
+        # Get the value from `self._vl_instance_vals` _before_
+        # incrementing `next_vl_instance` to honor the order of
+        # _compute_vl_instance_vals().
+        return (
+            self._leb128_size_for_val(
+                self._vl_instance_vals[next_vl_instance], type(item) is _SLeb128Int
+            ),
+            next_vl_instance + 1,
+        )
 
-    def _group_item_size(self, item: _Group, next_rep_instance: int):
+    def _group_item_size(self, item: _Group, next_vl_instance: int):
         size = 0
 
         for subitem in item.items:
-            subitem_size, next_rep_instance = self._item_size(
-                subitem, next_rep_instance
-            )
+            subitem_size, next_vl_instance = self._item_size(subitem, next_vl_instance)
             size += subitem_size
 
-        return size, next_rep_instance
+        return size, next_vl_instance
 
-    def _rep_item_size(self, item: _Rep, next_rep_instance: int):
-        # Get the value from `self._rep_instance_vals` _before_
-        # incrementing `next_rep_instance` to honor the order of
-        # _compute_rep_instance_vals().
-        mul = self._rep_instance_vals[next_rep_instance]
-        next_rep_instance += 1
+    def _rep_item_size(self, item: _Rep, next_vl_instance: int):
+        # Get the value from `self._vl_instance_vals` _before_
+        # incrementing `next_vl_instance` to honor the order of
+        # _compute_vl_instance_vals().
+        mul = self._vl_instance_vals[next_vl_instance]
+        next_vl_instance += 1
         size = 0
 
         for _ in range(mul):
-            iter_size, next_rep_instance = self._item_size(item.item, next_rep_instance)
+            iter_size, next_vl_instance = self._item_size(item.item, next_vl_instance)
             size += iter_size
 
-        return size, next_rep_instance
+        return size, next_vl_instance
 
     # Returns the size of `item` and the new next repetition instance.
-    def _item_size(self, item: _Item, next_rep_instance: int):
-        return self._item_size_funcs[type(item)](item, next_rep_instance)
+    def _item_size(self, item: _Item, next_vl_instance: int):
+        return self._item_size_funcs[type(item)](item, next_vl_instance)
 
     # Handles the byte item `item`.
-    def _handle_byte_item(self, item: _Byte, state: _GenState, next_rep_instance: int):
+    def _handle_byte_item(self, item: _Byte, state: _GenState, next_vl_instance: int):
         self._data.append(item.val)
         state.offset += item.size
-        return next_rep_instance
+        return next_vl_instance
 
     # Handles the string item `item`.
-    def _handle_str_item(self, item: _Str, state: _GenState, next_rep_instance: int):
+    def _handle_str_item(self, item: _Str, state: _GenState, next_vl_instance: int):
         self._data += item.data
         state.offset += item.size
-        return next_rep_instance
+        return next_vl_instance
 
     # Handles the byte order setting item `item`.
     def _handle_set_bo_item(
-        self, item: _SetBo, state: _GenState, next_rep_instance: int
+        self, item: _SetBo, state: _GenState, next_vl_instance: int
     ):
         # Update current byte order
         state.bo = item.bo
-        return next_rep_instance
+        return next_vl_instance
 
     # Handles the variable assignment item `item`.
     def _handle_var_assign_item(
-        self, item: _VarAssign, state: _GenState, next_rep_instance: int
+        self, item: _VarAssign, state: _GenState, next_vl_instance: int
     ):
         # Update variable
         state.variables[item.name] = self._eval_item_expr(item, state, True)
-        return next_rep_instance
+        return next_vl_instance
 
-    # Handles the value item `item`.
-    def _handle_val_item(self, item: _Val, state: _GenState, next_rep_instance: int):
+    # Handles the fixed-length integer item `item`.
+    def _handle_fl_int_item(
+        self, item: _FlInt, state: _GenState, next_vl_instance: int
+    ):
         # Compute value
         val = self._eval_item_expr(item, state, True)
 
@@ -1492,7 +1588,29 @@ class _Gen:
         # Append to current bytes and update offset
         self._data += data
         state.offset += len(data)
-        return next_rep_instance
+        return next_vl_instance
+
+    # Handles the LEB128 integer item `item`.
+    def _handle_leb128_int_item(
+        self, item: _Leb128Int, state: _GenState, next_vl_instance: int
+    ):
+        # Get the precomputed value
+        val = self._vl_instance_vals[next_vl_instance]
+
+        # Size in bytes
+        size = self._leb128_size_for_val(val, type(item) is _SLeb128Int)
+
+        # For each byte
+        for _ in range(size):
+            # Seven LSBs, MSB of the byte set (continue)
+            self._data.append((val & 0x7F) | 0x80)
+            val >>= 7
+
+        # Clear MSB of last byte (stop)
+        self._data[-1] &= ~0x80
+
+        # Consumed this instance
+        return next_vl_instance + 1
 
     # Handles the group item `item`, only removing the immediate labels
     # from `state.labels` if `remove_immediate_labels` is `True`.
@@ -1500,14 +1618,14 @@ class _Gen:
         self,
         item: _Group,
         state: _GenState,
-        next_rep_instance: int,
+        next_vl_instance: int,
         remove_immediate_labels: bool = True,
     ):
         # Compute the values of the immediate (not nested) labels. Those
         # labels are reachable by any expression within the group.
         offset = state.offset
         immediate_label_names = set()  # type: Set[str]
-        tmp_next_rep_instance = next_rep_instance
+        tmp_next_vl_instance = next_vl_instance
 
         for subitem in item.items:
             if type(subitem) is _SetOffset:
@@ -1518,14 +1636,14 @@ class _Gen:
                 state.labels[subitem.name] = offset
                 immediate_label_names.add(subitem.name)
 
-            subitem_size, tmp_next_rep_instance = self._item_size(
-                subitem, tmp_next_rep_instance
+            subitem_size, tmp_next_vl_instance = self._item_size(
+                subitem, tmp_next_vl_instance
             )
             offset += subitem_size
 
         # Handle each item now with the actual state
         for subitem in item.items:
-            next_rep_instance = self._handle_item(subitem, state, next_rep_instance)
+            next_vl_instance = self._handle_item(subitem, state, next_vl_instance)
 
         # Remove immediate labels if required so that outer items won't
         # reach inner labels.
@@ -1533,35 +1651,36 @@ class _Gen:
             for name in immediate_label_names:
                 del state.labels[name]
 
-        return next_rep_instance
+        return next_vl_instance
 
     # Handles the repetition item `item`.
-    def _handle_rep_item(self, item: _Rep, state: _GenState, next_rep_instance: int):
-        mul = self._rep_instance_vals[next_rep_instance]
-        next_rep_instance += 1
+    def _handle_rep_item(self, item: _Rep, state: _GenState, next_vl_instance: int):
+        # Get the precomputed repetition count
+        mul = self._vl_instance_vals[next_vl_instance]
+
+        # Consumed this instance
+        next_vl_instance += 1
 
         for _ in range(mul):
-            next_rep_instance = self._handle_item(item.item, state, next_rep_instance)
+            next_vl_instance = self._handle_item(item.item, state, next_vl_instance)
 
-        return next_rep_instance
+        return next_vl_instance
 
     # Handles the offset setting item `item`.
     def _handle_set_offset_item(
-        self, item: _SetOffset, state: _GenState, next_rep_instance: int
+        self, item: _SetOffset, state: _GenState, next_vl_instance: int
     ):
         state.offset = item.val
-        return next_rep_instance
+        return next_vl_instance
 
     # Handles the label item `item`.
-    def _handle_label_item(
-        self, item: _Label, state: _GenState, next_rep_instance: int
-    ):
-        return next_rep_instance
+    def _handle_label_item(self, item: _Label, state: _GenState, next_vl_instance: int):
+        return next_vl_instance
 
     # Handles the item `item`, returning the updated next repetition
     # instance.
-    def _handle_item(self, item: _Item, state: _GenState, next_rep_instance: int):
-        return self._item_handlers[type(item)](item, state, next_rep_instance)
+    def _handle_item(self, item: _Item, state: _GenState, next_vl_instance: int):
+        return self._item_handlers[type(item)](item, state, next_vl_instance)
 
     # Generates the data (`self._data`) and final state
     # (`self._final_state`) from `group` and the initial state `state`.
@@ -1572,26 +1691,30 @@ class _Gen:
         # Item handlers
         self._item_handlers = {
             _Byte: self._handle_byte_item,
+            _FlInt: self._handle_fl_int_item,
             _Group: self._handle_group_item,
             _Label: self._handle_label_item,
             _Rep: self._handle_rep_item,
             _SetBo: self._handle_set_bo_item,
             _SetOffset: self._handle_set_offset_item,
+            _SLeb128Int: self._handle_leb128_int_item,
             _Str: self._handle_str_item,
-            _Val: self._handle_val_item,
+            _ULeb128Int: self._handle_leb128_int_item,
             _VarAssign: self._handle_var_assign_item,
         }  # type: Dict[type, Callable[[Any, _GenState, int], int]]
 
         # Item size getters
         self._item_size_funcs = {
             _Byte: self._scalar_item_size,
+            _FlInt: self._scalar_item_size,
             _Group: self._group_item_size,
             _Label: self._zero_item_size,
             _Rep: self._rep_item_size,
             _SetBo: self._zero_item_size,
             _SetOffset: self._zero_item_size,
+            _SLeb128Int: self._leb128_int_item_size,
             _Str: self._scalar_item_size,
-            _Val: self._scalar_item_size,
+            _ULeb128Int: self._leb128_int_item_size,
             _VarAssign: self._zero_item_size,
         }  # type: Dict[type, Callable[[Any, int], Tuple[int, int]]]
 
index b4e9a334ce1353afdaa7e2cfdbb461ad2608a490..2e3f1152bd60ccf63c97f51def7159a72f64e404 100644 (file)
@@ -23,7 +23,7 @@
 
 [tool.poetry]
 name = 'normand'
-version = '0.3.0'
+version = '0.4.0'
 description = 'Text-to-binary processor with its own language'
 license = 'MIT'
 authors = ['Philippe Proulx <eeppeliteloop@gmail.com>']
diff --git a/tests/fail-fl-int-32b-out-of-range-neg.nt b/tests/fail-fl-int-32b-out-of-range-neg.nt
new file mode 100644 (file)
index 0000000..1322e87
--- /dev/null
@@ -0,0 +1,5 @@
+aa bb
+{be}
+{ -(2**31) - 1 : 32 }
+---
+3:3 - Value -2,147,483,649 is outside the 32-bit range when evaluating expression `-(2**31) - 1` at byte offset 2
diff --git a/tests/fail-fl-int-32b-out-of-range-pos.nt b/tests/fail-fl-int-32b-out-of-range-pos.nt
new file mode 100644 (file)
index 0000000..668b984
--- /dev/null
@@ -0,0 +1,4 @@
+"yoyo"
+{ 2**32 : 32 }
+---
+2:3 - Value 4,294,967,296 is outside the 32-bit range when evaluating expression `2**32` at byte offset 4
diff --git a/tests/fail-fl-int-8b-out-of-range-neg.nt b/tests/fail-fl-int-8b-out-of-range-neg.nt
new file mode 100644 (file)
index 0000000..1ce95be
--- /dev/null
@@ -0,0 +1,3 @@
+{ -129 : 8 }
+---
+1:3 - Value -129 is outside the 8-bit range when evaluating expression `-129` at byte offset 0
diff --git a/tests/fail-fl-int-8b-out-of-range-pos.nt b/tests/fail-fl-int-8b-out-of-range-pos.nt
new file mode 100644 (file)
index 0000000..028b7d4
--- /dev/null
@@ -0,0 +1,3 @@
+{ 256 : 8 }
+---
+1:3 - Value 256 is outside the 8-bit range when evaluating expression `256` at byte offset 0
diff --git a/tests/fail-fl-int-empty-expr.nt b/tests/fail-fl-int-empty-expr.nt
new file mode 100644 (file)
index 0000000..735c267
--- /dev/null
@@ -0,0 +1,3 @@
+{ : 8 }
+---
+1:3 - Expecting a fixed-length integer, a variable assignment, or a byte order setting
diff --git a/tests/fail-fl-int-eval-type.nt b/tests/fail-fl-int-eval-type.nt
new file mode 100644 (file)
index 0000000..5b7c642
--- /dev/null
@@ -0,0 +1,3 @@
+{ 'salut' : 8 }
+---
+1:3 - Invalid expression `'salut'`: expecting result type `int`, not `str`
diff --git a/tests/fail-fl-int-eval.nt b/tests/fail-fl-int-eval.nt
new file mode 100644 (file)
index 0000000..8f503e3
--- /dev/null
@@ -0,0 +1,3 @@
+{ 23 + zoom(14) : 8 }
+---
+1:3 - Failed to evaluate expression `23 + zoom(14)`: name 'zoom' is not defined
diff --git a/tests/fail-fl-int-inval-len.nt b/tests/fail-fl-int-inval-len.nt
new file mode 100644 (file)
index 0000000..7c578ef
--- /dev/null
@@ -0,0 +1,3 @@
+{ 23 : 17 }
+---
+1:8 - Expecting a length (multiple of eight bits), `uleb128`, or `sleb128`
diff --git a/tests/fail-fl-int-inval-syntax.nt b/tests/fail-fl-int-inval-syntax.nt
new file mode 100644 (file)
index 0000000..a4d8af2
--- /dev/null
@@ -0,0 +1,3 @@
+{ 19 + / 23 : 8 }
+---
+1:3 - Invalid expression `19 + / 23`: invalid syntax
diff --git a/tests/fail-fl-int-missing-bo.nt b/tests/fail-fl-int-missing-bo.nt
new file mode 100644 (file)
index 0000000..ce68c47
--- /dev/null
@@ -0,0 +1,3 @@
+{ 34 : 16 }
+---
+1:3 - Current byte order isn't defined at first value (`34`) to encode on more than 8 bits
diff --git a/tests/fail-fl-int-missing-len.nt b/tests/fail-fl-int-missing-len.nt
new file mode 100644 (file)
index 0000000..d59bbe6
--- /dev/null
@@ -0,0 +1,3 @@
+{ 23 :  }
+---
+1:9 - Expecting a length (multiple of eight bits), `uleb128`, or `sleb128`
diff --git a/tests/fail-fl-int-unknown-name-1.nt b/tests/fail-fl-int-unknown-name-1.nt
new file mode 100644 (file)
index 0000000..2663bf0
--- /dev/null
@@ -0,0 +1,3 @@
+{ meow : 8 }
+---
+1:3 - Illegal (unknown or unreachable) variable/label name `meow` in expression `meow`; the legal names are {`ICITTE`}
diff --git a/tests/fail-fl-int-unknown-name-2.nt b/tests/fail-fl-int-unknown-name-2.nt
new file mode 100644 (file)
index 0000000..c2c2547
--- /dev/null
@@ -0,0 +1,4 @@
+{ meow : 8 }
+{ meow = 34 }
+---
+1:3 - Illegal (unknown or unreachable) variable/label name `meow` in expression `meow`; the legal names are {`ICITTE`}
diff --git a/tests/fail-sleb128-empty-expr.nt b/tests/fail-sleb128-empty-expr.nt
new file mode 100644 (file)
index 0000000..dfe17b5
--- /dev/null
@@ -0,0 +1,3 @@
+{ : sleb128 }
+---
+1:3 - Expecting a fixed-length integer, a variable assignment, or a byte order setting
diff --git a/tests/fail-uleb128-empty-expr.nt b/tests/fail-uleb128-empty-expr.nt
new file mode 100644 (file)
index 0000000..a003535
--- /dev/null
@@ -0,0 +1,3 @@
+{ : uleb128 }
+---
+1:3 - Expecting a fixed-length integer, a variable assignment, or a byte order setting
diff --git a/tests/fail-uleb128-eval-type.nt b/tests/fail-uleb128-eval-type.nt
new file mode 100644 (file)
index 0000000..4bf01c1
--- /dev/null
@@ -0,0 +1,3 @@
+{ 'salut' : uleb128 }
+---
+1:3 - Invalid expression `'salut'`: expecting result type `int`, not `str`
diff --git a/tests/fail-uleb128-eval.nt b/tests/fail-uleb128-eval.nt
new file mode 100644 (file)
index 0000000..aba6ca8
--- /dev/null
@@ -0,0 +1,3 @@
+{ 23 + zoom(14) : uleb128 }
+---
+1:3 - Failed to evaluate expression `23 + zoom(14)`: name 'zoom' is not defined
diff --git a/tests/fail-uleb128-inval-syntax.nt b/tests/fail-uleb128-inval-syntax.nt
new file mode 100644 (file)
index 0000000..c8d5064
--- /dev/null
@@ -0,0 +1,3 @@
+{ 19 + / 23 : uleb128 }
+---
+1:3 - Invalid expression `19 + / 23`: invalid syntax
diff --git a/tests/fail-uleb128-unknown-name-1.nt b/tests/fail-uleb128-unknown-name-1.nt
new file mode 100644 (file)
index 0000000..2663bf0
--- /dev/null
@@ -0,0 +1,3 @@
+{ meow : 8 }
+---
+1:3 - Illegal (unknown or unreachable) variable/label name `meow` in expression `meow`; the legal names are {`ICITTE`}
diff --git a/tests/fail-uleb128-unknown-name-2.nt b/tests/fail-uleb128-unknown-name-2.nt
new file mode 100644 (file)
index 0000000..0e1700f
--- /dev/null
@@ -0,0 +1,4 @@
+{ meow : uleb128 }
+{ meow = 34 }
+---
+1:3 - Illegal (unknown or unreachable) variable/label name `meow` in expression `meow`; the legal names are {`ICITTE`}
diff --git a/tests/fail-uleb128-unreachable-label-1.nt b/tests/fail-uleb128-unreachable-label-1.nt
new file mode 100644 (file)
index 0000000..0d5fb4e
--- /dev/null
@@ -0,0 +1,6 @@
+<meow>
+aa bb {kilo = 23} cc
+{mix : uleb128}
+ee <mix>
+---
+3:2 - Illegal (unknown or unreachable) variable/label name `mix` in expression `mix`; the legal names are {`ICITTE`, `kilo`, `meow`}
diff --git a/tests/fail-uleb128-unreachable-label-2.nt b/tests/fail-uleb128-unreachable-label-2.nt
new file mode 100644 (file)
index 0000000..12a5b30
--- /dev/null
@@ -0,0 +1,6 @@
+<meow>
+aa {kilo = 99} bb {kilo = mix} cc
+{kilo : uleb128}
+ee <mix>
+---
+3:2 - Illegal (unknown or unreachable) variable/label name `kilo` in expression `kilo`; the legal names are {`ICITTE`, `meow`}
diff --git a/tests/fail-uleb128-unreachable-label-3.nt b/tests/fail-uleb128-unreachable-label-3.nt
new file mode 100644 (file)
index 0000000..ed3782f
--- /dev/null
@@ -0,0 +1,9 @@
+aa {mix = 23} bb <flake> cc
+(
+  dd {meow : uleb128}
+  ff
+  <meow>
+)
+"salut"
+---
+3:7 - Illegal (unknown or unreachable) variable/label name `meow` in expression `meow`; the legal names are {`ICITTE`, `flake`, `mix`}
diff --git a/tests/fail-val-32b-out-of-range-neg.nt b/tests/fail-val-32b-out-of-range-neg.nt
deleted file mode 100644 (file)
index 1322e87..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-aa bb
-{be}
-{ -(2**31) - 1 : 32 }
----
-3:3 - Value -2,147,483,649 is outside the 32-bit range when evaluating expression `-(2**31) - 1` at byte offset 2
diff --git a/tests/fail-val-32b-out-of-range-pos.nt b/tests/fail-val-32b-out-of-range-pos.nt
deleted file mode 100644 (file)
index 668b984..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-"yoyo"
-{ 2**32 : 32 }
----
-2:3 - Value 4,294,967,296 is outside the 32-bit range when evaluating expression `2**32` at byte offset 4
diff --git a/tests/fail-val-8b-out-of-range-neg.nt b/tests/fail-val-8b-out-of-range-neg.nt
deleted file mode 100644 (file)
index 1ce95be..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{ -129 : 8 }
----
-1:3 - Value -129 is outside the 8-bit range when evaluating expression `-129` at byte offset 0
diff --git a/tests/fail-val-8b-out-of-range-pos.nt b/tests/fail-val-8b-out-of-range-pos.nt
deleted file mode 100644 (file)
index 028b7d4..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{ 256 : 8 }
----
-1:3 - Value 256 is outside the 8-bit range when evaluating expression `256` at byte offset 0
diff --git a/tests/fail-val-empty-expr.nt b/tests/fail-val-empty-expr.nt
deleted file mode 100644 (file)
index 0e4fd5e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{ : 8 }
----
-1:3 - Expecting a value, a variable assignment, or a byte order setting
diff --git a/tests/fail-val-eval-type.nt b/tests/fail-val-eval-type.nt
deleted file mode 100644 (file)
index 5b7c642..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{ 'salut' : 8 }
----
-1:3 - Invalid expression `'salut'`: expecting result type `int`, not `str`
diff --git a/tests/fail-val-eval.nt b/tests/fail-val-eval.nt
deleted file mode 100644 (file)
index 8f503e3..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{ 23 + zoom(14) : 8 }
----
-1:3 - Failed to evaluate expression `23 + zoom(14)`: name 'zoom' is not defined
diff --git a/tests/fail-val-inval-len.nt b/tests/fail-val-inval-len.nt
deleted file mode 100644 (file)
index 10b5613..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{ 23 : 17 }
----
-1:7 - Expecting a length (multiple of eight bits)
diff --git a/tests/fail-val-inval-syntax.nt b/tests/fail-val-inval-syntax.nt
deleted file mode 100644 (file)
index a4d8af2..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{ 19 + / 23 : 8 }
----
-1:3 - Invalid expression `19 + / 23`: invalid syntax
diff --git a/tests/fail-val-missing-bo.nt b/tests/fail-val-missing-bo.nt
deleted file mode 100644 (file)
index ce68c47..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{ 34 : 16 }
----
-1:3 - Current byte order isn't defined at first value (`34`) to encode on more than 8 bits
diff --git a/tests/fail-val-missing-len.nt b/tests/fail-val-missing-len.nt
deleted file mode 100644 (file)
index 6742618..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{ 23 :  }
----
-1:7 - Expecting a length (multiple of eight bits)
diff --git a/tests/fail-val-unknown-name-1.nt b/tests/fail-val-unknown-name-1.nt
deleted file mode 100644 (file)
index 2663bf0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{ meow : 8 }
----
-1:3 - Illegal (unknown or unreachable) variable/label name `meow` in expression `meow`; the legal names are {`ICITTE`}
diff --git a/tests/fail-val-unknown-name-2.nt b/tests/fail-val-unknown-name-2.nt
deleted file mode 100644 (file)
index c2c2547..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{ meow : 8 }
-{ meow = 34 }
----
-1:3 - Illegal (unknown or unreachable) variable/label name `meow` in expression `meow`; the legal names are {`ICITTE`}
index 57cd451bdb11bb72d73ab08180c56b1d9fb4711a..ecae7c20382ecaa646c9c16296a2f75a967bc568 100644 (file)
@@ -1,3 +1,3 @@
 { hello }
 ---
-1:3 - Expecting a value, a variable assignment, or a byte order setting
+1:3 - Expecting a fixed-length integer, a variable assignment, or a byte order setting
diff --git a/tests/pass-fl-int-16b-be.nt b/tests/pass-fl-int-16b-be.nt
new file mode 100644 (file)
index 0000000..f8d5fd6
--- /dev/null
@@ -0,0 +1,27 @@
+{be}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{1966:16}
+{-1966:16}
+{1966 + var : 16}
+{1966 + lbl : 16}
+{1966 + var + lbl : 16}
+{-1:16}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+07 ae
+f8 52
+07 b3
+07 b4
+07 b9
+ff ff
+
+33
diff --git a/tests/pass-fl-int-16b-le.nt b/tests/pass-fl-int-16b-le.nt
new file mode 100644 (file)
index 0000000..c417dcf
--- /dev/null
@@ -0,0 +1,27 @@
+{le}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{1966:16}
+{-1966:16}
+{1966 + var : 16}
+{1966 + lbl : 16}
+{1966 + var + lbl : 16}
+{-1:16}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+ae 07
+52 f8
+b3 07
+b4 07
+b9 07
+ff ff
+
+33
diff --git a/tests/pass-fl-int-24b-be.nt b/tests/pass-fl-int-24b-be.nt
new file mode 100644 (file)
index 0000000..13c4d74
--- /dev/null
@@ -0,0 +1,27 @@
+{be}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{4192322:24}
+{-4192322:24}
+{4192322 + var : 24}
+{4192322 + lbl : 24}
+{4192322 + var + lbl : 24}
+{-1:24}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+3f f8 42
+c0 07 be
+3f f8 47
+3f f8 48
+3f f8 4d
+ff ff ff
+
+33
diff --git a/tests/pass-fl-int-24b-le.nt b/tests/pass-fl-int-24b-le.nt
new file mode 100644 (file)
index 0000000..d1f18a2
--- /dev/null
@@ -0,0 +1,27 @@
+{le}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{4192322:24}
+{-4192322:24}
+{4192322 + var : 24}
+{4192322 + lbl : 24}
+{4192322 + var + lbl : 24}
+{-1:24}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+42 f8 3f
+be 07 c0
+47 f8 3f
+48 f8 3f
+4d f8 3f
+ff ff ff
+
+33
diff --git a/tests/pass-fl-int-32b-be.nt b/tests/pass-fl-int-32b-be.nt
new file mode 100644 (file)
index 0000000..c7415e6
--- /dev/null
@@ -0,0 +1,27 @@
+{be}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{536890750:32}
+{-536890750:32}
+{536890750 + var : 32}
+{536890750 + lbl : 32}
+{536890750 + var + lbl : 32}
+{-1:32}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+20 00 4d 7e
+df ff b2 82
+20 00 4d 83
+20 00 4d 84
+20 00 4d 89
+ff ff ff ff
+
+33
diff --git a/tests/pass-fl-int-32b-le.nt b/tests/pass-fl-int-32b-le.nt
new file mode 100644 (file)
index 0000000..5865d25
--- /dev/null
@@ -0,0 +1,27 @@
+{le}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{536890750:32}
+{-536890750:32}
+{536890750 + var : 32}
+{536890750 + lbl : 32}
+{536890750 + var + lbl : 32}
+{-1:32}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+7e 4d 00 20
+82 b2 ff df
+83 4d 00 20
+84 4d 00 20
+89 4d 00 20
+ff ff ff ff
+
+33
diff --git a/tests/pass-fl-int-40b-be.nt b/tests/pass-fl-int-40b-be.nt
new file mode 100644 (file)
index 0000000..9b09c35
--- /dev/null
@@ -0,0 +1,27 @@
+{be}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{34359758191:40}
+{-34359758191:40}
+{34359758191 + var : 40}
+{34359758191 + lbl : 40}
+{34359758191 + var + lbl : 40}
+{-1:40}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+08 00 00 4d 6f
+f7 ff ff b2 91
+08 00 00 4d 74
+08 00 00 4d 75
+08 00 00 4d 7a
+ff ff ff ff ff
+
+33
diff --git a/tests/pass-fl-int-40b-le.nt b/tests/pass-fl-int-40b-le.nt
new file mode 100644 (file)
index 0000000..22713c4
--- /dev/null
@@ -0,0 +1,27 @@
+{le}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{34359758191:40}
+{-34359758191:40}
+{34359758191 + var : 40}
+{34359758191 + lbl : 40}
+{34359758191 + var + lbl : 40}
+{-1:40}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+6f 4d 00 00 08
+91 b2 ff ff f7
+74 4d 00 00 08
+75 4d 00 00 08
+7a 4d 00 00 08
+ff ff ff ff ff
+
+33
diff --git a/tests/pass-fl-int-48b-be.nt b/tests/pass-fl-int-48b-be.nt
new file mode 100644 (file)
index 0000000..4b3fe0b
--- /dev/null
@@ -0,0 +1,27 @@
+{be}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{35184372059993:48}
+{-35184372059993:48}
+{35184372059993 + var : 48}
+{35184372059993 + lbl : 48}
+{35184372059993 + var + lbl : 48}
+{-1:48}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+1f ff ff ff 8f 59
+e0 00 00 00 70 a7
+1f ff ff ff 8f 5e
+1f ff ff ff 8f 5f
+1f ff ff ff 8f 64
+ff ff ff ff ff ff
+
+33
diff --git a/tests/pass-fl-int-48b-le.nt b/tests/pass-fl-int-48b-le.nt
new file mode 100644 (file)
index 0000000..c6b4db4
--- /dev/null
@@ -0,0 +1,27 @@
+{le}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{35184372059993:48}
+{-35184372059993:48}
+{35184372059993 + var : 48}
+{35184372059993 + lbl : 48}
+{35184372059993 + var + lbl : 48}
+{-1:48}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+59 8f ff ff ff 1f
+a7 70 00 00 00 e0
+5e 8f ff ff ff 1f
+5f 8f ff ff ff 1f
+64 8f ff ff ff 1f
+ff ff ff ff ff ff
+
+33
diff --git a/tests/pass-fl-int-56b-be.nt b/tests/pass-fl-int-56b-be.nt
new file mode 100644 (file)
index 0000000..5d3a9c5
--- /dev/null
@@ -0,0 +1,27 @@
+{be}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{1125899906844617:56}
+{-1125899906844617:56}
+{1125899906844617 + var : 56}
+{1125899906844617 + lbl : 56}
+{1125899906844617 + var + lbl : 56}
+{-1:56}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+04 00 00 00 00 07 c9
+fb ff ff ff ff f8 37
+04 00 00 00 00 07 ce
+04 00 00 00 00 07 cf
+04 00 00 00 00 07 d4
+ff ff ff ff ff ff ff
+
+33
diff --git a/tests/pass-fl-int-56b-le.nt b/tests/pass-fl-int-56b-le.nt
new file mode 100644 (file)
index 0000000..523689c
--- /dev/null
@@ -0,0 +1,27 @@
+{le}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{1125899906844617:56}
+{-1125899906844617:56}
+{1125899906844617 + var : 56}
+{1125899906844617 + lbl : 56}
+{1125899906844617 + var + lbl : 56}
+{-1:56}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+c9 07 00 00 00 00 04
+37 f8 ff ff ff ff fb
+ce 07 00 00 00 00 04
+cf 07 00 00 00 00 04
+d4 07 00 00 00 00 04
+ff ff ff ff ff ff ff
+
+33
diff --git a/tests/pass-fl-int-64b-be.nt b/tests/pass-fl-int-64b-be.nt
new file mode 100644 (file)
index 0000000..a959080
--- /dev/null
@@ -0,0 +1,27 @@
+{be}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{4611686018427387158:64}
+{-4611686018427387158:64}
+{4611686018427387158 + var : 64}
+{4611686018427387158 + lbl : 64}
+{4611686018427387158 + var + lbl : 64}
+{-1:64}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+3f ff ff ff ff ff fd 16
+c0 00 00 00 00 00 02 ea
+3f ff ff ff ff ff fd 1b
+3f ff ff ff ff ff fd 1c
+3f ff ff ff ff ff fd 21
+ff ff ff ff ff ff ff ff
+
+33
diff --git a/tests/pass-fl-int-64b-le.nt b/tests/pass-fl-int-64b-le.nt
new file mode 100644 (file)
index 0000000..b1d6b9c
--- /dev/null
@@ -0,0 +1,27 @@
+{le}
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{4611686018427387158:64}
+{-4611686018427387158:64}
+{4611686018427387158 + var : 64}
+{4611686018427387158 + lbl : 64}
+{4611686018427387158 + var + lbl : 64}
+{-1:64}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+16 fd ff ff ff ff ff 3f
+ea 02 00 00 00 00 00 c0
+1b fd ff ff ff ff ff 3f
+1c fd ff ff ff ff ff 3f
+21 fd ff ff ff ff ff 3f
+ff ff ff ff ff ff ff ff
+
+33
diff --git a/tests/pass-fl-int-8b.nt b/tests/pass-fl-int-8b.nt
new file mode 100644 (file)
index 0000000..15fea63
--- /dev/null
@@ -0,0 +1,24 @@
+{var = 5}
+aa bb cc dd ee ff
+<lbl>
+33 44 55
+
+{66:8}
+{-66:8}
+{66 + var : 8}
+{66 + lbl : 8}
+{66 + var + lbl : 8}
+
+<end>
+33
+---
+aa bb cc dd ee ff
+33 44 55
+
+42
+be
+47
+48
+4d
+
+33
diff --git a/tests/pass-fl-int-icitte.nt b/tests/pass-fl-int-icitte.nt
new file mode 100644 (file)
index 0000000..a6a5e7f
--- /dev/null
@@ -0,0 +1,12 @@
+aa bb cc dd ee ff
+{ICITTE + 23 : 8}
+{be}
+{ICITTE + 23 : 16}
+{ICITTE + 23 : 32}
+{ICITTE + 23 : 64}
+---
+aa bb cc dd ee ff
+1d
+00 1e
+00 00 00 20
+00 00 00 00 00 00 00 24
diff --git a/tests/pass-readme-intro-leb128.nt b/tests/pass-readme-intro-leb128.nt
new file mode 100644 (file)
index 0000000..eb8d47b
--- /dev/null
@@ -0,0 +1,4 @@
+aa bb cc {-1993 : sleb128} <meow> dd ee ff
+{meow * 199 : uleb128}
+---
+aa bb cc b7 70 dd ee ff e3 07
diff --git a/tests/pass-readme-learn-fl-int-1.nt b/tests/pass-readme-learn-fl-int-1.nt
new file mode 100644 (file)
index 0000000..63af0d7
--- /dev/null
@@ -0,0 +1,4 @@
+{le} {345:16}
+{be} {-0xabcd:32}
+---
+59 01 ff ff 54 33
diff --git a/tests/pass-readme-learn-fl-int-2.nt b/tests/pass-readme-learn-fl-int-2.nt
new file mode 100644 (file)
index 0000000..472c545
--- /dev/null
@@ -0,0 +1,11 @@
+{be}
+
+# String length in bits
+{8 * (str_end - str_beg) : 16}
+
+# String
+<str_beg>
+  "hello world!"
+<str_end>
+---
+00 60 68 65 6c 6c 6f 20 77 6f 72 6c 64 21
diff --git a/tests/pass-readme-learn-fl-int-3.nt b/tests/pass-readme-learn-fl-int-3.nt
new file mode 100644 (file)
index 0000000..9426048
--- /dev/null
@@ -0,0 +1,3 @@
+{20 - ICITTE : 8} * 10
+---
+14 13 12 11 10 0f 0e 0d 0c 0b
diff --git a/tests/pass-readme-learn-leb128-1.nt b/tests/pass-readme-learn-leb128-1.nt
new file mode 100644 (file)
index 0000000..189854a
--- /dev/null
@@ -0,0 +1,3 @@
+{624485 : uleb128}
+---
+e5 8e 26
diff --git a/tests/pass-readme-learn-leb128-2.nt b/tests/pass-readme-learn-leb128-2.nt
new file mode 100644 (file)
index 0000000..844c13e
--- /dev/null
@@ -0,0 +1,7 @@
+aa bb cc dd
+<meow>
+ee ff
+{-981238311 + (meow * -23) : sleb128}
+"hello"
+---
+aa bb cc dd ee ff fd fa 8d ac 7c 68 65 6c 6c 6f
diff --git a/tests/pass-readme-learn-val-1.nt b/tests/pass-readme-learn-val-1.nt
deleted file mode 100644 (file)
index 63af0d7..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-{le} {345:16}
-{be} {-0xabcd:32}
----
-59 01 ff ff 54 33
diff --git a/tests/pass-readme-learn-val-2.nt b/tests/pass-readme-learn-val-2.nt
deleted file mode 100644 (file)
index 472c545..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{be}
-
-# String length in bits
-{8 * (str_end - str_beg) : 16}
-
-# String
-<str_beg>
-  "hello world!"
-<str_end>
----
-00 60 68 65 6c 6c 6f 20 77 6f 72 6c 64 21
diff --git a/tests/pass-readme-learn-val-3.nt b/tests/pass-readme-learn-val-3.nt
deleted file mode 100644 (file)
index 9426048..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{20 - ICITTE : 8} * 10
----
-14 13 12 11 10 0f 0e 0d 0c 0b
diff --git a/tests/pass-sleb128-1-byte.nt b/tests/pass-sleb128-1-byte.nt
new file mode 100644 (file)
index 0000000..2357d11
--- /dev/null
@@ -0,0 +1,3 @@
+{-1 : sleb128}
+---
+7f
diff --git a/tests/pass-sleb128-10-bytes.nt b/tests/pass-sleb128-10-bytes.nt
new file mode 100644 (file)
index 0000000..82df5a8
--- /dev/null
@@ -0,0 +1,3 @@
+{-6922985746849737371 : sleb128}
+---
+e5 aa b7 ef c8 a4 a7 f6 9f 7f
diff --git a/tests/pass-sleb128-2-bytes.nt b/tests/pass-sleb128-2-bytes.nt
new file mode 100644 (file)
index 0000000..ad98ec9
--- /dev/null
@@ -0,0 +1,3 @@
+{-116 : sleb128}
+---
+8c 7f
diff --git a/tests/pass-sleb128-3-bytes.nt b/tests/pass-sleb128-3-bytes.nt
new file mode 100644 (file)
index 0000000..fb7692d
--- /dev/null
@@ -0,0 +1,3 @@
+{-8680 : sleb128}
+---
+98 bc 7f
diff --git a/tests/pass-sleb128-4-bytes.nt b/tests/pass-sleb128-4-bytes.nt
new file mode 100644 (file)
index 0000000..6a51191
--- /dev/null
@@ -0,0 +1,3 @@
+{-2078359 : sleb128}
+---
+e9 92 81 7f
diff --git a/tests/pass-sleb128-5-bytes.nt b/tests/pass-sleb128-5-bytes.nt
new file mode 100644 (file)
index 0000000..3ae6c34
--- /dev/null
@@ -0,0 +1,3 @@
+{-238633602 : sleb128}
+---
+fe fa 9a 8e 7f
diff --git a/tests/pass-sleb128-6-bytes.nt b/tests/pass-sleb128-6-bytes.nt
new file mode 100644 (file)
index 0000000..87c3855
--- /dev/null
@@ -0,0 +1,3 @@
+{-23700055062 : sleb128}
+---
+ea b7 f7 da a7 7f
diff --git a/tests/pass-sleb128-7-bytes.nt b/tests/pass-sleb128-7-bytes.nt
new file mode 100644 (file)
index 0000000..a06be7f
--- /dev/null
@@ -0,0 +1,3 @@
+{-3724280114436 : sleb128}
+---
+fc a5 ed fc cd 93 7f
diff --git a/tests/pass-sleb128-8-bytes.nt b/tests/pass-sleb128-8-bytes.nt
new file mode 100644 (file)
index 0000000..106b424
--- /dev/null
@@ -0,0 +1,3 @@
+{-547712888934486 : sleb128}
+---
+aa df c3 be ba bb 83 7f
diff --git a/tests/pass-sleb128-9-bytes.nt b/tests/pass-sleb128-9-bytes.nt
new file mode 100644 (file)
index 0000000..e2300a4
--- /dev/null
@@ -0,0 +1,3 @@
+{-56890538594315647 : sleb128}
+---
+81 a5 85 c0 b4 cb f8 9a 7f
diff --git a/tests/pass-sleb128-limits.nt b/tests/pass-sleb128-limits.nt
new file mode 100644 (file)
index 0000000..f6b1f87
--- /dev/null
@@ -0,0 +1,9 @@
+{-65:sleb128}
+{-64:sleb128}
+{63:sleb128}
+{64:sleb128}
+---
+bf 7f
+40
+3f
+c0 00
diff --git a/tests/pass-sleb128-minus-one.nt b/tests/pass-sleb128-minus-one.nt
new file mode 100644 (file)
index 0000000..777a071
--- /dev/null
@@ -0,0 +1,3 @@
+{-1:sleb128}
+---
+7f
diff --git a/tests/pass-sleb128-zero.nt b/tests/pass-sleb128-zero.nt
new file mode 100644 (file)
index 0000000..4e481af
--- /dev/null
@@ -0,0 +1,3 @@
+{0:sleb128}
+---
+00
diff --git a/tests/pass-uleb128-1-byte.nt b/tests/pass-uleb128-1-byte.nt
new file mode 100644 (file)
index 0000000..83443d3
--- /dev/null
@@ -0,0 +1,3 @@
+{2 : uleb128}
+---
+02
diff --git a/tests/pass-uleb128-10-bytes.nt b/tests/pass-uleb128-10-bytes.nt
new file mode 100644 (file)
index 0000000..538032d
--- /dev/null
@@ -0,0 +1,3 @@
+{11662943340368564545 : uleb128}
+---
+c1 a2 b4 b1 cd a5 c6 ed a1 01
diff --git a/tests/pass-uleb128-2-bytes.nt b/tests/pass-uleb128-2-bytes.nt
new file mode 100644 (file)
index 0000000..36e3e84
--- /dev/null
@@ -0,0 +1,3 @@
+{138 : uleb128}
+---
+8a 01
diff --git a/tests/pass-uleb128-3-bytes.nt b/tests/pass-uleb128-3-bytes.nt
new file mode 100644 (file)
index 0000000..651acd4
--- /dev/null
@@ -0,0 +1,3 @@
+{22454 : uleb128}
+---
+b6 af 01
diff --git a/tests/pass-uleb128-4-bytes.nt b/tests/pass-uleb128-4-bytes.nt
new file mode 100644 (file)
index 0000000..d970f5a
--- /dev/null
@@ -0,0 +1,3 @@
+{3003030 : uleb128}
+---
+96 a5 b7 01
diff --git a/tests/pass-uleb128-5-bytes.nt b/tests/pass-uleb128-5-bytes.nt
new file mode 100644 (file)
index 0000000..64c0b9f
--- /dev/null
@@ -0,0 +1,3 @@
+{480029143 : uleb128}
+---
+d7 d3 f2 e4 01
diff --git a/tests/pass-uleb128-6-bytes.nt b/tests/pass-uleb128-6-bytes.nt
new file mode 100644 (file)
index 0000000..41187ec
--- /dev/null
@@ -0,0 +1,3 @@
+{65632604596 : uleb128}
+---
+b4 a3 88 c0 f4 01
diff --git a/tests/pass-uleb128-7-bytes.nt b/tests/pass-uleb128-7-bytes.nt
new file mode 100644 (file)
index 0000000..849ad0e
--- /dev/null
@@ -0,0 +1,3 @@
+{5790353763547 : uleb128}
+---
+db d9 ea df c2 a8 01
diff --git a/tests/pass-uleb128-8-bytes.nt b/tests/pass-uleb128-8-bytes.nt
new file mode 100644 (file)
index 0000000..7f483c5
--- /dev/null
@@ -0,0 +1,3 @@
+{946008033604205 : uleb128}
+---
+ed e4 b0 c6 ba 8c d7 01
diff --git a/tests/pass-uleb128-9-bytes.nt b/tests/pass-uleb128-9-bytes.nt
new file mode 100644 (file)
index 0000000..d7394a4
--- /dev/null
@@ -0,0 +1,3 @@
+{119795752416646235 : uleb128}
+---
+db a8 94 a3 a2 b3 e6 d4 01
diff --git a/tests/pass-uleb128-expr-label-inner.nt b/tests/pass-uleb128-expr-label-inner.nt
new file mode 100644 (file)
index 0000000..a89a8de
--- /dev/null
@@ -0,0 +1,23 @@
+11
+(
+  aa bb
+  <meow>
+  cc dd
+  {meow * 500 : uleb128}
+  ee ff
+) * 2
+22
+---
+11
+
+aa bb
+cc dd
+dc 0b
+ee ff
+
+aa bb
+cc dd
+fc 2a
+ee ff
+
+22
diff --git a/tests/pass-uleb128-expr-label.nt b/tests/pass-uleb128-expr-label.nt
new file mode 100644 (file)
index 0000000..c96fb13
--- /dev/null
@@ -0,0 +1,10 @@
+aa bb
+<meow>
+11 22
+{meow * 199 : uleb128}
+ee ff
+---
+aa bb
+11 22
+8e 03
+ee ff
diff --git a/tests/pass-uleb128-expr-var-1.nt b/tests/pass-uleb128-expr-var-1.nt
new file mode 100644 (file)
index 0000000..3f89282
--- /dev/null
@@ -0,0 +1,8 @@
+aa bb
+{meow = 1111}
+cc {meow : uleb128}
+ee ff
+---
+aa bb
+cc d7 08
+ee ff
diff --git a/tests/pass-uleb128-expr-var-2.nt b/tests/pass-uleb128-expr-var-2.nt
new file mode 100644 (file)
index 0000000..0379409
--- /dev/null
@@ -0,0 +1,16 @@
+aa <mix> bb
+{meow = 3}
+{meow = end}
+11 22
+(
+  {meow = mix * 2}
+  cc {meow << 7 : uleb128}
+) * 2
+ee ff
+<end>
+---
+aa bb
+11 22
+cc 80 02
+cc 80 02
+ee ff
diff --git a/tests/pass-uleb128-limits.nt b/tests/pass-uleb128-limits.nt
new file mode 100644 (file)
index 0000000..993531b
--- /dev/null
@@ -0,0 +1,5 @@
+{127:uleb128}
+{128:uleb128}
+---
+7f
+80 01
diff --git a/tests/pass-uleb128-zero.nt b/tests/pass-uleb128-zero.nt
new file mode 100644 (file)
index 0000000..d206294
--- /dev/null
@@ -0,0 +1,3 @@
+{0:uleb128}
+---
+00
diff --git a/tests/pass-val-16b-be.nt b/tests/pass-val-16b-be.nt
deleted file mode 100644 (file)
index f8d5fd6..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{be}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{1966:16}
-{-1966:16}
-{1966 + var : 16}
-{1966 + lbl : 16}
-{1966 + var + lbl : 16}
-{-1:16}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-07 ae
-f8 52
-07 b3
-07 b4
-07 b9
-ff ff
-
-33
diff --git a/tests/pass-val-16b-le.nt b/tests/pass-val-16b-le.nt
deleted file mode 100644 (file)
index c417dcf..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{le}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{1966:16}
-{-1966:16}
-{1966 + var : 16}
-{1966 + lbl : 16}
-{1966 + var + lbl : 16}
-{-1:16}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-ae 07
-52 f8
-b3 07
-b4 07
-b9 07
-ff ff
-
-33
diff --git a/tests/pass-val-24b-be.nt b/tests/pass-val-24b-be.nt
deleted file mode 100644 (file)
index 13c4d74..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{be}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{4192322:24}
-{-4192322:24}
-{4192322 + var : 24}
-{4192322 + lbl : 24}
-{4192322 + var + lbl : 24}
-{-1:24}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-3f f8 42
-c0 07 be
-3f f8 47
-3f f8 48
-3f f8 4d
-ff ff ff
-
-33
diff --git a/tests/pass-val-24b-le.nt b/tests/pass-val-24b-le.nt
deleted file mode 100644 (file)
index d1f18a2..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{le}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{4192322:24}
-{-4192322:24}
-{4192322 + var : 24}
-{4192322 + lbl : 24}
-{4192322 + var + lbl : 24}
-{-1:24}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-42 f8 3f
-be 07 c0
-47 f8 3f
-48 f8 3f
-4d f8 3f
-ff ff ff
-
-33
diff --git a/tests/pass-val-32b-be.nt b/tests/pass-val-32b-be.nt
deleted file mode 100644 (file)
index c7415e6..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{be}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{536890750:32}
-{-536890750:32}
-{536890750 + var : 32}
-{536890750 + lbl : 32}
-{536890750 + var + lbl : 32}
-{-1:32}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-20 00 4d 7e
-df ff b2 82
-20 00 4d 83
-20 00 4d 84
-20 00 4d 89
-ff ff ff ff
-
-33
diff --git a/tests/pass-val-32b-le.nt b/tests/pass-val-32b-le.nt
deleted file mode 100644 (file)
index 5865d25..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{le}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{536890750:32}
-{-536890750:32}
-{536890750 + var : 32}
-{536890750 + lbl : 32}
-{536890750 + var + lbl : 32}
-{-1:32}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-7e 4d 00 20
-82 b2 ff df
-83 4d 00 20
-84 4d 00 20
-89 4d 00 20
-ff ff ff ff
-
-33
diff --git a/tests/pass-val-40b-be.nt b/tests/pass-val-40b-be.nt
deleted file mode 100644 (file)
index 9b09c35..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{be}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{34359758191:40}
-{-34359758191:40}
-{34359758191 + var : 40}
-{34359758191 + lbl : 40}
-{34359758191 + var + lbl : 40}
-{-1:40}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-08 00 00 4d 6f
-f7 ff ff b2 91
-08 00 00 4d 74
-08 00 00 4d 75
-08 00 00 4d 7a
-ff ff ff ff ff
-
-33
diff --git a/tests/pass-val-40b-le.nt b/tests/pass-val-40b-le.nt
deleted file mode 100644 (file)
index 22713c4..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{le}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{34359758191:40}
-{-34359758191:40}
-{34359758191 + var : 40}
-{34359758191 + lbl : 40}
-{34359758191 + var + lbl : 40}
-{-1:40}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-6f 4d 00 00 08
-91 b2 ff ff f7
-74 4d 00 00 08
-75 4d 00 00 08
-7a 4d 00 00 08
-ff ff ff ff ff
-
-33
diff --git a/tests/pass-val-48b-be.nt b/tests/pass-val-48b-be.nt
deleted file mode 100644 (file)
index 4b3fe0b..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{be}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{35184372059993:48}
-{-35184372059993:48}
-{35184372059993 + var : 48}
-{35184372059993 + lbl : 48}
-{35184372059993 + var + lbl : 48}
-{-1:48}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-1f ff ff ff 8f 59
-e0 00 00 00 70 a7
-1f ff ff ff 8f 5e
-1f ff ff ff 8f 5f
-1f ff ff ff 8f 64
-ff ff ff ff ff ff
-
-33
diff --git a/tests/pass-val-48b-le.nt b/tests/pass-val-48b-le.nt
deleted file mode 100644 (file)
index c6b4db4..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{le}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{35184372059993:48}
-{-35184372059993:48}
-{35184372059993 + var : 48}
-{35184372059993 + lbl : 48}
-{35184372059993 + var + lbl : 48}
-{-1:48}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-59 8f ff ff ff 1f
-a7 70 00 00 00 e0
-5e 8f ff ff ff 1f
-5f 8f ff ff ff 1f
-64 8f ff ff ff 1f
-ff ff ff ff ff ff
-
-33
diff --git a/tests/pass-val-56b-be.nt b/tests/pass-val-56b-be.nt
deleted file mode 100644 (file)
index 5d3a9c5..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{be}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{1125899906844617:56}
-{-1125899906844617:56}
-{1125899906844617 + var : 56}
-{1125899906844617 + lbl : 56}
-{1125899906844617 + var + lbl : 56}
-{-1:56}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-04 00 00 00 00 07 c9
-fb ff ff ff ff f8 37
-04 00 00 00 00 07 ce
-04 00 00 00 00 07 cf
-04 00 00 00 00 07 d4
-ff ff ff ff ff ff ff
-
-33
diff --git a/tests/pass-val-56b-le.nt b/tests/pass-val-56b-le.nt
deleted file mode 100644 (file)
index 523689c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{le}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{1125899906844617:56}
-{-1125899906844617:56}
-{1125899906844617 + var : 56}
-{1125899906844617 + lbl : 56}
-{1125899906844617 + var + lbl : 56}
-{-1:56}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-c9 07 00 00 00 00 04
-37 f8 ff ff ff ff fb
-ce 07 00 00 00 00 04
-cf 07 00 00 00 00 04
-d4 07 00 00 00 00 04
-ff ff ff ff ff ff ff
-
-33
diff --git a/tests/pass-val-64b-be.nt b/tests/pass-val-64b-be.nt
deleted file mode 100644 (file)
index a959080..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{be}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{4611686018427387158:64}
-{-4611686018427387158:64}
-{4611686018427387158 + var : 64}
-{4611686018427387158 + lbl : 64}
-{4611686018427387158 + var + lbl : 64}
-{-1:64}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-3f ff ff ff ff ff fd 16
-c0 00 00 00 00 00 02 ea
-3f ff ff ff ff ff fd 1b
-3f ff ff ff ff ff fd 1c
-3f ff ff ff ff ff fd 21
-ff ff ff ff ff ff ff ff
-
-33
diff --git a/tests/pass-val-64b-le.nt b/tests/pass-val-64b-le.nt
deleted file mode 100644 (file)
index b1d6b9c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-{le}
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{4611686018427387158:64}
-{-4611686018427387158:64}
-{4611686018427387158 + var : 64}
-{4611686018427387158 + lbl : 64}
-{4611686018427387158 + var + lbl : 64}
-{-1:64}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-16 fd ff ff ff ff ff 3f
-ea 02 00 00 00 00 00 c0
-1b fd ff ff ff ff ff 3f
-1c fd ff ff ff ff ff 3f
-21 fd ff ff ff ff ff 3f
-ff ff ff ff ff ff ff ff
-
-33
diff --git a/tests/pass-val-8b.nt b/tests/pass-val-8b.nt
deleted file mode 100644 (file)
index 15fea63..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-{var = 5}
-aa bb cc dd ee ff
-<lbl>
-33 44 55
-
-{66:8}
-{-66:8}
-{66 + var : 8}
-{66 + lbl : 8}
-{66 + var + lbl : 8}
-
-<end>
-33
----
-aa bb cc dd ee ff
-33 44 55
-
-42
-be
-47
-48
-4d
-
-33
diff --git a/tests/pass-val-icitte.nt b/tests/pass-val-icitte.nt
deleted file mode 100644 (file)
index a6a5e7f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-aa bb cc dd ee ff
-{ICITTE + 23 : 8}
-{be}
-{ICITTE + 23 : 16}
-{ICITTE + 23 : 32}
-{ICITTE + 23 : 64}
----
-aa bb cc dd ee ff
-1d
-00 1e
-00 00 00 20
-00 00 00 00 00 00 00 24
This page took 0.069571 seconds and 4 git commands to generate.