ok variable \volume ok variable \name 16 allotHere we have created two variables, one named \volume and another named \name. We happen to prefix variables with a backslash to distinguish them from words and other storage types. Upon creation, \volume is automatically alloted one cell, enough to store a number between -2^31 and 2^31. A cell is made up of bytes, in the case of our 32 bit Forth, a cell is 4 bytes. A 64 bit Forth may define a cell to be 8 bytes and a 16 bit Forth might use 2 byte cells.
\name gets created exactly the same way as \volume, except that we tell Forth to set aside 16 more bytes for storage for storage purposes. This method is commonly used to store strings.
To store and retrieve numbers to a variable, we have two commands at our disposal: ! and @, respectively called store and fetch. These two words operate on memory addresses. If you place a variable on the stack, its location in memory is left on the stack as a positive integer. You can store or fetch the variable's value with ! and @.
ok name .s \ .s shows the contents of the stack. 119920 ok 10 swap .s ! 10 119920 ok .s Empty ok name @ .s 10variable ( "name" -- ) Create a variable with name "name".
allot ( n -- ) Allocate n bytes of memory for the most recently created variable.
! ( n addr -- ) Store n at memory location addr.
@ ( addr -- n ) Fetch the value stored at addr.
ok 4096 constant #step.resolution \ # of steps/Volt. ok #step.resolution .s 4096Most of our code prefixes constant names with a "#" for much the same reason as we prefix variable names with "\". Most of our older code has not undergone this change, though.
constant ( n "name" -- ) Define a constant "name" with value n.
ok " This is a typical string." .s 119921 24 \ The 1st number is the address, the 2nd is the length. ok p" This is a packed string." .s 119921 24 119920 ok count .s \ count extracts the length of the packed string. 119921 24 119921 24 ok type \ display the first n characters from address. This is a packed string. ok type This is a packed string. ok .s EmptySomething interesting and important has happened here. If you look carefully, we created two different strings, a normal string and a packed string, but when we printed each string out the same string was displayed. This happened because there is one specific address where temporary strings are stored, in this example the address is 119920. So, in order to maintain multiple strings we need to have a way of storing them.
ok variable pstring 80 allot \ To hold an 80 char packed string. ok variable nstring 80 allot \ To hold an 80 char normal string. ok p" This is a packed string." ok pstring "copy ok pstring ". \ ". is a synonym for COUNT TYPE. This is a packed string. ok " This is a normal string." nstring swap cmove ok nstring 24 type This is a normal string.Here we use "copy to copy the contents of a packed string address into another address and cmove to copy just the string itself to an address. We end up with two variables each containing different strings. You can easily convert a normal string to a packed string.
ok " This will be a packed string." ok pstring pack ok ". This will be a packed string."copy ( addr1 addr2 -- ) copies the packed string at addr1 to addr2.
cmove ( addr1 addr2 n -- ) copies n bytes from addr1 to addr2.
pack ( addr1 n addr2 -- addr2 ) makes a packed string out of addr1 for n bytes and stores it in addr2.
place ( addr1 n addr2 -- ) Same as pack except that addr2 is not left on the stack.
count ( pstr -- addr len ) Converts a packed string into an address and a length.
ok 10 . \ "dot" 10 ok 10 20 .s \ "dot-s" 10 20 ok : test-dot-quote \ "dot-quote" ." This is a string." ; ok test-dot-quote This is a string. ok .( Print this now!) \ "dot-paren" Print this now!type ( addr len -- ) displays len bytes from addr.
. ( n -- ) displays the top stack item, removing it in the process.
.s ( -- ) displays the current contents of the stack.
." ( "string<quote>" -- ) display the string located between ." and " during runtime (i.e. when a word is executed).
.( ( "string<paren>" -- ) display the string bounded by .( and ) immediately.
76 constant detsize \ # bytes in det structure create (det) detsize allot \ det structure for running system create (dummydet) detsize allot \ det structure for loading files defer det \ det structure itself - can be assigned to either of above ' (det) is det \ Default: det set for running 0 field det \detname \ detector file name 12 field det \clockpgm \ dsp 56k clock program file name 24 field det \datapgm \ dsp 56k data acquisition program 4 field det \nout \ detector outputs (etc...)There is no way of knowing how space is reserved for a string, so using a string entry correctly is difficult. A new data structure method devised by Nat Cowen, which you need not concern yourself with just yet, will look something like:
struct-type: {}(det) is" Detector Parameters" 12 strfield: \detfile is" (file) detector parameters" 12 strfield: \clockpgm is" (file) dsp clock program" 12 strfield: \datapgm is" (file) dsp data program" intfield: \nout is" # detector outputs" (etc...) end-struct-type struct: {}(det) {}det is" Running System (not loading from file)"Each {}det structure will be made up of new data types strfield: and intfield: from which information about each variable or string can be extracted.