🚀 Cosa Rende Pangea Speciale?
Pangea non è un linguaggio di programmazione ordinario. È un esperimento affascinante su come scrivere codice in modo completamente diverso. In questa guida scoprirai 7 feature straordinarie che lo rendono unico e come funzionano dietro le quinte!
1️⃣ Notazione Prefissa (Polish Notation)
Quando usi la maggior parte dei linguaggi di programmazione, scrivi operatore in mezzo agli operandi (notazione infissa):
5 + 6 ← standard (infissa)
In Pangea, scrivi l'operatore prima degli operandi:
add 5 6 ← Pangea (prefissa)
💡 Perché è Utile?
- Zero ambiguità: Non serve ricordare che la moltiplicazione ha priorità dell'addizione
- Niente parentesi: La struttura è sempre chiara
- Facile da interpretare: L'interprete sa esattamente cosa fare
Confronto: Infix vs Prefix
| Cosa Vuoi Fare | Standard (Infix) | Pangea (Prefix) | Risultato |
|---|---|---|---|
| Somma semplice | 5 + 6 |
add 5 6 |
11 |
| Moltiplicazione | 3 * 4 |
multiply 3 4 |
12 |
| Operazioni miste | (2 + 3) * 4 |
multiply add 2 3 4 |
20 |
| Operazioni complesse | ((5+6)*(7-2)) |
multiply add 5 6 subtract 7 2 |
55 |
Nel file main.lua, la funzione
phrase_length() calcola quanti token
un operatore consuma:
function phrase_length(word_index) local word = words[word_index] local length = 1 local word_definition = word_definitions[word] if word_definition == nil then return 1 end local argument_length = word_definition[1] -- Quanti argomenti? for _ = 1, argument_length do length = length + phrase_length(word_index + length) end return length end
Esempio: add ha arity=2 (prende 2 argomenti), quindi
phrase_length calcola quanti token occupano gli ultimi 2 valori da
valutare.
2️⃣ Literali Quotati con Escape Support
In Pangea, le stringhe (testi) sono semplicemente parole tra virgolette. Dentro le virgolette puoi scrivere qualsiasi cosa, inclusi spazi e caratteri speciali.
Sintassi Base
"Ciao Mondo" ← Una stringa semplice con spazi "nome" ← Un nome di variabile "Hello, World!" ← Con punteggiatura
Sequenze di Escape
All'interno di una stringa tra virgolette, puoi usare caratteri
speciali con il backslash (\):
| Sequenza | Cosa Rappresenta | Esempio |
|---|---|---|
\" |
Una virgoletta dentro la stringa |
"Lui ha detto \"Ciao\"" → Lui ha detto "Ciao"
|
\\ |
Un backslash letterale | "C:\\Users" → C:\Users |
\n |
Vai a capo (newline) | "Riga 1\nRiga 2" → due righe |
\t |
Una tabulazione (spazi allineati) | "Nome\tEtà" → colonne allineate |
Esempi Pratici
print "Benvenuto in Pangea!"
Output: Benvenuto in Pangea!
set "nome" "Mario" print get "nome"
Output: Mario
print "Riga 1\nRiga 2\nRiga 3"
Output: tre righe separate
Nel file main.lua, la funzione
program_words() analizza il testo
carattere per carattere e gestisce le stringhe quotate:
function program_words(pn_program) local in_string = false local escaping = false local quoted = {} for i = 1, #pn_program do local char = pn_program:sub(i, i) if in_string then if escaping then if char == '"' then table.insert(quoted, '"') elseif char == 'n' then table.insert(quoted, "\n") end escaping = false elseif char == '"' then in_string = false -- Fine stringa end elseif char == '"' then in_string = true -- Inizio stringa end end end
Il token viene marcato nella tabella string_literals in
modo che l'evaluatore sappia che è un letterale e non una parola da
cercare nei word_definitions.
\q), Pangea ti mostrerà un errore!
3️⃣ Input Testuale e Conversione Numerica
Pangea include due parole utili per i programmi interattivi:
read_text / leggi_testo per leggere una
riga da console e to_number /
numero_da_testo per convertirla in numero.
Lettura da Console
set "nome" read_text print get "nome"
Comportamento: legge una singola riga da input standard e la restituisce come testo.
Conversione da Testo a Numero
print to_number "42" print add to_number "7" 5
Risultato: il testo numerico viene convertito in
numero e puo essere usato direttamente con add,
multiply, modulus, ecc.
Comportamento su Input Non Valido
print to_number "abc" ← stampa nil add to_number "abc" 5 ← errore Lua: aritmetica su nil
Nota: la semantica corrente non forza errore in
to_number/numero_da_testo; in caso di testo
non numerico ritorna nil.
EOF su leggi_testo/read_text: se non ci sono piu
righe disponibili in input, viene restituita una stringa vuota
("").
function read_text_function() local text = io.read() if text == nil then return "" end return text end function to_number_function(arguments) local value = evaluate_word(arguments[1]) return tonumber(value) end
4️⃣ Scoping Lessicale (Variabili Locali)
Scope significa "area di validità". In Pangea, le variabili vivono solo dentro la funzione in cui sono dichiarate. Questo si chiama scoping lessicale.
Il Concetto di Call Stack
Immagina una pila di scatole (call stack). Ogni volta che chiami una funzione, una nuova scatola viene messa sopra. Le variabili dentro quella scatola esistono solo in quella funzione. Quando la funzione finisce, la scatola viene tolta e le variabili spariscono.
Come funziona il Call Stack
Programma:
set "x" 10 ← x va nello scope globale define_word "miaFunzione" 0 set "x" 20 ← x va nello scope locale della funzione miaFunzione print get "x" ← Stampa x globale (10)
Visualizzazione del Call Stack:
Stato 1: Prima di chiamare la funzione
x = 10
Stato 2: Durante l'esecuzione della funzione
x = 10
x = 20
Nota: la x nella funzione è diversa da quella globale!
Stato 3: Dopo la funzione
x = 10
Output: 10 (la x della funzione è
sparita)
Perché è Importante?
- Isolamento: Le funzioni non si interferiscono a vicenda
- Riutilizzabilità: Puoi usare lo stesso nome di variabile in funzioni diverse
- Sicurezza: Non rischi di sovrascrivere dati accidentalmente
In Pangea, c'è una variabile globale call_stack che è
una lista di tabelle:
local call_stack = {{}} -- Inizia con uno scope vuoto function get_function(arguments) local variables = call_stack[#call_stack] -- Leggi dall'ultimo scope (il corrente) local variable_name = evaluate_word(arguments[1]) return variables[variable_name] end function define_word_function(arguments) local word_function = function(word_arguments) -- CREA UN NUOVO SCOPE table.insert(call_stack, {}) -- Esegui il corpo della funzione local returned = evaluate_word(arguments[3]) -- ELIMINA LO SCOPE table.remove(call_stack) return returned end end
call_stack[#call_stack] significa "l'ultimo elemento
della lista", che è sempre lo scope corrente.
4️⃣ Recursive Descent (Valutazione Ricorsiva)
Recursive descent è il modo in cui Pangea legge e valuta quello che scrivi. È un processo ricorsivo: ogni funzione chiama altre funzioni per valutare i suoi argomenti.
Il Meccanismo Fondamentale
La funzione centrale è evaluate_word(word_index). Ecco cosa fa:
Prende il token all'indice word_index
- Se è un numero → restituisci il numero
- Se è una stringa quotata → restituisci la stringa
- Se è una parola registrata → cercala in word_definitions
Usa phrase_length() per sapere quanti token occupano gli argomenti
Per ogni argomento, chiama di nuovo evaluate_word()
Ora che hai i valori, esegui la vera operazione (add, print, ecc.)
Esempio Pratico: Traccia di Esecuzione
Programma: print add 5 6
Traccia:
evaluate_word(1) ← Valuta "print" ├─ "print" ha arity=1 ← Ha bisogno di 1 argomento ├─ Argomento 1: evaluate_word(2) ← Valuta "add" │ ├─ "add" ha arity=2 ← Ha bisogno di 2 argomenti │ ├─ Argomento 1: evaluate_word(3) ← Valuta "5" → 5 │ ├─ Argomento 2: evaluate_word(4) ← Valuta "6" → 6 │ └─ Restituisce: 5 + 6 = 11 └─ print(11) └─ Output: 11
function evaluate_word(word_index) local word = words[word_index] -- Caso 1: È un numero? local returned_value = tonumber(word) if returned_value ~= nil then return returned_value end -- Caso 2: È una stringa quotata? if string_literals[word_index] then return word end -- Caso 3: È una parola registrata? local word_definition = word_definitions[word] if word_definition == nil then return end -- Calcola argomenti ricorsivamente local arguments = {} local arity = word_definition[1] local argument_word_index = word_index + 1 for _ = 1, arity do table.insert(arguments, argument_word_index) argument_word_index = argument_word_index + phrase_length(argument_word_index) end -- Esegui la funzione return word_definition[2](arguments) end
Perché "Recursive Descent"?
Si chiama così perché:
- Recursive: Chiama se stessa (recursione)
- Descent: Scende dentro la struttura del programma
5️⃣ Modularità - Includere File Esterni
Non vuoi scrivere tutto in un solo file? In Pangea puoi dividere il tuo programma in più file e includerli uno dentro l'altro. Questo si chiama modularità.
La Parola Chiave: "!"
Per includere un file, usa il simbolo ! seguito dal nome
del file tra virgolette:
! "file-esterno.words"
Esempio Pratico
File 1: funzioni-comuni.words
define_word "doppio" 1 multiply argument 1 2
File 2: programma-principale.words
! "funzioni-comuni.words" print doppio 5 ← Usa la funzione da file-esterno
Output: 10
Path Relativi e Assoluti
Pangea supporta sia percorsi relativi che assoluti:
! "utils/helper.words" ← Relativo: cerca in subdirectory ! "/home/user/file.words" ← Assoluto: percorso completo
Nel file main.lua, c'è il concetto di
file_directory_stack:
local file_directory_stack = {} function execute_words_file(file_name) local file = io.open(resolved_file_name, "r") -- Metti la directory del file sullo stack table.insert(file_directory_stack, path_dirname(resolved_file_name)) -- Esegui il programma execute_program(program) -- Togli la directory dallo stack table.remove(file_directory_stack) end
In questo modo Pangea sa dove cercare i file relativi, anche quando includi file che a loro volta includono altri file (nesting).
Vantaggi della Modularità
- Organizzazione: Tieni il codice d'ordine
- Riutilizzabilità: Scrivi una funzione una volta, usala ovunque
- Manutenzione: Più facile trovare e correggere i bug
- Collaborazione: Puoi condividere file con gli amici
.words e quelli in italiano finiscono con
.parole.
6️⃣ Bilingual - Italiano e Inglese
Pangea supporta sia l'italiano che l'inglese come linguaggio di programmazione. Puoi scrivere il tuo codice nella lingua che preferisci!
Come Attivare la Modalità Italiana
Quando lanci Pangea, passa italian come primo argomento:
lua src/pangea1/main.lua ← Modalità Inglese (default) lua src/pangea1/main.lua italian ← Modalità Italiana
Parole Traducibili
Ecco un confronto tra inglese e italiano per le parole chiave:
| Funzione | Inglese | Italiano |
|---|---|---|
| Stampa output | print |
stampa |
| Addizione | add |
somma |
| Moltiplicazione | multiply |
moltiplica |
| Assegna variabile | set |
metti |
| Leggi variabile | get |
prendi |
| Condizione | if |
se |
| Ciclo | while |
mentre |
| Uguaglianza | equal |
uguale |
| Maggiore di | greater |
maggiore |
| Definifico funzione | define_word |
definisci_parola |
Esempio Comparativo
Lo stesso programma in inglese e italiano:
English (words)
print add 5 6 set "x" 10 print get "x"
Italiano (parole)
stampa somma 5 6 metti "x" 10 stampa prendi "x"
Nel file main.lua, c'è una tabella di traduzione e una
funzione tr():
local translate_italian = { ["print"] = "stampa", ["add"] = "somma", ["multiply"] = "moltiplica", -- ... e altri 20+ termini } function tr(string) if language == "italian" then local traduced = translate_italian[string] return traduced end return string end
Quando definisci le parole, usano tr() come chiave:
word_definitions[tr("print")] = {1, print_function} word_definitions[tr("add")] = {2, add_function}
Se la lingua è italiana, tr("print") restituisce
"stampa", quindi la parola viene registrata come
"stampa" e funziona!
7️⃣ REPL & Script Modes (Interattivo e Batch)
Pangea può funzionare in due modalità diverse: interattiva (REPL) dove scrivi comandi uno per uno, e script mode dove esegui un intero file.
Modalità REPL (Interattiva)
REPL significa "Read-Eval-Print Loop" (Leggi-Valuta-Stampa in Loop). È come avere una conversazione con il computer:
$ lua src/pangea1/main.lua pang version: 028 ? for help print "Ciao" ← Scrivi qui il tuo comando Ciao add 5 6 11 exit bye
Script Mode
Passa il nome di un file e Pangea esegue il file intero:
$ lua src/pangea1/main.lua mio-programma.words ← Il programma si esegue automaticamente
Risultato...
bye
Script Mode Ibrido: File + REPL
Se aggiungi un trattino - dopo il nome del file, Pangea
esegue il file E POI entra nella modalità interattiva:
$ lua src/pangea1/main.lua mio-programma.words - ← Esegue il file ← Poi entra in REPL print "Posso scrivere altri comandi!" Posso scrivere altri comandi!
Confronto delle Modalità
| Modalità | Comando | Uso Principale | Vantaggio |
|---|---|---|---|
| REPL | lua src/pangea1/main.lua |
Sperimentare e imparare | Feedback immediato |
| Script | lua src/pangea1/main.lua file.words |
Eseguire programmi | Automatizzazione |
| Ibrido | lua src/pangea1/main.lua file.words - |
Carica dati poi sperimenta | Entrambi i vantaggi |
Caso d'Uso Pratico
Immagina di avere un file setup.words che inizializza le
tue variabili:
set "nome" "Mario" set "numero_magico" 42
Poi esegui:
$ lua src/pangea1/main.lua setup.words - ← Ora entra in REPL con le variabili già caricate print get "nome" ← "Mario" è già disponibile! Mario add get "numero_magico" 8 50
Nel main.lua, la funzione
main() gestisce tutte e tre le
modalità:
function main() local filename = arg[1] if filename ~= nil then if filename == "-" then -- Solo REPL read_execute_loop() else -- Esegui file execute_words_file(filename) -- Se arg[2] == "-", entra anche in REPL if arg[2] == "-" then read_execute_loop() end end else -- Nessun file: REPL diretto read_execute_loop() end end
La funzione read_execute_loop() legge
linea per linea finché non premi exit:
function read_execute_loop() while true do local program = io.read() if program == nil or program == tr("exit") then break end execute_program(program) end end
🎉 Riassunto: Le 7 Features di Pangea
- 1️⃣ Notazione Prefissa: Operatore prima degli operandi, zero ambiguità
-
2️⃣
Literali Quotati: Stringhe con escape support
(
\",\\,\n,\t) - 3️⃣ Scoping Lessicale: Variabili isolate per funzione/scope
- 4️⃣ Recursive Descent: Valutazione ricorsiva e naturale di espressioni
-
5️⃣
Modularità: Includere file esterni con
! - 6️⃣ Bilingual: Italiano e Inglese interscambiabili
- 7️⃣ REPL & Script: Modalità interattiva e batch
🧠 Prossimi Passi
Ora che conosci le features in dettaglio, prova:
- Scrivi un piccolo programma in REPL
- Crea un file
.wordscon funzioni personalizzate - Fai un programma in italiano (
.parole) -
Leggi il codice Lua in
src/pangea1/main.luaper capire ancora meglio - Crea una funzione ricorsiva (come il fattoriale)