ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
add.c
Go to the documentation of this file.
1/*****************************************************************************
2 * ugBASIC - an isomorphic BASIC language compiler for retrocomputers *
3 *****************************************************************************
4 * Copyright 2021-2026 Marco Spedaletti (asimov@mclink.it)
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *----------------------------------------------------------------------------
18 * Concesso in licenza secondo i termini della Licenza Apache, versione 2.0
19 * (la "Licenza"); è proibito usare questo file se non in conformità alla
20 * Licenza. Una copia della Licenza è disponibile all'indirizzo:
21 *
22 * http://www.apache.org/licenses/LICENSE-2.0
23 *
24 * Se non richiesto dalla legislazione vigente o concordato per iscritto,
25 * il software distribuito nei termini della Licenza è distribuito
26 * "COSÌ COM'È", SENZA GARANZIE O CONDIZIONI DI ALCUN TIPO, esplicite o
27 * implicite. Consultare la Licenza per il testo specifico che regola le
28 * autorizzazioni e le limitazioni previste dalla medesima.
29 ****************************************************************************/
30
31/****************************************************************************
32 * INCLUDE SECTION
33 ****************************************************************************/
34
35#include "../../ugbc.h"
36
37/****************************************************************************
38 * CODE SECTION
39 ****************************************************************************/
40
50/* <usermanual>
51@keyword ADD
52
53@english
54
55The ''ADD'' statement is used to increment the value of a numeric variable by
56a specified amount. In other words, it is like adding one number to another.
57
58The basic syntax take the ''var'' to which you want
59to add a value and the ''expr'' as the expression you want to add to the variable.
60The full syntax takes also two additional parameters: ''min'' and ''max'',
61that are the minimum and maximum value that the variable can take after
62the increment. In other words, the ''var'' is incremented, but its value is
63"squeezed" between ''min'' and ''max''. If the result of the addition
64had been greater than ''max'', the level would be put to ''min''. Otherwise,
65if the ''var'' si less than ''min'', the variable will be set to ''max''.
66
67It is possible to "clamp" the value of ''var'' instead of turn around
68the limits. By using the ''CLAMP'' keyword, you can change the behaviour:
69''var'' will be assigned to ''min'' if a value is lesser than ''min'' and
70to ''max'' if a value is greater than ''max''. The same can be obtained by
71using the keyword ''ADDC''.
72
73The purpose of this second syntax is to prevent a variable from taking
74invalid value for your program. It can also help to simulating real-world
75systems: for example, in a game you can limit a character's life between
760 and 100. This instruction can also help to create special effects: you can
77create bouncing or wrapping effects, by making a variable "bounce" between
78two values. In videogames, the typical use is to limit the maximum score
79in a game, or to preventing a difficulty level from exceeding a certain value.
80
81@italian
82L'istruzione ''ADD'' viene utilizzata per incrementare il valore di una
83variabile numerica di una quantità specificata. In altre parole, è come
84aggiungere un numero a un altro.
85
86La sintassi di base prende la ''var'' a cui vuoi aggiungere un
87valore e il ''expr'' come espressione che si vuol aggiungere alla variabile.
88La sintassi completa prende anche due parametri aggiuntivi: ''min'' e
89''max'', che sono il valore minimo e massimo che la variabile può
90assumere dopo l'incremento. In altre parole, la ''variable'' viene
91incrementata, ma il suo valore viene "compresso" tra ''min'' e ''max''.
92Se il risultato dell'addizione fosse stato maggiore di ''max'', il
93valore sarebbe stato impostato su ''min''. Altrimenti, se ''var''
94è minore di ''min'', la variabile verrà impostata su ''max''.
95
96È possibile "bloccare" il valore di ''var'' invece di aggirare i
97limiti. Utilizzando la parola chiave ''CLAMP'', è possibile
98modificare il comportamento: ''var'' verrà assegnato a ''min''
99se un valore è minore di ''min'' e a ''max'' se un valore
100è maggiore di ''max''. Si otterrà lo stesso comportamento usando
101la parola chiave ''ADDC''.
102
103Lo scopo di questa seconda sintassi è impedire a una variabile di
104assumere valori non validi per il tuo programma. Può anche aiutare
105a simulare sistemi del mondo reale: ad esempio, in un gioco puoi
106limitare la vita di un personaggio tra 0 e 100. Questa istruzione
107può anche aiutare a creare effetti speciali: puoi creare effetti
108di rimbalzo o di avvolgimento, facendo "rimbalzare" una variabile
109tra due valori. Nei videogiochi, l'uso tipico è quello di limitare
110il punteggio massimo in un gioco o di impedire che un livello di
111difficoltà superi un certo valore.
112
113@syntax ADD var, expr [, min TO max] [CLAMP]
114
115@alias ADDC
116
117@example ADD y,10
118@example ADD x,42,1 TO 100 CLAMP
119@example ADDC x,42,1 TO 100 : REM equal to the previous command
120
121@usedInExample maths_fast_02.bas
122
123@target all
124</usermanual> */
125/* <usermanual>
126@keyword ADDC
127
128@english
129
130@italian
131
132@alias ADD
133
134@target all
135</usermanual> */
136void add_complex_vars( Environment * _environment, char * _variable, char * _expression, char * _limit_lower, char * _limit_upper, int _clamp ) {
137
139
140 char lessThanLabel[MAX_TEMPORARY_STORAGE]; sprintf( lessThanLabel, "%sl", label );
141 char greaterThanLabel[MAX_TEMPORARY_STORAGE]; sprintf( greaterThanLabel, "%sg", label );
142 char endLabel[MAX_TEMPORARY_STORAGE]; sprintf( endLabel, "%se", label );
143
144 outline2("; variable_add_inplace_vars( , %s, %s )", _variable, _expression );
145
146 variable_add_inplace_vars( _environment, _variable, _expression );
147
148 if ( _limit_lower ) {
149
150 outline2("; variable_less_than( , %s, %s, 0 )", _variable, _limit_lower );
151
152 Variable * less = variable_less_than( _environment, _variable, _limit_lower, 0 );
153
154 cpu_bveq( _environment, less->realName, greaterThanLabel );
155
156 outline2("; variable_move( , %s, %s )", _limit_upper, _variable );
157
158 if ( _clamp ) {
159 variable_move( _environment, _limit_lower, _variable );
160 } else {
161 variable_move( _environment, _limit_upper, _variable );
162 }
163
164 cpu_jump( _environment, endLabel );
165
166 cpu_label( _environment, greaterThanLabel );
167
168 if ( _limit_upper ) {
169
170 Variable * greater = variable_greater_than( _environment, _variable, _limit_upper, 0 );
171
172 cpu_bveq( _environment, greater->realName, endLabel );
173
174 if ( _clamp ) {
175 variable_move( _environment, _limit_upper, _variable );
176 } else {
177 variable_move( _environment, _limit_lower, _variable );
178 }
179
180 }
181
182 cpu_label( _environment, endLabel );
183
184 }
185
186}
187
188void add_complex_type_vars( Environment * _environment, char * _variable, char * _field, char * _expression, char * _limit_lower, char * _limit_upper, int _clamp ) {
189
191
192 char lessThanLabel[MAX_TEMPORARY_STORAGE]; sprintf( lessThanLabel, "%sl", label );
193 char greaterThanLabel[MAX_TEMPORARY_STORAGE]; sprintf( greaterThanLabel, "%sg", label );
194 char endLabel[MAX_TEMPORARY_STORAGE]; sprintf( endLabel, "%se", label );
195
196 variable_add_inplace_type_vars( _environment, _variable, _field, _expression );
197
198 if ( _limit_lower ) {
199
200 Variable * variable = variable_retrieve( _environment, _variable );
201 Field * field = field_find( variable->typeType, _field );
202 Variable * realValue = variable_temporary( _environment, field->type, "(temp)");
203 variable_move_type( _environment, variable->name, field->name, realValue->name );
204
205 Variable * less = variable_less_than( _environment, realValue->name, _limit_lower, 0 );
206
207 cpu_bveq( _environment, less->realName, greaterThanLabel );
208
209 if ( _clamp ) {
210 variable_move_type( _environment, _variable, _field, _limit_lower );
211 } else {
212 variable_move_type( _environment, _variable, _field, _limit_upper );
213 }
214
215 cpu_jump( _environment, endLabel );
216
217 cpu_label( _environment, greaterThanLabel );
218
219 if ( _limit_upper ) {
220
221 Variable * greater = variable_greater_than( _environment, realValue->name, _limit_upper, 0 );
222
223 cpu_bveq( _environment, greater->realName, endLabel );
224
225 if ( _clamp ) {
226 variable_move_type( _environment, _variable, _field, _limit_upper );
227 } else {
228 variable_move_type( _environment, _variable, _field, _limit_lower );
229 }
230
231 }
232
233 cpu_label( _environment, endLabel );
234
235 }
236
237}
238
248void add_complex_mt( Environment * _environment, char * _variable, char * _expression, char * _limit_lower, char * _limit_upper, int _clamp ) {
249
250 parser_array_init( _environment );
251 parser_array_index_symbolic( _environment, "PROTOTHREADCT" );
252 Variable * array = variable_retrieve( _environment, _variable );
253 if ( array->type != VT_TARRAY ) {
254 CRITICAL_NOT_ARRAY( _variable );
255 }
256 Variable * value = variable_move_from_array( _environment, array->name );
257 parser_array_cleanup( _environment );
258
259 add_complex_vars( _environment, value->name, _expression, _limit_lower, _limit_upper, _clamp );
260
261 parser_array_init( _environment );
262 parser_array_index_symbolic( _environment, "PROTOTHREADCT" );
263 array = variable_retrieve( _environment, _variable );
264 if ( array->type != VT_TARRAY ) {
265 CRITICAL_NOT_ARRAY( _variable );
266 }
267 variable_move_array( _environment, array->name, value->name );
268 parser_array_cleanup( _environment );
269
270}
271
281void add_complex_array( Environment * _environment, char * _variable, char * _expression, char * _limit_lower, char * _limit_upper, int _clamp ) {
282
283 Variable * array = variable_retrieve( _environment, _variable );
284 if ( array->type != VT_TARRAY ) {
285 CRITICAL_NOT_ARRAY( _variable );
286 }
287 Variable * value = variable_move_from_array( _environment, array->name );
288
289 add_complex_vars( _environment, value->name, _expression, _limit_lower, _limit_upper, _clamp );
290
291 variable_move_array( _environment, array->name, value->name );
292
293}
294
295void add_complex_array_type( Environment * _environment, char * _variable, char * _field, char * _expression, char * _limit_lower, char * _limit_upper, int _clamp ) {
296
297 outline0("; variable_move_from_array_type" );
298 Variable * value = variable_move_from_array_type( _environment, _variable, _field );
299
300 outline0("; add_complex_vars" );
301 add_complex_vars( _environment, value->name, _expression, _limit_lower, _limit_upper, _clamp );
302
303 outline0("; variable_move_array_type" );
304 variable_move_array_type( _environment, _variable, _field, value->name );
305
306}
307
308void add_complex( Environment * _environment, char * _variable, int _expression, int _limit_lower, int _limit_upper, int _clamp ) {
309
311
312 char lessThanLabel[MAX_TEMPORARY_STORAGE]; sprintf( lessThanLabel, "%sl", label );
313 char greaterThanLabel[MAX_TEMPORARY_STORAGE]; sprintf( greaterThanLabel, "%sg", label );
314 char endLabel[MAX_TEMPORARY_STORAGE]; sprintf( endLabel, "%se", label );
315
316 variable_add_inplace( _environment, _variable, _expression );
317
318 Variable * less = variable_less_than_const( _environment, _variable, _limit_lower, 0 );
319
320 cpu_bveq( _environment, less->realName, greaterThanLabel );
321
322 if ( _clamp ) {
323 variable_store( _environment, _variable, _limit_lower );
324 } else {
325 variable_store( _environment, _variable, _limit_upper );
326 }
327
328 cpu_jump( _environment, endLabel );
329
330 cpu_label( _environment, greaterThanLabel );
331
332 Variable * lesser = variable_less_than_const( _environment, _variable, _limit_upper, 1 );
333
334 cpu_bvneq( _environment, lesser->realName, endLabel );
335
336 if ( _clamp ) {
337 variable_store( _environment, _variable, _limit_upper );
338 } else {
339 variable_store( _environment, _variable, _limit_lower );
340 }
341
342 cpu_label( _environment, endLabel );
343
344}
345
346void add_complex_type( Environment * _environment, char * _variable, char * _field, int _expression, int _limit_lower, int _limit_upper, int _clamp ) {
347
349
350 char lessThanLabel[MAX_TEMPORARY_STORAGE]; sprintf( lessThanLabel, "%sl", label );
351 char greaterThanLabel[MAX_TEMPORARY_STORAGE]; sprintf( greaterThanLabel, "%sg", label );
352 char endLabel[MAX_TEMPORARY_STORAGE]; sprintf( endLabel, "%se", label );
353
354 variable_add_inplace_type( _environment, _variable, _field, _expression );
355
356 Variable * variable = variable_retrieve( _environment, _variable );
357 Field * field = field_find( variable->typeType, _field );
358 Variable * realValue = variable_temporary( _environment, field->type, "(temp)");
359 variable_move_type( _environment, variable->name, field->name, realValue->name );
360
361 Variable * less = variable_less_than_const( _environment, realValue->name, _limit_lower, 0 );
362
363 cpu_bveq( _environment, less->realName, greaterThanLabel );
364
365 if ( _clamp ) {
366 variable_store_type( _environment, _variable, _field, _limit_lower );
367 } else {
368 variable_store_type( _environment, _variable, _field, _limit_upper );
369 }
370
371 cpu_jump( _environment, endLabel );
372
373 cpu_label( _environment, greaterThanLabel );
374
375 Variable * lesser = variable_less_than_const( _environment, realValue->name, _limit_upper, 1 );
376
377 cpu_bvneq( _environment, lesser->realName, endLabel );
378
379 if ( _clamp ) {
380 variable_store_type( _environment, _variable, _field, _limit_upper );
381 } else {
382 variable_store_type( _environment, _variable, _field, _limit_lower );
383 }
384
385 cpu_label( _environment, endLabel );
386
387}
void cpu_bveq(Environment *_environment, char *_value, char *_label)
Definition 6309.c:334
void cpu_label(Environment *_environment, char *_label)
Definition 6309.c:356
void cpu_jump(Environment *_environment, char *_label)
Definition 6309.c:3739
void cpu_bvneq(Environment *_environment, char *_value, char *_label)
Definition 6309.c:345
Variable * variable_retrieve(Environment *_environment, char *_name)
void variable_add_inplace(Environment *_environment, char *_source, int _destination)
void parser_array_index_symbolic(Environment *_environment, char *_index)
Variable * variable_less_than_const(Environment *_environment, char *_source, int _destination, int _equal)
void variable_add_inplace_type(Environment *_environment, char *_source, char *_field, int _destination)
void parser_array_cleanup(Environment *_environment)
void variable_move_array(Environment *_environment, char *_array, char *_value)
Variable * variable_store_type(Environment *_environment, char *_destination, char *_field, unsigned int _value)
Variable * variable_less_than(Environment *_environment, char *_source, char *_destination, int _equal)
Compare two variable and return the result of comparation.
Variable * variable_greater_than(Environment *_environment, char *_source, char *_destination, int _equal)
Compare two variable and return the result of comparation.
Variable * variable_move(Environment *_environment, char *_source, char *_destination)
Store the value of a variable inside another variable by converting it.
Variable * variable_move_from_array(Environment *_environment, char *_array)
void variable_add_inplace_type_vars(Environment *_environment, char *_source, char *_field, char *_destination)
void variable_move_array_type(Environment *_environment, char *_array, char *_field, char *_value)
void variable_add_inplace_vars(Environment *_environment, char *_source, char *_destination)
Add two variable and return the sum of them on the first.
Field * field_find(Type *_type, char *_name)
void parser_array_init(Environment *_environment)
Variable * variable_temporary(Environment *_environment, VariableType _type, char *_meaning)
Define a temporary variable.
Variable * variable_store(Environment *_environment, char *_destination, unsigned int _value)
Store a direct value to a variable.
Variable * variable_move_from_array_type(Environment *_environment, char *_array, char *_field)
void variable_move_type(Environment *_environment, char *_type, char *_field, char *_value)
void add_complex_mt(Environment *_environment, char *_variable, char *_expression, char *_limit_lower, char *_limit_upper, int _clamp)
Emit code for ADD x,y,a TO b.
Definition add.c:248
void add_complex(Environment *_environment, char *_variable, int _expression, int _limit_lower, int _limit_upper, int _clamp)
Definition add.c:308
void add_complex_vars(Environment *_environment, char *_variable, char *_expression, char *_limit_lower, char *_limit_upper, int _clamp)
Emit code for ADD x,y,a TO b.
Definition add.c:136
void add_complex_array(Environment *_environment, char *_variable, char *_expression, char *_limit_lower, char *_limit_upper, int _clamp)
Emit code for ADD x,y,a TO b.
Definition add.c:281
void add_complex_type_vars(Environment *_environment, char *_variable, char *_field, char *_expression, char *_limit_lower, char *_limit_upper, int _clamp)
Definition add.c:188
void add_complex_type(Environment *_environment, char *_variable, char *_field, int _expression, int _limit_lower, int _limit_upper, int _clamp)
Definition add.c:346
void add_complex_array_type(Environment *_environment, char *_variable, char *_field, char *_expression, char *_limit_lower, char *_limit_upper, int _clamp)
Definition add.c:295
char * name
Definition ugbc.h:1231
VariableType type
Definition ugbc.h:1233
char * name
Definition ugbc.h:979
VariableType type
Definition ugbc.h:988
struct _Type * typeType
Definition ugbc.h:1222
char * realName
Definition ugbc.h:982
struct _Field Field
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
#define CRITICAL_NOT_ARRAY(v)
Definition ugbc.h:3480
struct _Variable Variable
Structure of a single variable.
#define outline2(s, a, b)
Definition ugbc.h:4254
struct _Environment Environment
Structure of compilation environment.
@ VT_TARRAY
Definition ugbc.h:480
#define outline0(s)
Definition ugbc.h:4252
#define MAKE_LABEL
Definition ugbc.h:3351