Repository: quilt/etk (language: rust)

Issue:
Assembler panic when instruction macro has a push macro inside
```asm
%macro bad()
        %push(0x01)
%end
%bad()
```
```console
$ eas test.etk
thread 'main' panicked at 'internal error: entered unreachable code', etk-asm/src/parse/mod.rs:53:14
stack backtrace:
   0: rust_begin_unwind
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/std/src/panicking.rs:498:5
   1: core::panicking::panic_fmt
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/panicking.rs:107:14
   2: core::panicking::panic
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/panicking.rs:48:5
   3: etk_asm::parse::parse_abstract_op
   4: etk_asm::parse::macros::parse
   5: etk_asm::parse::parse_abstract_op
   6: etk_asm::parse::parse_asm
   7: etk_asm::ingest::Ingest<W>::ingest_file
   8: eas::main
```


Discussion / hints:

Fix patch:
diff --git a/etk-asm/src/parse/asm.pest b/etk-asm/src/parse/asm.pest
index 5e484684..5d745168 100644
--- a/etk-asm/src/parse/asm.pest
+++ b/etk-asm/src/parse/asm.pest
@@ -35,11 +35,11 @@ half_word_size = @{ ("1" ~ '0'..'6') | '1'..'9' }
 // instruction macros //
 ////////////////////////
 instruction_macro_definition = { "%macro" ~ function_declaration ~ NEWLINE* ~ (instruction_macro_stmt ~ NEWLINE)* ~ "%end" }
-instruction_macro_stmt = _{ label_definition | builtin | instruction_macro | push | op }
+instruction_macro_stmt = _{ label_definition | "%" ~ push_macro | local_macro | push | op }
 instruction_macro_variable = @{ "$" ~ function_parameter }
 instruction_macro = !{ "%" ~ function_invocation }
 
-local_macro = { instruction_macro_definition | instruction_macro  | expression_macro_definition }
+local_macro = { !builtin ~ (instruction_macro_definition | instruction_macro  | expression_macro_definition) }
 builtin = ${ "%" ~ ( import | include | include_hex | push_macro ) }
 
 import = !{ "import" ~ arguments }
diff --git a/etk-asm/src/parse/macros.rs b/etk-asm/src/parse/macros.rs
index 1ad9adb9..c262917f 100644
--- a/etk-asm/src/parse/macros.rs
+++ b/etk-asm/src/parse/macros.rs
@@ -64,7 +64,12 @@ fn parse_instruction_macro_defn(pair: Pair<Rule>) -> Result<AbstractOp, ParseErr
 
     let mut contents = Vec::<AbstractOp>::new();
     for pair in pairs {
-        contents.push(super::parse_abstract_op(pair)?);
+        if pair.as_rule() == Rule::push_macro {
+            let expr = expression::parse(pair.into_inner().next().unwrap())?;
+            contents.push(AbstractOp::Push(expr.into()));
+        } else {
+            contents.push(super::parse_abstract_op(pair)?);
+        }
     }
 
     let defn = InstructionMacroDefinition {
diff --git a/etk-asm/src/parse/mod.rs b/etk-asm/src/parse/mod.rs
index 5cb5d48d..d84804cc 100644
--- a/etk-asm/src/parse/mod.rs
+++ b/etk-asm/src/parse/mod.rs
@@ -447,6 +447,8 @@ mod tests {
                 gasprice
                 pop
                 push1 $foo + $bar
+                %push(0x42)
+                %another_macro()
             %end
             %my_macro(0x42, 10)
             "#,
@@ -466,6 +468,11 @@ mod tests {
                             )
                             .into()
                         )),
+                        AbstractOp::Push(0x42.into()),
+                        AbstractOp::Macro(InstructionMacroInvocation {
+                            name: "another_macro".into(),
+                            parameters: vec![]
+                        })
                     ]
                 }
                 .into()


Test patch: