en:pfw:condicompi
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | |||
en:pfw:condicompi [2023-09-04 18:11] – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | en:pfw:condicompi [2023-09-04 18:11] (current) – ↷ Seite von pfw:condicompi nach en:pfw:condicompi verschoben uho | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | {{pfw: | ||
+ | ====== Conditional Compilation ====== | ||
+ | |||
+ | Conditional compilation lets you selectively process program text depending on certain conditions. We look at different flavours. | ||
+ | |||
+ | ==== The ICE concept ==== | ||
+ | |||
+ | One of Forth strengths is its ICE (interpret, compile, execute) concept: You can | ||
+ | |||
+ | * **interpret** expressions while the program text is processed, | ||
+ | * **compile** function definitions (words) to capture actions for reuse, and | ||
+ | * **execute** these words with different parameters | ||
+ | |||
+ | within the same program text. | ||
+ | |||
+ | In Forth you can switch between I, C, E arbitrarily.\\ | ||
+ | While interpreting you can make a definition via '' | ||
+ | While compiling you can enclose program text to be interpreted (and executed) in '' | ||
+ | //Immediate words// are always executed regardless of whether forth is in compiler mode or not. | ||
+ | ==== [IF] [ELSE] [THEN] ==== | ||
+ | |||
+ | Standard Forth proposes to have the immediate words '' | ||
+ | |||
+ | <code forth> | ||
+ | «words to be processed» | ||
+ | «some sequence of words that puts a value on the stack» | ||
+ | [IF] | ||
+ | | ||
+ | [ELSE] | ||
+ | | ||
+ | [THEN] | ||
+ | «more words to be processed» | ||
+ | </ | ||
+ | |||
+ | '' | ||
+ | '' | ||
+ | |||
+ | One drawback of '' | ||
+ | |||
+ | Inside a definition: | ||
+ | |||
+ | <code forth> | ||
+ | : «someword» ( ... -- ... ) | ||
+ | [ «some sequence of words that puts a value on the stack» ] | ||
+ | [IF] | ||
+ | ... | ||
+ | [THEN] | ||
+ | ... | ||
+ | ; | ||
+ | </ | ||
+ | |||
+ | ==== Variant based conditional compilation ==== | ||
+ | |||
+ | In this programming pearl Albert Nijhof shows how to do conditional compilation, | ||
+ | |||
+ | The idea here is to have a convenient conditional compilation syntax that can distinguish given variants. A //variant// is a specific (named) configuration that the program should be adapted to, such as a specific kind of arithmetic it should use or the presence of certain features.\\ | ||
+ | Each variant is denoted by a single symbol most often a single letter. The conditions have the form of disjunctions ('' | ||
+ | |||
+ | Instead of | ||
+ | |||
+ | <code forth> | ||
+ | «some sequence of words that puts a non zero value on the stack | ||
+ | if variant A or variant C or variant F is selected» | ||
+ | [IF] | ||
+ | «words to be processed if that value is not zero» | ||
+ | [THEN] | ||
+ | </ | ||
+ | |||
+ | we would like to write | ||
+ | |||
+ | <code forth> | ||
+ | [IF ACF] | ||
+ | «words to be processed if variant is A or C or F» | ||
+ | [THEN] | ||
+ | </ | ||
+ | |||
+ | So what we need is to define a new immediate word **'' | ||
+ | |||
+ | Here is Albert' | ||
+ | |||
+ | <code forth> | ||
+ | 1 \ Conditional compilation -- an 03mar2022 | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | 10 until then nip | ||
+ | 11 postpone [IF] ; immediate | ||
+ | 12 \ ----- end ----- | ||
+ | 13 | ||
+ | </ | ||
+ | |||
+ | The currently selected variant to be processed is supposed to be stored in the Forth value '' | ||
+ | |||
+ | Line 7 parses the input stream up to the next space, i.e. just including the trailing '' | ||
+ | |||
+ | Lines 8-10 then look in loop wether or not the string contains the (symbol denoting the) current variant by inspecting the string one character after the other: '' | ||
+ | |||
+ | Line 9 then checks that character against the variant symbol. If it is found then the loop also stops. | ||
+ | |||
+ | Note, that the loop is quite uncommon. It is a '' | ||
+ | |||
+ | - exit when there are no more characters to be processed (the length became 0) and the variant symbol has not been encountered. | ||
+ | - exit when the current variant symbol is encountered (the length then is not equal to zero) before the end of the string. | ||
+ | |||
+ | The '' | ||
+ | |||
+ | So the length is appropriate as the condition value that can be passed to '' | ||
+ | |||
+ | As '' | ||
+ | |||
+ | That's it the ICE principle in action: A nice custom syntax that allows for a concise notation. | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | Albert' | ||
+ | |||
+ | <code forth> | ||
+ | (* | ||
+ | [IF A] -code- [THEN] | ||
+ | [IF AB] | ||
+ | [IF ACDE] -code- [THEN] | ||
+ | | ||
+ | You want to write a generic code | ||
+ | that differs only slightly in some variants. | ||
+ | Conditional compilation can be a solution. | ||
+ | Name each variant with a letter. | ||
+ | [IF reads the next " | ||
+ | *) | ||
+ | | ||
+ | \ ----- Test | ||
+ | char A to variant | ||
+ | [IF AC] 1 [ELSE] 0 [THEN] . | ||
+ | [IF CA] 1 [ELSE] 0 [THEN] . | ||
+ | [IF B] 1 [ELSE] 0 [THEN] . | ||
+ | [IF BCEFD] 1 [ELSE] 0 [THEN] . | ||
+ | [IF 13%A] 1 [ELSE] 0 [THEN] . | ||
+ | [IF ] 1 [ELSE] 0 [THEN] . | ||
+ | : test1 [IF BCEFD] 1 [ELSE] 0 [THEN] . ; | ||
+ | char C to variant | ||
+ | : test2 [IF BCEFD] 1 [ELSE] 0 [THEN] . ; | ||
+ | test1 | ||
+ | test2 | ||
+ | | ||
+ | (* | ||
+ | ----- Test results | ||
+ | char A to variant | ||
+ | [IF AC] 1 [ELSE] 0 [THEN] . 1 OK | ||
+ | [IF CA] 1 [ELSE] 0 [THEN] . 1 OK | ||
+ | [IF B] 1 [ELSE] 0 [THEN] . 0 OK | ||
+ | [IF BCEFD] 1 [ELSE] 0 [THEN] . 0 OK | ||
+ | [IF 13%A] 1 [ELSE] 0 [THEN] . 1 OK | ||
+ | [IF ] 1 [ELSE] 0 [THEN] . 0 OK | ||
+ | : test1 [IF BCEFD] 1 [ELSE] 0 [THEN] . ; OK | ||
+ | char C to variant | ||
+ | : test2 [IF BCEFD] 1 [ELSE] 0 [THEN] . ; OK | ||
+ | test1 0 OK | ||
+ | test2 1 OK | ||
+ | ( Have a look at SEE TEST1 and SEE TEST2 ) | ||
+ | | ||
+ | ----- noForth code (VALUE and BL-WORD) | ||
+ | value VARIANT | ||
+ | : [IF ( ccc] -- ) \ ccc is case-sensitive | ||
+ | bl-word dup c@ 1 max | ||
+ | begin 1 /string dup | ||
+ | while over c@ variant = | ||
+ | until then nip | ||
+ | postpone [IF] ; immediate | ||
+ | *) | ||
+ | \ <><> | ||
+ | </ | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | uh 2022-03-28 | ||
+ | |||
+ | ===== Contributions ===== | ||
+ | |||
+ | < | ||
+ | |||