@@ -125,42 +125,48 @@ typedef struct ub_proc_fn_def {
125
125
* @brief An array of integers
126
126
*/
127
127
typedef struct ub_var_int_array {
128
+ uint64_t itemcount ;
128
129
const char * varname ;
129
130
int64_t * values ;
130
- uint64_t itemcount ;
131
131
struct ub_var_int_array * next ;
132
132
} ub_var_int_array ;
133
133
134
134
/**
135
135
* @brief An array of strings
136
136
*/
137
137
typedef struct ub_var_string_array {
138
+ uint64_t itemcount ;
138
139
const char * varname ;
139
140
const char * * values ;
140
- uint64_t itemcount ;
141
141
struct ub_var_string_array * next ;
142
142
} ub_var_string_array ;
143
143
144
144
/**
145
145
* @brief An array of real (double)
146
146
*/
147
147
typedef struct ub_var_double_array {
148
+ uint64_t itemcount ;
148
149
const char * varname ;
149
150
double * values ;
150
- uint64_t itemcount ;
151
151
struct ub_var_double_array * next ;
152
152
} ub_var_double_array ;
153
153
154
+ /**
155
+ * @brief A generic array, we can use
156
+ * this to represent any array regardless
157
+ * of its contained type.
158
+ */
159
+ typedef struct ub_var_generic_array {
160
+ uint64_t itemcount ;
161
+ const char * varname ;
162
+ void * values_inaccesible ;
163
+ struct ub_var_generic_array * next ;
164
+ } ub_var_generic_array ;
165
+
154
166
/**
155
167
* @brief Line reference in program.
156
- * Each program has a doubly linked list of these,
157
- * stored in ascending order. Once we iterate the
158
- * list past the search number we know we don't have
159
- * to search any further.
160
- *
161
- * TODO: If search number is < current line number,
162
- * search backwards instead and stop when previous
163
- * number is before search.
168
+ * Each program has a hashmap of these so it can find a line number
169
+ * in O(1) time.
164
170
*/
165
171
typedef struct ub_line_ref {
166
172
uint32_t line_number ;
@@ -181,61 +187,183 @@ typedef struct ub_line_ref {
181
187
#define STRINGIFY (x ) AUX(x)
182
188
183
189
/**
184
- * @brief BASIC program context
185
- * Every instance of a BASIC program has one of these,
186
- * also certain structures such as procedures will clone
187
- * the context and run on the clone until the procedure
188
- * completes. Cloned contexts share variables and you
189
- * should never call ubasic_destroy() on them!
190
+ * @brief BASIC program context.
191
+ * Every instance of a BASIC program has one of these,* also certain structures
192
+ * such as functions will clone the context and run on the clone until the function
193
+ * completes. Cloned contexts share variables and you should never call
194
+ * ubasic_destroy() on them!
190
195
*/
191
196
typedef struct ubasic_ctx {
197
+ /**
198
+ * @brief Pointer to the start of the next token
199
+ * Always between program_ptr and program_ptr + strlen(program_ptr)
200
+ */
192
201
char const * ptr ;
202
+ /**
203
+ * @brief Pointer to the character after the next token.
204
+ * Always between program_ptr and program_ptr + strlen(program_ptr)
205
+ */
193
206
char const * nextptr ;
207
+ /**
208
+ * @brief Numeric form of the token between ptr and nextptr.
209
+ * Should always be a value within the enum token_t
210
+ */
194
211
int current_token ;
212
+ /**
213
+ * @brief Current line number
214
+ */
195
215
int64_t current_linenum ;
216
+ /**
217
+ * @brief True if the program has thrown an error and should end.
218
+ * This may not actually cause termination of the program if we are
219
+ * inside an EVAL at the time.
220
+ */
196
221
bool errored ;
222
+ /**
223
+ * @brief True if the program has ended, e.g. it reached an explicit
224
+ * END statement, or fell off the end of the program to the terminating
225
+ * null char.
226
+ */
197
227
bool ended ;
228
+ /**
229
+ * @brief The whole program text, untokenized.
230
+ * May have been "cleaned" by an initial preprocessing phase which removes
231
+ * unneccesary spacing etc.
232
+ */
198
233
char * program_ptr ;
199
-
234
+ /**
235
+ * @brief A context-local string buffer used for parsing function/procedure
236
+ * parameter lists.
237
+ */
200
238
char string [MAX_STRINGLEN ];
201
-
239
+ /**
240
+ * @brief Local integer variable stack for variables declared within a
241
+ * function or procedure scope.
242
+ */
202
243
struct ub_var_int * local_int_variables [MAX_CALL_STACK_DEPTH ];
244
+ /**
245
+ * @brief Local string variable stack for variables declared within a
246
+ * function or procedure scope.
247
+ */
203
248
struct ub_var_string * local_string_variables [MAX_CALL_STACK_DEPTH ];
249
+ /**
250
+ * @brief Local real (double) variable stack for variables declared
251
+ * within a function or procedure scope.
252
+ */
204
253
struct ub_var_double * local_double_variables [MAX_CALL_STACK_DEPTH ];
205
-
206
- uint64_t gosub_stack [MAX_CALL_STACK_DEPTH ];
207
- uint64_t gosub_stack_ptr ;
208
-
254
+ /**
255
+ * @brief Call stack, holds the return line numbers for each
256
+ * level of calls to a procedure, function or GOSUB
257
+ */
258
+ uint64_t call_stack [MAX_CALL_STACK_DEPTH ];
259
+ /**
260
+ * @brief How far up the call stack we are. The call stack pointer
261
+ * starts at 0, and can go as high as MAX_CALL_STACK_DEPTH - 1
262
+ */
263
+ uint64_t call_stack_ptr ;
264
+ /**
265
+ * @brief Repeat stack, holds the return line numbers for each
266
+ * level of REPEAT...UNTIL loop.
267
+ */
209
268
uint64_t repeat_stack [MAX_LOOP_STACK_DEPTH ];
269
+ /**
270
+ * @brief How far up the REPEAT...UNTIL stack we are. The repeat
271
+ * stack pointer starts at 0, and can go as high as
272
+ * MAX_LOOP_STACK_DEPTH - 1
273
+ */
210
274
uint64_t repeat_stack_ptr ;
211
-
212
- int oldlen ;
275
+ /**
276
+ * @brief Previous program length, before an EVAL statement.
277
+ * An EVAL statement appends additional lines to the program
278
+ * beyond its original end, storing the previous size in this
279
+ * value. If this value is non-zero an EVAL is in progress,
280
+ * otherwise no EVAL is executing.
281
+ */
282
+ size_t oldlen ;
283
+ /**
284
+ * @brief The return line number for an EVAL statement
285
+ */
213
286
int64_t eval_linenum ;
214
-
287
+ /**
288
+ * @brief FOR stack, holds the return line numbers for each
289
+ * level of FOR...NEXT loop.
290
+ */
215
291
struct for_state for_stack [MAX_LOOP_STACK_DEPTH ];
292
+ /**
293
+ * @brief How far up the FOR...NEXT stack we are. The FOR
294
+ * stack pointer starts at 0, and can go as high as
295
+ * MAX_LOOP_STACK_DEPTH - 1
296
+ */
216
297
uint64_t for_stack_ptr ;
217
-
298
+ /**
299
+ * @brief Definitions for procedures and functions in the program
300
+ */
218
301
struct ub_proc_fn_def * defs ;
219
-
302
+ /**
303
+ * @brief Global integer variable list
304
+ */
220
305
struct ub_var_int * int_variables ;
306
+ /**
307
+ * @brief Global string variable list
308
+ */
221
309
struct ub_var_string * str_variables ;
310
+ /**
311
+ * @brief Global double variable list
312
+ */
222
313
struct ub_var_double * double_variables ;
223
-
314
+ /**
315
+ * @brief Global integer array variable list
316
+ */
224
317
struct ub_var_int_array * int_array_variables ;
318
+ /**
319
+ * @brief Global string array variable list
320
+ */
225
321
struct ub_var_string_array * string_array_variables ;
322
+ /**
323
+ * @brief Global double array variable list
324
+ */
226
325
struct ub_var_double_array * double_array_variables ;
227
-
326
+ /**
327
+ * @brief I/O Console
328
+ */
228
329
struct console * cons ;
229
-
330
+ /**
331
+ * @brief Function return type expected.
332
+ * This is only relavent when executing a function atomically.
333
+ */
230
334
ub_return_type fn_type ;
335
+ /**
336
+ * @brief Function return value pointer.
337
+ * This is only relavent when executing a function atomically.
338
+ */
231
339
void * fn_return ;
340
+ /**
341
+ * @brief Bracket depth when parsing function or procedure
342
+ * parameter lists.
343
+ */
232
344
int bracket_depth ;
345
+ /**
346
+ * @brief Item start pointer when parsing function or procedure
347
+ * parameter lists.
348
+ */
233
349
char const * item_begin ;
350
+ /**
351
+ * @brief Linked list of function parameters when parsing function
352
+ * or procedure parameter lists.
353
+ */
234
354
struct ub_param * param ;
235
-
236
- int32_t graphics_colour ; // Current GCOL
237
-
238
- struct hashmap * lines ; // Hash map of line number to char pointers
355
+ /**
356
+ * @brief Current graphics colour (GCOL) for graphics drawing commands
357
+ */
358
+ int32_t graphics_colour ;
359
+ /**
360
+ * @brief Hashmap of lines for O(1) lookup of line numbers
361
+ */
362
+ struct hashmap * lines ;
363
+ /**
364
+ * @brief Block IF...THEN...ELSE depth
365
+ */
366
+ uint64_t if_nest_level ;
239
367
} ubasic_ctx ;
240
368
241
369
/**
@@ -301,7 +429,7 @@ typedef struct ubasic_str_fn
301
429
[[maybe_unused]] char const* item_begin = ctx->ptr;
302
430
303
431
/**
304
- * @brief Get a function parameter of type
432
+ * @brief Get a function parameter of type.
305
433
* @param type Type of function parameter to get, fills one of the variables
306
434
* strval, doubleval or intval.
307
435
*/
@@ -358,7 +486,6 @@ typedef struct ubasic_str_fn
358
486
} \
359
487
}
360
488
361
-
362
489
/*
363
490
* Validation functions
364
491
*/
@@ -415,6 +542,22 @@ char* ubasic_inkey(struct ubasic_ctx* ctx);
415
542
char * ubasic_insocket (struct ubasic_ctx * ctx );
416
543
char * ubasic_upper (struct ubasic_ctx * ctx );
417
544
char * ubasic_lower (struct ubasic_ctx * ctx );
545
+
546
+ /*
547
+ * File I/O functions
548
+ */
549
+ void openin_statement (struct ubasic_ctx * ctx );
550
+ void openup_statement (struct ubasic_ctx * ctx );
551
+ void openout_statement (struct ubasic_ctx * ctx );
552
+ void read_statement (struct ubasic_ctx * ctx );
553
+ void close_statement (struct ubasic_ctx * ctx );
554
+ void eof_statement (struct ubasic_ctx * ctx );
555
+ void delete_statement (struct ubasic_ctx * ctx );
556
+ void mkdir_statement (struct ubasic_ctx * ctx );
557
+ void mount_statement (struct ubasic_ctx * ctx );
558
+ void rmdir_statement (struct ubasic_ctx * ctx );
559
+ void write_statement (struct ubasic_ctx * ctx );
560
+
418
561
/*
419
562
* Builtin real (double) functions
420
563
*/
@@ -472,6 +615,15 @@ void ubasic_set_string_array(const char* var, const char* value, struct ubasic_c
472
615
void ubasic_set_double_array (const char * var , double value , struct ubasic_ctx * ctx );
473
616
void dim_statement (struct ubasic_ctx * ctx );
474
617
void redim_statement (struct ubasic_ctx * ctx );
618
+ void pop_statement (struct ubasic_ctx * ctx );
619
+ void push_statement (struct ubasic_ctx * ctx );
620
+ int64_t arr_expr_set_index (struct ubasic_ctx * ctx , const char * varname );
621
+ bool ubasic_pop_string_array (const char * var , int64_t pop_pos , struct ubasic_ctx * ctx );
622
+ bool ubasic_pop_int_array (const char * var , int64_t pop_pos , struct ubasic_ctx * ctx );
623
+ bool ubasic_pop_double_array (const char * var , int64_t pop_pos , struct ubasic_ctx * ctx );
624
+ bool ubasic_push_string_array (const char * var , int64_t push_pos , struct ubasic_ctx * ctx );
625
+ bool ubasic_push_int_array (const char * var , int64_t push_pos , struct ubasic_ctx * ctx );
626
+ bool ubasic_push_double_array (const char * var , int64_t push_pos , struct ubasic_ctx * ctx );
475
627
476
628
/*
477
629
* Integer expression evaluation
@@ -490,3 +642,8 @@ void double_relation(struct ubasic_ctx* ctx, double* res);
490
642
*/
491
643
const char * str_expr (struct ubasic_ctx * ctx );
492
644
int64_t str_relation (struct ubasic_ctx * ctx );
645
+
646
+ /*
647
+ * Misc functions
648
+ */
649
+ char * printable_syntax (struct ubasic_ctx * ctx );
0 commit comments