flat assembler
Message board for the users of flat assembler.
![]() Goto page Previous 1, 2 |
Do you like the idea of inline macros? | |||||||||||||||||||||
|
|||||||||||||||||||||
Total Votes : 5 |
Author |
|
It seems that "macro ?!" also doesn't preprocess lines inside macros:
Code: macro ?! line& display `line, 10 line end macro macro test db 0 end macro Code: flat assembler version g.htee8 macro test 1 pass, 0 bytes. And this variant: Code: macro ?! line& display `line, 10 line end macro macro test db 0 end macro db 1 test Code: flat assembler version g.htee8 macro test db 1 test db 0 end macro 1 pass, 2 bytes. Code: flat assembler version g.htee8 db 1 test 1 pass, 2 bytes. Was it done to avoid preprocessing of "macro ?" itself? How does "macro ?!" work? Maybe it will be ok to pass macros bodies to the "macro ?!" at least. It will be ok to ignore just "macro ?" or "macro ?!" bodies themselves for avoiding of preprocessing of own code. |
|||
![]() |
|
VEG wrote: How does "macro ?!" work? |
|||
![]() |
|
VEG wrote: And a new problem First, you could simply make the "test" macro unconditional: Code: macro test! display <? concat '0x', <? tohex 12345 ?>, 10 ?> end macro test Second, you could define the macro with an analogous interceptor inside: Code: macro test macro ? line& ; ... end macro display <? concat '0x', <? tohex 12345 ?>, 10 ?> purge ? end macro test |
|||
![]() |
|
I remade your sample to show how some of the things may be done differently. I think that use of the namespace is simpler that the name suffix. I also added a "pmacro" variant which can be used to define macro that has preprocessing done for its line. We cannot safely do it for every macro, because applying this universally would also affect out own macros while they need to stay "low level".
Code: macro imacro_preprocess line& local buffer,preprocessed,inline,cursor define buffer line : define preprocessed : while 1 match a <=? b, preprocessed buffer redefine preprocessed a redefine buffer b match x =?> y, buffer redefine cursor x redefine buffer y else err 'missing ?>' break end match redefine inline : while 1 match <=? d, cursor match i, inline redefine inline i <? end match redefine cursor d ?> else match c <=? d, cursor match i, inline redefine inline i c <? end match redefine cursor d ?> else match i, inline cursor redefine inline i break end match match =?> y, buffer redefine buffer y else match x =?> y, buffer match c, cursor redefine cursor c x end match redefine buffer y else err 'missing ?>' break end match end while match :command, inline imacro_preprocess imacro.command match text, preprocessed $result redefine preprocessed text end match end match else match a, preprocessed buffer redefine preprocessed a break end match end while match :command:, preprocessed command end match end macro macro ? line& imacro_preprocess line end macro define imacro macro imacro! definition& esc macro imacro.definition end macro macro end?.imacro! esc end macro end macro macro ipurge? iname purge imacro.iname end macro macro pmacro! definition& esc macro definition macro ? line& imacro_preprocess line end macro end macro macro end?.pmacro?! purge ? esc end macro end macro macro ppurge? pname purge pname end macro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; imacro concat first*,rest*& local result result = string first iterate s, rest result = string result + (s) shl (((bsr result - 1) shr 3 + 1) shl 3) end iterate redefine $result result end imacro imacro tohex number*,digits:8 local result virtual at 0 repeat digits digit = ((number) shr ((%%-%) shl 2)) and 0Fh if digit < 10 db '0'+digit else db 'A'+digit-10 end if end repeat load result:$ from 0 end virtual redefine $result result end imacro pmacro test display <? concat '0x', <? tohex 12345 ?>, 10 ?> end pmacro test |
|||
![]() |
|
Another side note: this (excerpt from your macro) does not work like you probably expected it to:
Code: local result#n match :command args, inline imacro_preprocess resultn, command#_imacro result#n, args Code: local result |
|||
![]() |
|
VEG wrote: Tomasz Grysztar, oh, nice idea! I haven't thought about this use case. It seems that my variant also works with symbolic variables. Code: imacro d mode if mode = 16 $result equ dw else $result equ dd end if end imacro <? d 16 ?> -1 |
|||
![]() |
|
Thank you for your examples.
Tomasz Grysztar wrote: I think that use of the namespace is simpler that the name suffix. I had used suffix because I thought that it will help to honor current namespace. But it doesn't. Also it doesn't allow to call <? nsname.mname 1,2,3 ?> at all because match gets just the first piece before the dot, so it needs an improvement which will collect all pieces of name with dots. I just thought that it would be nice to preserve behavior of standard macros. It is not a frequent use case of course, so I'll try to do it later. |
|||
![]() |
|
VEG wrote: I had used suffix because I thought that it will help to honor current namespace. But it doesn't. Currently, it doesn't allow to call <? nsname.mname 1,2,3 ?> at all because match gets just the first piece before the dot, so it needs an improvement which will collect all pieces of name with dots. I just thought that it would be nice to preserve behavior of standard macros. It is not a frequent use case of course, so I'll try to do it later. Code: match iname= args, line esc macro iname#_imacro result, args Code: match iname= args, line esc macro iname.imacro result, args |
|||
![]() |
|
Quote: Try matching at the separating space: Quote: And perhaps even use a sub-namespace instead of a suffix? About pmacro. If "macro" instruction will be redefined after enabling the "macro ?" and defining the imacro_preprocess macros, maybe it will not affect them? Hm... Maybe it will be better to redefine the "macro" instruction, but add some flag which will disable preprocessing inside current macro. Or add an "llmacro" (low-level macro) instruction for special cases. It worth to think how to make it better ![]() |
|||
![]() |
|
VEG wrote: About pmacro. If "macro" instruction will be redefined after enabling the "macro ?" and defining the imacro_preprocess macros, maybe it will not affect them? |
|||
![]() |
|
As a curiosity: it also might be possible to redefine "macro" locally by embedding the area of source in a child namespace while using the "macro" instruction from the outer namespace when needed. But this is a very very tricky and fragile construction:
Code: define original_macro macro namespace embedded postpone end namespace end postpone match _macro, original_macro _macro macro?! definition& _macro end?.macro?! purge ? esc end macro purge end?.macro? end macro esc _macro definition esc esc _macro ? line& imacro_preprocess line esc esc end macro end macro end match ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; macro test display <? concat '0x', <? tohex 12345 ?>, 10 ?> end macro test |
|||
![]() |
|
Scrap the above, it actually works much better if there is a proxy macro for END too:
Code: define original_macro macro define original_end end namespace embedded postpone end namespace end postpone define end? match _macro:_end, original_macro:original_end iterate directive, macro,struc,virtual,namespace,if,match,rmatch,rawmatch,while,repeat,iterate,rept,irp,irpv,postpone _macro end?.directive?! esc _end directive _end macro end iterate _macro end?! directive end?.directive _end macro _macro macro?! definition& esc _macro definition _macro ? line& imacro_preprocess line _end macro _end macro _macro end?.macro?! purge ? esc _end macro _end macro end match ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; macro test display <? concat '0x', <? tohex 12345 ?>, 10 ?> end macro test Note that to allow "imacro" definitions to be processed correctly in the embedded namespace you have to make them use the original MACRO and END directives in the same way. |
|||
![]() |
|
Looks frightening. Maybe it would be better to add some construction like "postpone", which will allow to execute some instructions every time when any new block of the code starts. Like this:
Code: beforemacro imacro_init end beforemacro It will enable the inline macros for every following macro (or any other kind of block which create new "context" for code). |
|||
![]() |
|
The problem is: if you try to re-define portions of the same language that you used to build these redefinitions, it is going to create self-interference no matter what. The less troublesome route is to define another separate language on top of the basic one which is necessary make higher layers work. That's why my proposed solution was to separate namespaces of the two languages so that they would not interfere with each other.
|
|||
![]() |
|
Goto page Previous 1, 2 < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2019, Tomasz Grysztar.
Powered by rwasa.