Dzisiaj opublikowałem na GitHubie kod do interpretera mojego własnego języka programowania. Poniżej opiszę ogólny proces interpretacji pliku.
Jeśli chcesz przetestować mój interpreter lub zobaczyć więcej przykładów kodu to zapraszam na manio143/FunctionalScript na GitHubie.
Więc zobaczmy teraz co po kolei dzieje się z plikiem .fsc
po uruchomieniu programu.
Najpierw wczytujemy zawartość pliku do pamięci i uruchamiamy na niej parser pProgram
, zdefiniowany przy użyciu biblioteki Parsec. Jeśli parser zakończy się z sukcesem to dostaniemy strukturę programu w postaci drzewa AST (Abstract Syntax Tree). Jeśli nie to wypiszemy błąd i zakończymy działanie programu.
Program to w zasadzie lista deklaracji. Deklarujemy albo wartość albo adnotację typu albo typ. W następnym kroku rozdzielamy je na trzy kubełki. Najpierw robimy sortowanie topologiczne typów, aby określić ich zależności w porządku prawie liniowym, potem dla każdego typu rozszerzającego rekord faktycznie go rozszerzamy do pełnego typu, następnie ustalamy, że typy pisane z małej litery, które nie były zadeklarowane to tak naprawdę zmienne typowe, a jeśli gdzieś odwołujemy się do nieistniejącego typu to kończymy program z błędem.
Kolejnym krokiem jest wyciągnięcie konstruktorów z typów unii i sprawdzenie czy zaczynają się z wielkiej litery i nie powtarzają. Tworzymy również dla nich informacje o typach dla późniejszego kroku.
Następnie podobnie jak typy sortujemy deklaracje wartości i w blockach wzajemnie rekurencyjnych deklaracji przekazujemy je do type checkera. Tam dzieje się inferencja typów (w procesie unifikacji) i sprawdzenie czy na pewno wszystko gra.
Potem robimy translację deklaracji wartości do postaci używalnej przez ewaluator zdefiniowany w module ProgramState
i dostajemy store z wartościami.
Ostatnim krokiem jest uruchomienie ewaluatora na funkcji main
o z góry określonej sygnaturze.