forked from akjmicro/dclang
-
Notifications
You must be signed in to change notification settings - Fork 0
/
user_words.c
83 lines (73 loc) · 2.61 KB
/
user_words.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/* Here we add the functionality necessary for the user to define named
procedures (words). The idea is to have a struct that contains:
1) a string naming the word.
2) the position of that word in the 'prog' array.
The difference between this and the already defined primitives is that the
2nd element in the primitives struct was a function pointer. Here, it is
an index (which is also a pointer) to the start of a procedure, which
itself may contain other procedures that the code may jump to, or simply
resolve to some primitives.
In the 'prog' array, which is indexed by 'iptr', in effect, a word call
is simply a jump to the start of that procedure. When the 'compile'
function finds that a user-defined bit of code is being referenced, what is
put into 'prog' is a call to 'callfunc', with the parameter to that call
being the index in 'prog' where the word resides. */
/* for debugging */
void showdefined()
{
for (int x=0; x < num_user_words; x++) {
printf("Word %i: %s @ %li\n", x, user_words[x].name,\
user_words[x].word_start);
}
}
DCLANG_INT dclang_findword(const char *word)
{
for (DCLANG_INT x = num_user_words - 1; x > -1 ; x--) {
if (strcmp(user_words[x].name, word) == 0) {
return user_words[x].word_start;
}
}
return -1;
}
void callword(DCLANG_FLT where)
{
/* Don't consume more of the return stack if we are going nowhere.
This will allow better recursion */
return_stack[return_stack_ptr++] = iptr;
// set word target; execute word target
iptr = (DCLANG_PTR) where;
(*(prog[iptr].function.with_param)) (prog[iptr++].param);
}
void dclang_callword(DCLANG_PTR where)
{
callword((DCLANG_FLT) where);
// execute all until we reach the end of the iptr queue
while (iptr < max_iptr) {
(*(prog[iptr].function.with_param)) (prog[iptr++].param);
}
}
/* This word will restore 'iptr' to what it was before going on its
fancy journey into a word. It won't "Make America Great Again", but it's
a start. */
void returnfunc()
{
iptr = return_stack[--return_stack_ptr];
}
/* respond to ':' token: */
void startword()
{
/* grab name */
char *this_token;
/* TODO: validation */
this_token = get_token();
/* put name and current location in user_words lookup array */
user_words[num_user_words].name = this_token;
user_words[num_user_words++].word_start = iptr;
}
/* respond to ';' token: */
void endword()
{
/* Simply insert a return call into 'prog' where 'iptr' now points. */
prog[iptr++].function.without_param = returnfunc;
max_iptr = iptr;
}