[nem-pl] Uwagi różne

Marcin 'Qrczak' Kowalczyk qrczak at knm.org.pl
Fri Feb 20 19:33:34 CET 2004


W liście z pią, 20-02-2004, godz. 18:23, Kamil Skalski pisze:

> > Jeszcze jedno. Skąd kompilator wie, które identyfikatory ma
> > kwalifikować, a które nie? Zanim nie skompiluje rozwinięcia makra, nie
> 
> Hmm, myślałem żeby bezwględnie stosować zasadę lexical-scoping. To
> co jest widoczne w miejscu definicji makra to jest związane. To znaczy ew.
> to co wprowadzają makra przed miejscem definicji o której myślimy:
> 
> macro m () { <[ def ("a" : var) = 4; ]> }
> macro m'() { m(); assert (a == 4); ... <[ $(a : int) ]> }

Nie rozumiem. Rozważmy coś takiego:

using Foo.A; // Wprowadza funkcje foo() i bar()
macro m() {
  <[
    defrule bar {...}; // defrule to jakieś śmieszne makro
    foo() + bar()
  ]>
}

Intencja jest pewnie taka, żeby do wynikowego kodu trafiło
   defrule bar {...};
   Foo.A.foo() + bar()
które zostanie przetworzone na
   def bar() {...defrule coś tu pomieszało, wszystko jedno co...};
   Foo.A.foo() + bar()

Tylko że tego się nie da tą drogą zaimplementować: w momencie rozwijania
makra jeszcze nie wiadomo, że foo będzie wolne, a bar związane.

> chociaż w sumie... może zrobić żeby makra w quotowaniach też się 
> expandowały...?

Żeby je expandować, trzeba zmaterializować kawałek kodu wstawiany przez
makro z wdolarkowanymi rzeczami. A żeby to zrobić i nie pomylić
identyfikatorów użytych przez rozwinięcie z identyfikatorami wstawionymi
z parametrów makra, trzeba je wcześniej pokolorować (albo kwalifikować,
ale tego się chyba nie da). Nie ma łatwo.

Najlepszy opis implementacji higienicznego systemu makr, jaki znam, jest
w <http://www.cs.indiana.edu/~dyb/papers/syntactic.ps.gz>. Tyle że nie
rozumiem, dlaczego jest taki skomplikowany - moim zdaniem można zrobić
troszeczkę prościej. Być może to wynika z innych założeń, bo on jakoś
miesza przestrzeń nazw programu z metaprogramem.

Nie domyślałem mojego systemu do końca i nie jestem pewien, czy działa -
tym bardziej go nie implementowałem. Ledwo mi się mieści w głowie.

Ogólnie nazwy mają symbole, kolory i środowiska. Kolor jest listą
unikalnych numerków, środowisk jest tyle ile elementów na tej liście.
Główny program ma pusty kolor. Wstawienie cytatu dodaje unikalny element
koloru oraz środowisko z miejsca definicji makra wszystkim nazwom, a
wdolarkowane rzeczy są pozostawiane bez zmian.

(U Dybviga tutaj jest inaczej: on robi jakieś podstawienia na nazwach
w momencie rozwijania lambdy, które moim zdaniem u mnie są niepotrzebne;
żeby złożoność nie ucierpiała, on robi te podstawienia leniwie;
kolorowanie więc też musi być leniwe; technicznie to się komplikuje,
kolorowane są wdolarkowane rzeczy a potem całość jeszcze raz i kolory
się xorują, ale efekt chyba wychodzi podobny.)

Jeśli teraz szukamy nazwy w środowisku, to najpierw sprawdzamy jego
oryginalny kolor w pierwszym dołączonym środowisku - musi się zgadzać i
symbol, i kolor; jeśli go tam nie ma, to znaczy że makro się rozwinęło
do wolnego wystąpienia i szukamy jej z kolorem obciętym do ogona w
kolejnym środowisku; i tak dalej, a na końcu szukamy z pustym kolorem
w bieżącym środowisku.

Funkcja implicit produkuje nazwę pokolorowaną tak jak nazwa makra użyta
w jego wywołaniu, czyli makro udaje, że tę nazwę wpisał ten kto wołał
makro. Symbol jest podany, a kolor i środowiska są brane z wystąpienia
nazwy makra. W Schemie nazwa makra jest mu podana wprost i on ją sobie
może przekazać jako argument datum->syntax-object, a u mnie zamiast
jawnego przekazania wzorcowej nazwy kolor jest zawsze brany z
wystąpienia nazwy makra z miejsca użycia. Sama funkcja implicit jest
przekazana makru niejawnie (bo w różnych makrach jest różna).

Główne komplikacje, jakich jeszcze nie rozpracowałem, to środowiska
różnych metapoziomów. Czyli pytanie, co jest dostępne w języku używanym
w treści makr, sama realizacja wykonywania przed chwilą kompilowanego
kodu, odkładanie skompilowanego kodu makr na dysku (nie wiem, czy nie
trzeba będzie serializować tych środowisk - jeśli tak, to trzeba jakoś
poprawić system, żeby nie trzeba było) i widoczność nazw wprowadzanych
przez wzajemnie rekurencyjne definicje, z których jedne definiują makra,
a inne ich używają. Co do tego ostatniego, chyba trzeba będzie dzielić
program na segmenty między definicjami makr i analizować je osobno,
zabraniając odwoływania się z dołu do góry (bez makr wszystkie nazwy są
widoczne we wszystkich definicjach).

> Prawdę mówiąc to jest problematyczne tyko wtedy gdy ktoś pisze
> niehigieniczne makra

Nie. Kontrolowana niehigiena tylko troszeczkę komplikuje Dybvigowi
życie (patrz artykuł), ale bez niej istota systemu się nie zmienia.
Bez niehigieny w nazwie nie musiałyby siedziec całe środowiska, tylko
wartość odpowiadająca danej nazwie, znaleziona w którymś środowisku
(bądź informacja, że takiej nie ma i to ma być wiążące wystąpienie).
Możliwość podmiany symboli przy danym kolorze powoduje, że trzeba
pamiętać całe środowiska, bo być może będziemy w nich szukali różnych
symboli.

-- 
   __("<         Marcin Kowalczyk
   \__/       qrczak at knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/





More information about the devel-pl mailing list