Zmiana składni języka - separator wyrażeń #5

Closed
opened 2022-05-02 23:02:38 +02:00 by robben · 4 comments
robben commented 2022-05-02 23:02:38 +02:00 (Migrated from engi.evolpe.it)

Aktualnie, parsując następujący fragment repeat 5 [ i | c + i ] inc 42 możemy zinterpretować to następująco (zaprezentowane przy pomocy JS):

  1. repeat(5, function(i) { play(c+i); }); inc(42);
  2. repeat(5); (function(i) { play(c+i); })(inc(42));
  3. itd.

Parser wrażliwy na argumentowość funkcji

Rozwiązaniem zachowującym aktualną składnię jest znanie argumentowości (liczby argumentów) każdej z funkcji. Wiedząc, że repeat przyjmuje 2 argumenty, a inc 1, łatwo jest wybrać poprawną wersję spośród powyższych - 1.

Problemem jest to, że takie rozwiązanie jest masywną pesymizacją parsera (pogorszeniem jego wydajności), wymusza zwracanie uwagi na kolejność definicji w programie.

Niestety dopóki nie zaimplementujemy to nie wiemy jaką, więc trudno ocenić, czy taka pesymizacja wydajności parsera jest rozsądna.

Małe wtrącenie - niedecydowalność parsera

| function |

if random == 4 then 
  function = [ i | i + 1 ]
else
  function = [ i j | i + j + 1 ]

function 4
print 42

Bez wykonania programu, nie wiemy czy dwie ostatnie linie to function(4); print(42) czy function(4, print(42)). Czyni to parsowanie dużo większym wyzwaniem gdyż nie można zrobić go na raz. (i uniemożliwia kompilację do kodu bajtowego, czy dalsze przetwarzanie drzew składniowych - optymalizację)

Parser z seperatatorem wyrażeń

Powyższy przykład zostaje zapisany teraz następująco: repeat 5 [ i | c + i ]; inc 42.

Taka składnia redukuje złożoność pamięciową oraz obliczeniową parsera. (Czyni też parsing potencjalnie decydowalnym)

Należy zwrócić uwagę, że języki takie jak Haskell czy OCaml, które mają podobny problem wymuszają separator wyrażeń. Haskell wspiera dwa formy separacji wywołań: opartą o białe znaki oraz opartą o ;.

-- whitespace sensitive syntax
two_lines1 = do
  putStrLn "hello"  -- separatorem jest znak nowej linii
  putStrLn "world"

-- whitespace insensitive syntax
two_lines2 = do {
  putStrLn "hello";
  putStrLn "world"
}

Konkluzja

W związku z powyższym opisem problemu, postuluję wprowadzenie separatora wyrażeń. Dobrym wyborem wydaje się ;, z uwagi na występowanie . w literałach liczbowych (. jest stowana w Smalltalku).

Miałby on następujące przykrą konsekwencję brzydszych (i dłuższych!) literałów kolekcji, np: chord [c; e; g], chyba, że ktoś nie lubi spacji to liczba znaków jest bez zmian chord[c;e;g].

@pi w związku, z tym, że to duża decyzja dotycząca kształtu języka proponuję by każda osoba się wypowiedziała do 2022-05-04 bym mógł skończyć podstawowy parser w tym tygodniu.

Aktualnie, parsując następujący fragment `repeat 5 [ i | c + i ] inc 42` możemy zinterpretować to następująco (zaprezentowane przy pomocy JS): 1. `repeat(5, function(i) { play(c+i); }); inc(42);` 2. `repeat(5); (function(i) { play(c+i); })(inc(42));` 3. itd. # Parser wrażliwy na argumentowość funkcji Rozwiązaniem zachowującym aktualną składnię jest znanie [argumentowości](https://pl.wikipedia.org/wiki/Argumentowo%C5%9B%C4%87) (liczby argumentów) każdej z funkcji. Wiedząc, że `repeat` przyjmuje 2 argumenty, a `inc` 1, łatwo jest wybrać poprawną wersję spośród powyższych - 1. Problemem jest to, że takie rozwiązanie jest masywną pesymizacją parsera (pogorszeniem jego wydajności), wymusza zwracanie uwagi na kolejność definicji w programie. Niestety dopóki nie zaimplementujemy to nie wiemy jaką, więc trudno ocenić, czy taka pesymizacja wydajności parsera jest rozsądna. ## Małe wtrącenie - niedecydowalność parsera ``` | function | if random == 4 then function = [ i | i + 1 ] else function = [ i j | i + j + 1 ] function 4 print 42 ``` Bez wykonania programu, nie wiemy czy dwie ostatnie linie to `function(4); print(42)` czy `function(4, print(42))`. Czyni to parsowanie dużo większym wyzwaniem gdyż nie można zrobić go na raz. (i uniemożliwia kompilację do kodu bajtowego, czy dalsze przetwarzanie drzew składniowych - optymalizację) # Parser z seperatatorem wyrażeń Powyższy przykład zostaje zapisany teraz następująco: `repeat 5 [ i | c + i ]; inc 42`. Taka składnia redukuje złożoność pamięciową oraz obliczeniową parsera. (Czyni też parsing potencjalnie decydowalnym) Należy zwrócić uwagę, że języki takie jak Haskell czy OCaml, które mają podobny problem wymuszają separator wyrażeń. Haskell wspiera dwa formy separacji wywołań: opartą o białe znaki oraz opartą o `;`. ```haskell -- whitespace sensitive syntax two_lines1 = do putStrLn "hello" -- separatorem jest znak nowej linii putStrLn "world" -- whitespace insensitive syntax two_lines2 = do { putStrLn "hello"; putStrLn "world" } ``` # Konkluzja W związku z powyższym opisem problemu, postuluję wprowadzenie separatora wyrażeń. Dobrym wyborem wydaje się `;`, z uwagi na występowanie `.` w literałach liczbowych (`.` jest stowana w Smalltalku). Miałby on następujące przykrą konsekwencję brzydszych (i dłuższych!) literałów kolekcji, np: `chord [c; e; g]`, chyba, że ktoś nie lubi spacji to liczba znaków jest bez zmian `chord[c;e;g]`. @pi w związku, z tym, że to duża decyzja dotycząca kształtu języka proponuję by każda osoba się wypowiedziała do __2022-05-04__ bym mógł skończyć podstawowy parser w tym tygodniu.
robben commented 2022-05-02 23:02:39 +02:00 (Migrated from engi.evolpe.it)

changed due date to May 04, 2022

changed due date to May 04, 2022
matpia commented 2022-05-07 13:08:06 +02:00 (Migrated from engi.evolpe.it)

Po rozmowie na wydziale jestem przekonany, że taka zmiana jest konieczna. Z mojej strony akceptuję.

Po rozmowie na wydziale jestem przekonany, że taka zmiana jest konieczna. Z mojej strony akceptuję.
matdra commented 2022-05-07 19:01:06 +02:00 (Migrated from engi.evolpe.it)

Wiem że się spóźniłem, ale zgadzam się. Zróbmy w ten sposób, będzie lepiej. Ale czy jako separator nie możnaby użyć ,?

Wiem że się spóźniłem, ale zgadzam się. Zróbmy w ten sposób, będzie lepiej. Ale czy jako separator nie możnaby użyć ,?
robben commented 2022-05-07 21:04:11 +02:00 (Migrated from engi.evolpe.it)

By ciąg znaków przy braku stosowania spacji był rozróżnialny tylko ; pasuje:

  • , jest używane już w notacji akordowej (co jest już obecną konwencją), np c13, ma obniżony 3 dźwięk w akordzie;
  • . jest używane w notacji dziesiętnej 6.28

Rozpatruję wyłącznie te 3 znaki jako separatory, z uwagi na łatwość ich wpisywania: ,.; potrzebują wyłącznie wciśnięcia jednego klawisza.

Można zmienić jeśli zostanie wyrażona niechęć wobec tego znaku, jest to zmiana banalna: wystarczy zmienić ten case

By ciąg znaków przy braku stosowania spacji był rozróżnialny tylko `;` pasuje: - `,` jest używane już w notacji akordowej ([co jest już obecną konwencją](https://en.wikipedia.org/wiki/Helmholtz_pitch_notation)), np `c13,` ma obniżony 3 dźwięk w akordzie; - `.` jest używane w notacji dziesiętnej `6.28` Rozpatruję wyłącznie te 3 znaki jako separatory, z uwagi na łatwość ich wpisywania: `,.;` potrzebują wyłącznie wciśnięcia jednego klawisza. Można zmienić jeśli zostanie wyrażona niechęć wobec tego znaku, jest to zmiana banalna: [wystarczy zmienić ten `case`](https://engi.evolpe.it/pi/musique/-/blob/31262e74a0fcfefe47dc895a09b831d48460d537/src/lexer.cc#L69)
Sign in to join this conversation.
No Label
bug
enhancement
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: s416496/musique#5
No description provided.