ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
call.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
47/* <usermanual>
48@keyword CALL
49
50@english
51
52The ''CALL'' command is used to call a previously defined procedure
53(or subroutine) within the same program. A procedure is a separate
54block of code designed to perform a specific task. By using ''CALL'',
55you can execute the code within the procedure multiple times, without
56having to rewrite the same statements each time.
57
58Before you can call a procedure, you must define it. In ugBASIC, a
59procedure is typically defined with the ''PROCEDURE'' keyword followed
60by the name of the procedure. Inside the procedure, you write
61the statements that should be executed when the procedure is called.
62
63To execute the code within the procedure, you use the ''CALL'' command
64followed by the name of the procedure.
65
66When the program reaches this line, control is transferred to the
67first statement in the procedure. Once all the statements in the procedure
68are executed, control returns to the line after ''CALL''.
69
70Dividing a program into procedures makes the code more organized and easier to read,
71and a procedure can be called multiple times from different parts of the program,
72avoiding code duplication. Procedures can be used to break a complex problem into
73simpler subproblems, that helps to create a hierarchical structure in the program.
74
75You can also pass arguments to a procedure, enclosed in square parameters:
76arguments are values that are passed to the procedure when it is called and
77that can be used within the procedure itself. If the procedure returns a value,
78the calling statement just ignore it.
79
80By breaking code into procedures, it becomes easier to understand and maintain,
81and by reusing the same procedures in multiple parts of the program, you reduce
82the chances of introducing errors. Finally, if you need to change one part of
83the code, you can simply change the corresponding procedure, without having
84to make changes in all the parts of the program that use that part of the code.
85
86Important: if the ''OPTION CALL AS GOTO'' pragma is in effect, the instruction
87will be considered as a ''GOTO'' rather than a ''GOSUB''. So, no return value and
88no return, at all. This not applies to system calls.
89
90@italian
91
92Il comando ''CALL'' viene utilizzato per chiamare una procedura (o subroutine)
93definita in precedenza all'interno dello stesso programma. Una procedura è un
94blocco di codice separato progettato per eseguire un'attività specifica.
95Utilizzando ''CALL'', è possibile eseguire il codice all'interno della procedura più
96volte, senza dover riscrivere le stesse istruzioni ogni volta.
97
98Prima di poter chiamare una procedura, è necessario definirla. In ugBASIC, una
99procedura è in genere definita con la parola chiave ''PROCEDURE'' seguita dal nome
100della procedura. All'interno della procedura, si scrivono le istruzioni che devono essere
101eseguite quando la procedura viene chiamata.
102
103Per eseguire il codice all'interno della procedura, si utilizza il comando ''CALL''
104seguito dal nome della procedura. Quando il programma raggiunge questa riga, il controllo
105viene trasferito alla prima istruzione nella procedura. Una volta eseguite tutte le istruzioni
106nella procedura, il controllo torna alla riga dopo ''CALL''.
107
108Dividere un programma in procedure rende il codice più organizzato e facile da leggere,
109e una procedura può essere chiamata più volte da diverse parti del programma, evitando
110la duplicazione del codice. Le procedure possono essere utilizzate per suddividere un
111problema complesso in sottoproblemi più semplici, il che aiuta a creare una struttura
112gerarchica nel programma.
113
114Puoi anche passare argomenti a una procedura, racchiusi in parametri quadrati: gli
115argomenti sono valori che vengono passati alla procedura quando viene chiamata e che
116possono essere utilizzati all'interno della procedura stessa. Se la procedura restituisce
117un valore, l'istruzione chiamante lo ignora.
118
119Suddividendo il codice in procedure, diventa più facile da comprendere e gestire, e riutilizzando
120le stesse procedure in più parti del programma, riduci le possibilità di introdurre errori.
121Infine, se hai bisogno di modificare una parte del codice, puoi semplicemente modificare la
122procedura corrispondente, senza dover apportare modifiche in tutte le parti del programma che
123utilizzano quella parte del codice.
124
125Importante: se è in vigore il pragma ''OPTION CALL AS GOTO'', l'istruzione verrà considerata
126come un ''GOTO'' anziché un ''GOSUB''. Quindi, nessun valore di ritorno e nessun ritorno,
127per niente. Questo non si applica alle chiamate di sistema.
128
129@syntax CALL name
130@syntax CALL name parameters "[" [par1 [, par2[, ...]]] "]"
131
132@example CALL factorial[42]
133
134@usedInExample procedures_param_01.bas
135@usedInExample procedures_param_02.bas
136
137@target all
138</usermanual> */
139void call_procedure( Environment * _environment, char * _name ) {
140
141 if ( _environment->emptyProcedure ) {
142 return;
143 }
144
145 Procedure * procedure = _environment->procedures;
146
147 while( procedure ) {
148 if ( strcmp( procedure->name, _name ) == 0 ) {
149 break;
150 }
151 procedure = procedure->next;
152 }
153
154 if ( !procedure ) {
156 }
157
158 if ( procedure->protothread ) {
160 }
161
162 if ( procedure->declared ) {
163
164 int realParametersCount = 0;
165 if ( procedure->parameters ) {
166 for( int i=0; i<procedure->parameters; ++i ) {
167 if ( procedure->parametersTypeEach[i] != -1 ) {
168 ++realParametersCount;
169 if ( _environment->parametersEach[i] ) {
170 Variable * var = variable_retrieve( _environment, _environment->parametersEach[i] );
171 cpu_set_asmio_indirect( _environment, procedure->parametersAsmioEach[i], var->realName );
172 } else {
173 cpu_set_asmio( _environment, procedure->parametersAsmioEach[i], _environment->parametersValueEach[i] );
174 }
175 } else {
176 cpu_set_asmio( _environment, procedure->parametersAsmioEach[i], procedure->parametersValueEach[i] );
177 }
178 }
179 }
180
181 if ( _environment->parameters != realParametersCount ) {
182 CRITICAL_PROCEDURE_PARAMETERS_MISMATCH(_name, realParametersCount, _environment->parameters );
183 }
184
185 if ( procedure->system ) {
186 sys_call( _environment, procedure->address );
187 } else {
188 char address[MAX_TEMPORARY_STORAGE]; sprintf( address, "$%4.4x", procedure->address );
189 cpu_call( _environment, address );
190 }
191
192 if ( procedure->returns ) {
193 for( int i=0; i<procedure->returns; ++i ) {
194 Variable * var;
195 if ( procedure->returnsEach[procedure->returns-i-1] ) {
196 var = variable_retrieve_or_define( _environment, _environment->parametersEach[procedure->returns-i-1], procedure->returnsTypeEach[procedure->returns-i-1], 0 );
197 } else {
198 char paramName[MAX_TEMPORARY_STORAGE]; sprintf(paramName,"%s__PARAM", procedure->name );
199 var = variable_define( _environment, paramName, procedure->returnsTypeEach[procedure->returns-i-1], 0 );
200 }
201 cpu_get_asmio_indirect( _environment, procedure->returnsAsmioEach[procedure->returns-i-1], var->realName );
202 break;
203 }
204 }
205
206 } else {
207
208 if ( _environment->parameters != procedure->parameters ) {
209 CRITICAL_PROCEDURE_PARAMETERS_MISMATCH(_name, procedure->parameters, _environment->parameters );
210 }
211
212 int i=0;
213 for( i=0; i<procedure->parameters; ++i ) {
214 if ( _environment->parametersEach[i] ) {
215 char parameterName[MAX_TEMPORARY_STORAGE]; sprintf( parameterName, "%s__%s", procedure->name, procedure->parametersEach[i] );
216 Variable * parameter = variable_retrieve_or_define( _environment, parameterName, procedure->parametersTypeEach[i], 0 );
217 Variable * value = variable_retrieve( _environment, _environment->parametersEach[i] );
218 variable_move( _environment, value->name, parameter->name );
219 } else {
220 char parameterName[MAX_TEMPORARY_STORAGE]; sprintf( parameterName, "%s__%s", procedure->name, procedure->parametersEach[i] );
221 Variable * parameter = variable_retrieve_or_define( _environment, parameterName, procedure->parametersTypeEach[i], 0 );
222 variable_store( _environment, parameter->name, _environment->parametersValueEach[i] );
223 }
224 }
225 _environment->parameters = 0;
226
227 if ( _environment->optionCallAsGoto ) {
228 cpu_jump( _environment, procedure->realName );
229 } else {
230 cpu_call( _environment, procedure->realName );
231 }
232
233 }
234
235
236}
237
void cpu_set_asmio_indirect(Environment *_environment, int _asmio, char *_value)
Definition 6309.c:3904
void cpu_get_asmio_indirect(Environment *_environment, int _asmio, char *_value)
Definition 6309.c:3967
void cpu_call(Environment *_environment, char *_label)
Definition 6309.c:3755
void cpu_set_asmio(Environment *_environment, int _asmio, int _value)
Definition 6309.c:3838
void cpu_jump(Environment *_environment, char *_label)
Definition 6309.c:3739
Variable * variable_retrieve(Environment *_environment, char *_name)
Variable * variable_retrieve_or_define(Environment *_environment, char *_name, VariableType _type, int _value)
Variable * variable_move(Environment *_environment, char *_source, char *_destination)
Store the value of a variable inside another variable by converting it.
Variable * variable_define(Environment *_environment, char *_name, VariableType _type, int _value)
Define a variable for the program.
Variable * variable_store(Environment *_environment, char *_destination, unsigned int _value)
Store a direct value to a variable.
void sys_call(Environment *_environment, int _address)
Definition sys_call.c:41
void call_procedure(Environment *_environment, char *_name)
Emit code for CALL/PROC ....
Definition call.c:139
char * parametersEach[MAX_PARAMETERS]
Definition ugbc.h:2790
int optionCallAsGoto
Definition ugbc.h:2961
int parameters
Definition ugbc.h:2785
int parametersValueEach[MAX_PARAMETERS]
Definition ugbc.h:2805
Procedure * procedures
Definition ugbc.h:2621
int emptyProcedure
Definition ugbc.h:2932
char * parametersEach[MAX_PARAMETERS]
Definition ugbc.h:1269
int system
Definition ugbc.h:1299
struct _Procedure * next
Definition ugbc.h:1327
int protothread
Definition ugbc.h:1289
int address
Definition ugbc.h:1304
char * name
Definition ugbc.h:1256
int returnsAsmioEach[MAX_PARAMETERS]
Definition ugbc.h:1319
VariableType parametersTypeEach[MAX_PARAMETERS]
Definition ugbc.h:1284
int parameters
Definition ugbc.h:1264
int returns
Definition ugbc.h:1309
int parametersValueEach[MAX_PARAMETERS]
Definition ugbc.h:1279
VariableType returnsTypeEach[MAX_PARAMETERS]
Definition ugbc.h:1324
int declared
Definition ugbc.h:1294
int parametersAsmioEach[MAX_PARAMETERS]
Definition ugbc.h:1274
char * returnsEach[MAX_PARAMETERS]
Definition ugbc.h:1314
char * realName
Definition ugbc.h:1259
char * name
Definition ugbc.h:979
char * realName
Definition ugbc.h:982
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
struct _Variable Variable
Structure of a single variable.
#define CRITICAL_PROCEDURE_MISSING(n)
Definition ugbc.h:3483
struct _Environment Environment
Structure of compilation environment.
#define CRITICAL_PARALLEL_PROCEDURE_CANNOT_BE_CALLED(c)
Definition ugbc.h:3521
#define CRITICAL_PROCEDURE_PARAMETERS_MISMATCH(n, d1, d2)
Definition ugbc.h:3484
struct _Procedure Procedure