en:pfw:prefixes
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | |||
en:pfw:prefixes [2023-09-04 18:17] – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | en:pfw:prefixes [2023-09-04 18:17] (current) – ↷ Seite von pfw:prefixes nach en:pfw:prefixes verschoben uho | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Prefix TO ====== | ||
+ | A simple forth implementation of TO for values,\\ | ||
+ | extendable with other prefixes,\\ | ||
+ | extendable for other word types.\\ | ||
+ | (an 20dec2022) | ||
+ | |||
+ | |||
+ | ===== VARIABLE & VALUE, pros & cons ===== | ||
+ | |||
+ | === Style === | ||
+ | VARIABLE with @ ! and +! = nice pure forth style | ||
+ | VALUE with TO and +TO = typical non forth style | ||
+ | |||
+ | === Psychology === | ||
+ | • VARIABLE\\ | ||
+ | The name provides the location of the variable. | ||
+ | ! and @ produce programming noise that easily causes errors. | ||
+ | For pointers you need even the combinations @ @ and @ ! .\\ | ||
+ | • VALUE\\ | ||
+ | The name gives the value itself, which is very readable. | ||
+ | |||
+ | === Efficiency === | ||
+ | Generally variables or values are more often read than written. | ||
+ | With values you get rid of many fetch commands.\\ | ||
+ | ( BASE @ STATE @ >IN @ ) | ||
+ | |||
+ | === Programming technique === | ||
+ | Variables and values allow nearly the same programming techniques. | ||
+ | The weak point of values is that sometimes the address is needed. | ||
+ | For example if you want to access a value from assembler or in | ||
+ | factorisations like this: | ||
+ | |||
+ | AN and WO are variables: | ||
+ | : EXCHANGE | ||
+ | That's not possible with values. | ||
+ | AN and WO are values: | ||
+ | an wo to an to wo | ||
+ | We solved that (in noForth) with the ADR prefix. | ||
+ | ADR before a value returns the location of the value. That gives | ||
+ | VALUE at least all the technical capabilities of VARIABLE. | ||
+ | |||
+ | === Extendable === | ||
+ | With the code below you can define | ||
+ | * prefixes with other functions ( +TO INCR DECR ADR *TO ... ) | ||
+ | * prefixes for other word types ( 2VALUE STRINGVALUE ... ) | ||
+ | |||
+ | ===== About the code ===== | ||
+ | |||
+ | PREFIX stands for the global prefix (symbolic, a very small number). | ||
+ | PFX stands for the real action in a specific situation. | ||
+ | A PREFIX searches the PFX-LIST for the appropriate PFX. | ||
+ | |||
+ | Two steps in the code are //**not portable**//: | ||
+ | : WORD-TYPE ( token -- word-type ) @ ; | ||
+ | : DATA-ADDR ( token -- data-addr ) >body ; | ||
+ | |||
+ | Example: | ||
+ | 10 value TEST | ||
+ | Given the token of TEST we need a function WORD-TYPE that can determine | ||
+ | that TEST is a value. For indirect threading this could simply be a @ | ||
+ | assuming that the token = CFA and that CFA @ gives DOVALUE . | ||
+ | In some forth implementations this may be problematic. | ||
+ | |||
+ | In the code below we assume that | ||
+ | - xt @ of a value is characteristic for values (WORD-TYPE). | ||
+ | - the body of a value contains the data. | ||
+ | |||
+ | ===== The code ===== | ||
+ | < | ||
+ | \ words: | ||
+ | |||
+ | variable PFX-LINK | ||
+ | here 0 , pfx-link ! | ||
+ | |||
+ | \ Put a pfx in the pfx-list | ||
+ | : PFX ( 'pfx < | ||
+ | here >r pfx-link @ , | ||
+ | ' >body @ \ prefix# | ||
+ | ' @ \ word-type | ||
+ | + , \ pfx-id ( = word-type + prefix# ) | ||
+ | , \ xt of pfx-action | ||
+ | r> pfx-link ! ; | ||
+ | \ An element in the pfx-list consists of three cells: | link | pfx-id | 'pfx | | ||
+ | |||
+ | : FIND-PFX ( pfx-id -- link ) \ pfx-id = word-type + prefix# | ||
+ | pfx-link | ||
+ | begin dup @ \ continue if not end of list | ||
+ | while 2dup cell+ @ <> | ||
+ | while @ \ next element in the list | ||
+ | repeat then | ||
+ | nip ; | ||
+ | |||
+ | \ Define a (global) prefix | ||
+ | : PREFIX ( n < | ||
+ | create , immediate | ||
+ | does> | ||
+ | @ >r \ prefix# | ||
+ | ' dup >body swap \ data-address ' | ||
+ | @ \ word-type | ||
+ | r> + \ pfx-id ( = word-type + prefix# ) | ||
+ | find-pfx | ||
+ | dup @ 0= abort" Prefix not allowed " | ||
+ | cell+ cell+ @ \ jump over link and pfx-id and get xt of pfx | ||
+ | execute ; | ||
+ | </ | ||
+ | |||
+ | ===== The two user words ===== | ||
+ | |||
+ | PREFIX ( n < | ||
+ | This word is used to define a global prefix. It takes a (very small) number | ||
+ | and a name as input. The number serves as the identifier for the prefix. | ||
+ | The name is the symbolic name that will be used in your forth code. The word | ||
+ | PREFIX creates an immediate word with the provided name that, when invoked, | ||
+ | searches for the appropriate pfx action in the pfx-list based on the | ||
+ | combination of the prefix number and the word type of the next word in | ||
+ | the input stream. | ||
+ | PFX ( 'pfx < | ||
+ | This word is used to add a new entry to the pfx-list. It takes as input: | ||
+ | the pfx action execution token, the symbolic (global) prefix name and | ||
+ | the name of a data word (an instance of the word type which must be made | ||
+ | accessible through the prefix). | ||
+ | |||
+ | ===== Applying PREFIX and PFX ===== | ||
+ | < | ||
+ | \ ----- Defining global prefixes ----- | ||
+ | 0 prefix TO | ||
+ | 1 prefix +TO | ||
+ | 2 prefix ADR | ||
+ | \ etc. | ||
+ | |||
+ | \ ----- value ----- | ||
+ | : VALUE ( x name -- ) create , does> @ ; | ||
+ | |||
+ | \ pfx's for VALUE (internal words) | ||
+ | : TO.V ( x -- ) state @ if postpone literal postpone ! exit then ! ; | ||
+ | : +TO.V ( x -- ) state @ if postpone literal postpone +! exit then +! ; | ||
+ | : ADR.V ( -- x ) state @ if postpone literal then ; | ||
+ | |||
+ | \ Put the pfx's for VALUE in pfx-list. We have to create a value to achieve this. | ||
+ | 7 value AMSTERDAM | ||
+ | ' to-v pfx to amsterdam | ||
+ | ' +to.v pfx +to amsterdam | ||
+ | ' adr.v pfx adr amsterdam | ||
+ | |||
+ | \ Better: define !() in assembler (msp430 example) | ||
+ | \ code !() ( x -- ) \ store x in inline following address | ||
+ | \ ip )+ day mov \ read inline address | ||
+ | \ tos day ) mov \ store x in that address | ||
+ | \ sp )+ tos mov | ||
+ | \ next end-code | ||
+ | \ Then postpone literal postpone ! | ||
+ | \ becomes | ||
+ | |||
+ | \ ----- 2value ----- | ||
+ | : 2VALUE ( dx name -- ) create , , does> 2@ ; | ||
+ | : TO.2V ( x -- ) state @ if postpone literal postpone 2! exit then 2! ; | ||
+ | |||
+ | \ Put pfx's for 2VALUE in pfx-list | ||
+ | 77777. 2value ROTTERDAM | ||
+ | ' to.2v pfx to rotterdam | ||
+ | ' adr.v pfx adr rotterdam | ||
+ | </ | ||
+ | ===== Testing ===== | ||
+ | < | ||
+ | \ ----- value test ----- | ||
+ | amsterdam | ||
+ | 1 to amsterdam | ||
+ | 1 +to amsterdam amsterdam . | ||
+ | adr amsterdam | ||
+ | |||
+ | 10 value OSLO oslo . | ||
+ | : T1 1 to oslo ; t1 oslo . | ||
+ | : T2 1 +to oslo ; t2 oslo . | ||
+ | : T3 adr oslo ; t3 @ . | ||
+ | |||
+ | \ ----- 2value test ----- | ||
+ | rotterdam | ||
+ | 11111. to rotterdam | ||
+ | adr rotterdam 2@ d. | ||
+ | |||
+ | : T4 to rotterdam ; | ||
+ | 22222. t4 rotterdam d. | ||
+ | : T5 adr rotterdam 2@ ; t5 d. | ||
+ | 55555. +to rotterdam | ||
+ | \ <><> | ||
+ | </ | ||
+ | < |