aboutsummaryrefslogtreecommitdiff
path: root/include/pdp_forth.h
blob: a53291ff085d3d07bd19be056999baa54429bee1 (plain)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*
 *   Pure Data Packet header file. Packet processor system
 *   Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#ifndef __PDP_PROCESSOR__
#define __PDP_PROCESSOR__

#include "pdp_list.h"

/*

*/   


/*
  PDP Processor Model

  The model consists of two parts. 
  
  One being the forth system to provide a lowish level description of packet operations, 
  with a form of polymorphy that enables the system to call the right routines or 
  provide automatic conversion of packet types.

  Two being the object description language. It describes processors in terms of packet
  operations. In fact it is a forth process that sets up the input and output of the
  processors, and organizes the local storage into registers.

*/


/* PDP FORTH (low level stack processors) */

/* the error codes for a processor word */
typedef enum {
    e_ok = 0,
    e_type,        // a recoverable type error (stack untouched)
    e_garbled,     // a non recoverable error (stack messed up)
    e_underflow,   // a stack underflow error 
    e_undef,       // an undefined word error
    e_internal     // an internal error (abort)
} t_pdp_word_error;

typedef struct _pdp_list t_pdp_stack;

/* a pdp word operates on a stack containing atoms (floats, ints, symbols, packets)
   it should return zero on success and an error value on failure.
   whenever a (type) error occurs, the stack should be left untouched (this ensures the system
   can try another implementation of the same word. 

   the type of the first packet on the stack determines the 'type' of the processor method.
   this poses a problem for generating words (i.e pdp_noise or pdp_plasma). in that case
   the first word should be a symbol, indicating the type. if the first item is neither
   a symbol or a packet, the first word in the word list for the respective word symbol
   is called.

   words cannot be removed from the symbol table. (because compiled scripts will have
   their addresses stored) however, they can be redefined, since new definitions are
   appended to the start of a word list, and upon execution, the first (type) matching word
   is called.

   words can be accessed in two ways:
   * the central dispatching system, which chooses a word based on it's symbol and 
     the first item on the stack (a packet's class (or unique type description) or 
     a symbol describing a type) 
   * by calling it's code directly. this can be used to optimize (compile) scripts.

   a word may place invalid packets (-1) on the stack and must be robust at receiving
   them. this is a way to silently recover from non fatal errors.

   a stack error is always fatal and should abort execution. (e_garbled)

*/

typedef int (*t_pdp_forthword)(t_pdp_stack *); 


/* a dictionary item is the definition of a word.
   if a word is type oblivious, it is a high level word, which means it can operate on any type */


/* a struct describing a forth word implementation */
typedef struct _pdp_forthword_imp
{
    struct _pdp_symbol *name;             // the name of this word
    struct _pdp_list   *def;              // the word definition with symbols (word or immediate symbol),
                                          // pointer (primitive word) or int, float and packet immediates.
    struct _pdp_symbol *type;             // the type template this low level word operates on (0 == high level word)
} t_pdp_forthword_imp;

/* a struct describing a forth word specification 
   one specification can have multiple implementations (for type multiplexing) */
typedef struct _pdp_forthword_spec
{
    /* name of this forth word */
    struct _pdp_symbol *name;

    /* stack effect */
    int input_size; 
    int output_size;

    /* index of the stack element to be used for implementation
       multiplexing based on the implementation type template */
    int type_index;

    /* a list of implementations for this word */
    t_pdp_list *implementations;

} t_pdp_forthword_spec;



/* compile a string definition to a list definition */
t_pdp_list *pdp_forth_compile_def(char *chardef);


/* add words to the forth dictionary 
   if the word is type oblivious, the type index should be -1 and the type symbol NULL */
void pdp_forthdict_add_word(t_pdp_symbol *name, t_pdp_list *def, int input_size, int output_size,
			    int type_index, t_pdp_symbol *type);
void pdp_forthdict_add_primitive(t_pdp_symbol *name, t_pdp_forthword w,int input_size, int output_size,
			    int type_index, t_pdp_symbol *type);
void pdp_forthdict_compile_word(t_pdp_symbol *name, char *chardef, int input_size, int output_size,
			    int type_index, t_pdp_symbol *type);



/* execute a word definition (a program) or a single symbolic word */
t_pdp_word_error pdp_forth_execute_def(t_pdp_stack *stack, t_pdp_list *def);
t_pdp_word_error pdp_forth_execute_word(t_pdp_stack *stack, t_pdp_symbol *word);


/* PDP PDL (high level processor description language) */

/* this uses the forth words to describe a processor: defining inputs and outputs,
   preparing the stack, storing intermediates, .. */

/* TODO */


void pdp_forth_word_print_debug(t_pdp_symbol *s);





/* STACK OPERATIONS */


/* connecting the stack to the world */
t_pdp_word_error pdp_stack_push_float(t_pdp_stack *, float f);    // push thing to tos
t_pdp_word_error pdp_stack_push_int(t_pdp_stack *s,    int i);
t_pdp_word_error pdp_stack_push_symbol(t_pdp_stack *s, t_pdp_symbol *x);
t_pdp_word_error pdp_stack_push_packet(t_pdp_stack *s, int p);

t_pdp_word_error pdp_stack_pop_float(t_pdp_stack *, float *f);          // pop thing from tos
t_pdp_word_error pdp_stack_pop_int(t_pdp_stack *, int *i);
t_pdp_word_error pdp_stack_pop_symbol(t_pdp_stack *, t_pdp_symbol **s);
t_pdp_word_error pdp_stack_pop_packet(t_pdp_stack *, int *p);


/* stack operations */

// DUP SWAP DROP OVER ...
t_pdp_word_error pdp_stack_dup(t_pdp_stack *s);
t_pdp_word_error pdp_stack_swap(t_pdp_stack *s);
t_pdp_word_error pdp_stack_drop(t_pdp_stack *s);
t_pdp_word_error pdp_stack_over(t_pdp_stack *s);


/* some util stuff */
t_pdp_stack *pdp_stack_new(void);
void pdp_stack_free(t_pdp_stack *s);



#endif