$ ./course01 # Start application <ENTER> ok>Now we have a look at which words are already defined
ok> words <ENTER> . words drop hello * + ok>We have . (dot) words (already called) drop (which discards top of stack) * (which multiply top of stack with next of stack and leave the result on top of stack. Same with +.
Well, we try to add two numbers
ok> 1 <ENTER> 1 ok> ok> 2 <ENTER> 1 2 ok> ok> + <ENTER> 3 ok> drop <ENTER> ok>Or short:
ok> 1 2 + <ENTER> 3 ok> drop <ENTER> ok>As you can see, each item on stack will be displayed.
[next-of-stack] [top-of-stack] ok>
Here we have the main loop. word() discard any leading white spaces and answer with either the next single word to interpret or the null pointer. The nullpointer is the end of file sign.
int main() { register_primitives(); while((w=word())) interpret(w); return 0; }Next we have the interpreter which interprets one single word (string of characters without any white space).
static void interpret(char *w) { if((current_xt=find(w))) { // search the word in dictionary current_xt->prim(); // if found, execute it } else { // if not found, it may be is a number char *end; int number=strtol(w, &end, 0); // convert word into number if(*end) terminate("word not found"); // not even a number else sp_push(number); // push number on data stack } }To find and execute words (which are functions in other languages) each word has an execution token (xt). This token contains the primitive function of the host language (in this case a function pointer to f_dup(), f_words() etc.) In a single list all words are collected.
typedef struct xt_t { // Execution Token struct xt_t *next; char *name; void (*prim)(void); } xt_t; static xt_t *dictionary; static xt_t *find(char *w) { // find execution token xt_t *xt; for(xt=dictionary;xt;xt=xt->next) if(!strcmp(xt->name, w)) return xt; return 0; // not found }To add new words within the host language we maintain only the single dictionary list.
static void f_add(void) { int v1=sp_pop(); *sp+=v1; } static void add_word(char *name, void (*prim)(void)) { xt_t *xt=calloc(1, sizeof(xt_t)); xt->next=dictionary; dictionary=xt; xt->name=strdup(name); xt->prim=prim; } static void register_primitives(void) { add_word("+", f_add); add_word("*", f_mul); add_word("hello", f_hello_world); add_word("drop", f_drop); add_word("words", f_words); add_word(".", f_dot); }