vladx 1.2.1 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCUMENTAZIONE.md +320 -0
- package/README.md +126 -0
- package/examples/test_eccezioni.vx +33 -0
- package/examples/test_stdlib_fs.vx +43 -0
- package/examples/test_stdlib_rete.vx +46 -0
- package/install.sh +42 -0
- package/package.json +1 -1
- package/programs/1/index.vx +1 -0
- package/src/interpreter/interpreter.js +151 -0
- package/src/parser/ast.js +27 -0
- package/src/parser/parser.js +41 -1
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# 🇮🇹 Documentazione Ufficiale VladX
|
|
2
|
+
|
|
3
|
+
Benvenuti nella documentazione ufficiale di **VladX**, un linguaggio di programmazione moderno con **sintassi italiana**. VladX è progettato per essere leggibile, intuitivo e completo, ideale per chi vuole programmare in modo naturale senza rinunciare alla potenza di un linguaggio moderno.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 📑 Indice
|
|
8
|
+
|
|
9
|
+
1. [Installazione](#-installazione)
|
|
10
|
+
2. [Guida Rapida CLI](#-guida-rapida-cli)
|
|
11
|
+
3. [Sintassi di Base](#-sintassi-di-base)
|
|
12
|
+
4. [Tipi di Dati](#-tipi-di-dati)
|
|
13
|
+
5. [Operatori](#-operatori)
|
|
14
|
+
6. [Controllo del Flusso](#-controllo-del-flusso)
|
|
15
|
+
7. [Funzioni](#-funzioni)
|
|
16
|
+
8. [Moduli](#-moduli)
|
|
17
|
+
9. [Libreria Standard (StdLib)](#-libreria-standard-stdlib)
|
|
18
|
+
10. [Funzioni Globali](#-funzioni-globali)
|
|
19
|
+
11. [Metodi di Array e Oggetti](#-metodi-di-array-e-oggetti)
|
|
20
|
+
12. [VladPM (Package Manager)](#-vladpm-package-manager)
|
|
21
|
+
13. [Esempi Completi](#-esempi-completi)
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 🚀 Installazione
|
|
26
|
+
|
|
27
|
+
Puoi installare VladX sul tuo sistema in due modi:
|
|
28
|
+
|
|
29
|
+
### Tramite NPM (Consigliato)
|
|
30
|
+
Se hai Node.js installato, puoi installare VladX globalmente con un semplice comando:
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g vladx
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Tramite Script Bash
|
|
36
|
+
Puoi utilizzare lo script di installazione incluso nel repository:
|
|
37
|
+
```bash
|
|
38
|
+
chmod +x install.sh
|
|
39
|
+
./install.sh
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 🛠 Guida Rapida CLI
|
|
45
|
+
|
|
46
|
+
Il comando principale è `vladx`.
|
|
47
|
+
|
|
48
|
+
- **REPL Interattivo**: Digita semplicemente `vladx` per entrare nella console interattiva.
|
|
49
|
+
- **Esecuzione Script**: `vladx mio_programma.vx`
|
|
50
|
+
- **Analisi AST**: `vladx ast mio_programma.vx` (mostra la struttura interna del codice).
|
|
51
|
+
- **Lexing**: `vladx lex mio_programma.vx` (mostra i token analizzati).
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 📝 Sintassi di Base
|
|
56
|
+
|
|
57
|
+
### Commenti
|
|
58
|
+
```javascript
|
|
59
|
+
// Questo è un commento su riga singola
|
|
60
|
+
/* Questo è un commento
|
|
61
|
+
multilinea */
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Variabili e Costanti
|
|
65
|
+
In VladX, le variabili vengono dichiarate con la parola chiave `variabile` e le costanti con `costante`.
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
variabile nome = "Vlad";
|
|
69
|
+
nome = "VladX"; // Ok, è una variabile
|
|
70
|
+
|
|
71
|
+
costante VERSIONE = 1.2;
|
|
72
|
+
// VERSIONE = 1.3; // Errore! Non puoi riassegnare una costante
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 💎 Tipi di Dati
|
|
78
|
+
|
|
79
|
+
VladX supporta i seguenti tipi di dati fondamentali:
|
|
80
|
+
|
|
81
|
+
| Tipo | Esempio |
|
|
82
|
+
| :--- | :--- |
|
|
83
|
+
| **Numero** | `10`, `3.14`, `-5` |
|
|
84
|
+
| **Stringa** | `"Ciao Mondo"`, `'Esempio'` |
|
|
85
|
+
| **Booleano** | `vero`, `falso` |
|
|
86
|
+
| **Nullo** | `nullo` |
|
|
87
|
+
| **Array** | `[1, 2, 3, "test"]` |
|
|
88
|
+
| **Oggetto** | `{ nome: "Vlad", eta: 20 }` |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## ⚡ Operatori
|
|
93
|
+
|
|
94
|
+
### Aritmetici
|
|
95
|
+
Supporto completo per le operazioni matematiche:
|
|
96
|
+
- `+` (Addizione / Concatenazione stringhe)
|
|
97
|
+
- `-` (Sottrazione)
|
|
98
|
+
- `*` (Moltiplicazione)
|
|
99
|
+
- `/` (Divisione)
|
|
100
|
+
- `%` (Resto della divisione)
|
|
101
|
+
- `++` / `--` (Incremento e decremento)
|
|
102
|
+
|
|
103
|
+
### Confronto
|
|
104
|
+
- `==` / `===` (Uguaglianza)
|
|
105
|
+
- `!=` / `!==` (Diversità)
|
|
106
|
+
- `<` / `>` (Minore / Maggiore)
|
|
107
|
+
- `<=` / `>=` (Minore o uguale / Maggiore o uguale)
|
|
108
|
+
|
|
109
|
+
### Logici
|
|
110
|
+
- `e` (AND logico)
|
|
111
|
+
- `o` (OR logico)
|
|
112
|
+
- `non` (NOT logico)
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 🔄 Controllo del Flusso
|
|
117
|
+
|
|
118
|
+
### Condizionali (se / altrimenti)
|
|
119
|
+
```javascript
|
|
120
|
+
variabile voto = 8;
|
|
121
|
+
|
|
122
|
+
se (voto >= 6) {
|
|
123
|
+
stampa("Promosso!");
|
|
124
|
+
} altrimenti {
|
|
125
|
+
stampa("Bocciato!");
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Ciclo Mentre (mentre)
|
|
130
|
+
```javascript
|
|
131
|
+
variabile contatore = 0;
|
|
132
|
+
mentre (contatore < 5) {
|
|
133
|
+
stampa("Conteggio: " + contatore);
|
|
134
|
+
contatore++;
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Ciclo Per (per)
|
|
139
|
+
```javascript
|
|
140
|
+
per (variabile i = 0; i < 3; i++) {
|
|
141
|
+
stampa("Giro numero " + i);
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Gestione Errori (prova / cattura / finalmente)
|
|
146
|
+
VladX include un sistema robusto per gestire le eccezioni:
|
|
147
|
+
```javascript
|
|
148
|
+
prova {
|
|
149
|
+
lancia "Qualcosa è andato storto!";
|
|
150
|
+
} cattura (errore) {
|
|
151
|
+
stampa("Errore catturato: " + errore);
|
|
152
|
+
} finalmente {
|
|
153
|
+
stampa("Esecuzione terminata.");
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 📦 Funzioni
|
|
160
|
+
|
|
161
|
+
### Dichiarazione Funzione
|
|
162
|
+
```javascript
|
|
163
|
+
funzione saluta(nome) {
|
|
164
|
+
ritorna "Ciao, " + nome + "!";
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
stampa(saluta("Amico"));
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Arrow Functions
|
|
171
|
+
Sintassi compatta per funzioni rapide:
|
|
172
|
+
```javascript
|
|
173
|
+
costante quadrato = (n) => n * n;
|
|
174
|
+
stampa(quadrato(4)); // 16
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## 🧩 Moduli
|
|
180
|
+
|
|
181
|
+
VladX permette di organizzare il codice in più file.
|
|
182
|
+
|
|
183
|
+
**file: `matematica.vx`**
|
|
184
|
+
```javascript
|
|
185
|
+
esporta costante PI = 3.14;
|
|
186
|
+
esporta funzione doppia(n) { ritorna n * 2; }
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**file: `app.vx`**
|
|
190
|
+
```javascript
|
|
191
|
+
importa { PI, doppia } da "./matematica.vx";
|
|
192
|
+
|
|
193
|
+
stampa("Il doppio di PI è: " + doppia(PI));
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## 📚 Libreria Standard (StdLib)
|
|
199
|
+
|
|
200
|
+
La libreria standard offre strumenti potenti pronti all'uso.
|
|
201
|
+
|
|
202
|
+
### 📁 Archivio (File System)
|
|
203
|
+
Gestisci i file in modo semplice.
|
|
204
|
+
- `Archivio.leggi(percorso)`: Legge il contenuto di un file.
|
|
205
|
+
- `Archivio.scrivi(percorso, dati)`: Scrive dati in un file.
|
|
206
|
+
- `Archivio.esiste(percorso)`: Verifica se un file esiste.
|
|
207
|
+
- `Archivio.elimina(percorso)`: Rimuove un file.
|
|
208
|
+
|
|
209
|
+
### 💻 Sistema (OS)
|
|
210
|
+
Interagisci con il sistema operativo.
|
|
211
|
+
- `Sistema.esegui(comando)`: Esegue un comando shell e restituisce l'output.
|
|
212
|
+
- `Sistema.argomenti`: Array degli argomenti passati da riga di comando.
|
|
213
|
+
- `Sistema.piattaforma`: Stringa che indica l'OS (es. "linux", "darwin").
|
|
214
|
+
- `Sistema.cartellaCorrente()`: Percorso della directory attuale.
|
|
215
|
+
- `Sistema.esci(codice)`: Termina il programma.
|
|
216
|
+
|
|
217
|
+
### 🌐 Rete (HTTP)
|
|
218
|
+
Includi capacità di rete nei tuoi script.
|
|
219
|
+
- `Rete.chiama(url)`: Esegue una richiesta HTTP GET (utilizza curl internamente).
|
|
220
|
+
- `Rete.server(porta, gestore)`: Avvia un server web sulla porta specificata.
|
|
221
|
+
|
|
222
|
+
```javascript
|
|
223
|
+
funzione mioGestore(richiesta) {
|
|
224
|
+
ritorna {
|
|
225
|
+
stato: 200,
|
|
226
|
+
corpo: "Ciao dal server VladX!",
|
|
227
|
+
intestazioni: { "Content-Type": "text/plain" }
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
Rete.server(8080, mioGestore);
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## 🌍 Funzioni Globali
|
|
237
|
+
|
|
238
|
+
Funzioni sempre disponibili senza importazioni:
|
|
239
|
+
- `stampa(valore)`: Mostra un valore nella console.
|
|
240
|
+
- `aspetta(ms)`: Sospende l'esecuzione per il numero specificato di millisecondi.
|
|
241
|
+
- `lunghezza(valore)`: Restituisce la lunghezza di una stringa o array.
|
|
242
|
+
- `tipo(valore)`: Restituisce il tipo del valore (es. "number", "string").
|
|
243
|
+
- `numero(valore)`: Converte in numero.
|
|
244
|
+
- `stringa(valore)`: Converte in stringa.
|
|
245
|
+
- `array(valore)`: Verifica se il valore è un array.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## 📊 Metodi di Array e Oggetti
|
|
250
|
+
|
|
251
|
+
### Array
|
|
252
|
+
Gli array supportano metodi dinamici:
|
|
253
|
+
```javascript
|
|
254
|
+
variabile lista = [1, 2];
|
|
255
|
+
lista.aggiungi(3); // lista è [1, 2, 3]
|
|
256
|
+
variabile rimosso = lista.rimuovi(); // rimosso = 3, lista è [1, 2]
|
|
257
|
+
stampa(lista.lunghezza); // 2
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Oggetti
|
|
261
|
+
Accesso alle proprietà tramite punto o parentesi quadre:
|
|
262
|
+
```javascript
|
|
263
|
+
variabile auto = { marca: "Fiat", modello: "500" };
|
|
264
|
+
stampa(auto.marca); // "Fiat"
|
|
265
|
+
auto.anno = 2022;
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## 📦 VladPM (Package Manager)
|
|
271
|
+
|
|
272
|
+
VladPM è lo strumento per gestire le dipendenze e i progetti VladX.
|
|
273
|
+
|
|
274
|
+
- `vladpm init`: Crea un nuovo file `vladx.json` nel progetto.
|
|
275
|
+
- `vladpm install <pacchetto>`: Installa un pacchetto dal registry.
|
|
276
|
+
- `vladpm publish`: Pubblica il progetto nel registry VladX.
|
|
277
|
+
- `vladpm start`: Esegue lo script `start` definito in `vladx.json`.
|
|
278
|
+
- `vladpm run <nome>`: Esegue uno script personalizzato.
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## 🌟 Esempi Completi
|
|
283
|
+
|
|
284
|
+
#### Fibonacci
|
|
285
|
+
```javascript
|
|
286
|
+
funzione fibonacci(n) {
|
|
287
|
+
se (n <= 1) {
|
|
288
|
+
ritorna n;
|
|
289
|
+
}
|
|
290
|
+
ritorna fibonacci(n - 1) + fibonacci(n - 2);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
per (variabile i = 0; i < 10; i++) {
|
|
294
|
+
stampa(fibonacci(i));
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
#### Client HTTP API
|
|
299
|
+
```javascript
|
|
300
|
+
variabile risposta = Rete.chiama("https://api.github.com/users/octocat");
|
|
301
|
+
stampa("Nome utente: " + risposta.name);
|
|
302
|
+
stampa("Bio: " + risposta.bio);
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### Generatore di File
|
|
306
|
+
```javascript
|
|
307
|
+
costante NOME_FILE = "test.txt";
|
|
308
|
+
|
|
309
|
+
se (non Archivio.esiste(NOME_FILE)) {
|
|
310
|
+
Archivio.scrivi(NOME_FILE, "Contenuto generato automaticamente da VladX");
|
|
311
|
+
stampa("File creato con successo!");
|
|
312
|
+
} altrimenti {
|
|
313
|
+
stampa("Il file esiste già. Contenuto:");
|
|
314
|
+
stampa(Archivio.leggi(NOME_FILE));
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
Creato con ❤️ dal team di **VladX**.
|
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# 🇮🇹 VladX
|
|
2
|
+
|
|
3
|
+
**VladX** è un linguaggio di programmazione moderno con **sintassi italiana**, progettato per essere potente, leggibile e completo. Include un interprete robusto, una libreria standard (StdLib) estesa e un package manager dedicato (**VladPM**).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🚀 Installazione
|
|
8
|
+
|
|
9
|
+
Puoi installare VladX in due modi:
|
|
10
|
+
|
|
11
|
+
### Metodo 1: NPM (Consigliato)
|
|
12
|
+
Se hai Node.js installato:
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g vladx
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Metodo 2: Script di installazione
|
|
18
|
+
```bash
|
|
19
|
+
chmod +x install.sh
|
|
20
|
+
./install.sh
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 🛠️ Utilizzo CLI
|
|
26
|
+
|
|
27
|
+
- `vladx` - Avvia il REPL interattivo.
|
|
28
|
+
- `vladx programma.vx` - Esegue un file VladX.
|
|
29
|
+
- `vladx ast programma.vx` - Mostra l'Abstract Syntax Tree.
|
|
30
|
+
- `vladx lex programma.vx` - Mostra i token analizzati.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 📝 Sintassi in breve
|
|
35
|
+
|
|
36
|
+
### Variabili e Costanti
|
|
37
|
+
```javascript
|
|
38
|
+
variabile nome = "Vlad";
|
|
39
|
+
costante PI = 3.14;
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Controllo del Flusso
|
|
43
|
+
```javascript
|
|
44
|
+
se (x > 10) {
|
|
45
|
+
stampa("Maggiore di 10");
|
|
46
|
+
} altrimenti {
|
|
47
|
+
stampa("Minore o uguale a 10");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
per (variabile i = 0; i < 5; i++) {
|
|
51
|
+
stampa(i);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
mentre (condizione) { ... }
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Funzioni e Arrow Functions
|
|
58
|
+
```javascript
|
|
59
|
+
funzione saluta(nome) {
|
|
60
|
+
ritorna "Ciao, " + nome;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
costante somma = (a, b) => a + b;
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Gestione Errori (Try/Catch)
|
|
67
|
+
```javascript
|
|
68
|
+
prova {
|
|
69
|
+
lancia "Ops!";
|
|
70
|
+
} cattura (err) {
|
|
71
|
+
stampa("Errore: " + err);
|
|
72
|
+
} finalmente {
|
|
73
|
+
stampa("Fine.");
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 📦 Sistema Moduli
|
|
80
|
+
|
|
81
|
+
Dividi il tuo codice in più file:
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
// math.vx
|
|
85
|
+
esporta costante PI = 3.14;
|
|
86
|
+
esporta funzione doppia(n) { ritorna n * 2; }
|
|
87
|
+
|
|
88
|
+
// app.vx
|
|
89
|
+
importa { PI, doppia } da "./math.vx";
|
|
90
|
+
stampa(doppia(PI));
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 📚 Libreria Standard (StdLib)
|
|
96
|
+
|
|
97
|
+
VladX include moduli nativi potenti:
|
|
98
|
+
|
|
99
|
+
- **`Archivio`**: `leggi`, `scrivi`, `esiste`, `elimina`.
|
|
100
|
+
- **`Sistema`**: `esegui` (shell), `argomenti`, `piattaforma`, `esci`.
|
|
101
|
+
- **`Rete`**: `chiama` (HTTP GET), `server` (Crea server web).
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 📦 VladPM (Package Manager)
|
|
106
|
+
|
|
107
|
+
VladPM è il gestore di pacchetti ufficiale per VladX.
|
|
108
|
+
|
|
109
|
+
- `vladpm init` - Inizializza un nuovo progetto (`vladx.json`).
|
|
110
|
+
- `vladpm install <nome>` - Installa un pacchetto dal registry.
|
|
111
|
+
- `vladpm publish` - Pubblica il tuo pacchetto.
|
|
112
|
+
- `vladpm start` / `vladpm run <script>` - Esegue gli script definiti nel progetto.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 🌟 Esempi
|
|
117
|
+
|
|
118
|
+
Trovi molti esempi nella cartella `examples/`:
|
|
119
|
+
- `test_eccezioni.vx` - Test try/catch.
|
|
120
|
+
- `test_stdlib_fs.vx` - Test File System.
|
|
121
|
+
- `test_stdlib_rete.vx` - Test HTTP e Server.
|
|
122
|
+
- `moduli/` - Esempio di sistema a moduli.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
Creato con ❤️ per la comunità italiana.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Eccezioni VladX
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
stampa("--- Inizio Test Eccezioni ---");
|
|
6
|
+
|
|
7
|
+
prova {
|
|
8
|
+
stampa("1. Provo a fare qualcosa...");
|
|
9
|
+
lancia "Ops! Qualcosa è andato storto.";
|
|
10
|
+
stampa("Questo non dovrebbe apparire.");
|
|
11
|
+
} cattura (errore) {
|
|
12
|
+
stampa("2. Catturato errore: " + errore);
|
|
13
|
+
} finalmente {
|
|
14
|
+
stampa("3. Questo viene eseguito sempre (finalmente).");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
stampa("");
|
|
18
|
+
|
|
19
|
+
prova {
|
|
20
|
+
stampa("4. Provo divisione per zero (errore runtime)...");
|
|
21
|
+
variabile x = 10 / 0; // In JS è Infinity, non lancia errore. Proviamo qualcosa che lancia errore.
|
|
22
|
+
stampa("Risultato: " + x);
|
|
23
|
+
|
|
24
|
+
// Forza errore runtime reale (chiamata a non funzione)
|
|
25
|
+
variabile nonFunzione = 10;
|
|
26
|
+
nonFunzione();
|
|
27
|
+
} cattura (err) {
|
|
28
|
+
stampa("5. Catturato errore runtime: " + err);
|
|
29
|
+
} finalmente {
|
|
30
|
+
stampa("6. Fine secondo blocco prova.");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
stampa("--- Fine Test Eccezioni ---");
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Archivio e Sistema
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
stampa("--- Test Sistema ---");
|
|
6
|
+
stampa("Piattaforma: " + Sistema.piattaforma);
|
|
7
|
+
stampa("Cartella Corrente: " + Sistema.cartellaCorrente());
|
|
8
|
+
|
|
9
|
+
stampa("\n--- Test Archivio ---");
|
|
10
|
+
costante fileTest = "test_stdlib.txt";
|
|
11
|
+
costante contenuto = "Questo è un test della StdLib di VladX!";
|
|
12
|
+
|
|
13
|
+
stampa("Scrittura file...");
|
|
14
|
+
Archivio.scrivi(fileTest, contenuto);
|
|
15
|
+
|
|
16
|
+
se (Archivio.esiste(fileTest)) {
|
|
17
|
+
stampa("File creato con successo.");
|
|
18
|
+
costante letto = Archivio.leggi(fileTest);
|
|
19
|
+
stampa("Contenuto letto: " + letto);
|
|
20
|
+
|
|
21
|
+
se (letto == contenuto) {
|
|
22
|
+
stampa("VERIFICA: I contenuti corrispondono.");
|
|
23
|
+
} altrimenti {
|
|
24
|
+
stampa("ERRORE: I contenuti NON corrispondono!");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
stampa("Eliminazione file...");
|
|
28
|
+
Archivio.elimina(fileTest);
|
|
29
|
+
|
|
30
|
+
se (!Archivio.esiste(fileTest)) {
|
|
31
|
+
stampa("File eliminato con successo.");
|
|
32
|
+
}
|
|
33
|
+
} altrimenti {
|
|
34
|
+
stampa("ERRORE: Il file non è stato creato!");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
stampa("\n--- Esecuzione comando shell ---");
|
|
38
|
+
prova {
|
|
39
|
+
costante output = Sistema.esegui("ls -l bin/vladx");
|
|
40
|
+
stampa("Output ls: " + output);
|
|
41
|
+
} cattura (err) {
|
|
42
|
+
stampa("Errore esecuzione: " + err);
|
|
43
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Rete VladX
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
stampa("--- Test Rete.chiama ---");
|
|
6
|
+
prova {
|
|
7
|
+
// Chiamata a JSONPlaceholder per test
|
|
8
|
+
stampa("Eseguo chiamata a JSONPlaceholder...");
|
|
9
|
+
costante post = Rete.chiama("https://jsonplaceholder.typicode.com/posts/1");
|
|
10
|
+
|
|
11
|
+
stampa("Risposta ricevuta!");
|
|
12
|
+
stampa("Titolo: " + post.title);
|
|
13
|
+
stampa("ID: " + post.id);
|
|
14
|
+
} cattura (err) {
|
|
15
|
+
stampa("Errore chiamata: " + err);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
stampa("\n--- Test Rete.server ---");
|
|
19
|
+
// Creiamo un server che risponde con JSON
|
|
20
|
+
funzione mioGestore(req) {
|
|
21
|
+
stampa("Richiesta ricevuta: " + req.metodo + " " + req.url);
|
|
22
|
+
|
|
23
|
+
ritorna {
|
|
24
|
+
stato: 200,
|
|
25
|
+
intestazioni: { "Content-Type": "application/json" },
|
|
26
|
+
corpo: {
|
|
27
|
+
messaggio: "Ciao dal Server VladX!",
|
|
28
|
+
percorso: req.url,
|
|
29
|
+
metodo: req.metodo
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Avviamo il server sulla porta 8080
|
|
35
|
+
// Nota: In questo ambiente il server rimarrà attivo finché non terminiamo lo script.
|
|
36
|
+
// Per il test automatico, lo avviamo e poi usiamo Sistema.esegui per testarlo se possibile,
|
|
37
|
+
// ma Sistema.esegui è sincrono, quindi dovremmo usare un altro approccio se volessimo testarlo automatizzato qui.
|
|
38
|
+
// Per ora lo avviamo semplicemente per conferma visiva.
|
|
39
|
+
|
|
40
|
+
stampa("Avvio server su porta 8080...");
|
|
41
|
+
Rete.server(8080, mioGestore);
|
|
42
|
+
|
|
43
|
+
// Mock test: visto che non possiamo fare chiamate asincrone facilmente nel test suite qui,
|
|
44
|
+
// il test si ferma qui o continua se il server non blocca (http.listen non blocca in Node).
|
|
45
|
+
stampa("Server avviato. Test completato.");
|
|
46
|
+
Sistema.esci(0);
|
package/install.sh
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# VladX & VladPM Global Installer
|
|
4
|
+
# 🇮🇹 Script di installazione completa per VladX
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
echo "🚀 Inizio installazione VladX..."
|
|
9
|
+
|
|
10
|
+
# 1. Installazione NVM if not present
|
|
11
|
+
if [ -z "$NVM_DIR" ]; then
|
|
12
|
+
echo "📦 Installazione NVM (Node Version Manager)..."
|
|
13
|
+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
|
|
14
|
+
|
|
15
|
+
# Load nvm for current session
|
|
16
|
+
export NVM_DIR="$HOME/.nvm"
|
|
17
|
+
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
|
18
|
+
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
|
|
19
|
+
else
|
|
20
|
+
echo "✅ NVM già installato."
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# 2. Installazione Node.js (Ultima versione)
|
|
24
|
+
echo "🌐 Installazione dell'ultima versione di Node.js..."
|
|
25
|
+
nvm install node
|
|
26
|
+
nvm use node
|
|
27
|
+
|
|
28
|
+
# 3. Installazione VladX
|
|
29
|
+
echo "🛠️ Installazione globale di VladX e VladPM dal registry NPM..."
|
|
30
|
+
|
|
31
|
+
npm install -g vladx
|
|
32
|
+
|
|
33
|
+
echo ""
|
|
34
|
+
echo "✅ Installazione completata con successo!"
|
|
35
|
+
echo "Node.js: $(node -v)"
|
|
36
|
+
echo "NPM: $(npm -v)"
|
|
37
|
+
echo ""
|
|
38
|
+
echo "Puoi ora usare i comandi:"
|
|
39
|
+
echo " vladx"
|
|
40
|
+
echo " vladpm"
|
|
41
|
+
echo ""
|
|
42
|
+
echo "🇮🇹 Buona programmazione con VladX!"
|
package/package.json
CHANGED
package/programs/1/index.vx
CHANGED
|
@@ -118,6 +118,9 @@ class ArrowFunc {
|
|
|
118
118
|
|
|
119
119
|
const fs = require('fs');
|
|
120
120
|
const path = require('path');
|
|
121
|
+
const http = require('http');
|
|
122
|
+
const https = require('https');
|
|
123
|
+
const { execSync } = require('child_process');
|
|
121
124
|
const { Lexer } = require('../lexer/lexer.js');
|
|
122
125
|
const { Parser } = require('../parser/parser.js');
|
|
123
126
|
|
|
@@ -155,6 +158,113 @@ class Interpreter {
|
|
|
155
158
|
this.globals.define('array', {
|
|
156
159
|
call: (_, args) => Array.isArray(args[0])
|
|
157
160
|
});
|
|
161
|
+
|
|
162
|
+
this.globals.define('aspetta', {
|
|
163
|
+
call: (_, args) => {
|
|
164
|
+
const ms = args[0];
|
|
165
|
+
if (typeof ms === 'number') {
|
|
166
|
+
const start = Date.now();
|
|
167
|
+
while (Date.now() - start < ms);
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
this._registerStdLib();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
_registerStdLib() {
|
|
177
|
+
// --- ARCHIVIO (File System) ---
|
|
178
|
+
const Archivio = {
|
|
179
|
+
leggi: {
|
|
180
|
+
call: (_, args) => fs.readFileSync(path.resolve(this.currentPath, '..', args[0]), 'utf8')
|
|
181
|
+
},
|
|
182
|
+
scrivi: {
|
|
183
|
+
call: (_, args) => {
|
|
184
|
+
fs.writeFileSync(path.resolve(this.currentPath, '..', args[0]), args[1]);
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
esiste: {
|
|
189
|
+
call: (_, args) => fs.existsSync(path.resolve(this.currentPath, '..', args[0]))
|
|
190
|
+
},
|
|
191
|
+
elimina: {
|
|
192
|
+
call: (_, args) => {
|
|
193
|
+
fs.unlinkSync(path.resolve(this.currentPath, '..', args[0]));
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
this.globals.define('Archivio', Archivio);
|
|
199
|
+
|
|
200
|
+
// --- SISTEMA (Process/OS) ---
|
|
201
|
+
const Sistema = {
|
|
202
|
+
esegui: {
|
|
203
|
+
call: (_, args) => execSync(args[0], { encoding: 'utf8' })
|
|
204
|
+
},
|
|
205
|
+
argomenti: process.argv.slice(2),
|
|
206
|
+
esci: {
|
|
207
|
+
call: (_, args) => process.exit(args[0] || 0)
|
|
208
|
+
},
|
|
209
|
+
piattaforma: process.platform,
|
|
210
|
+
cartellaCorrente: {
|
|
211
|
+
call: () => process.cwd()
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
this.globals.define('Sistema', Sistema);
|
|
215
|
+
|
|
216
|
+
// --- RETE (HTTP) ---
|
|
217
|
+
const Rete = {
|
|
218
|
+
chiama: {
|
|
219
|
+
call: (_, args) => {
|
|
220
|
+
const url = args[0];
|
|
221
|
+
try {
|
|
222
|
+
const output = execSync(`curl -sL "${url}"`, { encoding: 'utf8' });
|
|
223
|
+
try {
|
|
224
|
+
return JSON.parse(output);
|
|
225
|
+
} catch (e) {
|
|
226
|
+
return output;
|
|
227
|
+
}
|
|
228
|
+
} catch (err) {
|
|
229
|
+
throw new Error(`Errore chiamata HTTP: ${err.message}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
server: {
|
|
234
|
+
call: (_, args) => {
|
|
235
|
+
const porta = args[0] || 3000;
|
|
236
|
+
const gestore = args[1]; // Una funzione VladX
|
|
237
|
+
|
|
238
|
+
const server = http.createServer(async (req, res) => {
|
|
239
|
+
if (gestore && gestore.call) {
|
|
240
|
+
// Creiamo un oggetto richiesta per VladX
|
|
241
|
+
const richiesta = {
|
|
242
|
+
metodo: req.method,
|
|
243
|
+
url: req.url,
|
|
244
|
+
intestazioni: req.headers
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
try {
|
|
248
|
+
const risposta = await gestore.call(this, [richiesta]);
|
|
249
|
+
res.writeHead(risposta.stato || 200, risposta.intestazioni || { 'Content-Type': 'text/plain' });
|
|
250
|
+
res.end(typeof risposta.corpo === 'object' ? JSON.stringify(risposta.corpo) : String(risposta.corpo));
|
|
251
|
+
} catch (e) {
|
|
252
|
+
res.writeHead(500);
|
|
253
|
+
res.end("Errore Server VladX: " + e.message);
|
|
254
|
+
}
|
|
255
|
+
} else {
|
|
256
|
+
res.writeHead(200);
|
|
257
|
+
res.end("Server VladX attivo sulla porta " + porta);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
server.listen(porta);
|
|
262
|
+
console.log(`Server VladX in ascolto sulla porta ${porta}`);
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
this.globals.define('Rete', Rete);
|
|
158
268
|
}
|
|
159
269
|
|
|
160
270
|
interpret(program) {
|
|
@@ -192,6 +302,10 @@ class Interpreter {
|
|
|
192
302
|
throw new BreakSignal();
|
|
193
303
|
case 'ContinueStatement':
|
|
194
304
|
throw new ContinueSignal();
|
|
305
|
+
case 'TryStatement':
|
|
306
|
+
return this.executeTryStatement(node);
|
|
307
|
+
case 'ThrowStatement':
|
|
308
|
+
return this.executeThrowStatement(node);
|
|
195
309
|
case 'ExportNamedDeclaration':
|
|
196
310
|
return this.executeExportNamedDeclaration(node);
|
|
197
311
|
case 'ImportDeclaration':
|
|
@@ -273,6 +387,43 @@ class Interpreter {
|
|
|
273
387
|
}
|
|
274
388
|
}
|
|
275
389
|
|
|
390
|
+
executeTryStatement(node) {
|
|
391
|
+
try {
|
|
392
|
+
this.execute(node.block);
|
|
393
|
+
} catch (error) {
|
|
394
|
+
// Se è un ReturnValue o Break/Continue Signal, non catturarlo qui
|
|
395
|
+
if (error instanceof ReturnValue || error instanceof BreakSignal || error instanceof ContinueSignal) {
|
|
396
|
+
throw error;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (node.handler) {
|
|
400
|
+
const catchEnv = new Environment(this.environment);
|
|
401
|
+
// Il valore errore può essere quello lanciato da LANCIA o un errore JS
|
|
402
|
+
const errorValue = error instanceof Error ? error.message : error;
|
|
403
|
+
catchEnv.define(node.handler.param, errorValue);
|
|
404
|
+
|
|
405
|
+
const previousEnv = this.environment;
|
|
406
|
+
this.environment = catchEnv;
|
|
407
|
+
try {
|
|
408
|
+
this.execute(node.handler.body);
|
|
409
|
+
} finally {
|
|
410
|
+
this.environment = previousEnv;
|
|
411
|
+
}
|
|
412
|
+
} else if (!node.finalizer) {
|
|
413
|
+
throw error;
|
|
414
|
+
}
|
|
415
|
+
} finally {
|
|
416
|
+
if (node.finalizer) {
|
|
417
|
+
this.execute(node.finalizer);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
executeThrowStatement(node) {
|
|
423
|
+
const value = this.evaluate(node.argument);
|
|
424
|
+
throw value;
|
|
425
|
+
}
|
|
426
|
+
|
|
276
427
|
executeExportNamedDeclaration(node) {
|
|
277
428
|
this.execute(node.declaration);
|
|
278
429
|
const name = node.declaration.name;
|
package/src/parser/ast.js
CHANGED
|
@@ -104,6 +104,30 @@ class PrintStatement extends ASTNode {
|
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
class TryStatement extends ASTNode {
|
|
108
|
+
constructor(block, handler, finalizer = null) {
|
|
109
|
+
super('TryStatement');
|
|
110
|
+
this.block = block;
|
|
111
|
+
this.handler = handler;
|
|
112
|
+
this.finalizer = finalizer;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
class CatchClause extends ASTNode {
|
|
117
|
+
constructor(param, body) {
|
|
118
|
+
super('CatchClause');
|
|
119
|
+
this.param = param;
|
|
120
|
+
this.body = body;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
class ThrowStatement extends ASTNode {
|
|
125
|
+
constructor(argument) {
|
|
126
|
+
super('ThrowStatement');
|
|
127
|
+
this.argument = argument;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
107
131
|
// === Espressioni ===
|
|
108
132
|
class Identifier extends ASTNode {
|
|
109
133
|
constructor(name) {
|
|
@@ -269,6 +293,9 @@ module.exports = {
|
|
|
269
293
|
ContinueStatement,
|
|
270
294
|
ExpressionStatement,
|
|
271
295
|
PrintStatement,
|
|
296
|
+
TryStatement,
|
|
297
|
+
CatchClause,
|
|
298
|
+
ThrowStatement,
|
|
272
299
|
ExportNamedDeclaration,
|
|
273
300
|
ImportDeclaration,
|
|
274
301
|
ImportSpecifier,
|
package/src/parser/parser.js
CHANGED
|
@@ -146,6 +146,8 @@ class Parser {
|
|
|
146
146
|
if (this.match(TokenType.INTERROMPI)) return this.breakStatement();
|
|
147
147
|
if (this.match(TokenType.CONTINUA)) return this.continueStatement();
|
|
148
148
|
if (this.match(TokenType.STAMPA)) return this.printStatement();
|
|
149
|
+
if (this.match(TokenType.PROVA)) return this.tryStatement();
|
|
150
|
+
if (this.match(TokenType.LANCIA)) return this.throwStatement();
|
|
149
151
|
if (this.match(TokenType.GRAFFA_APERTA)) return this.blockStatement();
|
|
150
152
|
return this.expressionStatement();
|
|
151
153
|
}
|
|
@@ -242,6 +244,39 @@ class Parser {
|
|
|
242
244
|
return new AST.PrintStatement(argument);
|
|
243
245
|
}
|
|
244
246
|
|
|
247
|
+
tryStatement() {
|
|
248
|
+
this.consume(TokenType.GRAFFA_APERTA, 'Atteso "{" dopo "prova"');
|
|
249
|
+
const block = this.blockStatement();
|
|
250
|
+
|
|
251
|
+
let handler = null;
|
|
252
|
+
if (this.match(TokenType.CATTURA)) {
|
|
253
|
+
this.consume(TokenType.PARENTESI_APERTA, 'Atteso "(" dopo "cattura"');
|
|
254
|
+
const param = this.consume(TokenType.IDENTIFICATORE, 'Nome variabile errore atteso').value;
|
|
255
|
+
this.consume(TokenType.PARENTESI_CHIUSA, 'Atteso ")" dopo nome variabile');
|
|
256
|
+
this.consume(TokenType.GRAFFA_APERTA, 'Atteso "{" dopo clausola "cattura"');
|
|
257
|
+
const body = this.blockStatement();
|
|
258
|
+
handler = new AST.CatchClause(param, body);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
let finalizer = null;
|
|
262
|
+
if (this.match(TokenType.FINALMENTE)) {
|
|
263
|
+
this.consume(TokenType.GRAFFA_APERTA, 'Atteso "{" dopo "finalmente"');
|
|
264
|
+
finalizer = this.blockStatement();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (!handler && !finalizer) {
|
|
268
|
+
throw new ParserError('Atteso "cattura" o "finalmente" dopo blocco "prova"', this.peek());
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return new AST.TryStatement(block, handler, finalizer);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
throwStatement() {
|
|
275
|
+
const argument = this.expression();
|
|
276
|
+
this.match(TokenType.PUNTO_VIRGOLA);
|
|
277
|
+
return new AST.ThrowStatement(argument);
|
|
278
|
+
}
|
|
279
|
+
|
|
245
280
|
expressionStatement() {
|
|
246
281
|
const expr = this.expression();
|
|
247
282
|
this.match(TokenType.PUNTO_VIRGOLA);
|
|
@@ -478,7 +513,12 @@ class Parser {
|
|
|
478
513
|
const properties = [];
|
|
479
514
|
if (!this.check(TokenType.GRAFFA_CHIUSA)) {
|
|
480
515
|
do {
|
|
481
|
-
|
|
516
|
+
let key;
|
|
517
|
+
if (this.match(TokenType.IDENTIFICATORE, TokenType.STRINGA)) {
|
|
518
|
+
key = this.previous().value;
|
|
519
|
+
} else {
|
|
520
|
+
throw new ParserError('Nome proprietà o stringa atteso', this.peek());
|
|
521
|
+
}
|
|
482
522
|
this.consume(TokenType.DUE_PUNTI, 'Atteso ":" dopo nome proprietà');
|
|
483
523
|
const value = this.expression();
|
|
484
524
|
properties.push(new AST.Property(key, value));
|