Kompilator SScript

27

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! ;)

3

Najważniejsza w każdym projekcie jest dokumentacja. Wiele projektów umarło właśnie z powodu braku dokumentacji lub jej kiepskiej jakości.

0

Mam jeszcze pytanie czy ten język skompilowałby fibonacci w wersji rekurencyjnej?

0

Tak, działa także Fibonacci w wersji rekurencyjnej:

function<int> fib(int n)
{
 if (n <= 2)
  return 1;

 return fib(n-2)+fib(n-1);
}

Natomiast jest to znacznie wolniejsze od wersji iteracyjnej (głównie z powodu liczenia kilkukrotnie tych samych wartości).

0

No to zaraz sobie to przetestuję....

1

Odpaliłem program rekurencyjny i działa dobrze ale VM trochę namieszała mi na ekranie. Nie rozumiem po co cofasz kursor na początek konsoli wyświetlania.

0

Stały callstack :|

10

Nie wiem po co, ale fajne ;) Fajnie, że ci się chciało.

0

Brawo, przeglądając kod stwierdziłem że jest w to włożone naprawdę masa roboty. Ja zawsze chciałem właśnie coś takiego napisać ale za każdym razem wychodziły mi jakieś pseudo-języki które nijak nie miały się do rzeczywistości. Zapewne brakowało mi teorii ^^

Życzę powodzenia w dalszej pracy :)

3

Update!

Edytor 0.2, kompilator 2.1 oraz maszyna wirtualna 0.2


Changelog - edytor: - parę małych usprawnień edytora kodu (automatyczne dopełnianie nawiasów oraz możliwość zmiany, czy kursor może wychodzić poza linię (jak domyślnie w SynEdit) czy nie) - dodano możliwość wyboru, czy ostatnio otwierany projekt ma być automatycznie otwierany przy uruchomieniu edytora od nowa (jak np.jest w Lazarusie) - naprawiono błąd, gdy próbowano zamknąć niezapisaną kartę - naprawiono crash, gdy próbowano otworzyć nieistniejący plik z listy 'ostatnio otworzonych' - od teraz można stworzyć nowy projekt gdy jeden został już otwarty/stworzony bez konieczności restartu edytora - obsługa języków (domyślny angielski + polski w osobnym pliku; język do wyboru z ustawień środowiska) - dodano możliwość zapisu komunikatów kompilatora do schowka bądź pliku - poprawiono maksymalizowanie formy przy uruchamianiu edytora - edytor kodu ma teraz własne menu kontekstowe - dodano możliwość edycji parametrów przekazywanych do maszyny wirtualnej - poprawiono formatowanie kodu przy `@` - dodano nowe demo: fraktal Mandelbrota (zaimplementowany na podstawie kodu bodajże z http://monk.4programmers.net/) - dodano mały easter-egg ;)
Changelog - kompilator: - dodano lokalne oraz globalne stałe - od teraz nie można stworzyć zmiennej lub parametru funkcji typu `void` - naprawiono konstrukcję `return;` - poprawiono optymalizator oraz dodano optymalizacje dla opcodów jednoparametrowych (`call`, `jmp`...) - dodano sprawdzanie typów dla operatorów `+=`, `-=`, `*=` (...) - naprawiono operator `=`, który nie działał w niektórych konstrukcjach (np.`println(zmienna = 10)` wyświetlało zero) - zmieniono sposób zapisu stringów w bajtkodzie - naprawiono pętlę `do..while` - dodano nowe komunikaty dla złego typu w przypisaniu oraz złego typu parametru przy wywoływaniu funkcji - dodano specjalne stałe (włączane poprzez `-sconst`): - `__selffunc` typu `string` = nazwa aktualnie parsowanej funkcji - `__self` typu `string` = aktualnie kompilowany plik (pełna ścieżka) - `__compiler_version` typu `string` = wersja kompilatora (np.`"2.1"`) - `__compiler_iversion` typu `float` = wersja kompilatora (np.`2.1`) - `__line` typu `int` = aktualna linia - `__date` typu `string` = data kompilacji; format: `dd-mm-yyy` - `__time` typu `string` = godzina kompilacji; format: `hh:mm` - naprawiono kolejność wykonywania kilku operatorów - naprawiono błąd w funkcji `RemoveRedundantPushes`, który - prostymi słowami - czasami usuwał rzeczy, których nie powinien.
Changelog - maszyna wirtualna: - poprawiono wydajność (na koszt tego, że jeżeli wykona się np.`jmp(92367129876123)` to nastąpi crash maszyny jako Access violation, a we wcześniejszej wersji pokazałoby, że nastąpiła próba czytania poza bajtkodem - ale raczej wielki problem to nie jest, biorąc pod uwagę skok wydajności - na moim Intel Core 2 Duo - średnio o 500 opcodów na milisekundę więcej) - naprawiono opcody `if_`, jeżeli przekazane argumenty to były `float, int` bądź `int, float` - poprawiono literówki w operatorach `TOpParam`, gdy oba argumenty były `float`ami (porównywało nie te wartości, w konsekwencji zawsze zwracając `true`) - usunięto niepotrzebne dane z `Opcodes.pas`
Jednocześnie mam do ogłoszenia także dwie rzeczy: 1.Kiedyś postawiłem małą Wiki dla tego języka, teraz ją zaczynam powoli uzupełniać o opisy funkcji, poradniki itd. - link: http://sscriptwiki.xorg.pl (anonimowi użytkownicy nie mogą nic zmieniać, a rejestracja jest zamknięta - nie chcę mieć tam niepotrzebnego bałaganu; dodatkowo najlepiej przeglądać z włączonym AdBlockiem; może kiedyś postawię to na jakimś płatnym serwerze bez reklam, jeżeli kogoś ten projekt bardziej zainteresuje) 2.Cały projekt już od tego 1.5 tygodnia jest na GitHubie, lecz postanowiłem, że dopiero przy tej wersji się podzielę tymi informacjami; tak więc i podaję linki: https://github.com/Piterolex/SScript-Editor https://github.com/Piterolex/SScript-Compiler https://github.com/Piterolex/SScript-VM Jeżeli ktoś znajdzie jakiś błąd, ma sugestię or something, niech tam pisze ;)

Pełna paczka z edytorem, przykładami i tym wszystkim do pobrania jest na:
https://github.com/Piterolex/SScript-Editor/tree/master/build

Pozdrawiam! ;)

#Edit: jeszcze odnośnie callstacka - alokuję ileś-tam rekordów na sztywno, by całość działała szybciej (bo nie trzeba się wtedy bawić w żadne kopiowanie skrawków pamięci i jej ponowne realokowanie cały czas); w następnej wersji VM-ki może jednak przemyślę robienie tego na mniej-sztywnej zasadzie, podobnie ze stosem.

0

Mnie osobiście projekt się podoba. Jak byś jeszcze dodał obsługę tablic to by było już super ,ale nie wiem czy było by to trudne do implementacji.

0

Fakt, tablice będą w wersji 2.2 (https://github.com/Piterolex/SScript-Compiler/issues/7) ;)

ale nie wiem czy było by to trudne do implementacji.

Będzie trudno to zrobić (zarówno od strony kompilatora, jak i maszyny wirtualnej), lecz nie byłoby zabawy, gdyby coś nie było trudne w implementacji ;)

0

Jeśli tablice w języku C-podobnym, czy tam Pascal-podobnym są trudne w implementacji to spieprzyłeś to projektowo. Powodzenia z listami, mapami, drzewami, etc.

0

Zapewniam Cię, że póki co nic nie zostało zepsute projektowo - kompilator od początku jest pisany tak, by dodanie implementacji tych tablic nie zajęło sporo więcej miejsca (jedyny powód dla którego nie chciałem ich wprowadzać na początku, to skoncentrowanie się na ówcześnie ważniejszych aspektach).
Pisząc Będzie trudno to zrobić (zarówno od strony kompilatora, jak i maszyny wirtualnej) miałem na myśli... no, cóż - samo pisanie kompilatora nie jest rzeczą as-is łatwą.
Zresztą, zobaczy się w praniu - jeżeli rzeczywiście nic nie spieprzyłem projektowo, to do końca tego tygodnia, o ile nic mi nie wypadnie, w repo pojawi się wersja z obsługą tablic i paru innych rzeczy.

1

@Patryk27: mam takie pytanie - po co?

Do rozszerzania aplikacji? Jest VBScript, Lua, Python, JScript, FastScript, Ch, V8 itd.
Jaka jest zaleta Twojego rozwiązania poza tym że jest Twoje i ma nową, być może lepszą ale nieznaną składnię?

5

Głównie z nudów i do mojego innego, mniej ważnego na ten czas projektu :P

Do rozszerzania aplikacji? Jest VBScript, Lua, Python, JScript, FastScript, Ch, V8 itd.

Wiem o tym.

Jaka jest zaleta Twojego rozwiązania poza tym że jest Twoje i ma nową, być może lepszą ale nieznaną składnię?

Dla kogoś innego oczywiście lepszym wyborem będzie po prostu skorzystanie z czegoś, co jest już gotowe i lepsze, jak np.rzeczona wcześniej Lua; ja nie chcę robić z SScriptu żadnego wielkiego projektu, nie chcę tworzyć drugie(go)(j) C++/Javy/JScripta/Pythona/Luy/wtf - ot, po prostu kiedyś zainteresował mnie temat kompilatorów i postanowiłem się w tym sprawdzić, a że i tak nie miałem co pisać, to pomyślałem "dlaczego by nie?".
Z racji tego, że coś-tam naskrobałem, jakoś to się trzyma całości i działa, to pomyślałem, że wrzucę to także na to forum.

GitHuba założyłem, bo dzięki temu łatwiej orientuję się w tym, co zostało zrobione, a co do zrobienia jeszcze zostało.
Wiki stworzone zostało, by... hm... bez konkretniejszego celu - po prostu również pomyślałem, że skoro coś nowego stworzyłem, to wypadałoby, aby miało to swój opis.

Nie każdy hobbystyczny projekt ma za zadanie podbić świat ;)

#Edit @winerfresh oraz @tomepaw również mają rację - zawsze jest to też coś nowego (czego wcześniej nie pisałem) i paru nowych rzeczy się w ciągu tych kilku miesięcy nauczyłem ;)

6

Jak ktoś by chciał sam coś takiego stworzyć to polecam:
Compiler Construction Using Java, JavaCC, and Yacc - Anthony J. Dos Reis - cena 400zł

@Patryk27
Ważne że robisz cokolwiek - motto twórcy Gambasa - Benoît Minisini:
"When you are doing something, you have against you every people doing the same thing, every people doing the opposite thing, and the very large majority of people doing nothing"

0
Patryk27 napisał(a):

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 ;)

Nie przeglądałem całego kodu, ale tokenizer można by trochę poprawić.
Serhiy Perevoznyk napisał swego czasu bardzo ładny kod do generowania podświetlanej składni w Rich Edit.
Projekt nazywa się "RichEdit Syntax Highlight".
Myślę że mógłbyś skorzystać czytając jego kod.
Było w nim trochę błędów, ale sama idea była bardzo ciekawa.
Analizator wychodził na tyle przejrzyście że Yacc się do tego nie umywa.

0

Patryk, tak w ogóle to mam pytanie - z jakich materiałów korzystałeś gdy zaczynałeś pisanie projektu? Chodzi mi tu głównie o jakieś teoretyczne informacje na temat zasady działania kompilatora, maszyny wirtualnej itp.

0

Podczas pisania kompilatora nie korzystałem z żadnych książek as-is (co można zobaczyć poprzez to, że niektóre rozwiązania w nim zastosowane mogą być nieco "niecodzienne" ;)) - głównie przeglądałem kody źródłowe FPC i różne artykuły w internecie na ten temat.
Podobnie odnośnie maszyny wirtualnej.

0

Dla tych którzy chcieli by stworzyć własny język w prosty sposób polecam ANTLR:
http://www.antlr.org/
oraz książkę do niego:
"Language Implementation Patterns: Create Your Own Domain-Specific and General Programming Languages" - Terence Parr
"The Definitive Antlr Reference: Building Domain-Specific Languages" - Terence Parr

0

W związku z drobnymi zmianami składni, chciałbym się dowiedzieć, co uważacie o tych czterech pomysłach:

1.type-casting aktualnie wygląda w ten sposób:
nazwa_typu(wartość)
Np.:

var<int> xyz = int(10.52);

Lecz sprawa mi to pewne trudności w związku ze zmianami we wnętrzu kompilatora (ponieważ w związku z wprowadzeniem przestrzeni nazw nieco inaczej obsługiwane są rzeczy globalne, typu funkcje czy stałe), więc pomyślałem o takiej składni, która byłaby także wg.mnie bardziej jednoznaczna:

var<int> xyz = type<int>(10.52);

Ewentualnie:

var<int> xyz = (int)10.52;

Które byłoby lepsze*?
* dla takich prostych typów to może nie robi różnicy, ale np.var<int[]> xyz = int[](some_pointer); bądź var<int[]> xyz = (int[])some_pointer wyglądają nieco dziwnie, imho.

2.Wprowadzone zostały także przestrzenie nazw (póki co niezacommitowane, bo w trakcie testów):

namespace costam
{
 function<void> func()
 {
 }
}

function<int> main()
{
 costam::func();

 use costam;
 func();
}

(działają identycznie jak np.w C++ oraz innych językach)
Jak to "wygląda"?

3.Co powinno być operatorem adresu funkcji?
Myślałem nad @ bądź &.

function<void> some_func()
{
}

function<int> main()
{
 var<function<void>()> func = @some_func(); // &some_func();

 func();
}

4.Wyjątki.

try
{
 raise "asdf"; // raise/throw?
} catch(error)
{
 println("Failed: "+error);
}

Kiedy wprowadzone zostaną klasy/obiekty, myślałem dodatkowo nad składnią:

try
{
 raise new Exception("asdf");
} catch(Exception error)
{
 println("Failed -> "+error.getClassName()+": "+ error.getMessage());
 // obiekt jest automatycznie zwalniany, gdy wychodzimy poza ten blok oraz ewentualnie automatycznie tworzony na początku, gdy wywołamy np.`raise "string";`
}
  • słówko finally oczywiście.
1

Ad. 1)

var<int> xyz = cast<int>(10.52);
  • zbliżone do SQL-owego sensu, poza tym w C++ jak tylko mam okazję, stosuję swoje cast'y (np. checked_cast - weryfikacja klasy ale tylko w DEBUG).

Ad. 2)
Namespace w C++ wygląda do d...
Głównie przez to że kończy się nieciekawie.
Ale podobnie jest w Scali, więc może to tylko subiektywna opinia.

W Javie (package) nie masz zagnieżdżeń.

Ad. 3)
A musisz używać w ogóle jakichś dziwnych znaczków?
Object Pascal działał bez tego:
http://www.publispain.com/supertutoriales/programacion/delphi/cursos/1/datatype.html#21792

Ad. 4)

Póki nie zrobisz OOP:

try
{
  throwSystemError("asdf");
} catch(...)
{
 println("Failed -> "+getLastError().getName()+": "+ getLastError().getMessage());
 // clearLastError();
 // throwLastError();
}
0
  1. faktycznie - cast jest lepsze.
  2. więc zostanie sama konstrukcja nazwa_funkcji, bez dodatkowego operatora
  3. ok, coś w tym guście postaram się zrobić. A jak już będzie OOP, to lepszy będzie operator throw czy raise?
0
Patryk27 napisał(a):
  1. faktycznie - cast jest lepsze.
  2. więc zostanie sama konstrukcja nazwa_funkcji, bez dodatkowego operatora
  3. ok, coś w tym guście postaram się zrobić. A jak już będzie OOP, to lepszy będzie operator throw czy raise?

Ad. 4 Kwestia gustu
Scala: throw new
Java: throw new
C#: throw new
PHP: throw new
C++: throw
JavaScript: throw
Delphi: raise
Python: raise
Ruby: raise

Wychodzi na to że bardziej popularne jest throw.

W JavaScript masz ładnie zrobione zgłaszanie nie-obiektowych wyjątków - ale tam język jest dynamicznie typowany.

x = prompt("Enter a number less than 5:","")
try
{
  if(x>5)
  throw "whoops"
}
catch(wronganswer)
{
  if(wronganswer=="whoops")alert("BZZZZzzzzZZZZTT!")
} 
1

Yay! Update!

Od czasu ostatniej aktualizacji minęły prawie 3 miesiące, lecz od tego czasu sporo się zmieniło:
http://sscriptwiki.xorg.pl/wiki/Changelog
(nie ma póki co changelogu edytora - potem planuje go uzupełnić, ale tak czy siak wielkich zmian w nim nie ma)

Na Wiki (http://sscriptwiki.xorg.pl/wiki/) znajduje się także parę poradników ukazujących co i jak (aby nie trzeba było już zgadywać składni) oraz opisy funkcji z biblioteki standardowej.

Jest to wersja RC0 (release-candidate 0) - nie powinna zawierać bardzo znaczących błędów, jednak pomniejsze mogą się znaleźć (chociaż starałem się naprawić jak największą ich ilość).

Prosiłbym o sugestie co mógłbym dodać, poprawić, usunąć i jak to ogólnie się prezentuje ;)


Tutaj jest binarka na Windowsa 32-bit: [220413_win32.zip](//4programmers.net/Download/7387825675175781ad32cd.zip) Tutaj na Linuksa (również 32-bit; niestety, 3 MB to za dużo do przemulenia przez Coyote, więc wrzucam na odrębny hosting): http://www.speedyshare.com/8qJRJ/220413-linux32.zip Kod źródłowy jak ktoś chce znajduje się oczywiście na GitHubie (branch `master`).
PS - odnośnie wersji Linuksowej - pingwinek jest dla mnie stosunkowo nową platformą, więc możliwe że nawet się nie uruchomi, niemniej u mnie działa ;P
0

WTF?

https://github.com/Piterolex/SScript-Compiler/commit/f9dba5471d5dba4ed35b6c9bc9424f6f7a050f43

Commit powinien być do bólu atomowy, a nie zawierać kilku(nastu) niezależnych poprawek... Jak poprawiasz 5 rzeczy na raz to robisz 5 commitów.

1

Mea culpa - po prostu jestem przystosowany do robienia rzeczy na zasadzie "a to zacznę naprawiać to, o proszę - tutaj także wymagana jest poprawka, a tutaj kolejna" i się tak ciągnie :P

0

Gratuluję nowej wersji :) Z błędu który rzucił mi się w oczy to brak jakichkolwiek zaznaczonych pozycji przy wyborze języka w edytorku mimo że aktualnie obowiązuje jedyny na liście angielski. Screen w załączniku.

4
Patryk27 napisał(a):

(nie ma póki co changelogu edytora - potem planuje go uzupełnić, ale tak czy siak wielkich zmian w nim nie ma)

Uważaj żebyś czasami nie zmienił celu projektu - bo robienie własnego edytorka bardzo wciąga (wiem co mówię)...
Polecam raczej rozszerzenie istniejących - PSPad, Notepad++, Sublime Text - jeśli chodzi o wsparcie dla Twojego języka.

1 użytkowników online, w tym zalogowanych: 0, gości: 1