Errori
Ogni messaggio qui sotto è copiato dall’output del compilatore. Gli esempi mostrano come individuare l’errore e usare le correzioni suggerite.
Per correggere un programma, un modello ha bisogno di sapere che cosa non funziona e dove. Un messaggio preciso può evitargli di rileggere interi file. Per questo gli errori di Heroes indicano il punto coinvolto, le eventuali dichiarazioni in conflitto e, quando possibile, una correzione.
Argomenti scambiati
Se due parametri hanno lo stesso tipo, il controllo dei tipi da solo non distingue un argomento dall’altro. Heroes richiede quindi le etichette, cioè i nomi degli argomenti nella chiamata:
error[needs_label]: two of `copy_text`'s parameters are `str`, so every one of them is named at the call site — this one is `from`
at tests/golden/check/swapped-arguments.hero:16:21
|
16 | print(copy_text("a", "b")) #~ needs_label needs_label
| ^^^
fix (certain): write `from: `
error[wrong_label]: `copy_text` has nothing called `to` at this position — it is `from`
at tests/golden/check/swapped-arguments.hero:18:21
|
18 | print(copy_text(to: "b", from: "a")) #~ wrong_label wrong_label
| ^^
fix (certain): write `from:`
Le annotazioni #~ needs_label servono ai test per verificare la posizione della sottolineatura. I caratteri ^ indicano esattamente la porzione di codice coinvolta, così puoi individuare l’argomento anche in una chiamata lunga.
Correzioni automatiche e suggerimenti
Una correzione contrassegnata da certain si basa su informazioni verificate dal compilatore, come il tipo dedotto o l’unico nome simile disponibile. heroes check --apply applica queste correzioni. Può essere necessario correggere altri errori prima che il programma sia completo. Le correzioni contrassegnate da guess sono suggerimenti da valutare e non vengono applicate automaticamente dal comando.
Gli stessi messaggi escono anche in JSON, schema 2, scritto su stderr, il
formato che i programmi leggono facilmente, per quando a leggerli non è
una persona ma un altro programma. Ogni correzione dice dove si applica, e
heroes check --apply è il comando che scrive nel programma
quelle certain. Un programma che ha ancora dei buchi, i segnaposto
???, li trova lì anche loro, ciascuno con ciò che ci va, e la
risposta dice se l’elenco li contiene tutti.
Il giro completo, in comandi:
$ heroes check program.hero # le diagnostiche, su stderr
$ heroes check --apply program.hero # applica le riparazioni certain
$ heroes check --apply --in-place program.hero
$ heroes run program.hero
Quel heroes è il binario che hai costruito tu:
./heroes, ottenuto compilando con clang il codice scaricato.
Come si costruisce →
Alcuni errori nelle dichiarazioni di funzioni C vengono rilevati da heroes build. Questo comando avvia clang, il compilatore C, che confronta le dichiarazioni con l’header della libreria, il file che ne descrive funzioni e tipi. Un nome di funzione C scritto male può quindi superare heroes check ed essere segnalato durante la compilazione. I controlli sulle librerie C →
Parole chiave di altri linguaggi
Un modello può usare per errore una parola chiave di un altro linguaggio. Heroes riconosce alcune di queste parole e indica la forma da usare:
tests/golden/check/reserved-words.hero:2:1: error[reserved_word]: `struct` is not a word in this language — use `record`: `record Point`
tests/golden/check/reserved-words.hero:3:1: error[reserved_word]: `let` is not a word in this language — bind with `=`: `x = 5`
tests/golden/check/reserved-words.hero:4:1: error[reserved_word]: `const` is not a word in this language — use `constant`: `constant MAX: i64`
tests/golden/check/deleted-int.hero:23:8: error[reserved_word]: `int` is not a word in this language — an integer says its width: `i64`, and also `i8` `i16` `i32` `u8` `u16` `u32` `u64`
Qui ogni messaggio occupa una riga, ed è quello che stampa heroes check --brief; negli esempi precedenti trovi la forma completa, quella del comando semplice. Tre dei quattro errori hanno una correzione certain e --apply le applica. let resta invariato: la correzione richiede di scegliere una forma di dichiarazione, non soltanto di sostituire una parola.
Completare un programma con l’aiuto del compilatore
Puoi scrivere ??? dove manca un’espressione. Il compilatore controlla il codice circostante e indica il tipo atteso, i nomi disponibili e le funzioni che restituiscono quel tipo. Se non ci sono altri errori, il controllo termina con codice zero. Finché restano espressioni incomplete, non viene prodotto un eseguibile:
hole at examples/gallery/09-holes.hero:24:5
position: statement — any type, or none
this function returns: Entry
in scope:
entries: [Entry]
hole at examples/gallery/09-holes.hero:28:74
expected type: str
in scope:
entries: [Entry]
functions that return it:
summary_of(entries: [Entry])
# The hole can be one argument of an otherwise finished line.
Puoi quindi abbozzare il programma e completarlo usando le indicazioni del compilatore. Nell’esempio, il primo ??? sostituisce un’istruzione intera: il compilatore indica che cosa deve restituire la funzione. Il secondo è dentro un’istruzione e richiede un tipo preciso.
Come si misura
heroes mutate introduce un errore plausibile alla volta in programmi funzionanti e conta quanti errori rileva il compilatore. Ripete poi il controllo sugli stessi programmi con le regole specifiche di Heroes disattivate. La differenza tra i risultati misura l’effetto di queste regole.
La tabella riporta un’esecuzione completa sui 120 programmi che
examples/ contiene oggi, con tutti i tipi di modifica
previsti dallo strumento. Include anche i casi in cui i controlli di Heroes
non migliorano il risultato o non rilevano l’errore. Puoi ripeterla con
il comando qui sotto: il corpus cresce, quindi i tuoi conteggi saranno più
alti e le percentuali quasi le stesse.
$ heroes mutate examples
mistake injected mutants caught without the rules
two arguments swapped in a call 1910 80% 58%
a positional argument needing a label 1335 66% 0%
a shadowed name 945 95% 0%
a lazy catch-all on a variant 457 100% 47%
a local that takes a module's name 1700 100% 96%
a dropped ? 236 100% 82%
a forgotten @= on a declaration 762 99% 99%
a dropped variant case 133 100% 100%
a bitwise & where && was meant 227 100% 100%
a name that was never declared 824 100% 100%
a typo in a name 10463 100% 100%
mixed integer and float arithmetic 1495 100% 100%
a typo in an error code 59 0% 0%
a typo in a digit 68 3% 3%
La percentuale considera soltanto i mutanti, cioè i programmi modificati, che mantengono una sintassi valida. Se la modifica rende il testo non valido, viene rilevata già durante l’analisi della sintassi. Questi casi vengono esclusi per misurare separatamente l’effetto dei controlli successivi.
Lo strumento non riassume i risultati in una media unica. Le prime righe mostrano l’effetto delle regole specifiche di Heroes, come le etichette obbligatorie e il divieto di nascondere un nome già dichiarato. Le righe centrali riguardano errori rilevabili con i normali controlli su nomi e tipi. La @ dimenticata viene esclusa dai riepiloghi perché il modo in cui lo strumento modifica il codice rende quasi tutti questi errori rilevabili per costruzione.
La tabella mostra anche i limiti dei controlli. Alcuni scambi di argomenti non vengono rilevati. Un refuso in una stringa usata come codice d’errore resta una stringa valida. Lo stesso vale per un numero: 10 e 100 sono entrambi ammessi. I controlli di Heroes non possono stabilire quale valore intendevi scrivere.
Questa tabella misura il compilatore, non un modello. Se un modello fa questi sbagli, e se rifiutarli lo porta prima a un programma che funziona, è una prova a sé, con le sue regole scritte prima che parta. Che cosa è misurato e che cosa non ancora →
Poi: Record e funzioni, dove un programma comincia ad avere forme sue. ← Prima: Un primo programma