Add the directive form of a repetition (`!repeat`) v0.8.0
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Mon, 2 Oct 2023 03:33:09 +0000 (23:33 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Mon, 2 Oct 2023 03:33:09 +0000 (23:33 -0400)
This patch introduces the first directive amongst other ones I'd like to
add later.

`!repeat` is equivalent to what's now called the post-item repetition
form:

    aa (bb cc dd) * 3 ee ff

    aa
    !repeat 3
      bb cc dd
    !end
    ff

`!repeat` (or the shorter `!r` alias) accepts exactly what's accepted
after a `*`: a constant integer, an expression, and (new) a name.

Obviously, the `!` symbol isn't considered a comment anymore.

See `README.adoc` and the new tests to learn more.

This patch also:

* Makes it legal to refer to the special `ICITTE` name within a
  repetition count expression.

  It's less natural for the post-item form, but it works nevertheless.

* Decouples the variables and labels dictionary types as `VariablesT`
  and `LabelsT`. Indeed, a variable value is (for the moment) an `int`
  or `float` instance, while a label value is always an integer (because
  it's an offset snapshot).

Change-Id: I77cd4c9f29639082612534940c48964a61e51392
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
103 files changed:
README.adoc
normand/normand.py
pyproject.toml
tests/fail-rep-blk-empty-expr.nt [new file with mode: 0644]
tests/fail-rep-blk-eval-type-1.nt [new file with mode: 0644]
tests/fail-rep-blk-eval-type-2.nt [new file with mode: 0644]
tests/fail-rep-blk-eval.nt [new file with mode: 0644]
tests/fail-rep-empty-expr.nt [deleted file]
tests/fail-rep-eval-type-1.nt [deleted file]
tests/fail-rep-eval-type-2.nt [deleted file]
tests/fail-rep-eval.nt [deleted file]
tests/fail-rep-icitte.nt [deleted file]
tests/fail-rep-inval-count.nt [deleted file]
tests/fail-rep-neg.nt [deleted file]
tests/fail-rep-post-empty-expr.nt [new file with mode: 0644]
tests/fail-rep-post-eval-type-1.nt [new file with mode: 0644]
tests/fail-rep-post-eval-type-2.nt [new file with mode: 0644]
tests/fail-rep-post-eval.nt [new file with mode: 0644]
tests/fail-rep-post-inval-count.nt [new file with mode: 0644]
tests/fail-rep-post-neg.nt [new file with mode: 0644]
tests/fail-rep-post-unreachable-label-1.nt [new file with mode: 0644]
tests/fail-rep-post-unreachable-label-2.nt [new file with mode: 0644]
tests/fail-rep-post-unreachable-label-3.nt [new file with mode: 0644]
tests/fail-rep-unreachable-label-1.nt [deleted file]
tests/fail-rep-unreachable-label-2.nt [deleted file]
tests/fail-rep-unreachable-label-3.nt [deleted file]
tests/pass-comment-sym-bin-const.nt
tests/pass-comment-sym-group.nt
tests/pass-comment-sym-hex-const.nt
tests/pass-comment-sym-rep-post.nt [new file with mode: 0644]
tests/pass-comment-sym-rep.nt [deleted file]
tests/pass-comment-text-rep-post.nt [new file with mode: 0644]
tests/pass-comment-text-rep.nt [deleted file]
tests/pass-readme-intro-rep.nt
tests/pass-readme-learn-rep-1.nt [deleted file]
tests/pass-readme-learn-rep-2.nt [deleted file]
tests/pass-readme-learn-rep-3-cond-0.nt [deleted file]
tests/pass-readme-learn-rep-3-cond-1.nt [deleted file]
tests/pass-readme-learn-rep-blk-1.nt [new file with mode: 0644]
tests/pass-readme-learn-rep-blk-2.nt [new file with mode: 0644]
tests/pass-readme-learn-rep-blk-3-cond-0.nt [new file with mode: 0644]
tests/pass-readme-learn-rep-blk-3-cond-1.nt [new file with mode: 0644]
tests/pass-readme-learn-rep-post-1.nt [new file with mode: 0644]
tests/pass-readme-learn-rep-post-2.nt [new file with mode: 0644]
tests/pass-rep-all-bytes.nt [deleted file]
tests/pass-rep-blk-all-bytes.nt [new file with mode: 0644]
tests/pass-rep-blk-cond.nt [new file with mode: 0644]
tests/pass-rep-blk-const-bin.nt [new file with mode: 0644]
tests/pass-rep-blk-const-dec.nt [new file with mode: 0644]
tests/pass-rep-blk-const-hex.nt [new file with mode: 0644]
tests/pass-rep-blk-expr-label-inner.nt [new file with mode: 0644]
tests/pass-rep-blk-expr-label.nt [new file with mode: 0644]
tests/pass-rep-blk-expr-var-1.nt [new file with mode: 0644]
tests/pass-rep-blk-expr-var-2.nt [new file with mode: 0644]
tests/pass-rep-blk-group.nt [new file with mode: 0644]
tests/pass-rep-blk-icitte.nt [new file with mode: 0644]
tests/pass-rep-blk-label.nt [new file with mode: 0644]
tests/pass-rep-blk-r.nt [new file with mode: 0644]
tests/pass-rep-blk-rep.nt [new file with mode: 0644]
tests/pass-rep-blk-str-u16be.nt [new file with mode: 0644]
tests/pass-rep-blk-str-u16le.nt [new file with mode: 0644]
tests/pass-rep-blk-str-u32be.nt [new file with mode: 0644]
tests/pass-rep-blk-str-u32le.nt [new file with mode: 0644]
tests/pass-rep-blk-str-u8.nt [new file with mode: 0644]
tests/pass-rep-blk-var.nt [new file with mode: 0644]
tests/pass-rep-blk-zero.nt [new file with mode: 0644]
tests/pass-rep-cond.nt [deleted file]
tests/pass-rep-const-bin.nt [deleted file]
tests/pass-rep-const-dec.nt [deleted file]
tests/pass-rep-const-hex.nt [deleted file]
tests/pass-rep-expr-label-inner.nt [deleted file]
tests/pass-rep-expr-label.nt [deleted file]
tests/pass-rep-expr-var-1.nt [deleted file]
tests/pass-rep-expr-var-2.nt [deleted file]
tests/pass-rep-group.nt [deleted file]
tests/pass-rep-one.nt [deleted file]
tests/pass-rep-post-all-bytes.nt [new file with mode: 0644]
tests/pass-rep-post-cond.nt [new file with mode: 0644]
tests/pass-rep-post-const-bin.nt [new file with mode: 0644]
tests/pass-rep-post-const-dec.nt [new file with mode: 0644]
tests/pass-rep-post-const-hex.nt [new file with mode: 0644]
tests/pass-rep-post-expr-label-inner.nt [new file with mode: 0644]
tests/pass-rep-post-expr-label.nt [new file with mode: 0644]
tests/pass-rep-post-expr-var-1.nt [new file with mode: 0644]
tests/pass-rep-post-expr-var-2.nt [new file with mode: 0644]
tests/pass-rep-post-group.nt [new file with mode: 0644]
tests/pass-rep-post-icitte.nt [new file with mode: 0644]
tests/pass-rep-post-label.nt [new file with mode: 0644]
tests/pass-rep-post-rep.nt [new file with mode: 0644]
tests/pass-rep-post-str-u16be.nt [new file with mode: 0644]
tests/pass-rep-post-str-u16le.nt [new file with mode: 0644]
tests/pass-rep-post-str-u32be.nt [new file with mode: 0644]
tests/pass-rep-post-str-u32le.nt [new file with mode: 0644]
tests/pass-rep-post-str-u8.nt [new file with mode: 0644]
tests/pass-rep-post-var.nt [new file with mode: 0644]
tests/pass-rep-post-zero.nt [new file with mode: 0644]
tests/pass-rep-rep.nt [deleted file]
tests/pass-rep-str-u16be.nt [deleted file]
tests/pass-rep-str-u16le.nt [deleted file]
tests/pass-rep-str-u32be.nt [deleted file]
tests/pass-rep-str-u32le.nt [deleted file]
tests/pass-rep-str-u8.nt [deleted file]
tests/pass-rep-zero.nt [deleted file]

index 40eafc28937c875be8b9d17dcefdd50aac4c38b8..f0852d140d8067831406377f96d932fa15fa8381 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.7, meaning both the Normand
+WARNING: This version of Normand is 0.8, meaning both the Normand
 language and the module/CLI interface aren't stable.
 
 ifdef::env-github[]
@@ -178,6 +178,10 @@ Input:
 +
 ----
 aa bb * 5 cc <zoom> "yeah\0" * {zoom * 3}
+
+!repeat 3
+  ff ee "juice"
+!end
 ----
 +
 Output:
@@ -190,6 +194,8 @@ aa bb bb bb bb bb cc 79  65 61 68 00 79 65 61 68  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢yeah
 61 68 00 79 65 61 68 00  79 65 61 68 00 79 65 61  â”† ah•yeah•yeah•yea
 68 00 79 65 61 68 00 79  65 61 68 00 79 65 61 68  â”† h•yeah•yeah•yeah
 00 79 65 61 68 00 79 65  61 68 00 79 65 61 68 00  â”† â€¢yeah•yeah•yeah•
+ff ee 6a 75 69 63 65 ff  ee 6a 75 69 63 65 ff ee  â”† â€¢â€¢juice••juice••
+6a 75 69 63 65                                    â”† juice
 ----
 
 Alignment::
@@ -363,18 +369,22 @@ This is similar to an assembly label.
 
 * A <<group,group>>, that is, a scoped sequence of items.
 
-Moreover, you can <<repetition,repeat>> any item above, except an offset
-or a label, a given fixed or variable number of times. This is called a
-repetition.
+* A <<repetition-block,repetition block>>.
+
+Moreover, you can repeat many items above a constant or variable number
+of times with the ``pass:[*]`` operator _after_ the item to repeat. This
+is called a <<post-item-repetition,post-item repetition>>.
 
 A Normand comment may exist:
 
 * Between items, possibly within a group.
 * Between the nibbles of a constant hexadecimal byte.
 * Between the bits of a constant binary byte.
-* Between the last item and the ``pass:[*]`` character of a repetition,
-  and between that ``pass:[*]`` character and the following number
-  or expression.
+* Between the last item and the ``pass:[*]`` character of a post-item
+  repetition, and between that ``pass:[*]`` character and the following
+  number or expression.
+* Between the ``!repeat``/``!r`` prefix and the following constant
+  integer, name, or expression of a repetition block.
 
 A comment is anything between two ``pass:[#]`` characters on the same
 line, or from ``pass:[#]`` until the end of the line. Whitespaces and
@@ -382,7 +392,7 @@ the following symbol characters are also considered comments where a
 comment may exist:
 
 ----
-/ \ ? & : ; . , + [ ] _ = | -
+/ \ ? & : ; . , + [ ] _ = | -
 ----
 
 The latter serve to improve readability so that you may write, for
@@ -953,8 +963,8 @@ A _group_ is a scoped sequence of items.
 
 The <<label,labels>> within a group aren't visible outside of it.
 
-The main purpose of a group is to <<repetition,repeat>> more than a
-single item.
+The main purpose of a group is to <<post-item-repetition,repeat>> more
+than a single item and to isolate labels.
 
 A group is:
 
@@ -1020,22 +1030,14 @@ Output:
 ----
 ====
 
-=== Repetition
-
-A _repetition_ represents the bytes of an item repeated a given number
-of times.
+=== Repetition block
 
-A repetition is:
-
-. Any item except:
+A _repetition block_ represents the bytes of one or more items repeated
+a given number of times.
 
-** A <<current-byte-order-setting,current byte order setting>>.
-** A <<current-offset-setting,current offset setting>>.
-** A <<label,label>>.
-** A <<offset-alignment,offset alignment>>.
-** A <<variable-assignment,variable assignment>>.
+A repetition block is:
 
-. The ``pass:[*]`` character.
+. The `!repeat` or `!r` prefix.
 
 . One of:
 
@@ -1049,21 +1051,38 @@ 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 <<label,label>> defined before{nbsp}__**L**__.
 * 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**__.
+  at{nbsp}__**L**__ which doesn't, directly or indirectly, refer to a
+  label defined after{nbsp}__**L**__.
 --
 +
-This expression must not contain the special name `ICITTE`.
+The value of the special name `ICITTE` (`int` type) in this expression
+is the <<cur-offset,current offset>> (before handling the items to
+repeat).
+
+** A valid {py3} name.
++
+For the name `__NAME__`, this is equivalent to the
+`pass:[{]__NAME__pass:[}]` form above.
+
+. Zero or more items.
+
+. The `!end` suffix.
+
+You may also use a <<post-item-repetition,post-item repetition>> after
+some items. The form ``!repeat{nbsp}__X__{nbsp}__ITEMS__{nbsp}!end``
+is equivalent to ``(__ITEMS__){nbsp}pass:[*]{nbsp}__X__``.
 
 ====
 Input:
 
 ----
-{end - ICITTE - 1 : 8} * 0x100 <end>
+!repeat 0x100
+  {end - ICITTE - 1 : 8}
+!end
+
+<end>
 ----
 
 Output:
@@ -1093,13 +1112,21 @@ Input:
 
 ----
 {times = 1}
+
 aa bb cc dd
-(
+
+!repeat 3
   <here>
-  (ee ff) * {here + 1}
-  11 22 33 * {times}
+
+  !repeat {here + 1}
+    ee ff
+  !end
+
+  11 22 !repeat times 33 !end
+
   {times = times + 1}
-) * 3
+!end
+
 "coucou!"
 ----
 
@@ -1122,14 +1149,18 @@ ff ee ff ee ff ee ff ee  ff ee ff ee ff 11 22 33  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
 ====
 
 ====
-This example shows how to use a repetition as a conditional section
-depending on some predefined variable.
+This example shows how to use a repetition block as a conditional
+section depending on some predefined variable.
 
 Input:
 
 ----
 aa bb cc dd
-(ee ff "meow mix" 00) * {cond}
+
+!repeat cond
+  ee ff "meow mix" 00
+!end
+
 {be} {-1993:16}
 ----
 
@@ -1147,6 +1178,119 @@ aa bb cc dd ee ff 6d 65  6f 77 20 6d 69 78 00 f8  â”† â€¢â€¢â€¢â€¢â€¢â€¢meow mix
 ----
 ====
 
+=== Post-item repetition
+
+A _post-item repetition_ represents the bytes of an item repeated a
+given number of times.
+
+A post-item repetition is:
+
+. Any item except:
+
+** A <<current-byte-order-setting,current byte order setting>>.
+** A <<current-offset-setting,current offset setting>>.
+** A <<label,label>>.
+** A <<offset-alignment,offset alignment>>.
+** A <<variable-assignment,variable assignment>>.
+** A <<repetition-block,repetition block>>.
+
+. The ``pass:[*]`` character.
+
+. One of:
+
+** A positive integer (hexadecimal starting with `0x` or `0X` accepted)
+   which is the number of times to repeat the previous item.
+
+** The ``pass:[{]`` prefix, a valid {py3} expression, and the
+   ``pass:[}]`` suffix.
++
+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**__.
+--
++
+The value of the special name `ICITTE` (`int` type) in this expression
+is the <<cur-offset,current offset>> (before handling the items to
+repeat).
+
+** A valid {py3} name.
++
+For the name `__NAME__`, this is equivalent to the
+`pass:[{]__NAME__pass:[}]` form above.
+
+You may also use a <<repetition-block,repetition block>>. The form
+``__ITEM__{nbsp}pass:[*]{nbsp}__X__`` is equivalent to
+``!repeat{nbsp}__X__{nbsp}__ITEM__{nbsp}!end``.
+
+====
+Input:
+
+----
+{end - ICITTE - 1 : 8} * 0x100 <end>
+----
+
+Output:
+
+----
+ff fe fd fc fb fa f9 f8  f7 f6 f5 f4 f3 f2 f1 f0  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+ef ee ed ec eb ea e9 e8  e7 e6 e5 e4 e3 e2 e1 e0  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+df de dd dc db da d9 d8  d7 d6 d5 d4 d3 d2 d1 d0  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+cf ce cd cc cb ca c9 c8  c7 c6 c5 c4 c3 c2 c1 c0  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+bf be bd bc bb ba b9 b8  b7 b6 b5 b4 b3 b2 b1 b0  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+af ae ad ac ab aa a9 a8  a7 a6 a5 a4 a3 a2 a1 a0  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+9f 9e 9d 9c 9b 9a 99 98  97 96 95 94 93 92 91 90  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+8f 8e 8d 8c 8b 8a 89 88  87 86 85 84 83 82 81 80  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+7f 7e 7d 7c 7b 7a 79 78  77 76 75 74 73 72 71 70  â”† â€¢~}|{zyxwvutsrqp
+6f 6e 6d 6c 6b 6a 69 68  67 66 65 64 63 62 61 60  â”† onmlkjihgfedcba`
+5f 5e 5d 5c 5b 5a 59 58  57 56 55 54 53 52 51 50  â”† _^]\[ZYXWVUTSRQP
+4f 4e 4d 4c 4b 4a 49 48  47 46 45 44 43 42 41 40  â”† ONMLKJIHGFEDCBA@
+3f 3e 3d 3c 3b 3a 39 38  37 36 35 34 33 32 31 30  â”† ?>=<;:9876543210
+2f 2e 2d 2c 2b 2a 29 28  27 26 25 24 23 22 21 20  â”† /.-,+*)('&%$#"!
+1f 1e 1d 1c 1b 1a 19 18  17 16 15 14 13 12 11 10  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+0f 0e 0d 0c 0b 0a 09 08  07 06 05 04 03 02 01 00  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+----
+====
+
+====
+Input:
+
+----
+{times = 1}
+aa bb cc dd
+(
+  <here>
+  (ee ff) * {here + 1}
+  11 22 33 * {times}
+  {times = times + 1}
+) * 3
+"coucou!"
+----
+
+Output:
+
+----
+aa bb cc dd ee ff ee ff  ee ff ee ff ee ff 11 22  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢"
+33 ee ff ee ff ee ff ee  ff ee ff ee ff ee ff ee  â”† 3•••••••••••••••
+ff ee ff ee ff ee ff ee  ff ee ff ee ff ee ff ee  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+ff ee ff ee ff 11 22 33  33 ee ff ee ff ee ff ee  â”† â€¢â€¢â€¢â€¢â€¢â€¢"33•••••••
+ff ee ff ee ff ee ff ee  ff ee ff ee ff ee ff ee  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+ff ee ff ee ff ee ff ee  ff ee ff ee ff ee ff ee  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+ff ee ff ee ff ee ff ee  ff ee ff ee ff ee ff ee  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+ff ee ff ee ff ee ff ee  ff ee ff ee ff ee ff ee  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+ff ee ff ee ff ee ff ee  ff ee ff ee ff ee ff ee  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+ff ee ff ee ff ee ff ee  ff ee ff ee ff ee ff ee  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢
+ff ee ff ee ff ee ff ee  ff ee ff ee ff 11 22 33  â”† â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢â€¢"3
+33 33 63 6f 75 63 6f 75  21                       â”† 33coucou!
+----
+====
+
 == Command-line tool
 
 If you <<install-normand,installed>> the `normand` package, then you
@@ -1184,10 +1328,11 @@ use the `--help` option to learn more.
 
 == {py3} API
 
-The whole `normand` package/module API is:
+The whole `normand` package/module public API is:
 
 [source,python]
 ----
+# Byte order.
 class ByteOrder(enum.Enum):
     # Big endian.
     BE = ...
@@ -1196,7 +1341,8 @@ class ByteOrder(enum.Enum):
     LE = ...
 
 
-class TextLoc:
+# Text location.
+class TextLocation:
     # Line number.
     @property
     def line_no(self) -> int:
@@ -1208,16 +1354,23 @@ class TextLoc:
         ...
 
 
+# Parsing error.
 class ParseError(RuntimeError):
     # Source text location.
     @property
-    def text_loc(self) -> TextLoc:
+    def text_loc(self) -> TextLocation:
         ...
 
 
-SymbolsT = typing.Dict[str, int]
+# Variables dictionary type (for type hints).
+VariablesT = typing.Dict[str, typing.Union[int, float]]
+
+
+# Labels dictionary type (for type hints).
+LabelsT = typing.Dict[str, int]
 
 
+# Parsing result.
 class ParseResult:
     # Generated data.
     @property
@@ -1245,6 +1398,9 @@ class ParseResult:
         ...
 
 
+# Parses the `normand` input using the initial state defined by
+# `init_variables`, `init_labels`, `init_offset`, and `init_byte_order`,
+# and returns the corresponding parsing result.
 def parse(normand: str,
           init_variables: typing.Optional[SymbolsT] = None,
           init_labels: typing.Optional[SymbolsT] = None,
index c3c76ad23e9dbadcca8d546f0e23b933be71f646..6b1e3d2cced6833847a036f0a9496499f22feef3 100644 (file)
 # Upstream repository: <https://github.com/efficios/normand>.
 
 __author__ = "Philippe Proulx"
-__version__ = "0.7.0"
+__version__ = "0.8.0"
 __all__ = [
     "ByteOrder",
     "parse",
     "ParseError",
     "ParseResult",
-    "TextLoc",
-    "SymbolsT",
+    "TextLocation",
+    "LabelsT",
+    "VariablesT",
     "__author__",
     "__version__",
 ]
@@ -49,21 +50,12 @@ import sys
 import enum
 import math
 import struct
-from typing import (
-    Any,
-    Set,
-    Dict,
-    List,
-    Union,
-    Pattern,
-    Callable,
-    NoReturn,
-    Optional,
-)
+import typing
+from typing import Any, Set, Dict, List, Union, Pattern, Callable, NoReturn, Optional
 
 
 # Text location (line and column numbers).
-class TextLoc:
+class TextLocation:
     @classmethod
     def _create(cls, line_no: int, col_no: int):
         self = cls.__new__(cls)
@@ -88,12 +80,12 @@ class TextLoc:
         return self._col_no
 
     def __repr__(self):
-        return "TextLoc({}, {})".format(self._line_no, self._col_no)
+        return "TextLocation({}, {})".format(self._line_no, self._col_no)
 
 
 # Any item.
 class _Item:
-    def __init__(self, text_loc: TextLoc):
+    def __init__(self, text_loc: TextLocation):
         self._text_loc = text_loc
 
     # Source text location.
@@ -118,7 +110,7 @@ class _RepableItem:
 
 # Single byte.
 class _Byte(_ScalarItem, _RepableItem):
-    def __init__(self, val: int, text_loc: TextLoc):
+    def __init__(self, val: int, text_loc: TextLocation):
         super().__init__(text_loc)
         self._val = val
 
@@ -137,7 +129,7 @@ class _Byte(_ScalarItem, _RepableItem):
 
 # String.
 class _Str(_ScalarItem, _RepableItem):
-    def __init__(self, data: bytes, text_loc: TextLoc):
+    def __init__(self, data: bytes, text_loc: TextLocation):
         super().__init__(text_loc)
         self._data = data
 
@@ -166,7 +158,7 @@ class ByteOrder(enum.Enum):
 
 # Byte order setting.
 class _SetBo(_Item):
-    def __init__(self, bo: ByteOrder, text_loc: TextLoc):
+    def __init__(self, bo: ByteOrder, text_loc: TextLocation):
         super().__init__(text_loc)
         self._bo = bo
 
@@ -180,7 +172,7 @@ class _SetBo(_Item):
 
 # Label.
 class _Label(_Item):
-    def __init__(self, name: str, text_loc: TextLoc):
+    def __init__(self, name: str, text_loc: TextLocation):
         super().__init__(text_loc)
         self._name = name
 
@@ -195,7 +187,7 @@ class _Label(_Item):
 
 # Offset setting.
 class _SetOffset(_Item):
-    def __init__(self, val: int, text_loc: TextLoc):
+    def __init__(self, val: int, text_loc: TextLocation):
         super().__init__(text_loc)
         self._val = val
 
@@ -210,7 +202,7 @@ class _SetOffset(_Item):
 
 # Offset alignment.
 class _AlignOffset(_Item):
-    def __init__(self, val: int, pad_val: int, text_loc: TextLoc):
+    def __init__(self, val: int, pad_val: int, text_loc: TextLocation):
         super().__init__(text_loc)
         self._val = val
         self._pad_val = pad_val
@@ -251,7 +243,7 @@ class _ExprMixin:
 # Variable assignment.
 class _VarAssign(_Item, _ExprMixin):
     def __init__(
-        self, name: str, expr_str: str, expr: ast.Expression, text_loc: TextLoc
+        self, name: str, expr_str: str, expr: ast.Expression, text_loc: TextLocation
     ):
         super().__init__(text_loc)
         _ExprMixin.__init__(self, expr_str, expr)
@@ -274,7 +266,7 @@ class _VarAssign(_Item, _ExprMixin):
 # Fixed-length number, possibly needing more than one byte.
 class _FlNum(_ScalarItem, _RepableItem, _ExprMixin):
     def __init__(
-        self, expr_str: str, expr: ast.Expression, len: int, text_loc: TextLoc
+        self, expr_str: str, expr: ast.Expression, len: int, text_loc: TextLocation
     ):
         super().__init__(text_loc)
         _ExprMixin.__init__(self, expr_str, expr)
@@ -300,7 +292,7 @@ class _FlNum(_ScalarItem, _RepableItem, _ExprMixin):
 
 # LEB128 integer.
 class _Leb128Int(_Item, _RepableItem, _ExprMixin):
-    def __init__(self, expr_str: str, expr: ast.Expression, text_loc: TextLoc):
+    def __init__(self, expr_str: str, expr: ast.Expression, text_loc: TextLocation):
         super().__init__(text_loc)
         _ExprMixin.__init__(self, expr_str, expr)
 
@@ -325,7 +317,7 @@ class _SLeb128Int(_Leb128Int, _RepableItem, _ExprMixin):
 
 # Group of items.
 class _Group(_Item, _RepableItem):
-    def __init__(self, items: List[_Item], text_loc: TextLoc):
+    def __init__(self, items: List[_Item], text_loc: TextLocation):
         super().__init__(text_loc)
         self._items = items
 
@@ -341,7 +333,7 @@ class _Group(_Item, _RepableItem):
 # Repetition item.
 class _Rep(_Item, _ExprMixin):
     def __init__(
-        self, item: _Item, expr_str: str, expr: ast.Expression, text_loc: TextLoc
+        self, item: _Item, expr_str: str, expr: ast.Expression, text_loc: TextLocation
     ):
         super().__init__(text_loc)
         _ExprMixin.__init__(self, expr_str, expr)
@@ -368,7 +360,7 @@ _ExprItemT = Union[_FlNum, _Leb128Int, _VarAssign, _Rep]
 # A parsing error containing a message and a text location.
 class ParseError(RuntimeError):
     @classmethod
-    def _create(cls, msg: str, text_loc: TextLoc):
+    def _create(cls, msg: str, text_loc: TextLocation):
         self = cls.__new__(cls)
         self._init(msg, text_loc)
         return self
@@ -376,7 +368,7 @@ class ParseError(RuntimeError):
     def __init__(self, *args, **kwargs):  # type: ignore
         raise NotImplementedError
 
-    def _init(self, msg: str, text_loc: TextLoc):
+    def _init(self, msg: str, text_loc: TextLocation):
         super().__init__(msg)
         self._text_loc = text_loc
 
@@ -387,12 +379,16 @@ class ParseError(RuntimeError):
 
 
 # Raises a parsing error, forwarding the parameters to the constructor.
-def _raise_error(msg: str, text_loc: TextLoc) -> NoReturn:
+def _raise_error(msg: str, text_loc: TextLocation) -> NoReturn:
     raise ParseError._create(msg, text_loc)  # pyright: ignore[reportPrivateUsage]
 
 
-# Variable/label dictionary type.
-SymbolsT = Dict[str, Union[int, float]]
+# Variables dictionary type (for type hints).
+VariablesT = Dict[str, Union[int, float]]
+
+
+# Labels dictionary type (for type hints).
+LabelsT = Dict[str, int]
 
 
 # Python name pattern.
@@ -406,7 +402,7 @@ _py_name_pat = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*")
 class _Parser:
     # Builds a parser to parse the Normand input `normand`, parsing
     # immediately.
-    def __init__(self, normand: str, variables: SymbolsT, labels: SymbolsT):
+    def __init__(self, normand: str, variables: VariablesT, labels: LabelsT):
         self._normand = normand
         self._at = 0
         self._line_no = 1
@@ -423,7 +419,7 @@ class _Parser:
     # Current text location.
     @property
     def _text_loc(self):
-        return TextLoc._create(  # pyright: ignore[reportPrivateUsage]
+        return TextLocation._create(  # pyright: ignore[reportPrivateUsage]
             self._line_no, self._col_no
         )
 
@@ -485,7 +481,7 @@ class _Parser:
 
     # Pattern for _skip_ws_and_comments()
     _ws_or_syms_or_comments_pat = re.compile(
-        r"(?:[\s!/\\?&:;.,+[\]_=|-]|#[^#]*?(?:\n|#))*"
+        r"(?:[\s/\\?&:;.,+[\]_=|-]|#[^#]*?(?:\n|#))*"
     )
 
     # Skips as many whitespaces, insignificant symbol characters, and
@@ -672,7 +668,7 @@ class _Parser:
 
     # Returns a stripped expression string and an AST expression node
     # from the expression string `expr_str` at text location `text_loc`.
-    def _ast_expr_from_str(self, expr_str: str, text_loc: TextLoc):
+    def _ast_expr_from_str(self, expr_str: str, text_loc: TextLocation):
         # Create an expression node from the expression string
         expr_str = expr_str.strip().replace("\n", " ")
 
@@ -828,7 +824,7 @@ class _Parser:
         self._expect_pat(self._val_var_assign_set_bo_suffix_pat, "Expecting `}`")
         return item
 
-    # Pattern for _try_parse_set_offset_val() and _try_parse_rep()
+    # Common positive constant integer pattern
     _pos_const_int_pat = re.compile(r"0[Xx][A-Fa-f0-9]+|\d+")
 
     # Tries to parse an offset setting value (after the initial `<`),
@@ -956,6 +952,77 @@ class _Parser:
         # Return item
         return _AlignOffset(val, pad_val, begin_text_loc)
 
+    # Patterns for _expect_rep_mul_expr()
+    _rep_expr_prefix_pat = re.compile(r"\{")
+    _rep_expr_pat = re.compile(r"[^}p]+")
+    _rep_expr_suffix_pat = re.compile(r"\}")
+
+    # Parses the multiplier expression of a repetition (block or
+    # post-item) and returns the expression string and AST node.
+    def _expect_rep_mul_expr(self):
+        expr_text_loc = self._text_loc
+
+        # Constant integer?
+        m = self._try_parse_pat(self._pos_const_int_pat)
+
+        if m is None:
+            # Name?
+            m = self._try_parse_pat(_py_name_pat)
+
+            if m is None:
+                # Expression?
+                if self._try_parse_pat(self._rep_expr_prefix_pat) is None:
+                    # At this point it's invalid
+                    self._raise_error(
+                        "Expecting a positive integral multiplier, a name, or `{`"
+                    )
+
+                # Expect an expression
+                expr_text_loc = self._text_loc
+                m = self._expect_pat(self._rep_expr_pat, "Expecting an expression")
+                expr_str = m.group(0)
+
+                # Expect `}`
+                self._expect_pat(self._rep_expr_suffix_pat, "Expecting `}`")
+            else:
+                expr_str = m.group(0)
+        else:
+            expr_str = m.group(0)
+
+        return self._ast_expr_from_str(expr_str, expr_text_loc)
+
+    # Pattern for _try_parse_rep_block()
+    _rep_block_prefix_pat = re.compile(r"!r(?:epeat)?\b\s*")
+    _rep_block_end_pat = re.compile(r"!end\b\s*")
+
+    # Tries to parse a repetition block, returning a repetition item on
+    # success.
+    def _try_parse_rep_block(self):
+        begin_text_loc = self._text_loc
+
+        # Match prefix
+        if self._try_parse_pat(self._rep_block_prefix_pat) is None:
+            # No match
+            return
+
+        # Expect expression
+        self._skip_ws_and_comments()
+        expr_str, expr = self._expect_rep_mul_expr()
+
+        # Parse items
+        self._skip_ws_and_comments()
+        items_text_loc = self._text_loc
+        items = self._parse_items()
+
+        # Expect end of block
+        self._skip_ws_and_comments()
+        self._expect_pat(
+            self._rep_block_end_pat, "Expecting an item or `!end` (end of repetition)"
+        )
+
+        # Return item
+        return _Rep(_Group(items, items_text_loc), expr_str, expr, begin_text_loc)
+
     # Tries to parse a base item (anything except a repetition),
     # returning it on success.
     def _try_parse_base_item(self):
@@ -995,45 +1062,26 @@ class _Parser:
         if item is not None:
             return item
 
-    # Pattern for _try_parse_rep()
-    _rep_prefix_pat = re.compile(r"\*\s*")
-    _rep_expr_prefix_pat = re.compile(r"\{")
-    _rep_expr_pat = re.compile(r"[^}p]+")
-    _rep_expr_suffix_pat = re.compile(r"\}")
+        # Repetition (block) item?
+        item = self._try_parse_rep_block()
 
-    # Tries to parse a repetition, returning the expression string and
-    # AST expression node on success.
-    def _try_parse_rep(self):
+        if item is not None:
+            return item
+
+    # Pattern for _try_parse_rep_post()
+    _rep_post_prefix_pat = re.compile(r"\*")
+
+    # Tries to parse a post-item repetition, returning the expression
+    # string and AST expression node on success.
+    def _try_parse_rep_post(self):
         # Match prefix
-        if self._try_parse_pat(self._rep_prefix_pat) is None:
+        if self._try_parse_pat(self._rep_post_prefix_pat) is None:
             # No match
             return
 
-        # Expect and return a decimal multiplier
+        # Return expression string and AST expression
         self._skip_ws_and_comments()
-
-        # Integer?
-        m = self._try_parse_pat(self._pos_const_int_pat)
-
-        if m is None:
-            # Expression?
-            if self._try_parse_pat(self._rep_expr_prefix_pat) is None:
-                # At this point it's invalid
-                self._raise_error("Expecting a positive integral multiplier or `{`")
-
-            # Expect an expression
-            expr_str_loc = self._text_loc
-            m = self._expect_pat(self._rep_expr_pat, "Expecting an expression")
-            expr_str = self._ast_expr_from_str(m.group(0), expr_str_loc)
-
-            # Expect `}`
-            self._expect_pat(self._rep_expr_suffix_pat, "Expecting `}`")
-            expr_str = m.group(0)
-        else:
-            expr_str_loc = self._text_loc
-            expr_str = m.group(0)
-
-        return self._ast_expr_from_str(expr_str, expr_str_loc)
+        return self._expect_rep_mul_expr()
 
     # Tries to parse an item, possibly followed by a repetition,
     # returning `True` on success.
@@ -1053,7 +1101,7 @@ class _Parser:
         if isinstance(item, _RepableItem):
             self._skip_ws_and_comments()
             rep_text_loc = self._text_loc
-            rep_ret = self._try_parse_rep()
+            rep_ret = self._try_parse_rep_post()
 
             if rep_ret is not None:
                 item = _Rep(item, rep_ret[0], rep_ret[1], rep_text_loc)
@@ -1104,8 +1152,8 @@ class ParseResult:
     def _create(
         cls,
         data: bytearray,
-        variables: SymbolsT,
-        labels: SymbolsT,
+        variables: VariablesT,
+        labels: LabelsT,
         offset: int,
         bo: Optional[ByteOrder],
     ):
@@ -1119,8 +1167,8 @@ class ParseResult:
     def _init(
         self,
         data: bytearray,
-        variables: SymbolsT,
-        labels: SymbolsT,
+        variables: VariablesT,
+        labels: LabelsT,
         offset: int,
         bo: Optional[ByteOrder],
     ):
@@ -1192,31 +1240,21 @@ class _NodeVisitor(ast.NodeVisitor):
 # Expression validator: validates that all the names within the
 # expression are allowed.
 class _ExprValidator(_NodeVisitor):
-    def __init__(self, item: _ExprItemT, allowed_names: Set[str], icitte_allowed: bool):
+    def __init__(self, item: _ExprItemT, allowed_names: Set[str]):
         super().__init__()
         self._item = item
         self._allowed_names = allowed_names
-        self._icitte_allowed = icitte_allowed
 
     def _visit_name(self, name: str):
         # Make sure the name refers to a known and reachable
         # variable/label name.
-        if name == _icitte_name and not self._icitte_allowed:
-            _raise_error(
-                "Illegal reserved name `{}` in expression `{}`".format(
-                    _icitte_name, self._item.expr_str
-                ),
-                self._item.text_loc,
-            )
-        elif name != _icitte_name and name not in self._allowed_names:
+        if name != _icitte_name and name not in self._allowed_names:
             msg = "Illegal (unknown or unreachable) variable/label name `{}` in expression `{}`".format(
                 name, self._item.expr_str
             )
 
             allowed_names = self._allowed_names.copy()
-
-            if self._icitte_allowed:
-                allowed_names.add(_icitte_name)
+            allowed_names.add(_icitte_name)
 
             if len(allowed_names) > 0:
                 allowed_names_str = ", ".join(
@@ -1248,8 +1286,8 @@ class _ExprNamesVisitor(_NodeVisitor):
 class _GenState:
     def __init__(
         self,
-        variables: SymbolsT,
-        labels: SymbolsT,
+        variables: VariablesT,
+        labels: LabelsT,
         offset: int,
         bo: Optional[ByteOrder],
     ):
@@ -1268,7 +1306,7 @@ class _GenState:
 # The steps of generation are:
 #
 # 1. Validate that each repetition and LEB128 integer expression uses
-#    only reachable names and not `ICITTE`.
+#    only reachable names.
 #
 # 2. Compute and keep the effective repetition count and LEB128 integer
 #    value for each repetition and LEB128 integer instance.
@@ -1289,8 +1327,8 @@ class _Gen:
     def __init__(
         self,
         group: _Group,
-        variables: SymbolsT,
-        labels: SymbolsT,
+        variables: VariablesT,
+        labels: LabelsT,
         offset: int,
         bo: Optional[ByteOrder],
     ):
@@ -1386,15 +1424,15 @@ class _Gen:
             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)
+            # Validate the expression
+            _ExprValidator(item, allowed_label_names | allowed_variable_names).visit(
+                item.expr
+            )
         elif type(item) is _Rep:
-            # Validate the expression first (`ICITTE` not allowed)
-            _ExprValidator(
-                item, allowed_label_names | allowed_variable_names, False
-            ).visit(item.expr)
+            # Validate the expression first
+            _ExprValidator(item, allowed_label_names | allowed_variable_names).visit(
+                item.expr
+            )
 
             # Validate inner item
             _Gen._validate_vl_exprs(
@@ -1413,29 +1451,25 @@ class _Gen:
     # Evaluates the expression of `item` considering the current
     # generation state `state`.
     #
-    # If `allow_icitte` is `True`, then the `ICITTE` name is available
-    # for the expression to evaluate.
-    #
     # If `allow_float` is `True`, then the type of the result may be
     # `float` too.
     @staticmethod
     def _eval_item_expr(
         item: _ExprItemT,
         state: _GenState,
-        allow_icitte: bool,
         allow_float: bool = False,
     ):
-        syms = state.labels.copy()
+        syms = {}  # type: VariablesT
+        syms.update(state.labels)
 
-        # Set the `ICITTE` name to the current offset, if any
-        if allow_icitte:
-            syms[_icitte_name] = state.offset
+        # Set the `ICITTE` name to the current offset
+        syms[_icitte_name] = state.offset
 
         # Add the current variables
         syms.update(state.variables)
 
         # Validate the node and its children
-        _ExprValidator(item, set(syms.keys()), True).visit(item.expr)
+        _ExprValidator(item, set(syms.keys())).visit(item.expr)
 
         # Compile and evaluate expression node
         try:
@@ -1529,16 +1563,14 @@ class _Gen:
 
             if do_eval:
                 # Evaluate the expression and keep the result
-                state.variables[item.name] = _Gen._eval_item_expr(
-                    item, state, True, True
-                )
+                state.variables[item.name] = _Gen._eval_item_expr(item, state, True)
         elif type(item) is _SetOffset:
             state.offset = item.val
         elif type(item) is _AlignOffset:
             state.offset = _Gen._align_offset(state.offset, item)
         elif isinstance(item, _Leb128Int):
             # Evaluate the expression
-            val = _Gen._eval_item_expr(item, state, True)
+            val = _Gen._eval_item_expr(item, state)
 
             # Validate result
             if type(item) is _ULeb128Int and val < 0:
@@ -1557,7 +1589,7 @@ class _Gen:
             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)
+            val = _Gen._eval_item_expr(item, state)
 
             # Validate result
             if val < 0:
@@ -1669,7 +1701,7 @@ class _Gen:
         self, item: _VarAssign, state: _GenState, next_vl_instance: int
     ):
         # Update variable
-        state.variables[item.name] = self._eval_item_expr(item, state, True, True)
+        state.variables[item.name] = self._eval_item_expr(item, state, True)
         return next_vl_instance
 
     # Handles the fixed-length integer item `item`.
@@ -1732,7 +1764,7 @@ class _Gen:
         self, item: _FlNum, state: _GenState, next_vl_instance: int
     ):
         # Compute value
-        val = self._eval_item_expr(item, state, True, True)
+        val = self._eval_item_expr(item, state, True)
 
         # Validate current byte order
         if state.bo is None and item.len > 8:
@@ -1916,8 +1948,8 @@ class _Gen:
 # Raises `ParseError` on any parsing error.
 def parse(
     normand: str,
-    init_variables: Optional[SymbolsT] = None,
-    init_labels: Optional[SymbolsT] = None,
+    init_variables: Optional[VariablesT] = None,
+    init_labels: Optional[LabelsT] = None,
     init_offset: int = 0,
     init_byte_order: Optional[ByteOrder] = None,
 ):
@@ -1997,7 +2029,7 @@ def _raise_cli_error(msg: str) -> NoReturn:
 # Returns a dictionary of string to integers from the list of strings
 # `args` containing `NAME=VAL` entries.
 def _dict_from_arg(args: Optional[List[str]]):
-    d = {}  # type: SymbolsT
+    d = {}  # type: LabelsT
 
     if args is None:
         return d
@@ -2028,7 +2060,7 @@ def _try_run_cli():
             normand = f.read()
 
     # Variables and labels
-    variables = _dict_from_arg(args.var)
+    variables = typing.cast(VariablesT, _dict_from_arg(args.var))
     labels = _dict_from_arg(args.label)
 
     # Validate offset
index f131ef7761a47e21cc1cb239bff2731390de5456..c439ac7f2f335984c88f7f23550b278bfd39c5a2 100644 (file)
@@ -23,7 +23,7 @@
 
 [tool.poetry]
 name = 'normand'
-version = '0.7.0'
+version = '0.8.0'
 description = 'Text-to-binary processor with its own language'
 license = 'MIT'
 authors = ['Philippe Proulx <eeppeliteloop@gmail.com>']
diff --git a/tests/fail-rep-blk-empty-expr.nt b/tests/fail-rep-blk-empty-expr.nt
new file mode 100644 (file)
index 0000000..b5b40f5
--- /dev/null
@@ -0,0 +1,3 @@
+!repeat { } 77 !end
+---
+1:10 - Invalid expression ``: invalid syntax
diff --git a/tests/fail-rep-blk-eval-type-1.nt b/tests/fail-rep-blk-eval-type-1.nt
new file mode 100644 (file)
index 0000000..91766e0
--- /dev/null
@@ -0,0 +1,3 @@
+!repeat { [1, 2, 3] } 77 !end
+---
+1:1 - Invalid expression `[1, 2, 3]`: expecting result type `int`, not `list`
diff --git a/tests/fail-rep-blk-eval-type-2.nt b/tests/fail-rep-blk-eval-type-2.nt
new file mode 100644 (file)
index 0000000..52acf49
--- /dev/null
@@ -0,0 +1,3 @@
+!repeat {3.4} 77 !end
+---
+1:1 - Invalid expression `3.4`: expecting result type `int`, not `float`
diff --git a/tests/fail-rep-blk-eval.nt b/tests/fail-rep-blk-eval.nt
new file mode 100644 (file)
index 0000000..93e7ac8
--- /dev/null
@@ -0,0 +1,3 @@
+aa !repeat { 23 + zoom(14) } bb !end
+---
+1:4 - Failed to evaluate expression `23 + zoom(14)`: name 'zoom' is not defined
diff --git a/tests/fail-rep-empty-expr.nt b/tests/fail-rep-empty-expr.nt
deleted file mode 100644 (file)
index e5db8f0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-77 * { }
----
-1:7 - Invalid expression ``: invalid syntax
diff --git a/tests/fail-rep-eval-type-1.nt b/tests/fail-rep-eval-type-1.nt
deleted file mode 100644 (file)
index c2d4e22..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-77 * { [1, 2, 3] }
----
-1:4 - Invalid expression `[1, 2, 3]`: expecting result type `int`, not `list`
diff --git a/tests/fail-rep-eval-type-2.nt b/tests/fail-rep-eval-type-2.nt
deleted file mode 100644 (file)
index 7fb72c7..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-77 * { 3.4 }
----
-1:4 - Invalid expression `3.4`: expecting result type `int`, not `float`
diff --git a/tests/fail-rep-eval.nt b/tests/fail-rep-eval.nt
deleted file mode 100644 (file)
index 6f3c898..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-aa bb * { 23 + zoom(14) }
----
-1:7 - Failed to evaluate expression `23 + zoom(14)`: name 'zoom' is not defined
diff --git a/tests/fail-rep-icitte.nt b/tests/fail-rep-icitte.nt
deleted file mode 100644 (file)
index 5badb82..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-99 * {ICITTE * 2}
----
-1:4 - Illegal reserved name `ICITTE` in expression `ICITTE * 2`
diff --git a/tests/fail-rep-inval-count.nt b/tests/fail-rep-inval-count.nt
deleted file mode 100644 (file)
index 74c6007..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-88 * salut
----
-1:6 - Expecting a positive integral multiplier or `{`
diff --git a/tests/fail-rep-neg.nt b/tests/fail-rep-neg.nt
deleted file mode 100644 (file)
index 2e37761..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-aa <meow> ff * {-meow}
----
-1:14 - Invalid expression `-meow`: unexpected negative result -1
diff --git a/tests/fail-rep-post-empty-expr.nt b/tests/fail-rep-post-empty-expr.nt
new file mode 100644 (file)
index 0000000..e5db8f0
--- /dev/null
@@ -0,0 +1,3 @@
+77 * { }
+---
+1:7 - Invalid expression ``: invalid syntax
diff --git a/tests/fail-rep-post-eval-type-1.nt b/tests/fail-rep-post-eval-type-1.nt
new file mode 100644 (file)
index 0000000..c2d4e22
--- /dev/null
@@ -0,0 +1,3 @@
+77 * { [1, 2, 3] }
+---
+1:4 - Invalid expression `[1, 2, 3]`: expecting result type `int`, not `list`
diff --git a/tests/fail-rep-post-eval-type-2.nt b/tests/fail-rep-post-eval-type-2.nt
new file mode 100644 (file)
index 0000000..7fb72c7
--- /dev/null
@@ -0,0 +1,3 @@
+77 * { 3.4 }
+---
+1:4 - Invalid expression `3.4`: expecting result type `int`, not `float`
diff --git a/tests/fail-rep-post-eval.nt b/tests/fail-rep-post-eval.nt
new file mode 100644 (file)
index 0000000..6f3c898
--- /dev/null
@@ -0,0 +1,3 @@
+aa bb * { 23 + zoom(14) }
+---
+1:7 - Failed to evaluate expression `23 + zoom(14)`: name 'zoom' is not defined
diff --git a/tests/fail-rep-post-inval-count.nt b/tests/fail-rep-post-inval-count.nt
new file mode 100644 (file)
index 0000000..13eddc6
--- /dev/null
@@ -0,0 +1,3 @@
+88 * "salut"
+---
+1:6 - Expecting a positive integral multiplier, a name, or `{`
diff --git a/tests/fail-rep-post-neg.nt b/tests/fail-rep-post-neg.nt
new file mode 100644 (file)
index 0000000..2e37761
--- /dev/null
@@ -0,0 +1,3 @@
+aa <meow> ff * {-meow}
+---
+1:14 - Invalid expression `-meow`: unexpected negative result -1
diff --git a/tests/fail-rep-post-unreachable-label-1.nt b/tests/fail-rep-post-unreachable-label-1.nt
new file mode 100644 (file)
index 0000000..abb5db0
--- /dev/null
@@ -0,0 +1,6 @@
+<meow>
+aa bb {kilo = 23} cc
+dd * {mix}
+ee <mix>
+---
+3:4 - Illegal (unknown or unreachable) variable/label name `mix` in expression `mix`; the legal names are {`ICITTE`, `kilo`, `meow`}
diff --git a/tests/fail-rep-post-unreachable-label-2.nt b/tests/fail-rep-post-unreachable-label-2.nt
new file mode 100644 (file)
index 0000000..80e8e8a
--- /dev/null
@@ -0,0 +1,6 @@
+<meow>
+aa {kilo = 99} bb {kilo = mix} cc
+dd * {kilo}
+ee <mix>
+---
+3:4 - Illegal (unknown or unreachable) variable/label name `kilo` in expression `kilo`; the legal names are {`ICITTE`, `meow`}
diff --git a/tests/fail-rep-post-unreachable-label-3.nt b/tests/fail-rep-post-unreachable-label-3.nt
new file mode 100644 (file)
index 0000000..4fc98f3
--- /dev/null
@@ -0,0 +1,9 @@
+aa {mix = 23} bb <flake> cc
+(
+  dd ee * {meow}
+  ff
+  <meow>
+)
+"salut"
+---
+3:9 - Illegal (unknown or unreachable) variable/label name `meow` in expression `meow`; the legal names are {`ICITTE`, `flake`, `mix`}
diff --git a/tests/fail-rep-unreachable-label-1.nt b/tests/fail-rep-unreachable-label-1.nt
deleted file mode 100644 (file)
index 0a64750..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<meow>
-aa bb {kilo = 23} cc
-dd * {mix}
-ee <mix>
----
-3:4 - Illegal (unknown or unreachable) variable/label name `mix` in expression `mix`; the legal names are {`kilo`, `meow`}
diff --git a/tests/fail-rep-unreachable-label-2.nt b/tests/fail-rep-unreachable-label-2.nt
deleted file mode 100644 (file)
index 1dffea3..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<meow>
-aa {kilo = 99} bb {kilo = mix} cc
-dd * {kilo}
-ee <mix>
----
-3:4 - Illegal (unknown or unreachable) variable/label name `kilo` in expression `kilo`; the legal names are {`meow`}
diff --git a/tests/fail-rep-unreachable-label-3.nt b/tests/fail-rep-unreachable-label-3.nt
deleted file mode 100644 (file)
index f01cf27..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-aa {mix = 23} bb <flake> cc
-(
-  dd ee * {meow}
-  ff
-  <meow>
-)
-"salut"
----
-3:9 - Illegal (unknown or unreachable) variable/label name `meow` in expression `meow`; the legal names are {`flake`, `mix`}
index 4e666f00e91298e702d41abb49ae299006455144..2e39488d6e535eb75c6591bebfdf81571b2084cc 100644 (file)
@@ -1,5 +1,5 @@
-%!1/01\0?1&0:1;0 %.0,1+0[1]0_1=0|1 %1111-0000
-% 1! 0 / 1 \ 0 ? 1 & 0 : 1 ; 0
+%1/01\0?1&0:1;0 %.0,1+0[1]0_1=0|1 %1111-0000
+% 1 0 / 1 \ 0 ? 1 & 0 : 1 ; 0
 % . 0 , 1 + 0 [ 1 ] 0 _ 1 = 0 | 1
 % 1111 - 0000
 ---
index 7ceea984aaed4b86bea2d549f3a51664db1f68cf..0b33c27766717219ea9cd53f50a9fe4f4a878d09 100644 (file)
@@ -1,3 +1,3 @@
-(0!12/3\4?5&6:7;8.9,a+b[c]d_e=f|0-1(!/\?&:;.,+[]_=|-))
+(012/3\4?5&6:7;8.9,a+b[c]d_e=f|0-1(/\?&:;.,+[]_=|-))
 ---
 01 23 45 67 89 ab cd ef 01
index 3b6be9ae94b7907b0bc6b80ea2a2eb1c54742988..4c3b99002d3ec10e4327ce2e59e4ee917de08373 100644 (file)
@@ -1,6 +1,6 @@
-/ \ ? & : ; . , + [ ] _ = | -
-0!12/3\4?5&6:7;8.9,a+b[c]d_e=f|0-1
-0 1 2 / 3 \ 4 ? 5 & 6 : 7 ; 8 . 9 , a + b [ c ] d_e = f | 0 - 1
+/ \ ? & : ; . , + [ ] _ = | -
+012/3\4?5&6:7;8.9,a+b[c]d_e=f|0-1
+0 1 2 / 3 \ 4 ? 5 & 6 : 7 ; 8 . 9 , a + b [ c ] d_e = f | 0 - 1
 ---
 01 23 45 67 89 ab cd ef 01
 01 23 45 67 89 ab cd ef 01
diff --git a/tests/pass-comment-sym-rep-post.nt b/tests/pass-comment-sym-rep-post.nt
new file mode 100644 (file)
index 0000000..08dc0c3
--- /dev/null
@@ -0,0 +1,4 @@
+# repetition
+ff/\?&:;.,+[]_=|-*/\?&:;.,+[]_=|-5
+---
+ff ff ff ff ff
diff --git a/tests/pass-comment-sym-rep.nt b/tests/pass-comment-sym-rep.nt
deleted file mode 100644 (file)
index b58bcc8..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# repetition
-ff!/\?&:;.,+[]_=|-*!/\?&:;.,+[]_=|-5
----
-ff ff ff ff ff
diff --git a/tests/pass-comment-text-rep-post.nt b/tests/pass-comment-text-rep-post.nt
new file mode 100644 (file)
index 0000000..9a69fff
--- /dev/null
@@ -0,0 +1,3 @@
+ff#comment#*#comment#5
+---
+ff ff ff ff ff
diff --git a/tests/pass-comment-text-rep.nt b/tests/pass-comment-text-rep.nt
deleted file mode 100644 (file)
index 9a69fff..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-ff#comment#*#comment#5
----
-ff ff ff ff ff
index 586afb3847b313e92c1110b662f712b7ffa37d4b..d4c0cee81a14f446e883bc331d611d6fc09442f9 100644 (file)
@@ -1,4 +1,8 @@
 aa bb * 5 cc <zoom> "yeah\0" * {zoom * 3}
+
+!repeat 3
+  ff ee "juice"
+!end
 ---
 aa bb bb bb bb bb cc 79 65 61 68 00 79 65 61 68
 00 79 65 61 68 00 79 65 61 68 00 79 65 61 68 00
@@ -7,3 +11,5 @@ aa bb bb bb bb bb cc 79 65 61 68 00 79 65 61 68
 61 68 00 79 65 61 68 00 79 65 61 68 00 79 65 61
 68 00 79 65 61 68 00 79 65 61 68 00 79 65 61 68
 00 79 65 61 68 00 79 65 61 68 00 79 65 61 68 00
+ff ee 6a 75 69 63 65 ff ee 6a 75 69 63 65 ff ee
+6a 75 69 63 65
diff --git a/tests/pass-readme-learn-rep-1.nt b/tests/pass-readme-learn-rep-1.nt
deleted file mode 100644 (file)
index 74283c7..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{end - ICITTE - 1 : 8} * 0x100 <end>
----
-ff fe fd fc fb fa f9 f8 f7 f6 f5 f4 f3 f2 f1 f0
-ef ee ed ec eb ea e9 e8 e7 e6 e5 e4 e3 e2 e1 e0
-df de dd dc db da d9 d8 d7 d6 d5 d4 d3 d2 d1 d0
-cf ce cd cc cb ca c9 c8 c7 c6 c5 c4 c3 c2 c1 c0
-bf be bd bc bb ba b9 b8 b7 b6 b5 b4 b3 b2 b1 b0
-af ae ad ac ab aa a9 a8 a7 a6 a5 a4 a3 a2 a1 a0
-9f 9e 9d 9c 9b 9a 99 98 97 96 95 94 93 92 91 90
-8f 8e 8d 8c 8b 8a 89 88 87 86 85 84 83 82 81 80
-7f 7e 7d 7c 7b 7a 79 78 77 76 75 74 73 72 71 70
-6f 6e 6d 6c 6b 6a 69 68 67 66 65 64 63 62 61 60
-5f 5e 5d 5c 5b 5a 59 58 57 56 55 54 53 52 51 50
-4f 4e 4d 4c 4b 4a 49 48 47 46 45 44 43 42 41 40
-3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30
-2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20
-1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10
-0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
diff --git a/tests/pass-readme-learn-rep-2.nt b/tests/pass-readme-learn-rep-2.nt
deleted file mode 100644 (file)
index 5bf9be1..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-{times = 1}
-aa bb cc dd
-(
-  <here>
-  (ee ff) * {here + 1}
-  11 22 33 * {times}
-  {times = times + 1}
-) * 3
-"coucou!"
----
-aa bb cc dd ee ff ee ff ee ff ee ff ee ff 11 22
-33 ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
-ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
-ff ee ff ee ff 11 22 33 33 ee ff ee ff ee ff ee
-ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
-ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
-ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
-ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
-ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
-ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
-ff ee ff ee ff ee ff ee ff ee ff ee ff 11 22 33
-33 33 63 6f 75 63 6f 75 21
diff --git a/tests/pass-readme-learn-rep-3-cond-0.nt b/tests/pass-readme-learn-rep-3-cond-0.nt
deleted file mode 100644 (file)
index df2d985..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{cond = 0}
-aa bb cc dd
-(ee ff "meow mix" 00) * {cond}
-{be} {-1993:16}
----
-aa bb cc dd f8 37
diff --git a/tests/pass-readme-learn-rep-3-cond-1.nt b/tests/pass-readme-learn-rep-3-cond-1.nt
deleted file mode 100644 (file)
index f96f821..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{cond = 1}
-aa bb cc dd
-(ee ff "meow mix" 00) * {cond}
-{be} {-1993:16}
----
-aa bb cc dd ee ff 6d 65 6f 77 20 6d 69 78 00 f8 37
diff --git a/tests/pass-readme-learn-rep-blk-1.nt b/tests/pass-readme-learn-rep-blk-1.nt
new file mode 100644 (file)
index 0000000..3483a59
--- /dev/null
@@ -0,0 +1,22 @@
+!repeat 0x100
+  {end - ICITTE - 1 : 8}
+!end
+
+<end>
+---
+ff fe fd fc fb fa f9 f8 f7 f6 f5 f4 f3 f2 f1 f0
+ef ee ed ec eb ea e9 e8 e7 e6 e5 e4 e3 e2 e1 e0
+df de dd dc db da d9 d8 d7 d6 d5 d4 d3 d2 d1 d0
+cf ce cd cc cb ca c9 c8 c7 c6 c5 c4 c3 c2 c1 c0
+bf be bd bc bb ba b9 b8 b7 b6 b5 b4 b3 b2 b1 b0
+af ae ad ac ab aa a9 a8 a7 a6 a5 a4 a3 a2 a1 a0
+9f 9e 9d 9c 9b 9a 99 98 97 96 95 94 93 92 91 90
+8f 8e 8d 8c 8b 8a 89 88 87 86 85 84 83 82 81 80
+7f 7e 7d 7c 7b 7a 79 78 77 76 75 74 73 72 71 70
+6f 6e 6d 6c 6b 6a 69 68 67 66 65 64 63 62 61 60
+5f 5e 5d 5c 5b 5a 59 58 57 56 55 54 53 52 51 50
+4f 4e 4d 4c 4b 4a 49 48 47 46 45 44 43 42 41 40
+3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30
+2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20
+1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10
+0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
diff --git a/tests/pass-readme-learn-rep-blk-2.nt b/tests/pass-readme-learn-rep-blk-2.nt
new file mode 100644 (file)
index 0000000..f6b9e6d
--- /dev/null
@@ -0,0 +1,30 @@
+{times = 1}
+
+aa bb cc dd
+
+!repeat 3
+  <here>
+
+  !repeat {here + 1}
+    ee ff
+  !end
+
+  11 22 !repeat times 33 !end
+
+  {times = times + 1}
+!end
+
+"coucou!"
+---
+aa bb cc dd ee ff ee ff ee ff ee ff ee ff 11 22
+33 ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff 11 22 33 33 ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff 11 22 33
+33 33 63 6f 75 63 6f 75 21
diff --git a/tests/pass-readme-learn-rep-blk-3-cond-0.nt b/tests/pass-readme-learn-rep-blk-3-cond-0.nt
new file mode 100644 (file)
index 0000000..930dc62
--- /dev/null
@@ -0,0 +1,11 @@
+{cond = 0}
+
+aa bb cc dd
+
+!repeat cond
+  ee ff "meow mix" 00
+!end
+
+{be} {-1993:16}
+---
+aa bb cc dd f8 37
diff --git a/tests/pass-readme-learn-rep-blk-3-cond-1.nt b/tests/pass-readme-learn-rep-blk-3-cond-1.nt
new file mode 100644 (file)
index 0000000..fbc6276
--- /dev/null
@@ -0,0 +1,11 @@
+{cond = 1}
+
+aa bb cc dd
+
+!repeat cond
+  ee ff "meow mix" 00
+!end
+
+{be} {-1993:16}
+---
+aa bb cc dd ee ff 6d 65 6f 77 20 6d 69 78 00 f8 37
diff --git a/tests/pass-readme-learn-rep-post-1.nt b/tests/pass-readme-learn-rep-post-1.nt
new file mode 100644 (file)
index 0000000..74283c7
--- /dev/null
@@ -0,0 +1,18 @@
+{end - ICITTE - 1 : 8} * 0x100 <end>
+---
+ff fe fd fc fb fa f9 f8 f7 f6 f5 f4 f3 f2 f1 f0
+ef ee ed ec eb ea e9 e8 e7 e6 e5 e4 e3 e2 e1 e0
+df de dd dc db da d9 d8 d7 d6 d5 d4 d3 d2 d1 d0
+cf ce cd cc cb ca c9 c8 c7 c6 c5 c4 c3 c2 c1 c0
+bf be bd bc bb ba b9 b8 b7 b6 b5 b4 b3 b2 b1 b0
+af ae ad ac ab aa a9 a8 a7 a6 a5 a4 a3 a2 a1 a0
+9f 9e 9d 9c 9b 9a 99 98 97 96 95 94 93 92 91 90
+8f 8e 8d 8c 8b 8a 89 88 87 86 85 84 83 82 81 80
+7f 7e 7d 7c 7b 7a 79 78 77 76 75 74 73 72 71 70
+6f 6e 6d 6c 6b 6a 69 68 67 66 65 64 63 62 61 60
+5f 5e 5d 5c 5b 5a 59 58 57 56 55 54 53 52 51 50
+4f 4e 4d 4c 4b 4a 49 48 47 46 45 44 43 42 41 40
+3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30
+2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20
+1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10
+0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
diff --git a/tests/pass-readme-learn-rep-post-2.nt b/tests/pass-readme-learn-rep-post-2.nt
new file mode 100644 (file)
index 0000000..5bf9be1
--- /dev/null
@@ -0,0 +1,22 @@
+{times = 1}
+aa bb cc dd
+(
+  <here>
+  (ee ff) * {here + 1}
+  11 22 33 * {times}
+  {times = times + 1}
+) * 3
+"coucou!"
+---
+aa bb cc dd ee ff ee ff ee ff ee ff ee ff 11 22
+33 ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff 11 22 33 33 ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee
+ff ee ff ee ff ee ff ee ff ee ff ee ff 11 22 33
+33 33 63 6f 75 63 6f 75 21
diff --git a/tests/pass-rep-all-bytes.nt b/tests/pass-rep-all-bytes.nt
deleted file mode 100644 (file)
index 494f343..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{ICITTE:8} * 256
----
-00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
-10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
-20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
-30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
-40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
-50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
-60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
-70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
-80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f
-90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
-a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af
-b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
-c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf
-d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df
-e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef
-f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
diff --git a/tests/pass-rep-blk-all-bytes.nt b/tests/pass-rep-blk-all-bytes.nt
new file mode 100644 (file)
index 0000000..f875059
--- /dev/null
@@ -0,0 +1,18 @@
+!repeat 256 {ICITTE:8} !end
+---
+00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
+10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
+80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f
+90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
+a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af
+b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
+c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf
+d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df
+e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef
+f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
diff --git a/tests/pass-rep-blk-cond.nt b/tests/pass-rep-blk-cond.nt
new file mode 100644 (file)
index 0000000..aa9fd56
--- /dev/null
@@ -0,0 +1,18 @@
+!repeat 10
+  <beg>
+  aa bb cc dd
+  <end>
+  {include = int(beg >= 4 * (end - beg))}
+  !repeat include 11 22 33 44 !end
+!end
+---
+aa bb cc dd
+aa bb cc dd
+aa bb cc dd
+aa bb cc dd
+aa bb cc dd 11 22 33 44
+aa bb cc dd 11 22 33 44
+aa bb cc dd 11 22 33 44
+aa bb cc dd 11 22 33 44
+aa bb cc dd 11 22 33 44
+aa bb cc dd 11 22 33 44
diff --git a/tests/pass-rep-blk-const-bin.nt b/tests/pass-rep-blk-const-bin.nt
new file mode 100644 (file)
index 0000000..a6db9c6
--- /dev/null
@@ -0,0 +1,3 @@
+!repeat 5 %11001010 !end
+---
+ca ca ca ca ca
diff --git a/tests/pass-rep-blk-const-dec.nt b/tests/pass-rep-blk-const-dec.nt
new file mode 100644 (file)
index 0000000..caa7e37
--- /dev/null
@@ -0,0 +1,3 @@
+!repeat 5 $-36 !end
+---
+dc dc dc dc dc
diff --git a/tests/pass-rep-blk-const-hex.nt b/tests/pass-rep-blk-const-hex.nt
new file mode 100644 (file)
index 0000000..cf9067b
--- /dev/null
@@ -0,0 +1,3 @@
+!repeat 5 4b !end
+---
+4b 4b 4b 4b 4b
diff --git a/tests/pass-rep-blk-expr-label-inner.nt b/tests/pass-rep-blk-expr-label-inner.nt
new file mode 100644 (file)
index 0000000..6486371
--- /dev/null
@@ -0,0 +1,20 @@
+11
+!repeat 2
+  aa bb
+  <meow>
+  cc !repeat meow dd !end
+  ee ff
+!end
+22
+---
+11
+
+aa bb
+cc dd dd dd
+ee ff
+
+aa bb
+cc dd dd dd dd dd dd dd dd dd dd dd
+ee ff
+
+22
diff --git a/tests/pass-rep-blk-expr-label.nt b/tests/pass-rep-blk-expr-label.nt
new file mode 100644 (file)
index 0000000..ca39ded
--- /dev/null
@@ -0,0 +1,8 @@
+aa bb
+<meow>
+cc !repeat meow dd !end
+ee ff
+---
+aa bb
+cc dd dd
+ee ff
diff --git a/tests/pass-rep-blk-expr-var-1.nt b/tests/pass-rep-blk-expr-var-1.nt
new file mode 100644 (file)
index 0000000..1ca6d5d
--- /dev/null
@@ -0,0 +1,8 @@
+aa bb
+{meow = 3}
+cc !repeat meow dd !end
+ee ff
+---
+aa bb
+cc dd dd dd
+ee ff
diff --git a/tests/pass-rep-blk-expr-var-2.nt b/tests/pass-rep-blk-expr-var-2.nt
new file mode 100644 (file)
index 0000000..1e7d4c8
--- /dev/null
@@ -0,0 +1,18 @@
+aa <mix> bb
+{meow = 3}
+{meow = end}
+11 22
+!repeat 2
+  {meow = mix * 2}
+  cc !repeat meow dd !end
+!end
+ee ff
+!repeat meow 88 !end
+<end>
+---
+aa bb
+11 22
+cc dd dd
+cc dd dd
+ee ff
+88 88
diff --git a/tests/pass-rep-blk-group.nt b/tests/pass-rep-blk-group.nt
new file mode 100644 (file)
index 0000000..a0b264a
--- /dev/null
@@ -0,0 +1,51 @@
+aa
+!repeat 0xa
+  bb cc
+  !repeat 3
+    dd ee
+  !end
+!end
+ff
+---
+aa
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+ff
diff --git a/tests/pass-rep-blk-icitte.nt b/tests/pass-rep-blk-icitte.nt
new file mode 100644 (file)
index 0000000..bcdd175
--- /dev/null
@@ -0,0 +1,9 @@
+aa bb cc
+!repeat ICITTE
+  dd
+!end
+ee ff
+---
+aa bb cc
+dd dd dd
+ee ff
diff --git a/tests/pass-rep-blk-label.nt b/tests/pass-rep-blk-label.nt
new file mode 100644 (file)
index 0000000..033374e
--- /dev/null
@@ -0,0 +1,3 @@
+aa ff <meow> dd !repeat meow bb !end cc
+---
+aa ff dd bb bb cc
diff --git a/tests/pass-rep-blk-r.nt b/tests/pass-rep-blk-r.nt
new file mode 100644 (file)
index 0000000..c267e38
--- /dev/null
@@ -0,0 +1,7 @@
+!r 3
+  aa bb cc
+!end
+---
+aa bb cc
+aa bb cc
+aa bb cc
diff --git a/tests/pass-rep-blk-rep.nt b/tests/pass-rep-blk-rep.nt
new file mode 100644 (file)
index 0000000..234c473
--- /dev/null
@@ -0,0 +1,12 @@
+!repeat 2
+  !repeat 8
+    !repeat 4
+      AA
+    !end
+  !end
+!end
+---
+aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
+aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
+aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
+aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
diff --git a/tests/pass-rep-blk-str-u16be.nt b/tests/pass-rep-blk-str-u16be.nt
new file mode 100644 (file)
index 0000000..8f68aec
--- /dev/null
@@ -0,0 +1,5 @@
+!repeat 3 u16be"yo" !end
+---
+00 79 00 6f
+00 79 00 6f
+00 79 00 6f
diff --git a/tests/pass-rep-blk-str-u16le.nt b/tests/pass-rep-blk-str-u16le.nt
new file mode 100644 (file)
index 0000000..9290579
--- /dev/null
@@ -0,0 +1,5 @@
+!repeat 3 u16le"yo" !end
+---
+79 00 6f 00
+79 00 6f 00
+79 00 6f 00
diff --git a/tests/pass-rep-blk-str-u32be.nt b/tests/pass-rep-blk-str-u32be.nt
new file mode 100644 (file)
index 0000000..04c6962
--- /dev/null
@@ -0,0 +1,5 @@
+!repeat 3 u32be"yo" !end
+---
+00 00 00 79 00 00 00 6f
+00 00 00 79 00 00 00 6f
+00 00 00 79 00 00 00 6f
diff --git a/tests/pass-rep-blk-str-u32le.nt b/tests/pass-rep-blk-str-u32le.nt
new file mode 100644 (file)
index 0000000..e874539
--- /dev/null
@@ -0,0 +1,5 @@
+!repeat 3 u32le"yo" !end
+---
+79 00 00 00 6f 00 00 00
+79 00 00 00 6f 00 00 00
+79 00 00 00 6f 00 00 00
diff --git a/tests/pass-rep-blk-str-u8.nt b/tests/pass-rep-blk-str-u8.nt
new file mode 100644 (file)
index 0000000..12e85c6
--- /dev/null
@@ -0,0 +1,5 @@
+!repeat 3 "yo" !end
+---
+79 6f
+79 6f
+79 6f
diff --git a/tests/pass-rep-blk-var.nt b/tests/pass-rep-blk-var.nt
new file mode 100644 (file)
index 0000000..dd690aa
--- /dev/null
@@ -0,0 +1,3 @@
+aa {meow = 5} dd !repeat meow bb !end cc
+---
+aa dd bb bb bb bb bb cc
diff --git a/tests/pass-rep-blk-zero.nt b/tests/pass-rep-blk-zero.nt
new file mode 100644 (file)
index 0000000..8c58975
--- /dev/null
@@ -0,0 +1,3 @@
+aa !repeat 0 bb !end cc
+---
+aa cc
diff --git a/tests/pass-rep-cond.nt b/tests/pass-rep-cond.nt
deleted file mode 100644 (file)
index 87a7c0c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-(
-  <beg>
-  aa bb cc dd
-  <end>
-  {include = int(beg >= 4 * (end - beg))}
-  (11 22 33 44) * {include}
-) * 10
----
-aa bb cc dd
-aa bb cc dd
-aa bb cc dd
-aa bb cc dd
-aa bb cc dd 11 22 33 44
-aa bb cc dd 11 22 33 44
-aa bb cc dd 11 22 33 44
-aa bb cc dd 11 22 33 44
-aa bb cc dd 11 22 33 44
-aa bb cc dd 11 22 33 44
diff --git a/tests/pass-rep-const-bin.nt b/tests/pass-rep-const-bin.nt
deleted file mode 100644 (file)
index 607a86d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-%11001010*5
----
-ca ca ca ca ca
diff --git a/tests/pass-rep-const-dec.nt b/tests/pass-rep-const-dec.nt
deleted file mode 100644 (file)
index fb7dec5..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-$-36*5
----
-dc dc dc dc dc
diff --git a/tests/pass-rep-const-hex.nt b/tests/pass-rep-const-hex.nt
deleted file mode 100644 (file)
index af172d5..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-4b*5
----
-4b 4b 4b 4b 4b
diff --git a/tests/pass-rep-expr-label-inner.nt b/tests/pass-rep-expr-label-inner.nt
deleted file mode 100644 (file)
index 895f5c1..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-11
-(
-  aa bb
-  <meow>
-  cc dd * {meow}
-  ee ff
-) * 2
-22
----
-11
-
-aa bb
-cc dd dd dd
-ee ff
-
-aa bb
-cc dd dd dd dd dd dd dd dd dd dd dd
-ee ff
-
-22
diff --git a/tests/pass-rep-expr-label.nt b/tests/pass-rep-expr-label.nt
deleted file mode 100644 (file)
index 1275025..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-aa bb
-<meow>
-cc dd * {meow}
-ee ff
----
-aa bb
-cc dd dd
-ee ff
diff --git a/tests/pass-rep-expr-var-1.nt b/tests/pass-rep-expr-var-1.nt
deleted file mode 100644 (file)
index 64eb8f5..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-
-aa bb
-{meow = 3}
-cc dd * {meow}
-ee ff
----
-aa bb
-cc dd dd dd
-ee ff
diff --git a/tests/pass-rep-expr-var-2.nt b/tests/pass-rep-expr-var-2.nt
deleted file mode 100644 (file)
index 92e0066..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-aa <mix> bb
-{meow = 3}
-{meow = end}
-11 22
-(
-  {meow = mix * 2}
-  cc dd * {meow}
-) * 2
-ee ff
-88 * {meow}
-<end>
----
-aa bb
-11 22
-cc dd dd
-cc dd dd
-ee ff
-88 88
diff --git a/tests/pass-rep-group.nt b/tests/pass-rep-group.nt
deleted file mode 100644 (file)
index 80e1f17..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-aa (bb cc (dd ee) * 3) * 0xa ff
----
-aa
-  bb cc
-    dd ee
-    dd ee
-    dd ee
-  bb cc
-    dd ee
-    dd ee
-    dd ee
-  bb cc
-    dd ee
-    dd ee
-    dd ee
-  bb cc
-    dd ee
-    dd ee
-    dd ee
-  bb cc
-    dd ee
-    dd ee
-    dd ee
-  bb cc
-    dd ee
-    dd ee
-    dd ee
-  bb cc
-    dd ee
-    dd ee
-    dd ee
-  bb cc
-    dd ee
-    dd ee
-    dd ee
-  bb cc
-    dd ee
-    dd ee
-    dd ee
-  bb cc
-    dd ee
-    dd ee
-    dd ee
-ff
diff --git a/tests/pass-rep-one.nt b/tests/pass-rep-one.nt
deleted file mode 100644 (file)
index 3484211..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-aa bb * 1 cc
----
-aa bb cc
diff --git a/tests/pass-rep-post-all-bytes.nt b/tests/pass-rep-post-all-bytes.nt
new file mode 100644 (file)
index 0000000..494f343
--- /dev/null
@@ -0,0 +1,18 @@
+{ICITTE:8} * 256
+---
+00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
+10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
+20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
+80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f
+90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
+a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af
+b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
+c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf
+d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df
+e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef
+f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
diff --git a/tests/pass-rep-post-cond.nt b/tests/pass-rep-post-cond.nt
new file mode 100644 (file)
index 0000000..87a7c0c
--- /dev/null
@@ -0,0 +1,18 @@
+(
+  <beg>
+  aa bb cc dd
+  <end>
+  {include = int(beg >= 4 * (end - beg))}
+  (11 22 33 44) * {include}
+) * 10
+---
+aa bb cc dd
+aa bb cc dd
+aa bb cc dd
+aa bb cc dd
+aa bb cc dd 11 22 33 44
+aa bb cc dd 11 22 33 44
+aa bb cc dd 11 22 33 44
+aa bb cc dd 11 22 33 44
+aa bb cc dd 11 22 33 44
+aa bb cc dd 11 22 33 44
diff --git a/tests/pass-rep-post-const-bin.nt b/tests/pass-rep-post-const-bin.nt
new file mode 100644 (file)
index 0000000..607a86d
--- /dev/null
@@ -0,0 +1,3 @@
+%11001010*5
+---
+ca ca ca ca ca
diff --git a/tests/pass-rep-post-const-dec.nt b/tests/pass-rep-post-const-dec.nt
new file mode 100644 (file)
index 0000000..fb7dec5
--- /dev/null
@@ -0,0 +1,3 @@
+$-36*5
+---
+dc dc dc dc dc
diff --git a/tests/pass-rep-post-const-hex.nt b/tests/pass-rep-post-const-hex.nt
new file mode 100644 (file)
index 0000000..af172d5
--- /dev/null
@@ -0,0 +1,3 @@
+4b*5
+---
+4b 4b 4b 4b 4b
diff --git a/tests/pass-rep-post-expr-label-inner.nt b/tests/pass-rep-post-expr-label-inner.nt
new file mode 100644 (file)
index 0000000..895f5c1
--- /dev/null
@@ -0,0 +1,20 @@
+11
+(
+  aa bb
+  <meow>
+  cc dd * {meow}
+  ee ff
+) * 2
+22
+---
+11
+
+aa bb
+cc dd dd dd
+ee ff
+
+aa bb
+cc dd dd dd dd dd dd dd dd dd dd dd
+ee ff
+
+22
diff --git a/tests/pass-rep-post-expr-label.nt b/tests/pass-rep-post-expr-label.nt
new file mode 100644 (file)
index 0000000..1275025
--- /dev/null
@@ -0,0 +1,8 @@
+aa bb
+<meow>
+cc dd * {meow}
+ee ff
+---
+aa bb
+cc dd dd
+ee ff
diff --git a/tests/pass-rep-post-expr-var-1.nt b/tests/pass-rep-post-expr-var-1.nt
new file mode 100644 (file)
index 0000000..22f5797
--- /dev/null
@@ -0,0 +1,8 @@
+aa bb
+{meow = 3}
+cc dd * {meow}
+ee ff
+---
+aa bb
+cc dd dd dd
+ee ff
diff --git a/tests/pass-rep-post-expr-var-2.nt b/tests/pass-rep-post-expr-var-2.nt
new file mode 100644 (file)
index 0000000..92e0066
--- /dev/null
@@ -0,0 +1,18 @@
+aa <mix> bb
+{meow = 3}
+{meow = end}
+11 22
+(
+  {meow = mix * 2}
+  cc dd * {meow}
+) * 2
+ee ff
+88 * {meow}
+<end>
+---
+aa bb
+11 22
+cc dd dd
+cc dd dd
+ee ff
+88 88
diff --git a/tests/pass-rep-post-group.nt b/tests/pass-rep-post-group.nt
new file mode 100644 (file)
index 0000000..80e1f17
--- /dev/null
@@ -0,0 +1,44 @@
+aa (bb cc (dd ee) * 3) * 0xa ff
+---
+aa
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+  bb cc
+    dd ee
+    dd ee
+    dd ee
+ff
diff --git a/tests/pass-rep-post-icitte.nt b/tests/pass-rep-post-icitte.nt
new file mode 100644 (file)
index 0000000..738614b
--- /dev/null
@@ -0,0 +1,5 @@
+aa bb cc dd*ICITTE ee ff
+---
+aa bb cc
+dd dd dd
+ee ff
diff --git a/tests/pass-rep-post-label.nt b/tests/pass-rep-post-label.nt
new file mode 100644 (file)
index 0000000..3d53a3b
--- /dev/null
@@ -0,0 +1,3 @@
+aa ff <meow> dd bb * meow cc
+---
+aa ff dd bb bb cc
diff --git a/tests/pass-rep-post-rep.nt b/tests/pass-rep-post-rep.nt
new file mode 100644 (file)
index 0000000..3166497
--- /dev/null
@@ -0,0 +1,6 @@
+((AA * 4) * 8) * 2
+---
+aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
+aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
+aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
+aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
diff --git a/tests/pass-rep-post-str-u16be.nt b/tests/pass-rep-post-str-u16be.nt
new file mode 100644 (file)
index 0000000..a43f1b1
--- /dev/null
@@ -0,0 +1,5 @@
+u16be"yo"*3
+---
+00 79 00 6f
+00 79 00 6f
+00 79 00 6f
diff --git a/tests/pass-rep-post-str-u16le.nt b/tests/pass-rep-post-str-u16le.nt
new file mode 100644 (file)
index 0000000..8577499
--- /dev/null
@@ -0,0 +1,5 @@
+u16le"yo"*3
+---
+79 00 6f 00
+79 00 6f 00
+79 00 6f 00
diff --git a/tests/pass-rep-post-str-u32be.nt b/tests/pass-rep-post-str-u32be.nt
new file mode 100644 (file)
index 0000000..cd4efc0
--- /dev/null
@@ -0,0 +1,5 @@
+u32be"yo"*3
+---
+00 00 00 79 00 00 00 6f
+00 00 00 79 00 00 00 6f
+00 00 00 79 00 00 00 6f
diff --git a/tests/pass-rep-post-str-u32le.nt b/tests/pass-rep-post-str-u32le.nt
new file mode 100644 (file)
index 0000000..33ef354
--- /dev/null
@@ -0,0 +1,5 @@
+u32le"yo"*3
+---
+79 00 00 00 6f 00 00 00
+79 00 00 00 6f 00 00 00
+79 00 00 00 6f 00 00 00
diff --git a/tests/pass-rep-post-str-u8.nt b/tests/pass-rep-post-str-u8.nt
new file mode 100644 (file)
index 0000000..84100a6
--- /dev/null
@@ -0,0 +1,5 @@
+"yo"*3
+---
+79 6f
+79 6f
+79 6f
diff --git a/tests/pass-rep-post-var.nt b/tests/pass-rep-post-var.nt
new file mode 100644 (file)
index 0000000..632f06e
--- /dev/null
@@ -0,0 +1,3 @@
+aa {meow = 5} dd bb * meow cc
+---
+aa dd bb bb bb bb bb cc
diff --git a/tests/pass-rep-post-zero.nt b/tests/pass-rep-post-zero.nt
new file mode 100644 (file)
index 0000000..2f677a4
--- /dev/null
@@ -0,0 +1,3 @@
+aa bb * 0 cc
+---
+aa cc
diff --git a/tests/pass-rep-rep.nt b/tests/pass-rep-rep.nt
deleted file mode 100644 (file)
index 3166497..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-((AA * 4) * 8) * 2
----
-aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
-aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
-aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
-aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
diff --git a/tests/pass-rep-str-u16be.nt b/tests/pass-rep-str-u16be.nt
deleted file mode 100644 (file)
index a43f1b1..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-u16be"yo"*3
----
-00 79 00 6f
-00 79 00 6f
-00 79 00 6f
diff --git a/tests/pass-rep-str-u16le.nt b/tests/pass-rep-str-u16le.nt
deleted file mode 100644 (file)
index 8577499..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-u16le"yo"*3
----
-79 00 6f 00
-79 00 6f 00
-79 00 6f 00
diff --git a/tests/pass-rep-str-u32be.nt b/tests/pass-rep-str-u32be.nt
deleted file mode 100644 (file)
index cd4efc0..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-u32be"yo"*3
----
-00 00 00 79 00 00 00 6f
-00 00 00 79 00 00 00 6f
-00 00 00 79 00 00 00 6f
diff --git a/tests/pass-rep-str-u32le.nt b/tests/pass-rep-str-u32le.nt
deleted file mode 100644 (file)
index 33ef354..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-u32le"yo"*3
----
-79 00 00 00 6f 00 00 00
-79 00 00 00 6f 00 00 00
-79 00 00 00 6f 00 00 00
diff --git a/tests/pass-rep-str-u8.nt b/tests/pass-rep-str-u8.nt
deleted file mode 100644 (file)
index 84100a6..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-"yo"*3
----
-79 6f
-79 6f
-79 6f
diff --git a/tests/pass-rep-zero.nt b/tests/pass-rep-zero.nt
deleted file mode 100644 (file)
index 2f677a4..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-aa bb * 0 cc
----
-aa cc
This page took 0.068482 seconds and 4 git commands to generate.