-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmacro_interpreter.ads
More file actions
642 lines (618 loc) · 31.9 KB
/
macro_interpreter.ads
File metadata and controls
642 lines (618 loc) · 31.9 KB
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
-----------------------------------------------------------------------
-- --
-- M A C R O I N T E R P R E T E R --
-- --
-- S p e c i f i c a t i o n --
-- --
-- $Revision: 1.0 $ --
-- --
-- Copyright (C) 2023 Hyper Quantum Pty Ltd. --
-- Written by Ross Summerfield. --
-- --
-- This package is a code interpreter for the combining character --
-- instruction set. The combining character instruction sets --
-- operate on a single cell. If that cell contains several Unicode --
-- characters, then it operates on all of them. If the cell --
-- contains one character, which for instance would be the case --
-- for the Latin character set, then it operates on just that one. --
--
-- Instruction Syntax
--
-- The command set may take a parameter, which is passed in as a constant.
-- The syntax for defining this is below. It is loaded into register H.
-- It is sourced from the database for the key to which it applies.
--
-- Each full command is separated by a semicolon (;).
-- White space is at least one of the space (' ' - 16#0020#), tab (16#0008#),
-- carriage return (16#000D#) and line feed (16#000A#) characters. It is used
--to separate sub- components of a command.
-- Comments commence with a double dash (--) character pair and terminate with
-- end of line (line feed - 16#000A#) character, and are ignored.
--
-- Data Sources
--
-- • 5 registers, A - E for numbers
-- • 1 character register, F
-- • 1 string register, G
-- • where each character is addressable as G(x), where x is some integer
-- or a numeric register containing an integer
-- • The parameter Length (as in G'Length) returns the string length
-- • 1 character register, H, which contains a parameter passed to the
-- command set and cannot be altered by the command set
-- • The Cell, represented by the register S
-- • The parameter Length (as in S'Length) returns the cell's string
-- length
-- • Constants (as a decimal number)
-- • Width of each 'space' character
-- • 'space' characters specified in a character set in the database
-- • the set of 'space' characters under operation are bounded by two
-- ASCII space (16#0020#) characters
-- • For the purposes of this language, these 'space' characters are non-
-- combining characters that occupy the current cell
-- • Position of each 'space' character.
--
-- Command Set
--
-- PROCEDURE
-- The PROCEDURE command is used to initiate the combining character command set.
-- Format is:
-- PROCEDURE <<name>> ({value}) IS
-- PROCEDURE <<name>> () IS
-- PROCEDURE IS
-- Where:
-- <<name>> is an optional procedure name;
-- {value} is a Unicode character to be passed in and is loaded into register
-- H.
-- If the {value} is not specified but the brackets () are, then the value in
-- the H register is taken from the key tool tip help text of the launching
-- combining character button.
-- If no brackets are specified, then the H register is left empty.
--
-- END
-- The END command on its own terminates combining character command set and is
-- terminated with a semicolon.
-- Format is:
-- END
-- END <<name>>
-- Where:
-- <<name>> is an optional name, but if supplied, must match the procedure
-- name (which must also then be supplied).
--
-- IF - THEN - ELSE
-- A conditional set of operations.
-- Format is:
-- IF {condition} THEN {operation}
-- ELSIF {condition} THEN {operation}
-- ELSE {operation} END IF
-- Where:
-- {condition} is some comparison of two data sources;
-- {operation} is a set of instructions using the command set. Each operation
-- (i.e. command) is separated by a semicolon (;) as noted above.
-- The ELSIF component together with its operation is optional. There may be
-- as many ELSIF components as is required.
-- The ELSE and ELSIF components together with their operation is optional.
--
-- INSERT
-- Insert just before the specified position the specified string. To insert
-- at the end, specify the last character plus 1. In determining the insert
-- point, combining characters, which take up no apparent 'space', must be
-- taken into account. For the vast majority of character sets, and definitely
-- for the Latin character set, just one character is used within a cell,
-- meaning that the instruction set operates on the (only) character in the
-- current cell (see note at the beginning about characters and cells).
-- After the insertion, the string's length is obviously adjusted (incremented)
-- by one.
-- Format is:
-- INSERT S({position}) WITH "{string}"
-- INSERT S({position}) WITH {register}
-- Where:
-- {position} is the 1 based position from the start of the 'space' sequence
-- of the desired 'space' character to be inserted before;
-- {string} is the string of characters that are to insert before the
-- specified 'space' character - it could be calculated from a
-- string formula;
-- {register} is one of either F (character) or G (string) to be inserted.
--
-- REPLACE
-- Replace the specified 'space' character with the specified string.
--
-- After the replacement, the string length is potentially modified,
-- particularly if the replacement string is longer than one character.
-- Format is:
-- REPLACE S({position}) WITH "{string}"
-- REPLACE S({position}) WITH {register}
-- Where:
-- {position} is the 1 based position from the start of the 'space' sequence
-- of the desired 'space' character to be replaced;
-- {string} is the string of characters that are to replace the specified
-- 'space' character - it could be calculated from a string
-- formula;
-- {register} is one of either F or G to replace.
--
-- DELETE
-- Delete the specified character in the string. This operation does affect
-- position counters that might be in operation, for instance in a For loop
-- that is working through a string of characters in a cell, where whilst the
-- loop counter is not modified, the position in the string that it may
-- reference relates to a string that is now one character shorter. The
-- default register is, of course, the S register.
-- Format is:
-- DELETE ({position})
-- DELETE ({register})
-- DELETE ({register} {position})
-- DELETE ({register} {register})
-- Where:
-- {position} is the 1 based position from the start of the character
-- sequence in the cell of the desired character to be deleted;
-- {register} is one of the numeric registers specifying the character
-- position to be deleted or, in the case of the last two formats
-- the first occurrence specifies the register to delete from.
--
-- FOR - LOOP
-- For each item in a list, perform a specified series of operations.
-- Format is:
-- FOR {register} IN {value} .. {value} LOOP {commands} END LOOP
-- FOR {register} IN REVERSE {value} .. {value} LOOP {commands} END LOOP
-- Where:
-- {register} is a numeric register, A - E, or the character register, F,
-- and the initial value in this register is lost for the counter
-- register (i.e. the first instance specified in the command) if
-- counting up (i.e. REVERSE is not specified) or if the range is
-- specified rather than an end value register; it tracks the loop
-- count from start to finish;
-- {value} specifies the start and end count ranges and must be integers
-- or characters. The value may be provided as either a register
-- or as a constant or as some kind of formula, and each value is
-- separated by the elipses (..);
-- {commands} is a set of instructions using the command set. Each operation
-- (i.e. command) is separated by a semicolon (;) as noted above.
-- The block of commands that the FOR loop operates on is
-- terminated by an 'END LOOP;' statement.
--
-- LOOP - END LOOP
-- Perform a specified series of operations in between the LOOP and END LOOP
-- commands, exiting when the EXIT command is encountered.
-- Format is:
-- LOOP {commands} END LOOP
-- Where:
-- {commands} is a set of instructions using the command set. Each operation
-- (i.e. command) is separated by a semicolon (;) as noted above.
-- The block of commands that the FOR loop operates on is
-- terminated by an 'END LOOP;' statement.
--
-- EXIT
-- Exit a For loop or a standard (i.e. infinite until the Exit command is
-- encountered) loop.
-- Format is:
-- EXIT
-- EXIT WHEN {condition}
-- Where:
-- {condition} is some comparison of two data sources (which could be
-- constant(s) or registers or some other equation formulae).
--
-- LIST
-- This is a 'function' that lists out the sequential characters or numbers
-- between two specified limits. It is used in a for loop (e.g.
-- FOR A IN 1 .. 3) and in a test in an if statement (e.g. IF A IN 1 .. 3).
-- Format is:
-- IN '{start}' .. '{end}'
-- Where:
-- {start} is the starting character or number;
-- {end} is the ending character or number.
--
-- FIND
-- This is a function that finds the specified combining accent or other
-- character position, returning the position number. If there are multiple
-- instances of the specified character, then it returns the position of the
-- first instance. If none are found then it returns 0.
-- It, of course, operates on the S register by default.
-- Format is:
-- FIND ('{c}')
-- FIND ({register})
-- FIND ({register}, {register})
-- Where:
-- {c} is a character to search on;
-- {register} is any register other than the G register, but if any of
-- registers A - E, then the number must be an integer and is
-- translated into its Unicode character value. Where specified,
-- the second optional register specifies the register to search
-- on, by default the S register
--
-- WIDTH
-- Provide the width of the specified character, usually a 'space' character.
-- Format is:
-- WIDTH ('{c}')
-- WIDTH ({register})
-- Where:
-- {c} is a character to search on;
-- {register} is any register other than the G (and S) register, but if any
-- of registers A - E, then the number must be an integer and is
-- translated into its Unicode character value.
--
-- CHAR
-- Provide the character that is the nearest first match for a given character
-- width, given a character starting position.
-- Format is:
-- CHAR ({start}, {size})
-- Where:
-- {start} is the starting character, either as a quoted constant (e.g. ' ')
-- or as a register (e.g. F). If it is a numeric register (i.e.
-- between A and E), then the number must be an integer and is
-- translated into its Unicode character value;
-- {size} is the character size (see WIDTH above) and may either be a
-- (floating point) constant or a register.
--
-- ABS
-- Provide the absolute value of the supplied number as a return value.
-- Format is:
-- ABS ({number})
-- Where:
-- {number} is number to return the absolute value of.
--
-- ERROR LOG
-- Provide a method of logging a message or a register. The log is sent to the
-- application’s standard logging channel with a log level of 1.
-- Format is:
-- ERROR_LOG ("{string}") or
-- ERROR_LOG ({register})
-- Where:
-- {string} is text string and is surrounded by double quotes ("), with a
-- special case of 'registers' which means log all registers;
-- {register} is a register (e.g. F). If it is a numeric register (i.e.
-- between A and E), then the number will be logged in human
-- readable (i.e. textual) format.
--
-- Mathematical Operators
-- := : make the left hand side (a register) equal to the right hand side
-- equation.
-- + : add two registers or a register and a constant together.
-- - : subtract one register or constant from another register or constant.
-- It can also be a unary operator where it negates the register or
-- constant to the right of it.
-- × : multiply the item to its left (register or constant) by the item
-- (register or constant) to the right. Multiplication and division
-- have precedence over addition and subtraction.
-- ÷ : divide the item (register or constant) on the left of the symbol by
-- the item (register or constant) to the right.
-- & : concatenate the register (either F or G) or double quote (")
-- enclosed constant to the operator's left with the register (either F
-- or G) or double quote enclosed constant to the operator's right. The
-- result must either go into register G (e.g. G := "constant" & F) or
-- must be the component of a comparison operation.
-- AND : boolean AND of the register or prior test with another register or
-- subsequent test; if a register, then a content of 0 is treated as
-- FALSE and anything else as TRUE.
-- OR : boolean OR of the register or prior test with another register or
-- subsequent test; if a register, then a content of 0 is treated as
-- FALSE and anything else as TRUE.
-- NOT : boolean NOT of the register or subsequent test; if a register, then
-- a content of 0 is treated as FALSE and anything else as TRUE.
--
-- Comparison Operators
-- = : test that the value (if an equation, then the calculated value) on
-- the left of the comparator is equal to that on the right, returning
-- TRUE if so.
-- > : test that the value (if an equation, then the calculated value) on
-- the left of the comparator is greater than that on the right,
-- returning TRUE if so.
-- >= : test that the value (if an equation, then the calculated value) on
-- the left of the comparator is greater than or equal to that on the
-- right, returning TRUE if so.
-- < : test that the value (if an equation, then the calculated value) on
-- the left of the comparator is less than that on the right, returning
-- TRUE if so.
-- <= : test that the value (if an equation, then the calculated value) on
-- the left of the comparator is less than or equal to that on the
-- right, returning TRUE if so.
--
-- --
-- Version History: --
-- $Log$
-- --
-- Macro_Interpreter is free software; you can redistribute it --
-- and/or modify it under terms of the GNU General Public Licence --
-- as published by the Free Software Foundation; either version 2, --
-- or (at your option) any later version. Cell_Writer is --
-- distributed in 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 --
-- Licence for more details. You should have received a copy of --
-- the GNU General Public Licence distributed with Macro_ --
-- Interpreter. If not, write to the Free Software Foundation, 51 --
-- Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --
-- --
-----------------------------------------------------------------------
-- with GNATCOLL.SQL.Exec;
-- with Gtkada.Builder; use Gtkada.Builder;
-- with Gtk.Drawing_Area; use Gtk.Drawing_Area;
with dStrings; use dStrings;
with Generic_Binary_Trees_With_Data;
with Generic_Stack;
package Macro_Interpreter is
BAD_MACRO_CODE : exception;
-- A handler at the top level main macro execution procedure logs and
-- then displays the error in a pop-up whin this exception is raised.
procedure Set_Log_Level(to : in natural);
-- Set the logging level number for logging the causes of error.
-- The default is 2.
type all_register_names is (const, A, B, C, D, E, F, G, H, S, Y);
subtype register_name is all_register_names range A .. Y;
subtype string_register is register_name range G .. S;
subtype number_register is register_name range A .. E;
subtype char_register is register_name range F .. F;
subtype bool_register is register_name range Y .. Y;
type register_type(reg : all_register_names) is private;
procedure Set_Re_raise_Exception_Preference(to : in boolean := false);
-- If this is set to true, then the exception will be reraised after the
-- pop-up is displayed.
procedure Clear_All_Macros;
-- Clears out all macros from the list of macros.
procedure Load(the_macro : in text; at_number : in natural);
-- Load the macros into memory and otherwise set up the interpreter ready
-- for operation. That includes stripping out comments from the macros
-- and simplifying spaces.
procedure Set(the_register : in number_register; to : in long_float);
procedure Set(the_register : in string_register; to : in text);
procedure Set(the_register : in char_register; to : in wide_character);
procedure Set(the_register : in bool_register; to : in boolean);
function The_Value(of_the_register: in number_register) return long_float;
function The_Value(of_the_register: in string_register) return text;
function The_Value(of_the_register: in char_register) return wide_character;
function The_Value(of_the_register: in bool_register) return boolean;
procedure Execute (the_macro_Number : in natural);
-- This main macro execution procedure the following parameters:
-- 1 The pointer to the currently selected cell;
-- 2 A pointer to the blob containing the instructions, as pointed to
-- by the combining character button;
-- 3 The 'passed-in parameter', taken from the combining character
-- button: if specified in the brackets after the procedure and its
-- optional name, then extracted from the procedure call, if the
-- brackets are provided but have no contents, extracted from the
-- button's tool tip help text, otherwise set to 16#0000# (NULL).
private
reraise_bad_macro_code_exception : boolean;
mloglvl : natural := 2;
multiply_ch: constant wide_character := wide_character'Val(16#00D7#); -- '×'
divide_ch : constant wide_character := wide_character'Val(16#00F7#); -- '÷'
null_ch : constant wide_character := wide_character'Val(16#0000#);
type reserved_words_and_attributes is
(cNull, cEQUATION, cPROCEDURE, cEND, cIF, cINSERT, cREPLACE,
cDELETE, cFOR, cLOOP, cEXIT, cELSE, cELSIF, cERROR_LOG,
cIS, cTHEN, cREVERSE, cWITH, cCHAR, cABS, cFIND, cWIDTH,cIN,
cLength, cSize, cFirst, cLast);
subtype reserved_words is reserved_words_and_attributes range cNull..cIN;
subtype command_set is reserved_words range cNull .. cERROR_LOG;
subtype function_set is reserved_words_and_attributes range cCHAR .. cLast;
type reserved_word_list is array (reserved_words) of text;
all_reserved_words : constant reserved_word_list :=
(Value("NULL"), Value(""), Value("PROCEDURE"), Value("END"), Value("IF"),
Value("INSERT"), Value("REPLACE"), Value("DELETE"), Value("FOR"),
Value("LOOP"), Value("EXIT"), Value("ELSE"), Value("ELSIF"),
Value("ERROR_LOG"),
Value("IS"), Value("THEN"), Value("REVERSE"),
Value("WITH"),
Value("CHAR"), Value("ABS"), Value("FIND"), Value("WIDTH"),Value("IN"));
subtype register_attributes is
reserved_words_and_attributes range cLength..cLast;
type attributes_list is array (register_attributes) of text;
all_attributes : constant attributes_list :=
(Value("'LENGTH"), Value("'SIZE"), Value("'FIRST"), Value("'LAST"));
type mathematical_operator is (none, assign, plus, minus, multiply,
divide, concat, logical_and, logical_or,
logical_not, ellipses,
greater_equal, greater, less_equal,
less, equals, range_condition);
type mathematical_operator_list is array (mathematical_operator) of text;
all_maths_operators : constant mathematical_operator_list :=
(Clear, Value(":="), Value("+"), Value("-"), to_text(multiply_ch),
to_text(divide_ch), Value("&"), Value("AND"), Value("OR"), Value("NOT"),
Value(".."), Value(">="), Value(">"), Value("<="), Value("<"),
Value("="), Value("IN"));
subtype numeric_operator is mathematical_operator range plus .. divide;
subtype logical_operator is mathematical_operator range
logical_and .. logical_not;
subtype comparison_operator is mathematical_operator range
greater_equal .. range_condition;
subtype string_operator is mathematical_operator range concat .. concat;
register_ids : constant array (all_register_names'Range) of wide_character:=
(' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'S', 'Y');
type for_loop_directions is (forward, in_reverse);
type cmd_block(cmd : command_set := cNull);
type code_block is access all cmd_block;
type number_type is (character_type, integer_type, float_type, null_type);
type equation_format is (none, mathematical, logical, textual, funct,
bracketed, comparison);
type equation_type(eq : equation_format := mathematical);
type equation_access is access all equation_type;
register_types:constant array (all_register_names'Range) of equation_format:=
(none, mathematical, mathematical, mathematical,
mathematical, mathematical, textual, textual, textual, textual, logical);
type equation_type(eq : equation_format := mathematical) is record
register : all_register_names := const;
reg_parm : equation_access := null; -- sub-component of reg., if any
operator : mathematical_operator := none;
equation : equation_access := null; -- forward pointer
last_equ : equation_access := null; -- backwards pointer
num_type : number_type := float_type;
case eq is
when mathematical =>
m_const : long_float := 0.0;
m_result : long_float := 0.0;
when logical =>
l_const : boolean := false;
l_result : boolean := false;
l_pos : wide_character := null_ch;
when textual =>
t_const : text;
t_result : text;
when bracketed =>
b_equation : equation_access := null;
b_result : long_float := 0.0;
when funct =>
f_type : function_set;
f_param1 : equation_access;
f_param2 : equation_access;
f_result : long_float := 0.0;
ft_result: text;
when comparison =>
c_const : boolean := false;
c_result : boolean := false;
c_lhs : equation_access := null;
c_rhs : equation_access := null;
when none =>
null;
end case;
end record;
type link_to_positions is (proc_body, then_part, else_part, else_parent,
else_block, ethen_part, parent_if, eelse_part,
for_block, loop_block, exit_point, next_command);
type cmd_block(cmd : command_set := cNull) is record
next_command : code_block;
last_command : code_block;
case cmd is
when cNull =>
null;
when cEQUATION =>
equation : equation_access;
when cPROCEDURE =>
proc_name : text;
parameter : text;
proc_body : code_block;
when cEND =>
end_type : command_set; -- IF/FOR/PROCEDURE
parent_block: code_block;
when cIF =>
condition : equation_access; -- : expression(boolean);
then_part : code_block; -- The THEN Block of code
else_part : code_block; -- points to next ELSIF/ELSE block
if_executed : boolean := false; -- stop ELSE executing on THEN
-- next_command points to END (IF)
when cELSE => -- this pops back to the cIF block's end
else_parent : code_block; -- prior ELSIF/IF command (path back)
else_block : code_block; -- The ELSE Block of code
-- next_command points to END (IF)
when cELSIF => -- this chains off next_command from cIF
econdition : equation_access;
ethen_part : code_block; -- The ELSIF Block of code
parent_if : code_block; -- prior ELSIF/IF command (path back)
eelse_part : code_block; -- next elsif or else or end block
eif_executed: boolean := false; -- for return trip
-- next_command points to END (IF)
when cINSERT =>
i_reg : register_name := S;
i_pos : equation_access;
i_val : all_register_names := const;
i_data: equation_access; -- equation_type;
when cREPLACE =>
r_reg : register_name := S;
r_pos : equation_access;
r_val : all_register_names := const;
r_data: equation_access; -- equation_type;
when cDELETE =>
d_reg : register_name := S;
d_position : equation_access;
when cFOR =>
for_reg : register_name;
f_start : equation_access;
f_end : equation_access;
direction : for_loop_directions := forward;
for_block : code_block;
when cLOOP =>
loop_block : code_block;
when cEXIT =>
exit_conditn: equation_access := null;
exit_point : code_block; -- FOR/LOOP statement that this applies to
exit_parent : code_block; -- prior IF/ELSIF/ELSE/FOR/LOOP command
when cERROR_LOG =>
e_reg : all_register_names := const;
e_val : text;
end case;
end record;
function LessThan(a, b : in natural) return boolean;
package Macro_Lists is new
Generic_Binary_Trees_With_Data(T=>natural,D=>code_block,"<"=>LessThan);
subtype macro_list is Macro_Lists.list;
function AtM(macros : macro_list; m : in natural) return code_block;
-- AtM(acro): Deliver macro number m from the macro_list macros.
the_macros : macro_list;
type register_access is access register_type;
type register_type(reg : all_register_names) is record
case reg is
when A .. E =>
reg_f : long_float := 0.0;
when G .. S =>
reg_t : text := Clear;
when F =>
reg_c : wide_character := null_ch;
when Y =>
reg_b : boolean := false;
when const =>
null;
end case;
end record;
type register_array is array (all_register_names) of register_access;
procedure Initialise(the_registers : out register_array);
-- set the discrimanent for each position to match the position
procedure Strip_Comments_And_Simplify_Spaces(for_macro : in out text);
-- Strip out all comments, indicated by '--' and terminated by an end of
-- line character, then go through and, knowing that commands are
-- separated by the ';' character, replace all multiple spaces type
-- characters, including end of line and tab characters, with a single
-- space character (or no character on either side of a ';' character).
procedure Load_Macro(into : out code_block; from : in text);
-- Load the textual macro into a command block structure, effectively
-- doing a first pass structural check on the macro. If there is any
-- issue, then the BAD_MACRO_CODE exception is raised.
-- The command stack is used to track (through pushing and popping) where
-- the second pass code interpreter (which is executed as the last pass of
-- Initialise_Interpreter) is up to in terms of procedures, if/then/elsif/
-- else statements, for loops and bracket sets in bracketed equations.
type stack_data is record
command : command_set; -- quick access to the relevant command
parent : code_block; -- the parent to which this command applies
end record;
empty_stack : constant stack_data := (cNull, null);
package Command_Stack is new Generic_Stack(T => stack_data,
empty_item => empty_stack);
-- The CHAR command is essentially about getting the size of a character.
-- It returns the first character after that specified with a close matching
-- size. As this data is not really readily avialable from the font
-- information, so we keep a table of values for key items. Here, the space
-- (' ') character is assumed to have a width of 1, just as are all non-
-- combining characters that are not Blissymbolics characters, along with
-- the full-width Blissymbolic full space character. The other Blissymbolic
-- space characters are given a size accordingly.
type char_size is record
the_char : wide_character;
size : long_float := 1.0;
end record;
type char_size_array is array (positive range <>) of char_size;
char_sizes : constant char_size_array :=
((' ',1.0),
(wide_character'Val(16#E100#),1.0), -- bliss_space
(wide_character'Val(16#E101#),0.5), -- bliss_hspace
(wide_character'Val(16#E102#),0.25), -- 1/4 space
(wide_character'Val(16#E103#),0.125),-- 1/8 space
(wide_character'Val(16#E104#),5.0/48.0),
(wide_character'Val(16#E105#),1.0/48.0),
(wide_character'Val(16#E106#),0.0),
(wide_character'Val(16#E18C#),0.0),
(wide_character'Val(16#E18D#),1.0));
procedure Execute (the_macro_code : in code_block;
on_registers : in out register_array;
loop_exit_triggered : in out boolean);
-- This main macro execution procedure the following parameters:
-- 1 The pointer to the currently selected cell;
-- 2 A pointer to the blob containing the instructions, as pointed to
-- by the combining character button;
-- 3 The 'passed-in parameter', taken from the combining character
-- button: if specified in the brackets after the procedure and its
-- optional name, then extracted from the procedure call, if the
-- brackets are provided but have no contents, extracted from the
-- button's tool tip help text, otherwise set to 16#0000# (NULL).
-- This Execute procedure is built to be recursive, and is called by the
-- abive (public) shell Execute procedure that simply sets up the data
-- and, after this Execute operation has run its course, saves the result
-- back to the currently active cell.
the_registers : register_array;
end Macro_Interpreter;