genie-formula.c
1 //! @file genie-formula.c
2 //! @author J. Marcel van der Veer
3
4 //! @section Copyright
5 //!
6 //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
7 //! Copyright 2001-2024 J. Marcel van der Veer [algol68g@xs4all.nl].
8
9 //! @section License
10 //!
11 //! This program is free software; you can redistribute it and/or modify it
12 //! under the terms of the GNU General Public License as published by the
13 //! Free Software Foundation; either version 3 of the License, or
14 //! (at your option) any later version.
15 //!
16 //! This program is distributed in the hope that it will be useful, but
17 //! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 //! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 //! more details. You should have received a copy of the GNU General Public
20 //! License along with this program. If not, see [http://www.gnu.org/licenses/].
21
22 //! @section Synopsis
23 //!
24 //! Interpreter routines for formulas.
25
26 #include "a68g.h"
27 #include "a68g-genie.h"
28 #include "a68g-frames.h"
29 #include "a68g-prelude.h"
30
31 //! @brief Push equality of two REFs.
32
33 PROP_T genie_identity_relation (NODE_T * p)
34 {
35 NODE_T *lhs = SUB (p), *rhs = NEXT_NEXT (lhs);
36 A68_REF x, y;
37 GENIE_UNIT (lhs);
38 POP_REF (p, &y);
39 GENIE_UNIT (rhs);
40 POP_REF (p, &x);
41 if (IS (NEXT_SUB (p), IS_SYMBOL)) {
42 PUSH_VALUE (p, (BOOL_T) (ADDRESS (&x) == ADDRESS (&y)), A68_BOOL);
43 } else {
44 PUSH_VALUE (p, (BOOL_T) (ADDRESS (&x) != ADDRESS (&y)), A68_BOOL);
45 }
46 PROP_T self;
47 UNIT (&self) = genie_identity_relation;
48 SOURCE (&self) = p;
49 return self;
50 }
51
52 //! @brief Push result of ANDF or THEF.
53
54 PROP_T genie_and_function (NODE_T * p)
55 {
56 A68_BOOL x;
57 GENIE_UNIT (SUB (p));
58 POP_OBJECT (p, &x, A68_BOOL);
59 if (VALUE (&x) == A68_TRUE) {
60 GENIE_UNIT (NEXT_NEXT (SUB (p)));
61 } else {
62 PUSH_VALUE (p, A68_FALSE, A68_BOOL);
63 }
64 PROP_T self;
65 UNIT (&self) = genie_and_function;
66 SOURCE (&self) = p;
67 return self;
68 }
69
70 //! @brief Push result of ORF or ELSF.
71
72 PROP_T genie_or_function (NODE_T * p)
73 {
74 A68_BOOL x;
75 GENIE_UNIT (SUB (p));
76 POP_OBJECT (p, &x, A68_BOOL);
77 if (VALUE (&x) == A68_FALSE) {
78 GENIE_UNIT (NEXT_NEXT (SUB (p)));
79 } else {
80 PUSH_VALUE (p, A68_TRUE, A68_BOOL);
81 }
82 PROP_T self;
83 UNIT (&self) = genie_or_function;
84 SOURCE (&self) = p;
85 return self;
86 }
87
88 //! @brief Call operator.
89
90 void genie_call_operator (NODE_T * p, ADDR_T pop_sp)
91 {
92 ADDR_T pop_fp = A68_FP;
93 MOID_T *pr_mode = MOID (TAX (p));
94 A68_PROCEDURE *z;
95 FRAME_GET (z, A68_PROCEDURE, p);
96 genie_call_procedure (p, pr_mode, MOID (z), pr_mode, z, pop_sp, pop_fp);
97 STACK_DNS (p, SUB (pr_mode), A68_FP);
98 }
99
100 //! @brief Push result of monadic formula OP "u".
101
102 PROP_T genie_monadic (NODE_T * p)
103 {
104 NODE_T *op = SUB (p);
105 NODE_T *u = NEXT (op);
106 ADDR_T pop_sp = A68_SP;
107 GENIE_UNIT (u);
108 STACK_DNS (u, MOID (u), A68_FP);
109 if (PROCEDURE (TAX (op)) != NO_GPROC) {
110 (void) ((*(PROCEDURE (TAX (op)))) (op));
111 } else {
112 genie_call_operator (op, pop_sp);
113 }
114 PROP_T self;
115 UNIT (&self) = genie_monadic;
116 SOURCE (&self) = p;
117 return self;
118 }
119
120 //! @brief Push result of formula.
121
122 PROP_T genie_dyadic_quick (NODE_T * p)
123 {
124 NODE_T *u = SUB (p);
125 NODE_T *op = NEXT (u);
126 NODE_T *v = NEXT (op);
127 GENIE_UNIT (u);
128 STACK_DNS (u, MOID (u), A68_FP);
129 GENIE_UNIT (v);
130 STACK_DNS (v, MOID (v), A68_FP);
131 (void) ((*(PROCEDURE (TAX (op)))) (op));
132 return GPROP (p);
133 }
134
135 //! @brief Push result of formula.
136
137 PROP_T genie_dyadic (NODE_T * p)
138 {
139 NODE_T *u = SUB (p);
140 NODE_T *op = NEXT (u);
141 NODE_T *v = NEXT (op);
142 ADDR_T pop_sp = A68_SP;
143 GENIE_UNIT (u);
144 STACK_DNS (u, MOID (u), A68_FP);
145 GENIE_UNIT (v);
146 STACK_DNS (v, MOID (v), A68_FP);
147 if (PROCEDURE (TAX (op)) != NO_GPROC) {
148 (void) ((*(PROCEDURE (TAX (op)))) (op));
149 } else {
150 genie_call_operator (op, pop_sp);
151 }
152 return GPROP (p);
153 }
154
155 //! @brief Push result of formula.
156
157 PROP_T genie_formula (NODE_T * p)
158 {
159 NODE_T *u = SUB (p);
160 NODE_T *op = NEXT (u);
161 ADDR_T pop_sp = A68_SP;
162 PROP_T self, lhs, rhs;
163 UNIT (&self) = genie_formula;
164 SOURCE (&self) = p;
165 GENIE_UNIT_2 (u, lhs);
166 STACK_DNS (u, MOID (u), A68_FP);
167 if (op != NO_NODE) {
168 NODE_T *v = NEXT (op);
169 GPROC *proc = PROCEDURE (TAX (op));
170 GENIE_UNIT_2 (v, rhs);
171 STACK_DNS (v, MOID (v), A68_FP);
172 UNIT (&self) = genie_dyadic;
173 if (proc != NO_GPROC) {
174 (void) ((*(proc)) (op));
175 UNIT (&self) = genie_dyadic_quick;
176 } else {
177 genie_call_operator (op, pop_sp);
178 }
179 return self;
180 } else if (UNIT (&lhs) == genie_monadic) {
181 return lhs;
182 }
183 (void) rhs;
184 return self;
185 }
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|