Switching Modes
Besides usingIMMEDIATEand
POSTPONEto switch immediacy, you can use the words
[and
](OPEN/CLOSE BRACKET) to switch modes in any word's compile time. The word
[changes compilation mode into interpretation mode. The word
]changes interpretation mode to compilation mode. An example:
: QQ 1 2 + . [ "hello!" . cr ] ;will display:
hello! okas it is being compiled.
see QQ [0] Literal<1> [1] Literal<2> [2] + [3] . okClearly, from the results of
SEE, the words within
[...
]are executed at
[...
]will not be executed when
LITERALs
Sometimes, you need to compute a value at compilation time and insert the result into the word being compiled. To do this you use the wordLITERAL.
LITERALis an immediate word. It is used only inside a colon definition. At compile time, compiles a value from the stack into the definition as a literal. At run time, the value will be pushed on the stack. For example consider the following word
HEY:
bp : hey [ "Hey " "Jude!" concat ] ; bp "seeing hey ..." . cr see hey --breakpoint #1-- <0> --breakpoint #2-- <1> Hey Jude! seeing hey ... okClearly,
HEYputs the result of
concat, "Hey Jude!", just once, on the stack at compilation time. (
SEE HEYtherefore shows that the word is empty. ) If we wanted to insert this text onto
HEYitself, here's what we do:
bp : hey [ "Hey " "Jude!" concat ] LITERAL ; bp "seeing hey ..." . cr see hey --breakpoint #1-- <0> --breakpoint #2-- <0> seeing hey ... [0] Literal(Hey Jude!) ok
Quiz
Question 1
Have you understand clearly how does[...
]works? Try out the following:
: test "test1" [ "test2" [ "test3" ] ] ;What is happening on the stack before and after you run the word
TEST? Explain clearly using
BP.
bp : test "test1" [ "test2" [ "test3" ] ] ; bp cr see test test bp
--breakpoint #1-- <0> --breakpoint #2-- <2> test2 test3 [0] Literal(test1) --breakpoint #3-- <3> test2 test3 test1 okBefore
testis compiled, nothing is on the stack. After
testis compiled, test2 and test3 are pushed because code inside
[and
]runs immediately and is not compiled into
test. Indeed, if we decompile
test, we can see that only test1 is compiled into
test. Therefore, test1 will be pushed whenever we execute
test.
Question 2
Write a word calledALLOTthat creates and initializes a data section for any word. The resulting data section should have length N and initilaized with the value 0.
ALLOTshould accept just one argument N. For example:
: say-hi "jello" . ; 6 allotshould create a data section for
SAY-HIof length 6, initialized with zeros.
: allot ( n -- ) 0 do 0 , loop ; : say-hi "jello" . ; 6 allot ' say-hi 0 @ . \ 0 ' say-hi 1 @ . \ 0 ' say-hi 2 @ . \ 0 ' say-hi 3 @ . \ 0 ' say-hi 4 @ . \ 0 ' say-hi 5 @ . \ 0
Question 3
Another way to create the word's data section is to do it within the word's definition like so:
: say-hi [ 0 , 41 , 777 , ] "yellow jello" . ;This creates a
SAY-HIwith three elements in the data section. Note that we used the Mode Switching words
[and
]. Ensure that you understand and test this example thoroughly.
: say-hi [ 0 , 41 , 777 , ] "yellow jello" . ; ' say-hi 0 @ . \ 0 ' say-hi 1 @ . \ 41 ' say-hi 2 @ . \ 777When
,executes, an element is inserted into the latest encountered word's data section. Since
,is not immediate, to execute
,immediately , we have to put
,inside
[and
]as in the above code. For this code, when
say-hiis being compiled,
,executes immediately and it finds that
say-hiis the latest word so it insert item into
say-hidata section.
Question 4
What would happen if you usedALLOTafter this like so
: say-hi [ 0 , 41 , 777 , ] "yellow jello" . ; 43 ALLOT
A data section of length 46 is created with the first 3 values being 0, 41, 777.
Question 5
Would this work?
: say-hi [ 43 ALLOT ] .... ;
Yes. It is the same as
: say-hi .... ; 43 allot
Question 6
The wordTHISis written as follows:
: this latestxt postpone literal ; immediate
THIScompiles the XT of the currently defined word as a Literal. Recall the word counting example in Postponing Actions*. Use
THISto make
;count as before, but using just one re-definition instead of two.
: ; postpone ; 1 this +! ; immediate -1 , : count? ['] ; @ . ; : hey "Hey Jude!" . ; : double dup + ; count? \ 2Note that now defining
countalso causes one increment so the data section is initialized to -1.
Question 7
Use[and
]to remove the need to use
THISas a separate word in your answer to Question 6. Hint: Why is
POSTPONEused in
THIS? Is it needed in Question 7?
: ; postpone ; 1 [ latestXT literal ] +! ; immediate -1 , : count? ['] ; @ . ; : hey "Hey Jude!" . ; : double dup + ; count? \ 2To understand how
THISworks, we can see its decompilation:
see this [0] LATESTXT [1] LITERAL okAs
thisis immediate, whenever
thisappears in a word's definition, we can replace
thiswith
[ latestXT literal ]. Also,
literalis immediate too so we have to use
postpone literalin
thisand we can write
[ latestXT ] literalin
;.