Witam! :)
Jakiś czas temu, gdy nie miałem nic konkretnego do roboty, pomyślałem, że napiszę sobie kompilator. Ot - taki prosty, a nuż mi się może kiedyś przyda jak będę pisał inne projekty. Tak więc i zacząłem pisanie...
... a dzisiaj (po jakichś 4-5 miesiącach) ukończyłem wersję pierwszą*.
Jest to w gruncie rzeczy kompilator do bajtkodu**, maszyna wirtualna dzięki której można te programy uruchamiać oraz prosty edytor (wszystko pisanie w Pascalu: Lazarusie).
Sama składnia mojego języka (który nazwałem SScript, już sam nie wiem dlaczego) jest prosta i podobna do większości języków pokroju C, C++, Javy, ...:
function<int> main()
{
return 0;
}
Najprostszy Hello World!
wygląda tak:
@("stdlib\\stdio.ss") // dołączamy moduł; podwójny backslash, ponieważ parser kodu obsługuje escapowanie stringów (`\n`, `\r` i tym podobne), więc `\s` zostałoby potraktowane nieco inaczej, niż byśmy chcieli
function<int> main()
{
println("Hello World!");
}
Istnieje 6 podstawowych typów dla zmiennych:
nazwa | objętość (bajty) | zakres | odpowiednik w Pascalu |
---|---|---|---|
bool | 1 | false..true | Boolean |
char | 1 | 0..255 | Char |
int | 4 | -2147483648 .. 2147483647 | LongInt |
float | 10 | 3.6 * 10-4951 .. 1.1 * 104932 | Extended |
string | - | - | String |
void | - | - | - |
Oraz parę podstawowych nagłówków: | |||
nazwa | opis | ||
---------------- | ---------------- | ||
math.ss | proste operacje matematyczne (sin, round, potęga) | ||
numbers.ss | operacje na liczbach (zamiana na string itp.) | ||
short_cast.ss | funkcje do szybkiego castowania pomiędzy typami; i2f (int to float), b2s (bool to string) itd. |
||
stdio.ss | obsługa standardowego wejścia oraz wyjścia | ||
string.ss | operacje na ciągach znaków (strpos, strreplace itd.) | ||
time.ss | operacje związane z czasem |
Przykład liczenia n-tej liczby Fibonacciego iteracyjnie:
@("stdlib\\stdio.ss")
// 'float' ma większy zakres od zwykłego 'int'-a, dlatego został ten typ tutaj użyty
function<float> fib(int n)
{
var<float> a=1, b=1, c;
if (n <= 0)
return 0;
if (n <= 2)
return n;
for (var<float> i=3; i<=n; i++)
{
c = a+b;
a = b;
b = c;
}
return c;
}
function<int> main()
{
var<int> n = read_int_t("Którą liczbę policzyć? ");
print("fibonacci(");
print(n);
print(") = ");
print(fib(n));
/*
Te 4 printy powyżej można by równie dobrze połączyć w jeden (uprzednio dodając `numbers.ss`):
println("fibonacci("+intstr(n)+") = "+fltstr(fib(n)));
Lecz to jest wg.mnie zbyt mało czytelne, stąd zostawiłem to tak jak jest.
*/
}
Jeżeli ktoś pisze w C, C++, Javie lub podobnych składniowo językach, to chyba zbytnio zaskoczony nie jest ;)
W języku istnieją pętle for
, while
(ale póki co nie ma do..while
), instrukcja if
oraz zmienne (stałe także są dopiero w planach, najprawdopodobniej następna wersja już je będzie miała). Podobnie z typami - jest to jedynie zalążek i nie ma póki co możliwości tworzenia typów (chociaż wersja 2.0a
je miała, ale to inna historia :>, bo aktualny 2.0b
jest pisany całkowicie od zera).
Póki co niezbyt wiele można w nim napisać (z racji tego, że dzisiaj wyszła dopiero pierwsza wersja, jak i sam język planuję raczej celować jako język skryptowy do gier, a nie ogólnego użytku/przeznaczenia), lecz mam nadzieję, że z czasem konstrukcji językowych będzie więcej (tj.napiszę więcej) ;)
Jak też wspomniałem na początku - sam kompilator jest napisany w-miarę prosto, więc nie ma w nim rzeczy typu single-static-assignment, natomiast postanowiłem zrobić taki "myk", że każde wyrażenie (w tym pętla, warunek itp.) są trzymane w osobnej tablicy/liście i najpierw po wejściu do funkcji, każde z wyrażeń jest zamieniane na drzewko i zapisywane do tej tablicy, a dopiero pod koniec wszystko jest ewaluowane (dzięki temu myślę, że łatwiej mi będzie zrobić optymalizacje w samym kodzie (bo wykrycie kodu x=3; x=5;
i usunięcie pierwszego przypisania nie będzie niczym trudnym), bo póki co mam jedynie optymalizator bajtkodu oraz skracanie wyrażeń stałych (2+2*2
jest bezpośrednio skracane do 6
, o ile włączone są optymalizacje)).
Dając wam ten kompilator, maszynę wirtualną oraz edytor liczę na sugestie, co mógłbym poprawić, co usunąć, a co dodać (bo wiem, że jeszcze długa droga, nim całość będzie można ogłosić "tró kompilatorem") - zarówno od strony użytkownika, jak i kodu :)
PS: wiem, że póki co nie ma szczegółowych opisów cd.składni, lecz myślę, że dacie radę się połapać (pooglądajcie pliki źródłowe w compiler\stdlib
, by połapać składnię).
PS2: jestem także w trakcie pisania opisu bibliotek i całej reszty SScript'u - http://sscriptwiki.xorg.pl
PS3: kod źródłowy (zajmujący nieco mniej od 6 MB) nie dał się wrzucić jako załącznik ("Rozmiar pliku przekracza rozmiar zadeklarowany w pliku konfiguracyjnym PHP"), więc wrzucam tutaj: http://speedy.sh/EfhZA/Kod.zip
*
sam kompilator ma tak naprawdę wersję 2.0b
, ponieważ nie jest to moje pierwsze podejście, a z pewnych powodów historycznych nie chciałem numerować od zera ;)
**
oczywiście bajtkod autorski, chociaż kilka razy mi przez myśl przeszło, by pisać na JVM.
#Edit
teraz zauważyłem, że zapomniałem usunąć z archiwów jeden ze starych plików: CTypes.pas
- nieużywana pozostałość, o której zapomniałem ;P
Pozdrawiam! ;)