ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
begin_procedure.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 PROCEDURE...END PROC
49
50@english
51This couple of keywords create a procedure by giving it a name. The name is
52then followed by a list of parameters and the procedure must be ended
53with an ''END PROC'' command. ''PROCEDURE'' and ''END PROC'' commands
54should be placed on their own individual lines, but it is not mandatory.
55
56It is possible to place the procedure definition anywhere in the program.
57When ugBASIC encounters a procedure statement, the procedure is recognised
58and a jump is made to the final ''END PROC''. In this way, there is no
59risk of executing your procedure by accident.
60
61Following the procedure's name can be given a list of parameters. This creates a
62group of local variables that can be loaded directly from the main program.
63Note that the values to be loaded into parameters must be entered between
64square brackets as part of the procedure call. This system works equally well
65with constants as well as variables, but although you are allowed to
66transfer integer, real or string variables, you may transfer also arrays
67using this method. If you need to enter more than one parameter, the
68variables must be separated by commas.
69
70@italian
71Questa coppia di parole chiave crea una procedura assegnandole un nome.
72Il nome è quindi seguito da un elenco di parametri e la procedura deve
73terminare con i comandi ''END PROC''. I comandi dovrebbero essere
74posti su singole righe, ma non è obbligatorio.
75
76Seguendo la convenzione in essere su altri BASIC dell'epoca, come il
77Simon's BASIC o il Tuned Simon's BASIC, il nome della procedura può
78anche contenere spazi. In tal caso, lo spazio finale non sarà considerato
79come parte del nome.
80
81È possibile posizionare la definizione della procedura ovunque nel programma.
82Quando ugBASIC incontra una definizione di procedura, la procedura viene
83riconosciuta come tale e viene eseguito un salto all' ''END PROC''. In
84questo modo non vi è alcun rischio di eseguire accidentalmente la procedura.
85
86Di seguito al nome della procedura può essere posto un elenco di parametri.
87Questo crea un gruppo di variabili locali che possono essere caricate
88direttamente dal programma principale. Da notare che i valori da caricare
89nei parametri devono essere inseriti tra parentesi quadre come parte della
90chiamata di procedura. Questo sistema funziona altrettanto bene con
91costanti e variabili, ma anche array. Se è necessario immettere più di
92un parametro, i parametri devono essere separate da virgole.
93
94@syntax PROCEDURE name[ par1[, par2[, ... ]]] ]
95@syntax ...
96@syntax END PROC[ expression ]
97
98@example PROCEDURE test[ a, b ]
99@example PRINT "HELLO WORLD! "; (a+b)
100@example END PROC
101@example
102@example PROCEDURE sumOf( x, y )
103@example END PROC[x+y]
104
105@usedInExample procedures_hello_01.bas
106@usedInExample procedures_hello_02.bas
107@usedInExample procedures_hello_03.bas
108@usedInExample procedures_parameters_01.bas
109@usedInExample procedures_parameters_02.bas
110
111@target all
112</usermanual> */
113void begin_procedure( Environment * _environment, char * _name ) {
114
115 if ( _environment->emptyProcedure ) {
116 return;
117 }
118
119 if ( _environment->procedureName ) {
121 }
122
123 Procedure * procedure = malloc( sizeof( Procedure ) );
124 memset(procedure, 0, sizeof( Procedure ) );
125
126 procedure->name = strdup( _name );
127 procedure->realName = malloc( strlen( _name ) + 6 );
128 memset(procedure->realName, 0, strlen( _name ) + 6 );
129 strcopy( procedure->realName, "PROC" );
130 strcat( procedure->realName, _name );
131
132 int i = 0;
133 for( i=0; i<_environment->parameters; ++i ) {
134 char parameterName[MAX_TEMPORARY_STORAGE]; sprintf( parameterName, "%s__%s", procedure->name, _environment->parametersEach[i] );
135 if ( variable_exists( _environment, parameterName ) ) {
137 }
138 Variable * parameter = variable_define( _environment, parameterName, _environment->parametersTypeEach[i], 0 );
139 }
140
141 procedure->parameters = _environment->parameters;
142 procedure->protothread = _environment->protothread;
143 _environment->protothreadStep = 0;
144
145 memcpy( &procedure->parametersEach, &_environment->parametersEach, sizeof( char * ) * _environment->parameters );
146 memcpy( &procedure->parametersTypeEach, &_environment->parametersTypeEach, sizeof( VariableType ) * _environment->parameters );
147 _environment->parameters = 0;
148
149 procedure->next = _environment->procedures;
150 _environment->procedures = procedure;
151
152 _environment->procedureName = strdup( _name );
153 _environment->procedureVariables = NULL;
154 ++_environment->currentProcedure;
155
156 char procedureAfterLabel[MAX_TEMPORARY_STORAGE]; sprintf(procedureAfterLabel, "%safter", _environment->procedureName );
157
158 cpu_jump( _environment, procedureAfterLabel );
159
160 cpu_label( _environment, procedure->realName );
161
162 if ( procedure->protothread ) {
163 _environment->anyProtothread = 1;
164 char procedureParallelDispatch[MAX_TEMPORARY_STORAGE]; sprintf(procedureParallelDispatch, "%sdispatch", _environment->procedureName );
165 cpu_jump( _environment, procedureParallelDispatch );
166 yield( _environment );
167 }
168
169}
void cpu_label(Environment *_environment, char *_label)
Definition 6309.c:356
void cpu_jump(Environment *_environment, char *_label)
Definition 6309.c:3739
int variable_exists(Environment *_environment, char *_name)
Variable * variable_define(Environment *_environment, char *_name, VariableType _type, int _value)
Define a variable for the program.
void begin_procedure(Environment *_environment, char *_name)
Emit code for PROCEDURE ... END PROC.
char * parametersEach[MAX_PARAMETERS]
Definition ugbc.h:2790
Variable * procedureVariables
Definition ugbc.h:2626
int anyProtothread
Definition ugbc.h:2835
int protothread
Definition ugbc.h:2830
int protothreadStep
Definition ugbc.h:2840
VariableType parametersTypeEach[MAX_PARAMETERS]
Definition ugbc.h:2800
int parameters
Definition ugbc.h:2785
int currentProcedure
Definition ugbc.h:2601
char * procedureName
Definition ugbc.h:2775
Procedure * procedures
Definition ugbc.h:2621
int emptyProcedure
Definition ugbc.h:2932
char * parametersEach[MAX_PARAMETERS]
Definition ugbc.h:1269
struct _Procedure * next
Definition ugbc.h:1327
int protothread
Definition ugbc.h:1289
char * name
Definition ugbc.h:1256
VariableType parametersTypeEach[MAX_PARAMETERS]
Definition ugbc.h:1284
int parameters
Definition ugbc.h:1264
char * realName
Definition ugbc.h:1259
void * malloc(YYSIZE_T)
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
struct _Variable Variable
Structure of a single variable.
struct _Environment Environment
Structure of compilation environment.
#define CRITICAL_PROCEDURE_NESTED_UNSUPPORTED(n)
Definition ugbc.h:3481
enum _VariableType VariableType
Type of variables.
struct _Procedure Procedure
#define CRITICAL_PROCEDURE_DUPLICATE_PARAMETER(p, v)
Definition ugbc.h:3707
char * strcopy(char *_dest, char *_source)
void yield(Environment *_environment)
Emit code for YIELD.
Definition yield.c:63