OBLICZANIE WYRAŻEŃ

PODPROGRAM 'SCANNING'

Podprogram ten jest używany do obliczania wartości 'następnego wyrażenia'.

Wynik jest zwracany jako 'ostatnia wartość' na stosie kalkulatora.  Dla wyniku liczbowego będzie to liczba zmiennoprzecinkowa. Jednakże przy wyniku łańcuchowym ostatnia wartość będzie złożona z zestawu parametrów. Pierwszy z pięciu bajtów jest nieokreślony, drugi i trzeci zawierają adres początku tego łańcucha, a czwarty i piąty jego długość.

Bit 6 zmiennej systemowej FLAGS jest ustawiony na 1 przy wyniku liczbowym, a wyzerowany przy wyniku łańcuchowym.

Gdy następne wyrażenie składa się tylko z pojedynczego argumentu, np. ... A ..., ... RND ..., ... A$ (4, 3 TO 7) ... , to ostatnią wartością jest po prostu wartość otrzymana z obliczenia tego argumentu.

Jednakże, gdy następne wyrażenie zawiera funkcję i jej argument, np. ...  CHR$ A..., ... NOT A ... , SIN 1 ..., to kod operacyjny tej funkcji jest przechowywany na stosie maszynowym aż do obliczenia ostatniej wartości argumentu. Wtedy ta ostatnia wartość jest wykorzystywana do wykonania odpowiedniej operacji, aby otrzymać nową ostatnią wartość.

W przypadku wykonywania operacji arytmetycznej lub logicznej, np. ...  A+B ... , A*B ..., ... A=B ... , zarówno ostatnia wartość pierwszego argumentu jak i kod operacji są pamiętane aż do momentu, gdy zostanie obliczony drugi argument. W rzeczywistości wyliczanie ostatniej wartości drugiego argumentu może również wymagać zapamiętania ostatnich wartości oraz kodów operacji na czas rachunków.

Można w ten sposób pokazać, że w trakcie wyliczania złożonego wyrażenia, np. ... CHR$ (T+A - 26*INT ((T+A)/26)+65)..., budowana jest hierarchia operacji, które należy jeszcze wykonać aż do momentu, gdy hierarchia ta zostanie rozłożona w celu otrzymania ostatecznej ostatniej wartości.

Każdy kod operacji posiada powiązany z sobą odpowiedni priorytet i operacje o wyższym priorytecie są zawsze wykonywane przed tymi, których priorytet jest niższy.

Podprogram rozpoczyna się od pobrania do rejestru A pierwszego znaku wyrażenia i od umieszczenia na stosie maszynowym znacznika początkowego priorytetu – zero.

24FB SCANNING     RST   0018,GET-CHAR       Pierwszy znak zostaje pobrany.
                  LD    B,+00               Znacznik początkowego priorytetu.
                  PUSH  BC                  jest umieszczany na stosie.
24FF S-LOOP-1     LD    C,A                 Główny punkt ponownego wejścia.
                  LD    HL,+2596            Indeks do tablicy funkcji skanowania
                  CALL  16DC,INDEXER        z kodem w C.
                  LD    A,C                 Odtwórz kod w A.
                  JP    NC,2684,S-ALPHNUM   Skocz, jeśli kodu nie ma w tablicy.
                  LD    B,+00               Użyj pozycji znalezionej w tablicy
                  LD    C,(HL)              do utworzenia wymaganego adresu
                  ADD   HL,BC               w parze rejestrów HL.
                  JP    (HL)                i skocz pod ten adres

Następnie pojawiają się cztery podprogramy; są one wywoływane przez procedury umieszczone w tablicy skanowania funkcji. Pierwsza z nich, 'procedura skanowania cudzysłowów', jest wykorzystywana przez S-QUOTE do sprawdzenia, czy każdy cudzysłów łańcucha posiada swój odpowiednik.

250F S-QUOTE-S    CALL  0074,CH-ADD+1       Wskaż na następny znak.
                  INC   BC                  Zwiększ licznik długości o jeden.
                  CP    +0D                 Czy to powrót karetki?
                  JP    Z,1C8A,REPORT-C     Jeśli tak, zgłoś błąd.
                  CP    +22                 Czy to kolejny '"'?
                  JR    NZ,250F,S-QUOTE-S   Jeśli nie, wróć na początek pętli.
                  CALL  0074,CH-ADD+1       Wskaż następny znak; ustaw
                  CP    +22                 znacznik zera, jeśli jest to kolejny '"'.
                  RET                       Skończone.

Następny podprogram, 'przeglądanie dwóch współrzędnych', wywoływana jest przez S-SCREEN$, S-ATTR i S-POINT w celu upewnienia się, że wymagane dwie współrzędne są podane we właściwej postaci.

2522 S-2-COORD    RST   0020, NEXT-CHAR     Pobierz następny znak..
                  CP    +28                 Czy jest to '('?
                  JR    NZ,252D,S-RPORT-C   Jeśli nie, zgłoś błąd.
                  CALL  1C79,NEXT-2NUM      Współrzędne na stos kalkulatora.
                  RST   0018,GET-CHAR       Pobierz bieżący znak.
                  CP    +29                 Czy jest to ')'?
252D S-RPORT-C    JP    NZ,1C8A,REPORT-C    Jeśli nie, zgłoś błąd.

PROCEDURA 'SYNTAX-Z'

Procedura ta jest wywoływana 32 razy, dając oszczędność 1 bajtu na każde z wywołań. Wykonywany jest prosty test bitu 7 zmiennej FLAGS, który zeruje znacznik zera w trakcie wykonywania programu, a ustawia go w czasie sprawdzania składni.

2530 SYNTAX-Z     BIT   7,(FLAGS)           Test bitu 7 zmiennej FLAGS.
                  RET                       Skończone.

Następny podprogram rozpoznaje znaki na ekranie i jest używany przez S-SCREENS$ do identyfikacji znaku, który pojawia się w wierszu x i kolumnie y ekranu. Przeszukiwany jest tylko zestaw znaków 'wskazywanych przez' zmienną CHARS.

Uwaga: Są to normalnie znaki od +20 (spacja) do +7F (©), chociaż użytkownik może zmienić zawartość CHARS, aby przeszukiwać również inne zestawy znaków, łącznie z grafiką definiowaną przez użytkownika.

2535 S-SCRN$-S    CALL  2307,STK-TO-BC      x do C, y do B; 0<=x<=23 dziesiętnie;
                  LD    HL,(CHARS)          O<=y<=31 dziesiętnie.
                  LD    DE,+0100            CHARS plus 256 dziesiętnie daje
                  ADD   HL,DE               HL wskazujące na zestaw znaków.
                  LD    A,C                 x jest zapisywane w A.
                  RRCA                      Liczba 32 (dziesietnie) * (x mod 8) + y
                  RRCA                      jest tworzona w A i zapisywana w E.
                  RRCA                      Jest to młodszy bajt pożądanego
                  AND   +E0                 adresu na ekranie.
                  XOR   B
                  LD    E,A
                  LD    A,C                 x jest ponownie zapisywane w A.
                  AND   +18                 Teraz liczba 64 (dziesiętnie) + 8*INT (x/8)
                  XOR   +40                 jest wstawiana do D.
                  LD    D,A                 DE teraz zawiera adres ekranu.
                  LD    B,+60               B zlicza 96 znaków.
254F S-SCRN-LP    PUSH  BC                  Zapamiętaj licznik.
                  PUSH  DE                  Oraz wskaźnik ekranu.
                  PUSH  HL                  I wskaźnik zestawu znaków.
                  LD    A,(DE)              Pobierz pierwszy wiersz znaku ekranowego.
                  XOR   (HL)                Porównaj go z wierszem z zestawu znaków.
                  JR    Z,255A,S-SC-MTCH    Skocz, jeśli znaleziono bezpośrednią zgodność.
                  INC   A                   Teraz testuj zgodność z negatywem znaku
                                            (ustaw +00 w A z +FF).
                  JR    NZ,2573,S-SCR-NXT   Skocz, jeśli nie było żadnej z tych dwóch zgodności.
                  DEC   A                   Przywróć +FF w A.
255A S-SC-MTCH    LD    C,A                 Stan negatywowy (+00 lub +FF) do C.
                  LD    B,+07               B zlicza przez kolejne 7 wierszy.
255D S-SC-ROWS    INC   D                   Przesuń DE na następny wiersz (dodaj 256 dziesiętnie).
                  INC   HL                  Przesuń HL na następny wiersz (tj. na następny bajt).
                  LD    A,(DE)              Pobierz wiersz ekranowy.
                  XOR   (HL)                Porównaj go z wierszem z ROM.
                  XOR   C                   Uwzględniaj stan negatywowy.
                  JR    NZ,2573,S-SCR-NXT   Skocz, jeśli nie ma zgodności.
                  DJNZ  255D,S-SC-ROWS      Skocz wstecz, aż wszystkie wiersze będą porównane.
                  POP   BC                  Usuń ze stosu wskaźnik zestawu znaków.
                  POP   BC                  Oraz wskaźnik ekranu.
                  POP   BC                  Na koniec licznik do BC.
                  LD    A,+80               Kod ostatniego znaku w zestawie plus jeden.
                  SUB   B                   A zawiera teraz pożądany kod.
                  LD    BC,+0001            Jedno miejsce jest teraz potrzebne w obszarze roboczym.
                  RST   0030,BC-SPACES      Zrób to miejsce.
                  LD    (DE),A              Wstaw w nie ten znak.
                  JR    257D,S-SCR-STO      Skocz, aby umieścić znak na stosie.
2573 S-SCR-NXT    POP   HL                  Odtwórz wskaźnik zestawu znaków.
                  LD    DE,+0008            Przesuń go o 8 bajtów na następny znak w zestawie.
                  ADD   HL,DE
                  POP   DE                  Odtwórz wskaźnik ekranu.
                  POP   BC                  Oraz licznik.
                  DJNZ  254F,S-SCRN-LP      Skocz na początek pętli dla 96 znaków.
                  LD    C,B                 Umieść na stosie pusty łańcuch (długość zero).
257D S-SCR-STO    JP 2AB2,STK-STO-$         Skocz, aby umieścić na stosie znaleziony znak
                                            lub pusty łańcuch, jeśli znak nie został rozpoznany.

Uwaga: To wyjście poprzez STK-STO-$ jest pomyłką, ponieważ prowadzi ono do podwojonego zapisywania wyniku łańcuchowego (zobacz na S-STRING, 25DB). Powinien tutaj znaleźć się rozkaz RET.

Ostatnim z tych czterech podprogramów jest podprogram skanowania atrybutów. Jest on wywoływany przez S-ATTR, aby zwrócić wartość ATTR (x,y), co koduje atrybuty wiersza x i kolumny y na ekranie telewizyjnym.

2580 S-ATTR-S     CALL  2307,STK-TO-BC      x do C, y do B. znów, 0<=x<=23 dziesiętnie;
                  LD    A,C                 0<=y<=31 dziesiętnie.
                  RRCA                      x jest zapisywane do A, a liczba
                  RRCA                      32 (dziesiętnie)*x (mod 8)+y jest
                  RRCA                      tworzona w A i zapisywana do L.
                  LD    C,A                 32*x(mod 8)+INT (x/8) zostaje również
                  AND   +E0                 zapisane do C.
                  XOR   B
                  LD    L,A                 L zawiera młodszy bajt adresu atrybutu.
                  LD    A,C                 32*x(mod 8)+INT (x/8) jest zapisywane w A.
                  AND   +03                 88 (dziesiętnie)+INT (x/8) jest
                  XOR   +58                 tworzone w A i zapisywane do H.
                  LD    H,A                 H zawiera starszy bajt adresu atrybutu.
                  LD    A,(HL)              Bajt atrybutu zostaje pobrany do A.
                  JP    2D28,STACK-A        Wyjście z umieszczeniem wyniku na stosie.

TABLICA FUNKCJI SKANOWANIA

Tablica ta zawiera 8 funkcji i 4 operatory. Wprowadza ona zatem 5 nowych funkcji Spectrum i udostępnia zgrabną metodę dostępu do niektórych funkcji i operatorów, które już istniały na komputerze ZX81.

położenie kod odstęp nazwa                  adres procedury obsługującej
2596      22  1C     S-QUOTE                25B3
2598      28  4F     S-BRACKET              25E8
259A      2E  F2     S-DECIMAL              268D
259C      2B  12     S-U-PLUS               25AF
259E      A8  56     S-FN                   25F5
25A0      A5  57     S-AND                  25F8
25A2      A7  84     S-PI                   2627
25A4      A6  8F     S-INKEY$               2634
25A6      C4  E6     S-BIN (EQU. S-DECIMAL) 268D
25A8      AA  BF     S-SCREEN$              2668
25AA      AB  C7     S-ATTR                 2672
25AC      A9  CE     S-POINT                267B
25AE      00  znacznik końca

PROCEDURY FUNKCJI SKANOWANIA

25AF S-U-PLUS     RST   0020,NEXTCHAR       Przy plusie po prostu przejdź
                  JP    24FF,S-LOOP-1       do następnego znaku i skocz wstecz
                                            do głównego wejścia do SCANNING.

Procedura 'szukania CUDZYSŁOWU' zajmuje się cudzysłowami łańcuchów tekstowych, czy to prostymi w stylu "nazwa", czy bardziej złożonymi jak "taki ""zielony"" domek", czy też na pozur nadmiarowymi VAL$ """a""".

25B3 S-QUOTE      RST   0018,GET-CHAR       Pobierz bieżący znak.
                  INC   HL                  Wskaż na początek łańcucha.
                  PUSH  HL                  Zapamiętaj adres początku.
                  LD    BC,+0000            Ustaw długość na zero.
                  CALL  250F,S-QUOTE-S      Wywołaj podprogram "porównania".
                  JR    NZ,25D9,S-Q-PRMS    Skocz przy skasowanym znaczniku zera - brak dalszych cudzysłowów.
25BE S-Q-AGAIN    CALL  250F,S-QUOTE-S      Wywołaj go ponownie dla trzeciego cudzysłowu.
                  JR    Z,25BE,S-Q-AGAIN    I ponownie dla piątego, siódmego, itd.
                  CALL  2530,SYNTAX-Z       Przy sprawdzaniu składni skocz, aby wyzerować
                  JR    Z,25D9,S-Q-PRMS     bit 6 zmiennej FLAGS i aby kontynuować skanowanie.
                  RST   0030,BC-SPACES      Zrób miejsce w obszarze roboczym
                                            na łańcuch oraz zamykający cudzysłów.
                  POP   HL                  Pobierz wskaźnik początku.
                  PUSH  DE                  Zapamiętaj wskaźnik pierwszego miejsca.
25CB S-Q-COPY     LD    A,(HL)              Pobierz znak z łańcucha.
                  INC   HL                  Wskaż na następny.
                  LD    (DE),A              Skopiuj ostatni do obszaru roboczego.
                  INC   DE                  Wskaż na następne miejsce.
                  CP    +22                 Czy ostatnim znakiem jest '"'?
                  JR    NZ,25CB,S-Q-COPY    Jeśli nie, skocz, aby skopiować następny.
                  LD    A,(HL)              Lecz jeśli tak, nie kopiuj następnego;
                  INC   HL                  jeśli następnym jest '"', skocz,
                  CP    +22                 aby skopiować znak umieszczony za nim;
                  JR    Z,25CB,S-Q-COPY     inaczej zakończ kopiowanie.
25D9 S-Q-PRMS     DEC   BC                  Wstaw prawdziwą długość do BC.

Zwróć uwagę, że pierwszy cudzysłów nie został wliczony w długość; ostatni został i jest teraz pomijany. Wewnątrz łańcucha pierwszy, trzeci, piaty, itd. cudzysłów został wliczony, lecz drugi, czwarty, itd. nie został.

                  POP   DE                  Odtwórz początek kopiowanego łańcucha.
25DB S-STRING     LD    HL,+5C3B            To jest FLAGS; ten punkt wejścia
                  RES   6,(HL)              jest używany, gdy ma zostać skasowany bit 6
                  BIT   7,(HL)              a łańcuch zapisany w pamięci, jeśli
                  CALL  NZ,2AB2,STK-STO-S   przetwarza się wiersz. Teraz jest to wykonywane.
                  JP    2712,S-CONT-2       Skocz, aby kontynuować skanowanie wiersza.

Zwróć uwagę, że przy kopiowaniu łańcucha do obszaru roboczego każde dwa cudzysłowy wewnątrz tego łańcucha ("") zostały zredukowane do jednego cudzysłowu (").

25E8 S-BRACKET    RST 0020,NEXT-CHAR        Procedura 'szukania NAWIASU'
                  CALL  24FB,SCANNING       po prostu pobiera znak
                  CP    +29                 i wywołuje rekurencyjnie SCANNING.
                  JP    NZ,1C8A,REPORT-C    Zgłoś błąd, jeśli nie ma pasującego nawiasu;
                  RST   0020,NEXT-CHAR      Kontynuuj skanowanie.
                  JP    2712,S-CONT-2
Ta procedura dla funkcji zdefiniowanych przez użytkownika po prostu skacze do 'podprogramu skanowania FN'.
25F5 S-FN         JP    27BD,S-FN-SBRN      'Procedura skanowania FN'.
25F8 S-RND        CALL  2530,SYNTAX-Z       Jeśli nie sprawdzana jest składnia,
                  JR    Z,2626,S-RND-END    skocz, aby obliczyć liczbę pseudolosową.
                  LD    BC,(SEED)           Pobierz bieżącą wartość zmiennej SEED.
                  CALL  2D2B,STACK-BC       Umieść ją na stosie kalkulatora.
                  RST   0028,FP-CALC        Teraz użyj kalkulatora.
                  DEFB  +A1,stk-one         Ostatnią wartością jest teraz
                  DEFB  +0F,addition        SEED+1.
                  DEFB  +34,stk-data        Umieść na stosie liczbę dziesiętną 75.
                  DEFB  +37,exponent+87
                  DEFB  +16,(+00,+00,+00)
                  DEFB  +04,multiply        (SEED+1)*75.
                  DEFB  +34,stk-data        Zobacz na UMIESZCZANIE LITERAŁÓW, aby zobaczyć,
                  DEFB  +80,(four bytes)    jak bajty są rozwijane w celu umieszczenia
                  DEFB  +41,exponent +91    liczby dziesiętnej 65537
                  DEFB  +00,+00,+80,(+00)   na stosie kalkulatora.
                  DEFB  +32,n-mod-m         Podziel (SEED+1)*75 przez 65537,
                                            aby dostać 'resztę' i 'odpowiedź'.
                  DEFB  +02,delete          Usuń 'odpowiedź'.
                  DEFB  +A1,stk-one         Teraz ostatnią wartością jest
                  DEFB  +03,subtract        'reszta' - 1.
                  DEFB  +31,duplicate       Zrób kopię z 'ostatniej wartości'.
                  DEFB  +38,end-calc        Rachunki zakończone.
                  CALL  2DA2,FP-TO-BC       Użyj 'ostatniej wartości', aby nadać
                  LD    (SEED),BC           nową wartość zmiennej SEED.
                  LD    A,(HL)              Pobierz wykładnik 'ostatniej wartości'.
                  AND   A                   Skocz naprzód, jeśli wykładnik jest
                  JR    Z,2625,S-RND-END    równy zero.
                  SUB   +10                 Zmniejsz wykładni, tj. podziel
                  LD    (HL),A              'ostatnią wartość' przez 65536, aby dostać
                                            wymaganą 'ostatnią wartość'.
2625 S-RND-END    JR    2630,S-PI-END       Przeskocz przez procedurę 'PI'.

'Procedura skanowania-PI': jeśli nie jest sprawdzana składnia, to wartość 'PI' zostaje obliczona i tworzy 'ostatnią wartość' na stosie kalkulatora.

2627 S-PI         CALL  2530,SYNTAX-Z       Testuj sprawdzanie składni.
                  JR    Z,2630,S-PI-END     Skocz, jeśli trzeba.
                  RST   0028,FP-CALC        Teraz użyj kalkulatora.
                  DEFB  +A3,stk-pi/2        Na stos kalkulatora trafia PI/2 jako
                  DEFB  +3B,end-calc        'ostatnia wartość'.
                  INC   (HL)                Wykładnik jest zwiększany, co odpowiada
                                            podwojeniu 'ostatniej wartości', dając PI.
2630 S-PI-END     RST   0020,NEXT-CHAR      Przesuń się na następny znak.
                  JP    26C3,S-NUMERIC      Skocz naprzód.
2634 S-INKEY$     LD    BC,+105A            Priorytet +10 szesnastkowo, kod operacji
                  RST   0020,NEXT-CHAR      +5A dla procedury 'wczytania'.
                  CP    +23                 Jeśli następnym znakiem jest '#', skocz.
                  JP    Z,270D,S-PUSH-PO    Będzie argument liczbowy.
                  LD    HL,+5C3B            To jest zmienna FLAGS.
                  RES   6,(HL)              Resetuj bit 6 dla wyniku łańcuchowego.
                  BIT   7,(HL)              Testuj sprawdzanie składni.
                  JR    Z,2665,S-INK$-EN    Skocz, jeśli trzeba.
                  CALL  028E,KEY-SCAN       Pobierz wartość klawisza do DE.
                  LD    C,+00               Przygotuj pusty łańcuch; umieść go na stosie,
                  JR    NZ,2660,S-IK$-STK   jeśli naciśnięto zbyt wiele klawiszy.
                  CALL  031E,K-TEST         Testuj wartość klawisza; jeśli jest zła,
                  JR    NC,2660,S-IK$-STK   umieść na stosie pusty łańcuch.
                  DEC   D                   +FF do D dla przygotowanego L (bit 3 ustawiony).
                  LD    E,A                 Wartość klawisza do E w celu dekodowania.
                  CALL  0333,K-DECODE       Dekoduj wartość klawisza.
                  PUSH  AF                  Zachowaj krótko wartość ASCII.
                  LD    BC,+0001            W obszarze roboczym potrzeba jednego miejsca.
                  RST   0030,BC-SPACES      Zrób je teraz.
                  POP   AF                  Odtwórz wartość ASCII.
                  LD    (DE),A              Przygotuj się do zapisania go na stosie jako łańcucha.
                  LD    C,+01               Jego długość wynosi jeden.
2660 S-IK$-STK    LD    B,+00               Skompletuj parametr długości.
                  CALL  2AB2,STK-STO-$      Umieść na stosie pożądany łańcuch.
2665 S-INK$-EN    JP    2712,S-CONT-2       Skocz naprzód.
2668 S-SCREEN$    CALL  2522,S-2-COORD      Sprawdź, czy są podane dwie współrzędne.
                  CALL  NZ,2535,S-SCRN$-S   Wywołaj ten podprogram, o ile nie jest
                  RST   0020,NEXT-CHAR      sprawdzana składnia; następnie pobierz
                  JP    25DB,S-STRING       kolejny znak i skocz wstecz.
2672 S-ATTR       CALL  2522,5-2-COORD      Sprawdź, czy są podane dwie współrzędne.
                  CALL  NZ,2580,S-ATTR-S    Wywołaj ten podprogram, o ile nie jest
                  RST   0020,NEXT-CHAR      sprawdzana składnia; następnie pobierz
                  JR    26C3,S-NUMERIC      kolejny znak i skocz naprzód.
267B S-POINT      CALL  2522,S-2-COORD      Sprawdź, czy są podane dwie współrzędne.
                  CALL  NZ,22CB,POINT-SUB   Wywołaj ten podprogram, o ile nie jest
                  RST   0020,NEXT-CHAR      sprawdzana składnia; następnie pobierz
                  JR    26C3,S-NUMERIC      kolejny znak i skocz naprzód.
2684 S-ALPHNUM    CALL  2C88,ALPHANUM       Czy znak jest alfanumeryczny?
                  JR    NC,26DF,S-NEGATE    Skocz, jeśli nie jest to litera lub cyfra.
                  CP    +41                 Teraz skocz, jeśli jest to litera;
                  JR    NC,26C9,S-LETTER    inaczej kontynuuj w S-DECIMAL.

Procedura 'skanowania liczby dziesiętnej', która znajduje się tutaj, zajmuje się kropką dziesiętną lub liczbą rozpoczynającą się od cyfry. Troszczy się ona również o wyrażenie 'BIN', które jest obsługiwane w procedurze zamiany 'liczby dziesiętnej na zmiennoprzecinkową'.

268D S-DECIMAL    CALL  2530,SYNTAX-Z       Skocz naprzód, jeśli wiersz
     (EQU. S-BIN) JR    NZ,2685,S-STK-DEC   jest wykonywany.

Podejmowane działanie różni się teraz istotnie przy sprawdzaniu składni i przy wykonywaniu wiersza. Jeśli jest sprawdzana składnia, to postać zmiennoprzecinkowa musi być obliczona i wstawiona do bieżącego wiersza języka BASIC. Jednakże przy wykonywaniu wiersza postać zmiennoprzecinkowa zawsze będzie dostępna, zatem jest kopiowana na stos kalkulatora, aby utworzyć 'ostatnią wartość'.

Podczas sprawdzania składni:

                  CALL  2C9B,DEC-TO-FP      Zostaje znaleziona postać zmiennoprzecinkowa.
                  RST   0018,GET-CHAR       Ustaw HL na adres o jeden większy od adresu ostatniej cyfry.
                  LD    BC,+0006            Potrzebne jest sześć miejsc.
                  CALL  1655,MAKE-ROOM      Zrób miejsce w wierszu języka BASIC.
                  INC   HL                  Wskaż pierwsze wolne miejsce.
                  LD    (HL),+0E            Wprowadź kod znacznika liczby.
                  INC   HL                  Wskaż na drugie miejsce.
                  EX    DE,HL               Ten wskaźnik jest potrzebny w DE.
                  LD    HL,(STKEND)         Pobierz 'stare' STKEND.
                  LD    C,+05               Pięć bajtów do przesłania.
                  AND   A                   Wyczyść znacznik przeniesienia.
                  SBC   HL,BC               'nowe' STKEND='stare' STKEND-5.
                  LD    (STKEND),HL         Przenieś liczbę zmiennoprzecinkową
                  LDIR                      ze stosu kalkulatora do wiersza.
                  EX    DE,HL               Wstaw wskaźnik wiersza do HL.
                  DEC   HL                  Wskaż ostatni dodany bajt.
                  CALL  0077,TEMP-PTR1      To ustawia CH-ADD.
                  JR    26C3,S-NUMERIC      Skocz naprzód.

Podczas wykonania:

26B5 S-STK-DEC    RST   0018,GET-CHAR       Pobierz bieżący znak.
26B6 S-SD-SKIP    INC   HL                  Teraz przesuwaj się po znakach, aż
                  LD    A,(HL)              do znalezienia kodu znacznika liczby.
                  CP    +0E
                  JR    NZ,26B6,S-SD-SKIP
                  INC   HL                  Wskaż pierwszy bajt tej liczby.
                  CALL  33B4,STACK-NUM      Przenieś liczbę zmiennoprzecinkową.
                  LD    (CH-ADD),HL         Ustaw CH-ADD.

Wynik liczbowy został właśnie zidentyfikowany, pochodzący z RND, PI, ATTR, POINT lub z liczby dziesiętnej, dlatego należy ustawić bit 6 zmiennej FLAGS.

26C3 S-NUMERIC    SET   6,(FLAGS)           Ustaw znacznik wyniku liczbowego.
                  JR    26DD,S-CONT-1       Skocz naprzód.

PROCEDURA SKANOWANIA ZMIENNEJ

Gdy zostaje rozpoznana nazwa zmiennej jest wykonywane wywołanie procedury LOOK-VARS, która przeszukuje zmienne już istniejące w obszarze zmiennych (lub w obszarze programu przy poleceniach DEF FN dla funkcji FN definiowanej przez użytkownika). Jeśli zostanie znaleziona odpowiednia wartość liczbowa, to jest ona umieszczana na stosie kalkulatora za pomocą STACK-NUM. Jednakże łańcuch lub tablica łańcuchów wymaga przekazania odpowiednich parametrów na stos kalkulatora przez procedurę STK-VAR (lub w przypadku funkcji definiowanej przez użytkownika przez procedurę STK-F-ARG wywoływaną z LOOK-VARS).

26C9 S-LETTER     CALL  28B2,LOOK-VARS      Szukaj wśród istniejących zmiennych
                                            pasującego elementu.
                  JP    C,1C2E,REPORT-2     Zgłaszany jest błąd, jeśli taki
                                            element nie istnieje.
                  CALL  Z,2996,STK-VARS     Umieść na stosie parametry
                                            łańcucha/zwróć adres bazowy elementu
                                            liczbowego.
                  LD    A,(FLAGS)           Pobierz FLAGS.
                  CP    +C0                 Testuj razem bity 6 i 7.
                  JR    C,26DD,S-CONT-1     jeden lub oba bity są zerowe.
                  INC   HL                  Należy pobrać wartość liczbową.
                  CALL  33B4,STACK-NUM      Przenieś tę liczbę.
26DD S-CONT-1     JR    2712,S-CONT-2       Skocz naprzód.

Znak sprawdza się z '-', aby w ten sposób zidentyfikować operację 'pojedynczego minusa'.

Przed wykonaniem testu rejestr B jest ustawiany na priorytet +09 a rejestr C na kod operacji +D8, co jest wymagane przez procedurę.

26DF S-NEGATE     LD    BC,+09DB            Priorytet +09, kod operacji +D8.
                  CP    +2D                 Czy jest to '-'?
                  JR    Z,270D,S-PUSH-PO    Skocz naprzód przy 'pojedynczym minusie'.

Następnie znak sprawdza się na zgodność z kodem 'VAL$', z priorytetem 16 i kodem operacji 18 szesnastkowo.

                  LD    BC,+1018            Priorytet 16 dziesiętnie, kod operacji +18 szesnastkowo.
                  CP    +AE                 Czy to jest 'VAL$'?
                  JR    Z,270D,S-PUSH-PO    Skocz naprzód, jeśli to 'VAL$'.

Bieżący znak musi teraz reprezentować jedną z funkcji od CODE do NOT o kodach od +AF do +C3.

                  SUB   +AF                 Zakres funkcji jest zmieniany
                                            z +AF do +C3 na zakres od +00 do +14 szesnastkowo.
                  JP    C,1C8A,REPORT-C     Zgłoś błąd, jeśli poza zakresem.

Funkcja 'NOT' jest identyfikowana i obsługiwana osobno od pozostałych.

                  LD    BC,+04F0            Priorytet +04, kod operacji +F0.
                  CP    +14                 Czy to funkcja 'NOT'?
                  JR    Z,270D,S-PUSH-PO    Skocz, jeśli tak.
                  JP    NC,1C8A,REPORT-C    Sprawdź ponownie zakres.

Pozostałe funkcje posiadają priorytet 16 dziesiętnie. teraz zostają obliczone kody operacyjne dla tych funkcji. Funkcje operujące na łańcuchach muszą w swoim kodzie operacyjnym posiadać ustawiony na zero bit 6, funkcje dające wynik w postaci łańcucha muszą w kodzie operacyjnym posiadać bit 7 ustawiony na 0.

                  LD    B,+10               Priorytet 16 dziesiętnie.
                  ADD   A,+DC               teraz zakres funkcji wynosi od +DC do +EF.
                  LD    C,A                 Przenieś kod operacyjny.
                  CP    +DF                 Oddziel CODE, VAL i LEN, które
                  JR    NC,2707,S-NO-TO-$   operują na łańcuchach i dają
                  RES   6,C                 wyniki liczbowe.
2707 S-NO-TO-$    CP    +EE                 Oddziel STR$ i CHR$,
                  JR    C,2700,S-PUSH-PO    które operują na liczbach
                                            i dają wyniki łańcuchowe.
                  RES   7,C                 Zaznacz kody operacyjne.
                                            Pozostałe kody operacyjne
                                            mają oba bity 6 i 7 ustawione na 1.

Kody priorytetu i operacyjny dla przetwarzanej funkcji są teraz umieszczane na stosie maszynowym. W ten sposób jest budowana hierarchia operacji.

270D S-PUSH-PO    PUSH  BC                  Umieść na stosie kody priorytetu oraz
                  RST   0020,NEXT-CHAR      operacyjny przed przejściem do przetwarzania
                  JP    24FF,S-LOOP-1       następnej części wyrażenia.

Kontynuowane jest przeglądanie wiersza. Za obecnym argumentem mogą wystąpić '(', operator podwójny lub po osiągnięciu końca wyrażenia znak powrotu karetki, przecinek, separator lub 'THEN'.

2712 S-CONT-2     RST   0018,GET-CHAR       Pobierz bieżący znak.
2713 S-CONT-3     CP    +28                 Skocz naprzód, jeśli nie jest to '(',
                  JR    NZ,2723,S-OPERTR    co oznacza wyrażenie w nawiasach.

Jeśli 'ostatnia wartość' jest liczbą, to wyrażenie w nawiasach jest prawdziwym podwyrażeniem i samo musi zostać obliczone. Jednakże, jeśli 'ostatnia wartość' jest łańcuchem, to wyrażenie w nawiasach oznacza element tablicy lub podłańcuch. Wymagane jest wywołanie procedury SLICING modyfikującej wg potrzeb parametry łańcucha.

                  BIT   6,(FLAGS)           Skocz naprzód, jeśli mamy do czynienia
                  JR    NZ,2734,S-LOOP      wyrażeniem liczbowym w nawiasach.
                  CALL  2A52,SLICING        Zmodyfikuj parametry 'ostatniej wartości'.
                  RST   0020,NEXT-CHAR      Idź dalej, aby przetworzyć kolejny
                  JR    2713,S-CONT-3       znak.

Jeśli bieżący znak jest faktycznie operatorem podwójnym, to zostanie mu nadany kod w zakresie od +C3 do +CF szesnastkowo, oraz odpowiedni kod priorytetu.

2723 S-OPERTR     LD    B,+00               Oryginalny kod do BC, aby indeksować nim
                  LD    C,A                 w tablicy operatorów.
                  LD    HL,+2795            Wskaźnik tej tablicy.
                  CALL  16DC,INDEXER        Indeksuj tablicę.
                  JR    NC,2734,SLOOP       Skocz naprzód, jeśli nie znaleziono operacji.
                  LD    C,(HL)              Pobierz wymagany kod z tablicy.
                  LD    HL,+26ED            Wskaźnik tablicy priorytetów:
                                            tj. 26ED +C3 daje 27B0 jako pierwszy adres.
                  ADD   HL,BC               Indeksuj tablicę.
                  LD    B,(HL)              Pobierz odpowiedni priorytet.

Teraz następuje wejście do głównej pętli tej procedury. Na tym etapie mamy:

i. 'Ostatnią wartość' na stosie kalkulatora.
ii. Początkowy priorytet na stosie maszynowym pod hierarchią, niewiadomego rozmiaru, funkcji i kodów binarnych. Hierarchia ta może być pusta.
iii. Para rejestrów BC zawiera 'obecną' operację i priorytet, który po osiągnięciu końca wyrażenia stanie się priorytetem zero.

Na początku 'ostatnia' operacja i priorytet są pobierane ze stosu maszynowego i porównywane z 'bieżącą' operacją i priorytetem.

Jeśli 'bieżący' priorytet jest wyższy od 'ostatniego', to wykonywane jest opuszczenie tej pętli, ponieważ 'bieżący' priorytet mocniej wiąże od 'ostatniego'.

Jednakże jeśli bieżący priorytet jest mniej wiążący, to operacja określona jako 'ostatnia' zostaje wykonana. 'Bieżąca' operacja i priorytet wracają na stos maszynowy, aby trafić z powrotem do pętli w następnym jej obiegu. W ten sposób hierarchia funkcji i operacji dwuargumentowych, które zostały ustawione w kolejkę, jest przetwarzana we właściwej kolejności.

2734 S-LOOP       POP   DE                  Pobierz 'ostatnią' operację i priorytet.
                  LD    A,D                 Priorytet idzie do rejestru A.
                  CP    B                   Porównaj 'ostatni' z 'bieżącym'.
                  JR    C,2773,S-TIGHTER    Wyjdź, aby zaczekać na argument.
                  AND   A                   Czy oba priorytety są zerami?
                  JP    Z,0018,GET-CHAR     Wyjdź poprzez GET-CHAR, czyniąc w ten sposób
                                            'ostatnią' wartość pożądanym wynikiem.

Zanim zostanie wykonana 'ostatnia' operacja, funkcja 'USR' zostaje podzielona na 'USR liczba' i 'USR łańcuch', zgodnie z ustawieniem bądź wyzerowaniem bitu 6 zmiennej FLAGS, gdy argument funkcji był umieszczany na stosie jako 'ostatnia wartość'.

                  PUSH  BC                  Umieść na stosie 'bieżące' wartości.
                  LO    HL,+5C3B            To jest zmienna FLAGS.
                  LD    A,E                 'Ostatnia' operacja jest porównywana
                  CP    +ED                 z kodem USR, co da wynik
                  JR    NZ,274C,S-STK-LST   'USR liczba', jeśli nie zostanie zmienione;
                                            skocz, jeśli kod nie jest kodem 'USR'.
                  BIT   6,(HL)              Testuj bit 6 zmiennej FLAGS.
                  JR    NZ,274C,S-STK-LST   Skocz, jeśli jest ustawiony ('USR liczba').
                  LD    E,+99               Zmień kod 'ostatniej' operacji:
                                            'przesunięcie' 19, +80 dla danych łańcuchowych
                                            z wynikiem liczbowym ('USR string').
274C S-STK-LST    PUSH  DE                  Przechowaj krótko na stosie 'ostatnie' wartości.
                  CALL  2530,SYNTAX-Z       Nie wykonuj operacji przy sprawdzaniu składni.
                  JR    Z,275B,S-SYNTEST
                  LD    A,E                 Kod 'ostatniej' operacji.
                  AND   +3F                 Usuń bity 6 i 7, aby zamienić kod operacji
                  LD    B,A                 na offset kalkulatora.
                  RST   0028,FP-CALC        Teraz użyj kalkulatora.
                  DEFB  +3B,fp-calc-2       Wykonaj właściwą operację.
                  DEFB  +38,end-calc        Zrobione.
                  JR    2764,S-RUNTEST      Skocz naprzód.

Ważną częścią sprawdzania składni jest przetestowanie operacji, aby upewnić się, że natura 'ostatniej wartości' jest poprawnego typu dla danej operacji.

275B S-SYNTEST    LD    A,E                 Pobierz kod 'ostatniej' operacji.
                  XOR   (FLAGS)             To ustawia naturę 'ostatniej wartości'
                  AND   +40                 względem wymagań operacji. Aby składnia była poprawna,
                                            muszą być takie same.
2761 S-RPORT-C    JP    NZ,1C8A,REPORT-C    Skocz, jeśli składnia jest zła.

Przed wykonaniem skoku wstecz, aby ponownie wejść w pętlę, natura 'ostatniej' wartości musi zostać odnotowana w zmiennej FLAGS.

2764 S-RUNTEST    POP   DE                  Pobierz kod 'ostatniej' operacji.
                  LD    HL,+5C3B            To jest zmienna FLAGS.
                  SET   6,(HL)              Załóż wynik liczbowy.
                  BIT   7,E                 Skocz naprzód, jeśli natura
                  JR    NZ,2770,S-LOOPEND   'ostatniej wartości' jest liczbowa.
                  RES   6,(HL)              To jest łańcuch.
2770 S-LOOPEND    POP   BC                  Pobierz 'bieżące' wartości do BC.
                  JR    2734,S-LOOP         Skocz wstecz.

Whenever the 'present' operation binds tighter, the 'last' and the 'present' values go back on the machine stack. However if the 'present' operation requires a string as its operand then the operation code is modified to indicate this requirement.

2773 S-TIGHTER    PUSH  DE                  'Ostatnie' wartości idą na stos.
                  LD    A,C                 Pobierz 'bieżący' kod operacji.
                  BIT   6,(FLAGS)           Nie zmieniaj kodu operacji, jeśli mamy do czynienia
                  JR    NZ,2790,S-NEXT      z liczbowym argumentem.
                  AND   +3F                 Wyczyść bity 6 i 7.
                  ADD   A,+08               Zwiększ kod o +08.
                  LD    C,A                 Zwróć kod de rejestru C.
                  CP    +10                 Czy operacją jest 'AND'?
                  JR    NZ,2788,S-NOT-AND   Skocz, jeśli tak nie jest.
                  SET   6,C                 'AND' wymaga argumentu liczbowego.
                  JR    2790,S-NEXT         Skocz naprzód.
2788 S-NOT-AND    JR    C,2761,S-RPORT-C    Operacje -, *, /, ^ i OR nie są
                                            możliwe na łańcuchach.
                  CP    +17                 Czy operacją jest '+'?
                  JR    Z,2790,S-NEXT       Skocz, jeśli tak jest.
                  SET   7,C                 Pozostałe operacje dają wynik liczbowy.
2790 S-NEXT       PUSH  BC                  'Bieżące' wartości idą na stos maszynowy.
                  RST   0020,NEXT-CHAR      Przetwarzaj następny znak.
                  JP    24FF,S-LOOP-1       Wróć do pętli.

TABLICA OPERATORÓW

adres kod kod operator   adres kod kod operator
2795  2B  CF  +          27A3  3C  CD  <
2797  2D  C3  -          27A5  C7  C9  <=
2799  2A  C4  *          27A7  C8  CA  >=
279B  2F  C5  /          27A9  C9  CB  <>
279D  5E  C6  ^          27AB  C5  C7  OR
279F  3D  CE  =          27AD  C6  C8  AND
27A1  3E  CC  >          27AF  00  Znacznik końca

TABLICA PRIORYTETÓW (tablica poprzedzania)

adres priorytet operator  adres priorytet operator
27B0  06        -         27B7  05        >=
27B1  08        *         27B8  05        <>
27B2  08        /         27B9  05        >
27B3  0A        ^         27BA  05        <
27B4  02        OR        27BB  05        =
27B5  03        AND       27BC  06        +
27B6  05        <=

PROCEDURA 'SKANOWANIA FUNKCJI'

Procedura ta wywoływana jest przez 'procedurę skanowania funkcji FN' w celu obliczenia wartości funkcji zdefiniowanej przez użytkownika w wierszu programu w języku BASIC. Procedurę można rozważyć w czterech etapach:

i. Składnia polecenia FN jest sprawdzana podczas fazy sprawdzania składni.

ii. Podczas wykonywania wiersza dokonuje się przeszukania obszaru programu w celu znalezienia rozkazu DEF FN, a następnie porównuje się nazwy funkcji, aż będą takie same – lub zostanie zgłoszony błąd.

iii. Argumenty FN są obliczane przez wywołania do SCANNING.

iv. Sama funkcja również jest wyliczana przez wywołanie SCANNING, które z kolei wywołuje procedury LOOK-VARS oraz 'UMIESZCZENIE NA STOSIE ARGUMENTU FUNKCJI'.

27BD S-FN-SBRN    CALL  2530,SYNTAX-Z       O ile nie jest sprawdzana składnia,
                  JR    NZ,27F7,SF-RUN      wykonaj skok do SF-RUN.
                  RST   0020,NEXT-CHAR      Pobierz pierwszy znak nazwy.
                  CALL  2C8D,ALPHA          Jeśli nie jest to litera alfabetu,
                  JP    NC,1C8A,REPORT-C    to zgłoś błąd.
                  RST   0020,NEXT-CHAR      Pobierz następny znak.
                  CP    +24                 Czy jest to '$'?
                  PUSH  AF                  Zapamiętaj znacznik zera na stosie.
                  JR    NZ,27D0,SF-BRKT-1   Skocz, jeśli to nie był znak '$'.
                  RST   0020,NEXT-CHAR      Lecz jeśli był, to pobierz następny znak.
27D0 SF-BRKT-1    CP    +28                 Jeśli znakiem nie jest '(',
                  JR    NZ,27E6,SF-RPRT-C   to zgłoś błąd.
                  RST   0020,NEXT-CHAR      Pobierz następny znak.
                  CP    +29                 Czy jest to ')'?
                  JR    Z,27E9,SF-FLAG-6    Skocz, jeśli tak; nie ma argumentów.
27D9 SF-ARGMTS    CALL  24FB,SCANNING       Wewnątrz pętli wywołaj SCANNING,
                                            aby sprawdzić składnię każdego
                                            argumentu i wstawić liczby zmiennoprzecinkowe.
                  RST   0018,GET-CHAR       Pobierz znak, który jest za argumentem.
                  CP    +2C                 Jeśli nie jest nim ',',
                  JR    NZ,27E4,SF-BRKT-2   to skocz - nie ma więcej argumentów.
                  RST   0020,NEXT-CHAR      Pobierz pierwszy znak w następnym argumencie.
                  JR    27D9,SF-ARGMTS      Wróć na początek pętli, aby przetworzyć ten argument.
27E4 SF-BRKT-2    CP    +29                 Czy bieżący znak to ')'?
27E6 SF-RPRT-C    JP    NZ,1C8A,REPORT-C    Jeśli nie, zgłoś błąd.
27E9 SF-FLAG-6    RST   0020,NEXT-CHAR      Wskaż następny znak w wierszu BASIC.
                  LD    HL.+5C3B            To zmienna FLAGS; załóż funkcję łańcuchową
                  RES   6,(HL)              i wyzeruj bit 6 zmiennej FLAGS.
                  POP   AF                  Odtwórz znacznik zera, skocz, jeśli
                  JR    Z,27F4,SF-SYN-EN    FN jest faktycznie funkcją łańcuchową.
                  SET   6,(HL)              Inaczej ustaw bit 6 zmiennej FLAGS
27F4 SF-SYN-EN    JP    2712,S-CONT-2       Skocz wstecz, aby kontynuować skanowanie wiersza.

ii. Podczas wykonywania wiersza należy wyszukać polecenie DEF FN.

27F7 SF-RUN       RST   0020,NEXT-CHAR      Pobierz pierwszy znak nazwy.
                  AND   +DF                 Zresetuj bit 5, aby otrzymać duże litery.
                  LD    B,A                 Skopiuj nazwę do B.
                  RST   0020,NEXT-CHAR      Pobierz następny znak.
                  SUB   +24                 Odejmij 24 szesnastkowo, kod znaku '$'.
                  LD    C,A                 Skopiuj wynik do C (zero dla łańcucha,
                                            różne od zera dla funkcji liczbowej).
                  JR    NZ,2802,SF-ARGMT1   Skocz przy wartości różnej od zera: funkcja liczbowa.
                  RST   0020,NEXT-CHAR      Pobierz następny znak, '('.
2802 SF-ARGMT1    RST   0020,NEXT-CHAR      Pobierz pierwszy znak pierwszego argumentu.
                  PUSH  HL                  Zapamiętaj na stosie wskaźnik do niego.
                  LD    HL,(PROG)           Wskaż początek programu.
                  DEC   HL                  Cofnij się o jedną komórkę.
2808 SF-FND-DF    LD    DE,+00CE            Szukane będzie 'DEF FN'.
                  PUSH  BC                  Zapamiętaj nazwę oraz 'stan łańcuchowy'.
                  CALL  1D86,LOOK-PROG      Teraz przeszukaj program.
                  POP   BC                  Odtwórz nazwę i stan.
                  JR    NC,2814,SF-CP-DEF   Skocz przy znalezionym rozkazie DEF FN.

RAPORT P - FN bez DEF.

2812 REPORT-P     RST   0008,ERROR-1        Wywołaj procedurę obsługi błędów.
                  DEFB  +18

Gdy zostanie znaleziony rozkaz DEF FN, będzie porównana nazwa oraz stan tych dwóch funkcji: jeśli nie będą do siebie pasować, poszukiwanie zostanie wznowione.

2814 SF-CP-DEF    PUSH  HL                  Zapamiętaj wskaźnik znaku DEF FN
                                            na wypadek potrzeby wznowienia poszukiwań.
                  CALL  28AB,FN-SKPOVR      Pobierz nazwę funkcji DEF FN.
                  AND   +DF                 Wyzeruj bit 5, aby otrzymać duą literę.
                  CP    B                   Czy pasuje do nazwy funkcji FN?
                  JR    NZ,2825,SF-NOT-FD   Skocz, jeśli nie pasuje.
                  CALL  28AB,FN-SKPOVR      Pobierz następny znak w DEF FN.
                  SUB   +24                 Odejmij 24 szesnastkowo, kod znaku '$'.
                  CP    C                   Porównaj stan ze stanem FN.
                  JR    Z,2831,SF-VALUES    Skocz, jeśli znaleziono teraz pełną zgodność.
2825 SF-NOT-FD    POP   HL                  Odtwórz wskaźnik do 'DEF FN'.
                  DEC   HL                  Cofnij się o jedną komórkę.
                  LD    DE,+0200            Użyj procedury poszukującej, aby znaleźć koniec
                  PUSH  BC                  polecenia DEF FN,
                  CALL  198B,EACH-STMT      przygotowując się na następne poszukiwanie;
                  POP   BC                  w międzyczasie zapamiętaj nazwę oraz stan.
                  JR    2808,SF-FND-DF      Skocz wstecz, aby szukać dalej.

ii. Teraz znalezione zostało poprawne polecenie DEF FN. Argumenty polecenia FN zostaną obliczone przez powtarzające się wywołania SCANNING, a ich 5-cio bajtowe wartości (lub parametry dla łańcuchów) zostaną wstawione w polecenie DEF FN w miejscach zarezerwowanych tam podczas sprawdzania składni. HL będzie wykorzystywane do wskazywania pozycji wzdłuż polecenia DEF FN (przez wywoływanie w razie konieczności FN-SKPOVR), podczas gdy CH-ADD wskazuje wzdłuż polecenia FN (przez wywoływanie wg potrzeb RST 0020, NEXT-CHAR).

2831 SF-VALUES    AND   A                   Jeśli HL teraz wskazuje '$',
                  CALL  Z,28AB,FN-SKPOVR    przesuń się do '('.
                  POP   DE                  Usuń wskaźnik do 'DEF FN'.
                  POP   DE                  Pobierz wskaźnik do pierwszego
                  LD    (CH-ADD),DE         argumentu FN i skopiuj go do CH-ADD.
                  CALL  28AB,FN-SKPOVR      Teraz przejdź za znak '('.
                  PUSH  HL                  Zapamiętaj ten wskaźnik na stosie.
                  CP    +29                 Czy wskazuje na ')'?
                  JR    Z,2885,SF-R-BR-2    Jeśli tak, skocz: FN nie ma argumentów.
2843 SF-ARG-LP    INC   HL                  Wskaż następny kod.
                  LD    A,(HL)              Umieść ten kod w A.
                  CP    +0E                 Czy jest to kod 'znacznika liczby', 0E szesnastkowo?
                  LD    D,+40               Ustaw bit 6 rejestru D przy argumencie liczbowym.
                  JR    Z,2852,SF-ARG-VL    Skocz przy zerze: argument liczbowy.
                  DEC   HL                  Teraz upewnij się, że HL wskazuje na
                                            znak '$' (a nie, przykładowo, na kod sterujący)
                  CALL  28AB,FN-SKPOVR
                  INC   HL                  Teraz HL wskazuje na 'znacznik liczby'.
                  LD    D,+00               Bit 6 rejestru D jest zerowany: argument łańcuchowy.
2852 SF-ARG-VL    INC   HL                  Wskaż pierwszy z pięciu bajtów w DEF FN.
                  PUSH  HL                  Zapamiętaj ten wskaźnik na stosie.
                  PUSH  DE                  Zapamiętaj 'status łańcuchowy' argumentu.
                  CALL  24FB,SCANNING       Teraz oblicz ten argument.
                  POP   AF                  Pobierz znacznik liczba/łańcuch do A.
                  XOR   (FLAGS)             Testuj jego bit 6 względem wyniku
                  AND   +40                 zwróconego przez SCANNING.
                  JR    NZ,288B,REPORT-Q    Jeśli się nie zgadzają, zgłoś raport Q.
                  POP   HL                  Pobierz do DE wskaźnik pierwszego bajtu z 5 pustych
                  EX    DE,HL               w DEF FN.
                  LD    HL,(STKEND)         Ustaw HL na STKEND.
                  LD    BC,+0005            BC będzie zliczało 5 bajtów do przesunięcia.
                  SBC   HL,BC               Najpierw zmniejsz STKEND o 5,
                  LD    (STKEND),HL         usuwając w ten sposób 'ostatnią wartość' ze stosu.
                  LDIR                      Skopiuj te 5 bajtów do pustego miejsca w DEF FN.
                  EX    DE,HL               Ustaw HL na następny kod.
                  DEC   HL                  Upewnij się, że HL wskazuje na znak
                  CALL  28AB,FN-SKPOVR      po tych 5 bajtach.
                  CP    +29                 Czy jest to ')'?
                  JR    Z,2885,SF-R-BR-2    Jeśli tak, skocz: nie ma więcej argumentów w DEF FN.
                  PUSH  HL                  To jest ',': zapamiętaj wskaźnik do tego znaku.
                  RST   0018,GET-CHAR       Pobierz znak za ostatnim argumentem,
                                            który był obliczany z FN.
                  CP    +2C                 Jeśli nie jest to ',' skocz: argumenty
                  JR    NZ,288B,REPORT-Q    FN i  DEF FN nie są zgodne ze sobą.
                  RST   0020,NEXT-CHAR      Ustaw CH-ADD na następny argument w FN.
                  POP   HL                  Ustaw HL ponownie na ',' w DEF FN.
                  CALL  28AB,FN-SKPOVR      Przesuń HL na następny argument w DEF FN.
                  JR    2843,SF-ARG-LP      Skocz wstecz, aby przetworzyć ten argument.
2885 SF-R-BR-2    PUSH  HL                  Zapamiętaj wskaźnik do znaku ')' w DEF FN.
                  RST   0018,GET-CHAR       Pobierz znak za ostatnim argumentem w FN.
                  CP    +29                 Czy jest to ')'?
                  JR    Z,288D,SF-VALUE     Jeśli tak, skocz, aby obliczyć funkcję;
                                            lecz jeśli nie, zgłoś błąd Q.

RAPORT Q - Błąd parametru.

288B REPORT-Q     RST   0008,ERROR-1        Wywołaj procedurę obsługi błędów.
                  DEFB  +19

iv. Na koniec sama funkcja jest obliczana przez wywołanie SCANNING, po wcześniejszym ustawieniu w DEFADD adresu argumentów tak, jak występują one w poleceniu DEF FN. Zagwarantuje to, że procedura LOOK-VARS po wywołaniu z wnętrza SCANNING najpierw przeszuka te argumenty dla potrzebnych wartości przed wykonaniem poszukiwań w obszarze zmiennych.

288D SF-VALUE     POP   DE                  Odtwórz wskaźnik do znaku ')' w DEF FN.
                  EX    DE,HL               Umieść ten wskaźnik w HL.
                  LD    (CH-ADD),HL         Wstaw go w CH-ADD.
                  LD    HL,(DEFADD)         Pobierz starą wartość DEFADD.
                  EX    (SP),HL             Umieść ją na stosie i wstaw do DEFADD adres startowy
                  LD    (DEFADD),HL         obszaru argumentów z DEF FN.
                  PUSH  DE                  Zapamietaj adres znaku ')' w FN.
                  RST   0020,NEXT-CHAR      Przesuń CH-ADD za znaki ')' i
                  RST   0020,NEXT-CHAR      '=' na początek wyrażenia dla funkcji w DEF FN.
                  CALL  24FB,SCANNING       Teraz oblicz tę funkcję.
                  POP   HL                  Odtwórz adres znaku ')' w FN.
                  LD    (CH-ADD),HL         Umieść go w CH-ADD.
                  POP   HL                  Odtwórz pierwotną wartość DEFADD.
                  LD    (DEFADD),HL         Umieść ją z powrotem w DEFADD.
                  RST   0020,NEXT-CHAR      Pobierz następny znak w wierszu programu.
                  JP    2712,S-CONT-2       Skocz wstecz, aby kontynuować przeszukiwanie.

PROCEDURA 'POMINIĘCIA FUNKCJI'

Procedura ta jest wykorzystywana przez FN i STK-F-ARG w celu przesunięcia HL wzdłuż polecenia DEF FN bez niszczenia CH-ADD, ponieważ wskazuje ona na zawartość polecenia FN.

28AB FN-SKPOVR    INC   HL                  Wskaż na następny kod w poleceniu.
                  LD    A,(HL)              Skopiuj ten kod do  A.
                  CP    +21                 Skocz wstecz, aby go ominąć, jeśli jest to
                  JR    C,28AB,FN-SKPOVR    kod sterujący lub spacja.
                  RET                       Skończone.

PROCEDURA 'LOOK-VARS'

Tę procedurę wywołuje się zawsze przy potrzebie przeszukania obszaru zmiennych lub obszaru argumentów polecenia DEF FN. Wejście do procedury następuje ze zmienną systemową CH-ADD wskazującą na pierwszą literę nazwy zmiennej, której położenie jest poszukiwane. Nazwa ta będzie się znajdowała w obszarze programu lub w przestrzeni roboczej. Procedura początkowo tworzy bajt dyskryminatora w rejestrze C, który opiera się na pierwszej literze nazwy zmiennej. Bity 5 i 6 tego bajtu wskazują rodzaj obsługiwanej zmiennej.

Rejestr B jest uzywany jako rejestr bitowy do przechowywania znaczników.

28B2 LOOK-VARS    SET   6,(FLAGS)           Załóż zmienną liczbową.
                  RST   0018,GET-CHAR       Pobierz pierwszy znak do A.
                  CALL  2C8D,ALPHA          Czy jest to litera?
                  JP    NC,1C8A,REPORT-C    Zgłoś błąd, jeśli nie.
                  PUSH  HL                  Zapamiętaj wskaźnik do pierwszej litery.
                  AND   +1F                 Przenieś bity od 0 do 4 litery
                  LD    C,A                 do rejestru C; bity 5 i 7 są zawsze wyzerowane.
                  RST   0020,NEXT-CHAR      Pobierz drugi znak do A.
                  PUSH  HL                  Ten wskaźnik również zapamiętaj.
                  CP    +28                 Czy drugim znakiem jest '('?
                  JR    Z,28EF,V-RUN/SYN    Tablice liczb potraktuj osobno.
                  SET   6,C                 Teraz ustaw bit 6.
                  CP    +24                 Czy drugim znakiem jest '$'?
                  JR    Z,28DE,V-STR-VAR    Wszystkie łańcuchy potraktuj osobno.
                  SET   5,C                 Teraz ustaw bit 5.
                  CALL  2C88,ALPHANUM       Jeśli nazwa zmiennej składa się tylko
                  JR    NC,28E3,V-TEST-FN   z jednej litery, to skocz naprzód.

Teraz znajdź końcowy znak nazwy zbudowanej z więcej niż jednego znaku.

28D4 V-CHAR       CALL  2C88,ALPHANUM       Czy znak jest literą lub cyfrą?
                  JR    NC,28EF,V-RUN/SYN   Wyskocz z pętli po znalezieniu końca nazwy.
                  RES   6,C                 Oznacz bajt dyskryminatora.
                  RST   0020,NEXT-CHAR      Pobierz następny znak.
                  JR    28D4,V-CHAR         Wróć, aby go przetestować.

Proste łańcuchy oraz tablice łańcuchów wymagają wyzerowania bitu 6 zmiennej systemowej FLAGS.

28DE V-STR-VAR    RST   0020,NEXT-CHAR      Ustaw CH-ADD za znakiem '$'.
                  RES   6,(FLAGS)           Zeruj bit 6, aby oznaczyć łańcuch.

Jeśli starszy bajt DEFADD ma wartość różną od zera, co oznacza obliczanie 'funkcji' (FN), oraz jeśli jest czas wykonania programu, to zostanie wykonane przeszukanie argumentów w poleceniu DEF FN.

28E3 V-TEST-FN    LD    A,(DEFADD-hi)       Czy starszy bajt DEFADD wynosi zero?
                  AND   A
                  JR    Z,28EF,V-RUN/SYN    Jeśli tak, skocz naprzód.
                  CALL  2530,SYNTAX-Z       Czy 'czas wykonania'?
                  JP    NZ,2951,STK-F-ARG   Jeśli tak, skocz naprzód, aby przeszukać polecenie DEF FN.

W przeciwnym razie (lub gdy zmienna nie została znaleziona wewnątrz polecenia DEF FN) zostanie wykonane przeszukanie obszaru zmiennych, o ile nie jest właśnie sprawdzana składnia.

28EF V-RUN/SYN    LD    B,C                 Skopiuj bajt dyskryminatora do rejestru B.
                  CALL  2530,SYNTAX-Z       Skocz naprzód przy wykonywaniu programu.
                  JR    NZ,28FD,V-RUN
                  LD    A,C                 Przenieś dyskryminator do A.
                  AND   +E0                 Usuń część związaną ze znakiem.
                  SET   7,A                 Zaznacz sprawdzanie składni przez ustawienie bitu 7.
                  LD    C,A                 Odtwórz dyskryminator.
                  JR    2934,V-SYNTAX       Skocz naprzód, aby kontynuować.

Wiersz języka BASIC jest wykonywany, zatem przeszukaj obszar zmiennych.

28FD V-RUN        LD    HL,(VARS)           Pobierz wskaźnik VARS.

Teraz wejdź do pętli, aby zająć się nazwami istniejących zmiennych.

2900 V-EACH       LD    A,(HL)              Pierwsza litera każdej istniejącej zmiennej.
                  AND   +7F                 Usuń najstarszy bit.
                  JR    Z,2932,V-80-BYTE    Jeśli otrzymasz zero, to osiągnięty został bit znacznika końca.
                  CP    C                   Właściwe porównanie.
                  JR    NZ,292A,V-NEXT      Skocz naprzód, jeśli pierwsze znaki są różne.
                  RLA                       Obróć A w lewo, a następnie podwój je,
                  ADD   A,A                 aby sprawdzić bity 5 i 6.
                  JP    P,293F,V-FOUND-2    Zmienne łańcuchów i tablic łańcuchów.
                  JR    C,293F,V-FOUND-2    Proste zmienne liczbowe oraz zmienne FOR-NEXT.

Długie nazwy należy sprawdzić do końca.

                  POP   DE                  Skopiuj znacznik do drugiego znaku
                  PUSH  DE
                  PUSH  HL                  Zapamiętaj znacznik pierwszej litery.
2912 V-MATCHES    INC   HL                  Przetwórz następny znak.
2913 V-SPACES     LD    A,(DE)              Pobieraj kolejno każdy znak.
                  INC   DE                  Wskaż na następny znak.
                  CP    +20                 Czy znak jest 'spacją'?
                  JR    Z,2913,V-SPACES     Spacje ignoruj.
                  OR    +20                 Ustaw bit 5, aby zrównać duże i małe litery.
                  CP    (HL)                zrób porównanie.
                  JR    Z,2912,V-MATCHES    Jeśli jest zgodność, wróć dla kolejnego znaku.
                  OR    +80                 Czy będzie zgodność z ustawionym bitem 7?
                  CP    (HL)                Sprawdź.
                  JR    NZ,2929,V-GET-PTR   Skocz naprzód, jeśli 'ostatnie znaki' są różne.
                  LD    A,(DE)              Sprawdź, czy osiągnięto koniec nazwy
                  CALL  2C88,ALPHANUM       przed skokiem naprzód.
                  JR    NC,293E,V-FOUND-1

W każdym przypadku, gdy nazwy są różne, para rejestrów HL musi zostać ustawiona na początek nazwy kolejnej zmiennej w obszarze zmiennych.

2929 V-GET-PTR    POP   HL                  Pobierz wskaźnik.
292A V-NEXT       PUSH  BC                  Na krótko zapamiętaj B i C.
                  CALL  19B8,NEXT-ONE       DE zostanie ustawione na adres następnej zmiennej.
                  EX    DE,HL               Zamień ze sobą te dwa wskaźniki.
                  POP   BC                  Odtwórz z powrotem B i C.
                  JR    2900,V-EACH         Wróć ponownie na początek pętli.

Tutaj trafia się, gdy żadna ze zmiennych nie posiadała pożądanej nazwy.

2932 V-80-BYTE    SET   7,B                 Sygnalizuj 'zmienna nieznaleziona'.

Tutaj trafia się przy sprawdzaniu składni.

2934 V-SYNTAX     POP   DE                  Usuń wskaźnik do drugiego znaku.
                  RST   0018,GET-CHAR       Pobierz bieżący znak.
                  CP    +28                 Czy jest to '('?
                  JR    Z,2943,V-PASS       Jeśli tak, skocz naprzód.
                  SET   5,B                 Zaznacz, że nie mamy do czynienia
                  JR    294B,V-END          z tablicą i skocz naprzód.

Tutaj trafia się po znalezieniu właściwej nazwy.

293E V-FOUND-1    POP   DE                  Usuń zapamiętany wskaźnik zmiennej.
293F V-FOUND-2    POP   DE                  Usuń wskaźnik drugiego znaku.
                  POP   DE                  Usuń wskaźnik pierwszej litery.
                  PUSH  HL                  Zapamiętaj wskaźnik 'ostatniej' litery.
                  RST   0018,GET-CHAR       Pobierz bieżący znak.

Jeśli znaleziona nazwa zmiennej składa się z więcej niż jednej litery, to pozostałe znaki należy przeskoczyć.

Uwaga: wygląda na to, że zostało to już zrobione w V-CHAR.

2943 V-PASS       CALL  2C88,ALPHANUM       Czy jest to znak alfanumeryczny?
                  JR    NC,294B,V-END       Skocz, jeśli znaleziono koniec nazwy.
                  RST   0020,NEXT-CHAR      Pobierz następny znak.
                  JR    2943,V-PASS         Wróć i sprawdź go.

Teraz są ustawiane parametry wyjściowe.

294B V-END        POP   HL                  HL zawiera wskaźnik litery krótkiej nazwy
                                            lub 'ostatniego' znaku nazwy długiej.
                  RL    B                   Obróć cały rejestr.
                  BIT   6,B                 Określ stan bitu 6.
                  RET                       Skończone.

Parametry wyjściowe tej procedury można podsumować następująco: Zmienna systemowa CH-ADD wskazuje na pierwszą komórkę za nazwą zmiennej, jak występuje w wierszu języka BASIC.

Gdy 'zmienna nie została znaleziona':

i. Znacznik przeniesienia jest ustawiony.
ii. Znacznik zera jest ustawiony tylko przy poszukiwaniu zmiennej tablicowej.
iii. Para rejestrów HL wskazuje na pierwszy znak nazwy zmiennej, jak występuje w wierszu języka BASIC.

Gdy 'zmienna została znaleziona':

i. Znacznik przeniesienia jest wyzerowany.
ii. Znacznik zera jest ustawiony zarówno dla zmiennych łańcuchowych jak i wszystkich zmiennych tablicowych.
iii. Para rejestrów HL wskazuje na literę 'krótkiej' nazwy lub na ostatnią literę 'długiej' nazwy zmiennej znalezionej w obszarze zmiennych.

We wszystkich przypadkach bity 5 i 6 rejestru C wskazują rodzaj przetwarzanej zmiennej. Bit 7 jest zaprzeczeniem znacznika SYNTAX/RUN. Lecz jedynie przy korzystaniu z tej procedury w czasie wykonania programu bity od 0 do 4 będą zawierały kod pierwszej litery nazwy zmiennej.

W czasie sprawdzania składni powrót zawsze następuje z wyzerowanym znacznikiem przeniesienia. Znacznik zera jest ustawiony dla tablic, a wyzerowany dla wszystkich innych zmiennych, z wyjątkiem tego, że nazwa prostej zmiennej łańcuchowej niepoprawnie zakończona znakiem '$' ustawia znacznik zera, w tym przypadku SAVE "nazwa" DATA a$() również przechodzi etap sprawdzania składni.

PROCEDURA 'UMIESZCZANIA NA STOSIE ARGUMENTU FUNKCJI'

Procedura ta jest wywoływana przez LOOK-VARS przy DEFADD-hi różnym od zera w celu przeszukania obszaru argumentów polecenia DEF FN przed przeszukaniem obszaru zmiennych. Jeśli dana zmienna zostanie znaleziona w poleceniu DEF FN, to parametry zmiennej łańcuchowej są umieszczane na stosie i sygnalizowany jest brak konieczności wywołania STK/VAR. Lecz umieszczanie na stosie wartości zmiennych liczbowych jest pozostawianie procedurze SCANNING pod adresem 26DA w sposób standardowy.

2951 STK-F-ARG    LD    HL,(DEFADD)         Wskaż pierwszy znak w obszarze
                  LD    A,(HL)              argumentów i umieść go w A.
                  CP    +29                 Czy jest to ')'?
                  JP    Z,28EF,V-RUN/SYN    Skocz, aby przeszukać obszar zmiennych.
295A SFA-LOOP     LD    A,(HL)              W pętli pobieraj kolejny argument.
                  OR    +60                 Ustaw bity 5 i 6, zakładając prostą
                  LD    B,A                 zmienną liczbową; skopiuj ją do B.
                  INC   HL                  Wskaż następny kod.
                  LD    A,(HL)              Umieść go w rejestrze A. Czy jest to
                  CP    +0E                 kod 0E szesnastkowo 'znacznika liczby'?
                  JR    Z,296B,SFA-CP-VR    Jeśli tak, to skocz: zmienna liczbowa.
                  DEC   HL                  Upewnij się, że HL wskazuje znak, a nie
                  CALL  28AB,FN-SKPOVR      spację lub kod sterujący.
                  INC   HL                  Teraz HL wskazuje na 'znacznik liczby'.
                  RES   5,B                 Wyzeruj bit 5 rejestru B: zmienna łańcuchowa.
296B SFA-CP-VR    LD    A,B                 Pobierz nazwę zmiennej do A.
                  CP    C                   Czy jest to ta poszukiwana?
                  JR    Z,2981,SFA-MATCH    Skocz przy zgodności.
                  INC   HL                  Teraz pomiń 5 bajtów
                  INC   HL                  liczby zmiennoprzecinkowej lub
                  INC   HL                  parametrów łańcucha, aby przejść
                  INC   HL                  do następnego argumentu.
                  INC   HL
                  CALL  28AB,FN-SKPOVR      Przejdź do następnego znaku.
                  CP    +29                 Czy jest to ')'?
                  JP    Z,28EF,V-RUN/SYN    Jeśli tak, skocz, aby przeszukać obszar zmiennych.
                  CALL  28AB,FN-SKPOVR      Wskaż następny argument.
                  JR    295A,SFA-LOOP       Skocz wstecz, aby go rozważyć.

Znaleziono zgodność. Parametry zmiennej łańcuchowej zostają umieszczone na stosie, unikając potrzeby wywołania procedury STK-VAR.

2981 SFA-MATCH    BIT   5,C                 Sprawdź, czy zmienna jest liczbowa.
                  JR    NZ,2991,SFA-END     Skocz, jeśli tak; SCANNING umieści ją na stosie.
                  INC   HL                  Wskaż pierwszy z pięciu bajtów do umieszczenia na stosie.
                  LD    DE,(STKEND)         Wskaż DE na STKEND.
                  CALL  33C0,MOVE-FP        Umieść na stosie 5 bajtów.
                  EX    DE,HL               Wskaż HL na nową pozycję STKEND
                  LD    (STKEND),HL         i uaktualnij zmienną systemową.
2991 SFA-END      POP   DE                  Pozbądź się wskaźników LOOK-VARS
                  POP   DE                  (wskaźniki pierwszego i drugiego znaku).
                  XOR   A                   Powróć z poszukiwania z wyzerowanymi oboma
                  INC   A                   znacznikami przeniesienia i zera – sygnalizując, że
                                            wywołanie STK-VAR nie jest wymagane.
                  RET                       Skończone.

PROCEDURA 'STK-VAR'

Procedura ta jest zwykle używana albo do znalezienia parametrów definiujących istniejącą zmienną w obszarze zmiennych, albo do zwrócenia w parze rejestrów HL adresu bazowego określonego elementu lub ciągu liczb. Gdy zostanie wywołana z DIM, to procedura sprawdza jedynie składnię polecenia języka BASIC.

Zwróć uwagę, że parametry definiujące pewien łańcuch mogą zostać zmienione przez wywołanie procedury SLICING.

Początkowo rejestry A i B zostają wyzerowane, a bit 7 rejestru C jest sprawdzany w celu określenia, czy jest sprawdzana składnia.

2996 STK-VAR      XOR   A                   Wyzeruj znacznik ciągu.
                  LD    B,A                 Wyzeruj rejestr B na później.
                  BIT   7,C                 Skocz naprzód, jeśli właśnie jest
                  JR    NZ,29E7,SV-COUNT    sprawdzana składnia.

Następnie proste łańcuchy są oddzielane od zmiennych tablicowych.

                  BIT   7,(HL)              Skocz naprzód, jeśli mamy do czynienia
                  JR    NZ,29AE,SV-ARRAYS   z jakąś zmienną tablicową.

Znajdowane są gotowe parametry prostego łańcucha.

                  INC   A                   Sygnalizuj 'prosty łańcuch'.
29A1 SV-SIMPLE$   INC   HL                  Przesuń się wzdłuż elementu.
                  LD    C,(HL)              Pobierz młodszy bajt licznika długości.
                  INC   HL                  Przesuń do przodu wskaźnik.
                  LD    B,(HL)              Pobierz starszy bajt licznika długości.
                  INC   HL                  Przesuń wskaźnik.
                  EX    DE,HL               Przekaż wskaźnik do właściwego łańcucha.
                  CALL  2AB2,STK-STORE      Przekaż te parametry na stos kalkulatora.
                  RST   0018,GET-CHAR       Pobierz bieżący znak i skocz naprzód, aby
                  JP    2A49,SV-SLICE?      sprawdzić, czy jest potrzebne dzielenie łańcucha.

Teraz zostaje znaleziony adres bazowy elementu w ciągu. Początkowo pobrana zostaje 'liczba wymiarów'.

29AE SV-ARRAYS    INC   HL                  Przejdź poza bajty długości.
                  INC   HL
                  INC   HL
                  LD    B,(HL)              Zbierz 'liczbę wymiarów'.
                  BIT   6,C                 Skocz naprzód, jeśli obsługujemy
                  JR    Z,29C0,SV-PTR       ciąg liczb.

Jeśli ciąg łańcuchów posiada swoją 'liczbę wymiarów' równą '1', to taki ciąg można obsłużyć jak prosty łańcuch.

                  DEC   B                   Zmniejsz 'liczbę wymiarów'
                  JR    Z,29A1,SV-SIMPLE$   i skocz, jeśli jest teraz równa zero.

Teraz sprawdza się, czy faktycznie w wierszu języka BASIC po tej zmiennej występuje indeks.

                  EX    DE,HL               Zapamiętaj wskaźnik w DE.
                  RST   0018,GET-CHAR       Pobierz obecny znak.
                  CP    +28                 Czy jest to '('?
                  JR    NZ,2A20,REPORT-3    Jeśli nie, zgłoś błąd.
                  EX    DE,HL               Odtwórz wskaźnik.

Zarówno dla ciągów liczbowych jak i dla ciągów łańcuchów wskaźnik zmiennej jest przekazywany do pary rejestrów DE przed wyliczeniem indeksu.

29C0 SV-PTR       EX    DE,HL               Przekaż wskaźnik do DE.
                  JR    29E7,SV-COUNT       Skocz naprzód.

Poniższa pętla jest używana do znalezienia parametrów określonego elementu wewnątrz ciągu. Wejście do pętli następuje w punkcie środkowym - SV-COUNT -, gdzie licznik elementów jest ustawiany na zero.
Pętla jest używana 'B' razy, co dla ciągu liczbowego odpowiada liczbie używanych wymiarów, lecz dla ciągu łańcuchów 'B' ma wartość o jeden mniejszą od liczby używanych wymiarów, ponieważ ostatni indeks jest wykorzystywany do określenia podziału łańcucha.

29C3 SV-COMMA     PUSH  HL                  Zapamiętaj licznik.
                  RST   0018,GET-CHAR       Pobierz obecny znak.
                  POP   HL                  Odtwórz znak.
                  CP    +2C                 Czy bieżący znak to','?
                  JR    Z,29EA,SV-LOOP      Jeśli tak, to skocz naprzód, aby przetworzyć kolejny indeks.
                  BIT   7,C                 Jeśli wiersz jest wykonywany,
                  JR    Z,2A20,REPORT-3     to powstaje błąd.
                  BIT   6,C                 Skocz naprzód, jeśli mamy do czynienia
                  JR    NZ,29D8,SV-CLOSE    z ciągiem łańcuchów.
                  CP    +29                 Czy bieżący znak to ')'?
                  JR    NZ,2A12,SV-RPT-C    Jeśli nie, zgłoś błąd.
                  RST   0020,NEXT-CHAR      Zwiększ CH-ADD.
                  RET                       Wróć, skoro składnia jest poprawna.

Dla ciągu łańcuchów obecny indeks może przedstawiać 'podział' albo indeks z 'podziałem' może wciąż występować w wierszu języka BASIC.

29D8 SV-CLOSE     CP    +29                 Czy obecny znak to ')'?
                  JR    Z,2A48,SV-DIM       Skocz naprzód i sprawdź, czy jest kolejny indeks.
                  CP    +CC                 Czy obecny znak to 'TO'?
                  JR    NZ,2A12,SV-RPT-C    Nie powinno być inaczej.
29E0 SV-CH-ADD    RST   0018,GET-CHAR       Pobierz obecny znak.
                  DEC   HL                  Wskaż na poprzedzający znak
                  LD    (CH-ADD),HL         i ustaw CH-ADD.
                  JR    2A45,SV-SLICE       Oblicz ten 'podział'.

Tutaj jest wejście do pętli.

29E7 SV-COUNT     LD    HL,+0000            Wyzeruj licznik.
29EA SV-LOOP      PUSH  HL                  Zapamiętaj na krótko licznik.
                  RST   0020,NEXT-CHAR      Zwiększ CH-ADD.
                  POP   HL                  Odtwórz licznik.
                  LD    A,C                 Pobierz bajt dyskryminatora.
                  CP    +C0                 Skocz o ile nie jest sprawdzana
                  JR    NZ,29FB,SV-MULT     składnia ciągu łańcuchów.
                  RST   0018,GET-CHAR       Pobierz obecny znak.
                  CP    +29                 Czy jest to ')'?
                  JR    Z,2A48,SV-DIM       Skocz naprzód, skoro zliczanie elementów jest skończone.
                  CP    +CC                 Czy jest to 'TO'?
                  JR    Z,29E0,SV-CH-ADD    Skocz wstecz, jeśli mamy do czynienia z 'podziałem'.
29FB SV-MULT      PUSH  BC                  Zachowaj licznik liczby wymiarów oraz bajt dyskryminatora.
                  PUSH  HL                  Zachowaj licznik elementów.
                  CALL  2AEE,DE,(DE+1)      Pobierz rozmiar wymiaru do DE.
                  EX    (SP),HL             Licznik idzie do HL, a wskaźnik zmiennej na stos.
                  EX    DE,HL               Licznik idzie do DE a rozmiar wymiaru do HL.
                  CALL  2ACC,INT-EXP1       Oblicz następny indeks.
                  JR    C,2A20,REPORT-3     Jeśli poza zakresem, zgłoś błąd.
                  DEC   BC                  Wynik obliczenia jest zmniejszany o 1, ponieważ
                                            licznik ma zliczać elementy występujące przed
                                            określonym elementem.
                  CALL  2AF4,GET-HL*DE      Pomnóż licznik przez rozmiar wymiaru.
                  ADD   HL,BC               Dodaj wynik 'INT-EXP1' do obecnego licznika.
                  POP   DE                  Pobierz wskaźnik zmiennej.
                  POP   BC                  Pobierz liczbę wymiarów oraz bajt dyskryminatora.
                  DJNZ  29C3,SV-COMMA       Wykonuj pętlę aż do wyzerowania rejestru 'B'.

Znacznik składnia/uruchomienie jest sprawdzany przed rozdzieleniem ciągów łańcuchów od ciągów liczb.

                  BIT   7,C                 Jeśli jest sprawdzana składnia, to w tym miejscu
2A12 SV-RPT-C     JR    NZ,2A7A,SL-RPT-C    zgłoś błąd.
                  PUSH  HL                  Zachowaj licznik.
                  BIT    6,C                Skocz naprzód, jeśli mamy do czynienia
                  JR    NZ,2A2C,SV-ELEM$    z ciągiem łańcuchów.

Jeśli mamy do czynienia z ciagiem liczb, to bieżącym znakiem musi być ')'.

                  LD    B,D                 Przenieś wskaźnik zmiennej
                  LD    C,E                 pary rejestrów BC.
                  RST   0018,GET-CHAR       Pobierz bieżący znak.
                  CP    +29                 Czy jest to ')'?
                  JR    Z,2A22,SV-NUMBER    Przeskocz zgłoszenie błędu, chyba że jest potrzebne.

Raport 3 - Indeks poza zakresem

2A20 REPORT-3     RST   0008,ERROR-1        Wywołaj procedurę obsługi błędów.
                  DEFB  +02

Teraz może zostać obliczony adres przed właściwą postacią zmiennoprzecinkową.

2A22 SV-NUMBER    RST   0020,NEXT-CHAR      Zwiększ CH-ADD.
                  POP   HL                  Pobierz licznik.
                  LD    DE,+0005            Każdy element ciagu liczbowego ma 5 bajtów.
                  CALL  2AF4,GET-HL*DE      Oblicz całkowitą liczbę bajtów przed wymaganym elementem.
                  ADD   HL,BC               Ustaw HL na wskazywanie miejsca przed elementem.
                  RET                       Wróć z tym adresem.

Gdy mamy do czynienia z ciągiem łańcuchów, to długość elementu jest podana jako ostatni 'rozmiar wymiaru'. Odpowiednie parametry są obliczane i umieszczane na stosie kalkulatora.

2A2C SV-ELEM$     CALL  2AEE,DE,(DE+1)      Pobierz rozmiar ostatniego wymiaru.
                  EX    (SP),HL             Wskaźnik zmiennej idzie na stos, a licznik do HL.
                  CALL  2AF4,GET-HL*DE      Pomnóż 'licznik' przez 'rozmiar wymiaru'.
                  POP   BC                  Pobierz wskaźnik zmiennej.
                  ADD   HL,BC               To spowoduje, że HL wskaże komórkę przed łańcuchem.
                  INC   HL                  Ustaw HL na faktyczny 'początek'.
                  LD    B,D                 Przekaż ostatni rozmiar wymiaru do BD
                  LD    C,E                 aby utworzyć 'długość'.
                  EX    DE,HL               Przenieś 'początek' do DE.
                  CALL  2AB1,STK-ST-0       Przekaż te parametry na stos kalkulatora.
                                            Uwaga: pierwszy parametr ma wartość zero oznaczającą,
                                            łańcuch z 'ciągu łańcuchów', a stąd istniejący element
                                            nie będzie zwracany do puli pamięci systemu.

Istnieją trzy możliwe postacie ostatniego indeksu. Pierwsza to - A$(2,4 TO 8) -, druga - A$(2)(4 TO 8) - i trzecia - A$(2) - co jest standardową postacią i oznacza, że wymagany jest cały łańcuch.

                  RST   0018,GET-CHAR       Pobierz obecny znak.
                  CP    +29                 Czy jest to ')'?
                  JR    Z,2A48,SV-DIM       Skocz, jeśli tak jest.
                  CP    +2C                 Czy jest to ','?
                  JR    NZ,2A20,REPORT-3    Zgłoś błąd, jeśli tak nie jest.
2A45 SV-SLICE     CALL  2A52,SLICING        Użyj SLICING do zmiany zestawu parametrów.
2A48 SV-DIM       RST   0020,NEXT-CHAR      Pobierz następny znak..
2A49 SV-SLICE?    CP    +28                 Czy to '('?
                  JR    Z,2A45,SV-SLICE     Skocz wstecz, jeśli jest 'podział' do obsłużenia.

Po obsłużeniu ostatniego indeksu można wykonać powrót.

                  RES   6,(FLAGS)           Sygnalizuj - wynik łańcuchowy.
                  RET                       Wróć z parametrami łańcucha jako 'ostatnia wartość'
                                            na stosie kalkulatora.

PROCEDURA 'SLICING'

Łańcuch znakowy może być poddawany podziałowi za pomocą tej procedury. Wejście następuje z parametrami łańcucha obecnymi na szczycie stosu kalkulatora oraz w rejestrach A, B, C, D i E. Na początku testowany jest znacznik składnia/uruchomienie, a parametry łańcucha są pobierane tylko w czasie wykonywania się programu.

2A52 SLICING      CALL  2530,SYNTAX-Z       Sprawdź znacznik.
                  CALL  NZ,2BF1,STK-FETCH   W 'czasie wykonania' pobierz parametry ze stosu.

Sprawdza się możliwość wystąpienia pustego podziału '()'.

                  RST   0020,NEXT-CHAR      Pobierz następny znak.
                  CP    +29                 Czy jest to ')'?
                  JR    Z,2AAD,SL-STORE     Skocz naprzód, jeśli tak jest.

Przed rozpoczęciem operacji w rejestrach są umieszczane następujące dane:

                  PUSH  DE                  'początek' idzie na stos maszynowy.
                  XOR   A                   Rejestr A zostaje wyzerowany i zapamiętany.
                  PUSH  AF
                  PUSH  BC                  Chwilowo zapamiętana zostaje 'długość'.
                  LD    DE,+0001            Zakładamy, że 'podział' rozpocznie się od pierwszego znaku.
                  RST   0018,GET-CHAR       Pobierz ten pierwszy znak.
                  POP   HL                  Przekaż 'długość' do HL.

Teraz zostaje wyliczony pierwszy parametr podziału.

                  CP    +CC                 Czy obecny znak to 'TO'?
                  JR    Z,2A81,SL-SECOND    Jeśli zostanie wykonany skok, to pierwszy parametr
                                            standardowo przyjmie wartość  '1'.
                  POP   AF                  Na tym etapie A ma wartość zero.
                  CALL  2ACD,INT-EXP2       Pierwszy parametr trafi do BC. Jeśli wystąpił błąd
                                            wyjścia poza zakres, to A będzie zawierać +FF.
                  PUSH  AF                  W każdym wypadku zachowujemy tę wartość.
                  LD    D,B                 Przenieś pierwszy parametr do DE.
                  LD    E,C
                  PUSH  HL                  Chwilowo zapamiętaj 'długość'.
                  RST   0018,GET-CHAR       Pobierz obecny znak.
                  POP   HL                  Odtwórz 'długość'.
                  CP    +CC                 Czy bieżącym znakiem jest 'TO'?
                  JR    Z,2A81,SL-SECOND    Jeśli tak, to skocz naprzód, aby obsłużyć
                                            drugi parametr;
                  CP +29                    inaczej upewnij się, że istnieje nawias
2A7A SL-RPT-C     JP    NZ,1C8A,REPORT-C    zamykający.

W tym miejscu został zidentyfikowany podział dotyczący pojedynczego znaku łańcucha, np. – A$(4).

                  LD    H,D                 Ostatni znak 'podziału' jest
                  LD    L,E                 również pierwszym znakiem.
                  JR    2A94,SL-DEFINE      Skocz naprzód.

Tutaj zostaje wyznaczony drugi parametr 'podziału'.

2A81 SL-SECOND    PUSH  HL                  Chwilowo zapamiętaj 'długość'.
                  RST   0020,NEXT-CHAR      Pobierz następny znak.
                  POP   HL                  Odtwórz 'długość'.
                  CP    +29                 Czy obecny znak to ')'?
                  JR    Z,2A94,SL-DEFINE    Skocz, jeśli brak drugiego parametru.
                  POP   AF                  jeśli pierwszy parametr był w zakresie,
                                            rejestr A będzie zawierał zero; inaczej +FF.
                  CALL  2ACD,INT-EXP2       Wstaw drugi parametr do BC.
                  PUSH  AF                  Zapamiętaj 'rejestr błędu'.
                  RST   0018,GET-CHAR       Pobierz obecny znak.
                  LD    H,B                 Przekaż wynik otrzymany w
                  LD    L,C                 INT-EXP2 do pary rejestrów HL.
                  CP    +29                 Sprawdź, czy teraz jest nawias zamykający.
                  JR    NZ,2A7A,SL-RPT-C

Teraz 'nowe' parametry są zdefiniowane.

2A94 SL-DEFINE    POP   AF                  Pobierz 'rejestr błędu'.
                  EX    (SP),HL             Drugi parametr idzie na stos, a 'początek do HL.
                  ADD   HL,DE               Pierwszy parametr jest dodawany do 'początku'.
                  DEC   HL                  Cofnij się o komórkę, aby otrzymać poprawny adres.
                  EX    (SP),HL             'Nowy początek' idzie na stos, a drugi parametr do HL.
                  AND   A                   Odejmij pierwszy parametr od drugiego, aby otrzymać
                  SBC   HL,DE               długość fragmentu łańcucha.
                  LD    BC,+0000            Ustaw 'nową długość'.
                  JR    C,2AA8,SL-OVER      Ujemny 'podział' daje pusty łańcuch.
                  INC   HL                  Zezwól na dodatkowy bajt.
                  AND   A                   Tylko teraz testuj 'rejestr błędu'.
                  JP    M,2A20,REPORT-3     Skocz, jeśli dowolny z parametrów był poza zakresem dla łańcucha.
                  LD    B,H                 Prześlij 'nową długość' do BC.
                  LD    C,L
2AA8 SL-OVER      POP   DE                  Pobierz 'nowy start'.
                  RES   6,(FLAGS)           Upewnij się, że łańcuch jest wciąż oznaczony.
2AAD SL-STORE     CALL  2530,SYNTAX-Z       Wróć w tym punkcie, jeśli sprawdzana jest składnia;
                  RET   Z                   inaczej przejdź do procedury STK-STORE.

PROCEDURA 'STK-STORE'

Ta procedura umieszcza wartości przechowywane w rejestrach A, B, C, D i E na stos kalkulatora. Dlatego stos ten rośnie o 5 bajtów przy każdym wywołaniu tej procedury.

Procedura jest zwykle wykorzystywana do przekazywania parametrów łańcuchów, lecz używają jej również procedury STACK-BC i LOG (2^A) do przesyłania 'małych liczb całkowitych' na stos.

Zwróć uwagę, że przy zapisywaniu parametrów łańcucha pierwszą zapamiętaną wartością (pochodzącą z rejestru A) będzie zero, jeśli łańcuch pochodzi z tablicy łańcuchów lub jest łańcuchem poddanym 'podziałowi'. Wartość ta będzie równa 1 przy kompletnym łańcuchu. 'Znacznik' ten jest używany w procedurze rozkazu 'LET', gdzie '1' sygnalizuje potrzebę usunięcia z pamięci starej kopii łańcucha.

2AB1 STK-ST-0     XOR   A                   Sygnalizuj - łańcuch z tablicy lub łańcuch 'podzielony'.
2AB2 STK-STO-$    RES   6,(FLAGS)           Upewnij się, że znacznik oznacza wynik łańcuchowy.
2AB6 STK-STORE    PUSH  BC                  Zapamiętaj na krótko B i C.
                  CALL  33A9,TEST-5-SP      Czy jest miejsce na 5 bajtów?
                                            Nie wracaj, jeśli brak miejsca.
                  POP   BC                  Odtwórz B i C.
                  LD    HL,(STKEND)         Pobierz adres pierwszej komórki ponad obecnym stosem.
                  LD    (HL),A              Prześlij pierwszy bajt.
                  INC   HL                  Przejdź dalej.
                  LD    (HL),E              Prześlij drugi i trzeci bajt;
                  INC   HL                  dla łańcucha będzie to jego 'początek'.
                  LD    (HL),D
                  INC   HL                  Przejdź dalej.
                  LD    (HL),C              Prześlij czwarty i piaty bajt;
                  INC   HL                  dla łańcucha będzie to jego 'długość'.
                  LD    (HL),B
                  INC   HL                  Przejdź dalej, aby wskazać komórkę ponad stosem.
                  LD    (STKEND),HL         Adres ten zapamiętaj w STKEND
                  RET                       i powróć.

PROCEDURA 'INT-EXP'

Ta procedura zwraca wynik obliczenia 'następnego wyrażenia' jako wartości całkowitej przechowywanej przez parę rejestrów BC.  Procedura również sprawdza, czy wynik ten nie przekroczył wartości granicznej dostarczonej w parze rejestrów HL. Znacznik przeniesienia jest ustawiany, jeśli jest błąd 'przekroczenia zakresu'.

Rejestr A jest używany jako 'rejestr błędu' i przechowuje +00, jeśli nie ma 'poprzedniego błędu' lub +FF, jeśli taki błąd wystąpił.

2ACC INT-EXP1     XOR   A                   Wyzeruj 'rejestr błędu'.
2ACD INT-EXP2     PUSH  DE                  Zapamiętaj pary rejestrów DE i HL
                  PUSH  HL                  na czas wykonywania procedury.
                  PUSH  AF                  Zapamiętaj tymczasowo 'rejestr błędu'.
                  CALL  1C82,EXPT-1NUM      'Następne wyrażenie' zostaje obliczone w celu utworzenia
                                            'ostatniej wartości' na stosie kalkulatora.
                  POP   AF                  Odtwórz 'rejestr błędu'.
                  CALL  2530,SYNTAX-Z       Skocz naprzód przy sprawdzaniu składni.
                  JR    Z,2AEB,I-RESTORE
                  PUSH  AF                  Ponownie zapamiętaj 'rejestr błędu'.
                  CALL  1E99,FIND-INT2      'Ostatnia wartość' jest kompresowana do BC.
                  POP   DE                  Rejestr błędu do D.
                  LD    A,B                 'Następne wyrażenie' o wartości zero
                  OR    C                   jest zawsze w zakresie, zatem skocz do przodu,
                  SCF                       jeśli tak jest.
                  JR    Z,2AE8,I-CARRY
                  POP   HL                  Pobierz kopię wartości granicznej.
                  PUSH  HL                  Będzie to 'rozmiar wymiaru', 'granica DIM'
                                            lub 'długość łańcucha'.
                  AND   A                   Teraz porównaj wynik obliczenia wyrażenia
                  SBC   HL,BC               z wartością graniczną.

Stan znacznika przeniesienia oraz wartość przechowywana w rejestrze D są teraz przetwarzane, aby otrzymać odpowiednią wartość dla 'rejestru błędu'.

2AE8 I-CARRY      LD    A,D                 Pobierz 'starą wartość błędu'.
                  SBC   A,+00               Utwórz 'nową wartość błędu';
                                            +00, jeśli nie było wcześniej błędu
                                            +FF lub mniej, jeśli w tym lub poprzednim
                                            przebiegu pojawił się błąd przekroczenia zakresu.

Przed powrotem odtwórz rejestry.

2AEB I-RESTORE    POP   HL                  Odtwórz HL i DE.
                  POP   DE
                  RET                       Wróć, 'rejestr błędu' w A.

PROCEDURA 'DE,(DE+1)'

Procedura wykonuje operację – LD DE,(DE+1) – i zwraca HL wskazujące na 'DE+2'.

2AEE DE,(DE+1)    EX    DE,HL               Użyj HL do operacji.
                  INC   HL                  Wskaż na 'DE+1'.
                  LD    E,(HL)              W wyniku - LD E,(DE+1).
                  INC   HL                  Wskaż na 'DE+2'.
                  LD    D,(HL)              W wyniku - LD D,(DE+2).
                  RET                       Skończone.

PROCEDURA 'GET-HL*DE'

O ile nie jest sprawdzana składnia, procedura wywołuje podprogram 'HL=HL*DE', który wykonuje wymagane mnożenie.

Nadmiar poza 16 bitów dostępnych w parze rejestrów HL daje raport błędu 'brak pamięci'. Nie jest to dokładnie ta sytuacja, lecz implikuje ona, że pamięć jest zbyt mała do przeprowadzenia zadania zamierzonego przez programistę.

2AF4 GET-HL*DE    CALL  2530,SYNTAX-Z       Jeśli jest sprawdzana składnia,
                  RET   Z                   wróć bezpośrednio.
                  CALL  30A9,HL=HL*DE       Wykonaj mnożenie.
                  JP    C,1F15,REPORT-4     Raport 'brak pamięci'.
                  RET                       Skończone.

PROCEDURA ROZKAZU 'LET'

Jest to rzeczywista procedura przypisująca dla rozkazów LET, READ i INPUT.

Jeśli docelowa zmienna jest 'nowo zadeklarowaną zmienną', to DEST będzie wskazywało pierwszą literę jej nazwy w wierszu języka BASIC. Bit 1 zmiennej systemowej FLAGX zostanie ustawiony na 1.

Jednakże, jeśli zmienna docelowa 'już istnieje', to bit 1 FLAGX zostanie wyzerowany, a DEST będzie wskazywało pozycję przed pięcioma bajtami 'starej wartości', a dla zmiennej łańcuchowej będzie wskazywało na pierwszy znak 'starego łańcucha'. Używanie DEST w ten sposób odnosi się do prostych zmiennych oraz do elementów tablic.

Bit 0 FLAGX jest ustawiany, jeśli docelowa zmienna jest 'pełną' zmienną łańcuchową (sygnalizując potrzebę usunięcia starej kopii).

Początkowo pobrana zostaje bieżąca wartość DEST i testowany jest bit 1 zmiennej systemowej FLAGS.

2AFF LET          LD    HL,(DEST)           Pobierz bieżący adres w DEST.
                  BIT   1,(FLAGX)           Skocz, jeśli jest obsługiwana
                  JR    Z,2B66,L-EXISTS     'istniejąca już zmienna'.

Jest używana 'nowo zadeklarowana zmienna'. Zatem najpierw zostaje znaleziona długość jej nazwy.

                  LD    BC,+0005            Załóż zmienną liczbową - 5 bajtów.

Wejdź do pętli zajmującej się znakami długiej nazwy. Spacje oraz kody kolorów w nazwie są ignorowane.

2B0B L-EACH-CH    INC   BC                  Dodaj '1' do licznika przy każdym znaku nazwy.
2B0C L-NO-SP      INC   HL                  Idź wzdłuż nazwy zmiennej.
                  LD    A,(HL)              Pobierz 'obecny kod'.
                  CP    +20                 Skocz wstecz, jeśli jest nim 'spacja';
                  JR    Z,2B0C,L-NO-SP      co w efekcie spowoduje jej zignorowanie.
                  JR    NC,2B1F,L-TEST-CH   Skocz naprzód, jeśli kod jest w zakresie od +21 do +FF.
                  CP    +10                 Zaakceptuj jako końcowy kod kody
                  JR    C,2B29,L-SPACES     w zakresie od +00 do +0F.
                  CP    +16                 Również zaakceptuj zakres
                  JR    NC,2B29,L-SPACES    od +16 do +1F.
                  INC   HL                  Przejdź poza kod sterujący po kodach od INK do OVER.
                  JR    2B0C,L-NO-SP        Skocz wstecz, ponieważ kody te są traktowane jak spacje.

Rozdziel nazwy zmiennych 'liczbowych' od 'łańcuchowych'.

2B1F L-TEST-CH    CALL  2C88,ALPHANUM       Czy kod jest alfanumeryczny?
                  JR    C,2B0B,L-EACH-CH    Jeśli tak, to zaakceptuj go jako znak 'długiej nazwy'.
                  CP    +24                 Czy obecny kod to '$'?
                  JP    Z,2BC0,L-NEWS       Skocz naprzód przy obsłudze 'nowo zadeklarowanego'
                                            prostego łańcucha.

'Nowo zadeklarowana zmienna liczbowa' obecnie obsługiwana będzie wymagała 'BC bajtów' w obszarze zmiennych na swoją nazwę oraz wartość. Tworzone jest to miejsce i nazwa zmiennej zostaje skopiowana wraz ze znakami 'oznaczanymi' jako wymagane.

2B29 L-SPACES     LD    A,C                 Skopiuj 'długość' do A.
                  LD    HL,(E-LlNE)         Ustaw HL na adres 'bajtu 80' na końcu obszaru zmiennych.
                  CALL  1655,MAKE-ROOM      Teraz zrób miejsce w obszarze zmiennych.
                                            Uwaga: 'BC' bajtów zostaje udostępnionych
                                            przed przesuniętym 'bajtem 80'.
                  INC   HL                  Wskaż pierwszy z 'nowych' bajtów.
                  INC   HL                  DE ustaw na drugi z 'nowych bajtów.
                  EX    DE,HL
                  PUSH  DE                  Zapamiętaj ten wskaźnik.
                  LD    HL,(DEST)           Pobierz wskaźnik początku nazwy.
                  DEC   DE                  Ustaw DE na adres pierwszego 'nowego' bajtu.
                  SUB   +06                 Ustaw w B 'liczbę dodatkowych znaków', które
                  LD    B,A                 znajdują się w 'długiej nazwie'.
                  JR    Z,2B4F,L-SINGLE     Skocz naprzód przy zmiennej o 'krótkiej nazwie'.

'Dodatkowe' znaki długiej nazwy są przekazywane do obszaru zmiennych.

2B3E L-CHAR       INC   HL                  Wskaż każdy z 'dodatkowych' znaków.
                  LD    A,(HL)              Pobierz znak.
                  CP    +21                 Akceptuj kody od +21 do +FF;
                  JR    C,2B3E,L-CHAR       ignoruj kody od +00 do +20.
                  OR    +20                 Ustaw bit 5 dla małych liter.
                  INC   DE                  Umieszczaj po kolei te kody
                  LD    (DE),A              od drugiego 'nowego' bajtu dalej.
                  DJNZ  2B3E,L-CHAR         Wróć na początek pętli, aby przesłać wszystkie
                                            'dodatkowe' kody.

Ostatni znak 'długiej' nazwy musi być poddany operacji LUB z +80.

                  OR    +80                 Oznacz ten kod jako wymagany
                  LD    (DE),A              i nadpisz ostatni kod.

Teraz zostanie obsłużona pierwsza litera nazwy zmiennej.

                  LD    A,+C0               Przygotuj się do oznaczenia znaku 'długiej' nazwy.
2B4F L-SINGLE     LD    HL,(DEST)           Pobierz wskaźnik znaku.
                  XOR   (HL)                A zawiera +00 dla nazwy 'krótkiej' lub +C0 dla 'długiej'.
                  OR    +20                 Ustaw bit 5 dla małych liter.
                  POP   HL                  Teraz usuń wskaźnik.

Podprogram L-FIRST jest teraz wywoływany, aby wprowadzić tę 'literę' na jej właściwe miejsce.

                  CALL  2BEA,L-FIRST        Wstaw literę i wróć z HL wskazującym 'nowy bajt 80'.

Teraz 'ostatnia wartość' może zostać przeniesiona do obszaru zmiennych. Zwróć uwagę, że w tym miejscu HL zawsze wskazuje na adres za pięcioma bajtami przydzielonymi liczbie..

Instrukcja 'RST 0028' jest wykorzystywana do wywołania KALKULATORA i ostatnia wartość zostaje usunięta. Jednakże nie jest ona nadpisana..

2B59 L-NUMERIC    PUSH  HL                  Zapamiętaj wskaźnik 'docelowy'.
                  RST   0028,FP-CALC        Użyj kalkulatora.
                  DEFB  +02,delete          To przesunie STKEND wstecz o pięć bajtów.
                  DEFB  +38,end-calc
                  POP   HL                  Odtwórz wskaźnik.
                  LD    BC,+0005            Na liczbę potrzebne jest pięć bajtów.
                  AND   A                   Ustaw HL na adres pierwszego z nich
                  SBC   HL,BC
                  JR    2BA6,L-ENTER        i skocz naprzód, aby przesłać liczbę.

W to miejsce przychodzi się, jeśli zmienna 'już istnieje'. Najpierw testowany jest bit 6 zmiennej systemowej FLAGS, aby rozdzielić zmienne liczbowe od łańcuchowych lub od tablic łańcuchów.

2B66 L-EXISTS     BIT  6,(FLAGS)            Skocz naprzód, jeśli mamy do czynienia z
                  JR    Z,2B72,L-DELETES    jakąkolwiek zmienną łańcuchową.

Przy zmiennych liczbowych 'nowa' liczba nadpisuje 'starą'. Zatem najpierw należy ustawić HL na adres za pięcioma bajtami istniejącej wartości. Obecnie HL wskazuje adres przed tymi pięcioma bajtami.

                  LD    DE,+0006            Pięć bajtów liczby + '1'.
                  ADD   HL,DE               Teraz HL wskazuje 'za'.
                  JR    2B59,L-NUMERIC      Skocz wstecz, aby dokonać właściwego przesyłu.

Parametry zmiennej łańcuchowej są pobierane, a pełne proste łańcuchy zostają odseparowane od łańcuchów 'dzielonych' lub od tablic łańcuchów.

2B72 L-DELETE$    LD    HL,(DEST)           Pobierz 'początek'. Uwaga: ten rozkaz jest nadmiarowy.
                  LD    BC,(STRLEN)         Pobierz 'długość'.
                  BIT   0,(FLAGX)           Skocz, jeśli mamy do czynienia z pełnym, prostym łańcuchem;
                  JR    NZ,2BAF,L-ADD$      stary łańcuch będzie musiał zostać 'usunięty' tylko
                                            w tym przypadku.

Jeśli mamy do czynienia z 'podziałem' istniejącego łańcucha prostego, z 'podziałem' łańcucha z tablicy łańcuchów lub pełnym łańcuchem z tablicy łańcuchów, to potrzebne są dwa różne etapy. W pierwszym zostaje utworzony 'nowy' łańcuch w obszarze roboczym, skrócony lub wydłużony wg potrzeb. W drugim etapie 'nowy' łańcuch zostaje skopiowany do przeznaczonego mu miejsca w obszarze zmiennych.

Jednakże nic nie robimy w przypadku łańcucha o zerowej długości.

                  LD    A,B                 Wróć, jeśli łańcuch jest pusty
                  OR    C
                  RET   Z

Następnie utwórz w obszarze roboczym odpowiednie miejsce.

                  PUSH  HL                  Zapamiętaj 'początek' (DEST).
                  RST   0030,BC-SPACES      Utwórz potrzebne miejsce w obszarze roboczym.
                  PUSH  DE                  Zapamiętaj wskaźnik do pierwszej komórki.
                  PUSH  BC                  Zapamiętaj 'długość' do późniejszego użytku.
                  LD    D,H                 Ustaw DE na adres ostatniej komórki.
                  LD    E,L
                  INC   HL                  Ustaw HL na adres 'o jeden większy' od nowego obszaru.
                  LD    (HL),+20            Wstaw znak 'spacji'.
                  LDDR                      Skopiuj ten znak na wszystkie komórki.
                                            Zakończ z HL wskazującym pierwszą nową komórkę.

Teraz zostają pobrane ze stosu kalkulatora parametry obsługiwanego łańcucha.

                  PUSH  HL                  Zapamiętaj tymczasowo wskaźnik.
                  CALL  2BF1,STK-FETCH      Pobierz 'nowe' parametry.
                  POP   HL                  Odtwórz wskaźnik.

Uwaga: W tym miejscu wymagana ilość miejsca została udostępniona w przestrzeni roboczej dla 'przypisywanej zmiennej', np. dla polecenia LET A$(4 to 8)="abcdefg" - utworzono obszar pięciu bajtów.

Parametry pobrane wyżej jako 'ostatnia wartość' reprezentują łańcuch, który ma zostać skopiowany do nowego miejsca z wydłużeniem lub skróceniem wg potrzeb.

Długość 'nowego' łańcucha jest porównywana z długością udostępnionego mu miejsca.

                  EX    (SP),HL             'Długość' nowego obszaru do HL.
                                            'Wskaźnik' nowego obszaru na stos.
                  AND   A                   Porównaj te dwie 'długości'
                  SBC   HL,BC               i skocz naprzód, jeśli 'nowy'
                  ADD   HL,BC               łańcuch zmieści się w przydzielony obszar.
                  JR    NC,2B9B,L-LENGTH    tj. nie potrzeba go skracać.
                  LD    B,H                 Jednakże zmodyfikuj 'nową'
                  LD    C,L                 długość, jeśli jest zbyt długi.
2B9B L-LENGTH     EX    (SP),HL             'Długość' nowego obszaru na stos.
                                            'Wskaźnik' nowego obszaru do HL.

Nowy łańcuch zostaje skopiowany do obszaru roboczego, jeśli nie jest pusty. Wydłużenie jest osiągane automatycznie, jeżeli 'nowy' łańcuch jest krótszy od udostępnionego mu miejsca.

                  EX    DE,HL               'Początek' nowego łańcucha do HL.
                                            'Wskaźnik' nowego obszaru do DE.
                  LD    A,B                 Skocz naprzód, jeśli 
                  OR    C                   'nowy' łańcuch jest
                  JR    Z,2BA3,L-IN-W/S     łańcuchem pustym.
                  LDIR                      Inaczej przenieś 'nowy' łańcuch do przestrzeni roboczej.

Wartości umieszczone na stosie są odtwarzane.

2BA3 L-IN-W/S     POP   BC                  'Długość' nowego obszaru.
                  POP   DE                  'Wskaźnik' nowego obszaru.
                  POP   HL                  Początek - wskaźnik 'przypisywanej zmiennej', który
                                            pierwotnie znajdował się w DEST.
                                            L-ENTER jest teraz wykorzystywane do przekazania
                                            'nowego' łańcucha do obszaru zmiennych.

PROCEDURA 'L-ENTER'

Ta krótka procedura jest używana do przekazania albo wartości liczbowej ze stosu kalkulatora lub łańcucha z przestrzeni roboczej do odpowiedniego miejsca w obszarze zmiennych.

Stąd procedury tej używa się do wszystkich przypadków z wyjątkiem 'nowo zadeklarowanych' oraz 'pełnych i istniejących' łańcuchów prostych.

2BA6 L-ENTER      EX    DE,HL               Wymień wskaźniki.
                  LD    A,B                 Jeszcze raz sprawdź, że długość jest niezerowa.
                  OR    C
                  RET   Z
                  PUSH  DE                  Zapamiętaj wskaźnik przeznaczenia.
                  LDIR                      Przenieś wartość liczbową lub łańcuch.
                  POP   HL                  Wróć z parą rejestrów HL wskazującą na pierwszy bajt
                  RET                       tej wartości liczbowej lub tego łańcucha.

PROCEDURA LET JEST KONTYNUOWANA TUTAJ

Gdy jest obsługiwany 'pełny i istniejący' łańcuch prosty, to nowy łańcuch zostaje wprowadzony tak, jakby był 'nowo zadeklarowanym' łańcuchem prostym, zanim istniejąca wersja będzie 'usunieta' z pamięci.

2BAF L-ADD$       DEC   HL                  Ustaw HL na adres litery
                  DEC   HL                  nazwy zmiennej.
                  DEC   HL                  tj. DEST - 3.
                  LD    A,(HL)              Pobierz tę literę.
                  PUSH  HL                  Zapamiętaj wskaźnik do 'istniejącej wersji'.
                  PUSH  BC                  Zapamiętaj 'długość' 'istniejącego łańcucha'.
                  CALL  2BC6,L-STRING       Użyj L-STRING do dodania nowego łańcucha do obszaru zmiennych.
                  POP   BC                  Odtwórz 'długość'.
                  POP   HL                  Odtwórz wskaźnik.
                  INC   BC                  Do długości dodaj 3 na bajt litery oraz dwa bajty długości.
                  INC   BC
                  INC   BC
                  JP    19E8,RECLAIM-2      Wyjdź przez skok do RECLAIM-2, które usunie całość istniejącej wersji.

'Nowo zadeklarowane' łańcuchy są obsługiwane w sposób następujący:

2BC0 L-NEW$       LD    A,+DF               Przygotuj się na oznaczenie litery zmiennej.
                  LD    HL,(DEST)           Pobierz wskaźnik do litery.
                  AND   (HL)                Oznacz literę wg potrzeb.
                                            L-STRING zostanie teraz użyte do dodania nowego łańcucha
                                            do obszaru zmiennych.

PODPROGRAM 'L-STRING'

Parametry 'nowego' łańcucha zostają pobrane, tworzy się wystarczające miejsce dla niego, a następnie kopiuje.

2BC6 L-STRING     PUSH  AF                  Zapamiętaj literę zmiennej
                  CALL  2BF1,STK-FETCH      Pobierz 'początek' i 'długość' 'nowego' łańcucha.
                  EX    DE,HL               Umieść 'początek' w HL.
                  ADD   HL,BC               Ustaw HL na adres o 1 większy od końca łańcucha.
                  PUSH  BC                  Zapamiętaj 'długość'.
                  DEC   HL                  Ustaw HL na adres końca łańcucha.
                  LD    (DEST),HL           Zapamiętaj wskaźnik na krótko.
                  INC   BC                  Do długości dodaj 3 na literę zmiennej
                  INC   BC                  oraz na dwa bajty długości łańcucha.
                  INC   BC
                  LD    HL,(E-LINE)         Ustaw HL na adres 'bajtu 80' na końcu obszaru zmiennych.
                  CALL  1655,MAKE-ROOM      Zrób miejsce w obszarze zmiennych.
                                            Uwaga: W rezultacie 'BC' bajtów zostaje zarezerwowanych
                                            przed przemieszczonym 'bajtem 80'.
                  LD    HL,(DEST)           Odtwórz wskaźnik końca 'nowego' łańcucha.
                  POP   BC                  Utwórz kopię długości
                  PUSH  BC                  'nowego' łańcucha.
                  INC   BC                  Dodaj jeden do długości w przypadku, gdyby
                                            'nowy' łańcuch był pusty.
                  LDDR                      Skopiuj 'nowy' łańcuch + jeden bajt.
                  EX    DE,HL               Ustaw HL na adres starszego bajtu długości łańcucha.
                  INC   HL
                  POP   BC                  Pobierz 'długość'.
                  LD    (HL),B              Wprowadź starszy bajt.
                  DEC   HL                  Do tyłu o jeden.
                  LD    (HL),C              Wprowadź młodszy bajt.
                  POP   AF                  Pobierz znak zmiennej.

PODPROGRAM 'L-FIRST'

Wejście do tego podprogramu następuje z literą nazwy zmiennej, odpowiednio oznaczoną, w rejestrze A. Litera nadpisuje 'stary bajt 80' w obszarze zmiennych. Powrót jest wykonywany z parą rejestrów HL wskazującą 'nowy bajt 80'.

2BEA L-FIRST      DEC   HL                  Ustaw HL na adres 'starego bajtu 80'.
                  LD    (HL),A              Zostaje on nadpisany przez literę zmiennej.
                  LD    HL,(E-LINE)         Ustaw HL na adres 'nowego bajtu 80'.
                  DEC   HL                  Zakończone ze wszystkimi
                  RET                       'nowo zadeklarowanymi zmiennymi'.

PODPROGRAM 'STK-FETCH'

Ten ważny podprogram pobiera 'ostatnią wartość' ze stosu kalkulatora. Pięć bajtów może reprezentować albo liczbę zmiennoprzecinkową w postaci 'długiej' lub 'krótkiej', albo zestaw parametrów definiujących łańcuch.

2BF1 STK-FETCH    LD    HL,(STKEND)         Pobierz STKEND.
                  DEC   HL                  O jeden adres do tyłu;
                  LD    B,(HL)              Piąta wartość.
                  DEC   HL                  Wstecz o jeden.
                  LD    C,(HL)              Czwarta wartość.
                  DEC   HL                  Wstecz o jeden.
                  LD    D,(HL)              Trzecia wartość.
                  DEC   HL                  Wstecz o jeden.
                  LD    E,(HL)              Druga wartość.
                  DEC   HL                  Wstecz o jeden.
                  LD    A,(HL)              Pierwsza wartość.
                  LD    (STKEND),HL         Ustaw STKEND na nowy adres.
                  RET                       Skończone.

PROCEDURA ROZKAZU 'DIM'

Ta procedura tworzy nową tablicę w obszarze zmiennych. Zaczyna od przeszukania istniejących zmiennych w celu określenia, czy istnieje wśród nich tablica o takiej samej nazwie. Jeśli taka tablica zostanie znaleziona, to procedura usuwa ją przed utworzeniem nowej.

Nowa tablica będzie zawierała wszystkie elementy wyzerowane, jeśli jest tablicą liczbową, lub z wpisanymi spacjami, jeśli jest tablicą łańcuchów.

2C02 DIM          CALL  28B2,LOOK-VARS      Przeszukaj obszar zmiennych.
2C05 D-RPORT-C    JP    NZ,1C8A,REPORT-C    Zgłoś raport C, ponieważ wystąpił błąd.
                  CALL  2530,SYNTAX-Z       Skocz naprzód, jeśli trwa wykonywanie programu.
                  JR    NZ,2C15,D-RUN
                  RES   6,C                 Sprawdź składnię tablic łańcuchów, jakby były tablicami liczbowymi.
                  CALL  2996,STK-VAR        Sprawdź składnię wyrażenia w nawiasach.
                  CALL  1BEE,CHECK-END      Przejdź do następnego rozkazu w wierszu, skoro składnia była dobra.

'Istniejąca tablica' jest usuwana z pamięci.

2C15 D-RUN        JR    C,2C1F,D-LETTER     Skocz naprzód, jeśli nie ma 'istniejącej tablicy'.
                  PUSH  BC                  Zapamiętaj bajt dyskryminatora.
                  CALL  19B8,NEXT-ONE       Znajdź początek następnej zmiennej.
                  CALL  19E8,RECLAIM-2      Usuń 'istniejącą tablicę'.
                  POP   BC                  Odtwórz bajt dyskryminatora.

Znajdowane są początkowe parametry nowej tablicy.

2C1F D-LETTER     SET   7,C                 Ustaw bit 7 w bajcie dyskryminatora.
                  LD    B,+00               Wyzeruj licznik wymiarów.
                  PUSH  BC                  Zapamiętaj licznik i bajt dyskryminatora.
                  LD    HL,+0001            Para rejestrów HL będzie przechowywała
                  BIT   6,C                 rozmiar elementów w tablicy,
                  JR    NZ,2C2D,D-SIZE      '1' dla tablicy łańcuchów/'5' dla tablicy liczbowej.
                  LD    L,+05
2C2D D-SIZE       EX    DE,HL               Rozmiar elementu do DE.

Poniższa pętla jest wykonywana dla każdego wymiaru wyszczególnionego w wyrażeniu objętym nawiasami w rozkazie DIM. Całkowita liczba bajtów potrzebnych dla elementów tablicy jest tworzona w parze rejestrów DE.

2C2E D-NO-LOOP    RST   0020,NEXT-CHAR      Przesuwaj do przodu CH-ADD przy każdym obiegu.
                  LD    H,+FF               Ustaw 'wartość graniczną'.
                  CALL  2ACC,INT-EXP1       Oblicz parametr.
                  JP    C,2A20,REPORT-3     Zgłoś błąd, jeśli 'jest poza zakresem'.
                  POP   HL                  Pobierz licznik wymiarów i bajt dyskryminatora.
                  PUSH  BC                  Zapamiętaj parametr przy każdym obiegu pętli.
                  INC   H                   Również zwiększ przy każdym obiegu licznik wymiarów.
                  PUSH  HL                  Ponownie umieść na stosie licznik wymiarów i bajt dyskryminatora.
                  LD    H,B                 Parametr jest przenoszony do
                  LD    L,C                 pary rejestrów  HL.
                  CALL  2AF4,GET-HL*DE      Całkowita liczba bajtów jest tworzona w HL
                  EX    DE,HL               i zostaje przeniesiona do DE.
                  RST   0018,GET-CHAR       Pobierz obecny znak
                  CP    +2C                 i wróć na początek pętli, jeśli
                  JR    Z,2C2E,D-NO-LOOP    jest kolejny wymiar.

Uwaga: W tym punkcie para rejestrów DE wskazuje liczbę bajtów potrzebnych na elementy nowej tablicy, a rozmiar każdego wymiaru jest umieszczany na stosie maszynowym.

Teraz sprawdź, czy rzeczywiście jest nawias zamykający wyrażenie w nawiasach.

                  CP    +29                 Czy jest to ')'?
                  JR    NZ,2C05,D-REPORT-C  Jeśli nie, to skocz wstecz.
                  RST   0020,NEXT-CHAR      Zwiększ CH-ADD, aby go minąć.

Teraz sprawdzane są podane wymiary nowej tablicy.

                  POP   BC                  Pobierz licznik wymiarów oraz bajt dyskryminatora.
                  LD    A,C                 Przekaż bajt dyskryminatora do rejestru A na później.
                  LD    L,B                 Licznik przenieś do  L.
                  LD    H,+00               Wyzeruj rejestr H.
                  INC   HL                  Zwiększ liczbę wymiarów o 2
                  INC   HL
                  ADD   HL,HL               i podwój wynik, a następnie utwórz całkowitą
                  ADD   HL,DE               długość zmiennej, dodając całkowitą liczbę bajtów.
                  JP    C,1F15,REPORT-4     Jeśli trzeba, zgłoś błąd 'Brak pamięci'.
                  PUSH  DE                  Zapamiętaj całkowitą liczbę bajtów dla elementów.
                  PUSH  BC                  Zapamiętaj licznik wymiarów i bajt dyskryminatora.
                  PUSH  HL                  Również zapamiętaj całkowitą długość.
                  LD    B,H                 Przenieś całkowitą długość do BC.
                  LD    C,L

Na końcu obszaru zmiennych zostaje utworzone miejsce na nową tablicę.

                  LD    HL,(E-LINE)         Ustaw parę rejestrów HL
                  DEC   HL                  na adres 'bajtu 80'.
                  CALL  1655,MAKE-ROOM      Udostępnij to miejsce.
                  INC   HL                  HL zostaje ustawione na adres pierwszej komórki w nowym obszarze.

Teraz zostają wstawione parametry.

                  LD    (HL),A              Najpierw jest wstawiana litera, odpowiednio oznaczona.
                  POP   BC                  Całkowita długość zostaje pobrana
                  DEC   BC                  i zmniejszona o '3'.
                  DEC   BC
                  DEC   BC
                  INC   HL                  Przesuń do przodu adres w HL.
                  LD    (HL),C              Wstaw młodszy bajt długości.
                  INC   HL                  Przesuń HL.
                  LD    (HL),B              Wstaw starszy bajt długości.
                  POP   BC                  Pobierz licznik wymiarów.
                  LD    A,B                 Przenieś go do rejestru A.
                  INC   HL                  Przesuń HL.
                  LD    (HL),A              Wprowadź licznik wymiarów.

Elementy nowej tablicy są teraz 'czyszczone'.

                  LD    H,D                 HL jest ustawiane na
                  LD    L,E                 adres końca tablicy,
                  DEC   DE                  a DE na adres o jedną komórkę niższy.
                  LD    (HL),+00            Wstaw zero na ostatnią pozycję,
                  BIT   6,C                 lecz nadpisz je spacją,
                  JR    Z,2C7C,DIM-CLEAR    jeśli mamy do czynienia
                  LD    (HL),+20            z tablicą łańcuchów.
2C7C DIM-CLEAR    POP   BC                  Pobierz całkowitą liczbę bajtów dla elementów tablicy.
                  LDDR                      Wyczyść tablicę + jedną dodatkową komórkę.

Teraz zostają wstawione 'rozmiary-wymiarów'.

2C7F DIM-SIZES    POP   BC                  Pobierz rozmiar wymiaru.
                  LD    (HL),B              Wstaw starszy bajt.
                  DEC   HL                  Do tyłu o jeden.
                  LD    (HL),C              Wstaw młodszy bajt.
                  DEC   HL                  Do tyłu o jeden.
                  DEC   A                   Zmniejsz licznik wymiarów.
                  JR    NZ,2C7F,DIM-SIZES   Powtarzaj tę operację dla wszystkich wymiarów;
                  RET                       po czym powróć.

PODPROGRAM 'ALPHANUM'

Ten podprogram wraca z ustawionym znacznikiem przeniesienia, jeśli obecna zawartość rejestru A reprezentuje kod cyfry lub litery.

2C88 ALPHANUM     CALL  2D1B,NUMERIC        Sprawdź, czy mamy cyfrę; przy cyfrze przeniesienie będzie wyzerowane.
                  CCF                       Neguj przeniesienie.
                  RET   C                   Wróć przy cyfrze, inaczej kontynuuj w 'ALPHA'.

PODPROGRAM 'ALPHA'

Ten podprogram wraca z ustawionym znacznikiem przeniesienia, jeśli obecna wartość w rejestrze A reprezentuje literę alfabetu.

2C8D ALPHA        CP    +41                 Sprawdź z kodem litery 'A'.
                  CCF                       Neguj znacznik przeniesienia.
                  RET   NC                  Jeśli zły kod, wróć.
                  CP    +5B                 Sprawdź z kodem litery 'Z'.
                  RET   C                   Jeśli duża litera, wróć.
                  CP    +61                 Sprawdź z kodem litery 'a'.
                  CCF                       Neguj znacznik przeniesienia.
                  RET   NC                  Wróć przy złym kodzie znaku.
                  CP    +7B                 Sprawdź z kodem o 1 większym od kodu 'z'.
                  RET                       Skończone.

PODPROGRAM 'LICZBA DZIESIĘTNA NA ZMIENNOPRZECINKOWĄ'

Jako część procesu sprawdzania składni liczby dziesiętne pojawiające się w wierszach języka BASIC są zamieniane na odpowiadające im liczby zmiennoprzecinkowe. Ten podprogram czyta liczbę dziesiętną cyfra po cyfrze i daje jej wartość jako 'ostatnią wartość' na stosie kalkulatora. Lecz najpierw zajmuje się alternatywnym zapisem BIN, który wprowadza ciąg zer i jedynek, dając dwójkową reprezentację pożądanej liczby.

2C9B DEC-TO-FP    CP    +C4                 Czy znak to 'BIN'?
                  JR    NZ,2CB8,NOT-BIN     Skocz, jeśli to nie 'BIN'.
                  LD    DE,+0000            Ustaw wynik zero w DE.
2CA2 BIN-DIGIT    RST   0020,NEXT-CHAR      Pobierz następny znak.
                  SUB   +31                 Odejmij kod cyfry '1'.
                  ADC   A,+00               0 teraz da 0 z ustawionym znacznikiem przeniesienia;
                                            1 daje 0 z wyzerowanym przeniesieniem.
                  JR    NZ,2CB3,BIN-END     Każdy inny znak powoduje skok do BIN-END,
                                            gdzie jest sprawdzana składnia w czasie lub po przeglądnięciu wiersza.
                  EX    DE,HL               Obecny wynik teraz do HL.
                  CCF                       Neguj znacznik przeniesienia.
                  ADC   HL,HL               Przesuń wynik w lewo z przeniesieniem wskakującym na bit 0.
                  JP    C,31AD,REPORT-6     Zgłoś błąd przy wyniku większym od 65535.
                  EX    DE,HL               Zwróć dotychczasowy wynik do DE.
                  JR    2CA2,BIN-DIGIT      Skocz wstecz dla następnego 0 lub 1.
2CB3 BIN-END      LD    B,D                 Skopiuj wynik do BC dla umieszczenia na stosie.
                  LD    C,E                 
                  JP    2D2B,STACK-BC       Skocz naprzód, aby umieścić wynik na stosie.

Dla pozostałych liczb najpierw zamieniana jest część całkowita; jeśli następnym znakiem jest kropka dziesiętna, to przetworzona zostanie część ułamkowa.

2CB8 NOT-BIN      CP    +2E                 Czy pierwszym znakiem jest '.'?
                  JR    Z,2CCB,DECIMAL      Jeśli tak, to skocz naprzód.
                  CALL  2D3B,INT-TO-FP      Inaczej utwórz 'ostatnią wartość' części całkowitej.
                  CP    +2E                 Czy następnym znakiem jest '.'?
                  JR    NZ,2CEB,E-FORMAT    Skocz naprzód, aby sprawdzić, czy jest to 'E'.
                  RST   0020,NEXT-CHAR      Pobierz następny znak.
                  CALL  2D1B,NUMERIC        Czy to cyfra?
                  JR    C,2CEB,E-FORMAT     Skocz, jeśli nie (np. 1.E4 jest dozwolone).
                  JR    2CD5,DEC-STO-1      Skocz naprzód, aby zająć się cyframi po kropce dziesiętnej.
2CCB DECIMAL      RST   0020,NEXT-CHAR      Jeśli liczba rozpoczęła się od kropki dziesiętnej,
                  CALL  2D1B,NUMERIC        to sprawdź, czy następnym znakiem jest cyfra.
2CCF DEC-RPT-C    JP    C,1C8A,REPORT-C     Jeśli nie, zgłoś błąd.
                  RST   0028,FP-CALC        Użyj kalkulatora, aby umieścić na stosie zero
                  DEFB  +A0,stk-zero        jako część całkowitą takich liczb.
                  DEFB  +38,end-calc
2CD5 DEC-STO-1    RST   0028,FP-CALC        Ponownie użyj kalkulatora.
                  DEFB  +A1,stk-one         Znajdź postać zmiennoprzecinkową
                  DEFB  +C0,st-mem-0        liczby dziesiętnej '1'
                  DEFB +02,delete           i zapamiętaj ją w obszarze pamięci.
                  DEFB  +38,end-calc
2CDA NXT-DGT-1    RST   0018,GET-CHAR       Pobierz obecny znak.
                  CALL  2D22,STK-DIGIT      Jeśli to cyfra, to umieść ją na stosie.
                  JR    C,2CEB,E-FORMAT     Jeśli nie, skocz naprzód.
                  RST   0028,FP-CALC        Teraz użyj kalkulatora.
                  DEFB  +E0,get-mem-0       Przy każdym obiegu pętli
                  DEFB  +A4,stk-ten         liczba zapamiętana w obszarze pamięci
                  DEFB  +05,division        jest pobierana, dzielona przez 10
                  DEFB  +C0,st-mem-0        i zapamiętywana ponownie: tj. idzie od .1
                                            do .01 do .001 itd.
                  DEFN  +04,multiply        Obecna cyfra jest mnożona
                  DEFB  +0F,addition        przez 'zapamiętaną liczbę'
                  DEFB  +38,end-calc        i dodawana do 'ostatniej wartości'.
                  RST   0020,NEXT-CHAR      Pobierz następny znak.
                  JR    2CDA,NXT-DGT-1      Skocz wstecz (o jeden bajt za dużo), aby go przetworzyć.

Następnie zajmij się 'zapisem E', tj. postacią xEm lub xem, gdzie m jest liczbą całkowitą.

2CEB E-FORMAT     CP    +45                 Czy obecny znak to 'E'?
                  JR    Z,2CF2,SIGN-FLAG    Skocz naprzód, jeśli tak.
                  CP    +65                 Czy to jest 'e'?
                  RET   NZ                  Zakończ, jeśli nie.
2CF2 SIGN-FLAG    LD    B,+FF               Użyj B jako znacznika znaku, FF dla '+'.
                  RST   0020,NEXT-CHAR      Pobierz następny znak.
                  CP    +2B                 Czy jest to '+'?
                  JR    Z,2CFE,SIGN-DONE    Skocz naprzód.
                  CP    +2D                 Czy jest to '-'?
                  JR    NZ,2CFF,ST-E-PART   Skocz, jeśli ani '+', ani '-'.
                  INC   B                   Zmień znak znacznika.
2CFE SIGN-DONE    RST   0020,NEXT-CHAR      Wskaż pierwszą cyfrę.
2CFF ST-E-PART    CALL  2D1B,NUMERIC        Czy faktycznie to cyfra?
                  JR    C,2CCF,DEC-RPT-C    Jeśli nie, zgłoś błąd.
                  PUSH  BC                  Tymczasowo zapamiętaj znacznik w B.
                  CALL  2D3B,INT-TO-FP      Umieść na stosie ABS m, gdzie m jest wykładnikiem.
                  CALL  2DD5,FP-TO-A        Przenieś ABS m do A.
                  POP   BC                  Odtwórz znacznik znaku w B.
                  JP    C,31AD,REPORT-6     Zgłoś teraz przepełnienie, jeśli
                  AND   A                   ABS m jest większe od 255 lub większe od 127
                  JP    M,31AD,REPORT-6     (inne wartości większe od 39 zostaną rozpoznane później).
                  INC   B                   Testuj znak w B; '+' (tj. +FF) ustawi teraz znacznik zera.
                  JR    Z,2D18,E-FP-JUMP    Skocz, jeśli znakiem m jest '+'.
                  NEG                       Neguj m, jeśli znakiem jest '-'.
2D18 E-FP-JUMP    JP    2D4F,E-TOO-FP       Skocz, aby przypisać 'ostatniej wartości' wynik x*10^m.

PODPROGRAM 'NUMERIC'

Ten podprogram wraca z wyzerowanym znacznikiem przeniesienia, jeśli wartość w rejestrze A oznacza poprawną cyfrę.

2D1B NUMERIC      CP    +30                 Sprawdź na kod cyfry '0'.
                  RET   C                   Wróć, jeśli niepoprawny znak.
                  CP    +3A                 Sprawdź ponownie z górną granicą.
                  CCF                       Neguj znacznik przeniesienia.
                  RET                       Skończone.

PODPROGRAM 'STK DIGIT'

Ten podprogram po prostu wraca, jeśli bieżąca wartość przechowywana w rejestrze A nie przedstawia cyfry, jednakże jeśli jest to cyfra, to jej wartość zmiennoprzecinkowa staje się 'ostatnią wartością' na stosie kalkulatora.

2D22 STK-DIGIT    CALL  2D1B,NUMERIC        Czy znak jest cyfrą?
                  RET   C                   Wróć, jeśli poza zakresem.
                  SUB   +30                 Zastąp kod przez wartość cyfry.

PODPROGRAM 'STACK-A'

Ten podprogram umieszcza na stosie kalkulatora zawartość akumulatora traktowaną jako liczbę dodatnią.

2D28 STACK-A      LD    C,A                 Przenieś wartość do rejestru C.
                  LD    B,+00               Wyzeruj rejestr B.

PODPROGRAM 'STACK-BC'

Ten podprogram umieszcza na stosie kalkulatora liczbę zmiennoprzecinkową odpowiadającą zawartości pary rejestrów BC traktowanej jako dodatnia liczba całkowita.

Postać zmiennoprzecinkowa używana w tym oraz również w dwóch poprzednich podprogramach jest postacią zarezerwowaną w Spectrum dla małych liczb całkowitych n, gdzie -65535 <= n <= 65535. Pierwszy i piaty bajt mają wartość zero; trzeci i czwarty to bajty mniej i bardziej znaczący 16 bitowej liczby całkowitej w kodzie uzupełnień do dwóch (jeśli n jest ujemne, to te dwa bajty przechowują 65536+n); a drugi bajt jest bajtem znaku, 00 dla '+' i FF dla  '-'.

2D2B STACK-BC     LD    IY,+5C3A            Ponownie ustaw IY na ERR-NR.
                  XOR   A                   Wyzeruj rejestr A
                  LD    E,A                 oraz rejestr E, aby oznaczyć '+'.
                  LD    D,C                 Skopiuj mniej znaczący bajt do D.
                  LD    C,B                 A bardziej znaczący bajt do C.
                  LD    B,A                 Wyzeruj rejestr B.
                  CALL  2AB6,STK-STORE      Teraz umieść liczbę na stosie.
                  RST   0028,FP-CALC        Ustaw HL na wskazywanie
                  DEFB  +38,end-calc        STKEND-5.
                  AND   A                   Wyzeruj znacznik przeniesienia.
                  RET                       Skończone.

PODPROGRAM 'LICZBA CAŁKOWITA NA ZMIENNOPRZECINKOWĄ'

Ten podprogram zwraca 'ostatnią wartość' na stosie kalkulatora, która jest wynikiem przekształcenia liczby całkowitej w wierszu języka BASIC, tj. części całkowitej liczby dziesiętnej lub numeru wiersza na jej odpowiednik zmiennoprzecinkowy.

Wywołania do CH-ADD+1 pobierają kolejne cyfry liczby. Wyjście następuje po pobraniu kodu, który nie jest cyfrą.

2D3B INT-TO-FP    PUSH  AF                  Zapamiętaj pierwszą cyfrę przechowywaną w A.
                  RST   0028,FP-CALC        Użyj kalkulatora.
                  DEFB  +A0,stk-zero        Teraz 'ostatnia wartość' jest zerem.
                  DEFB  +38,end-calc
                  POP   AF                  Odtwórz pierwszą cyfrę.

Teraz tworzona jest pętla. Dopóki kod przedstawia cyfrę, znajdowana jest jej postać zmiennoprzecinkowa i umieszczana na stosie jako 'ostatnia wartość', którą następnie mnoży się przez 10 i dodaje do 'liczby', otrzymując 'ostatnią wartość, która z kolei jest przenoszona na początek pętli.

2D40 NXT-DGT-2    CALL  2D22,STK-DIGIT      Jeśli kod przedstawia cyfrę, to umieść na stosie jej postać zmiennoprzecinkową.
                  RST   0028,FP-CALC        Użyj kalkulatora.
                  DEFB  +01,exchange        'Cyfra' idzie pod 'ostatnią wartość'.
                  DEFB  +A4,stk-ten         Umieść na stosie 10.
                  DEFB  +04,multiply        'Ostatnia wartość' = 'ostatnia wartość' *10.
                  DEFB  +0F,addition        'Ostatnia wartość' = 'ostatnia wartość' + 'cyfra'.
                  DEFB    +38,end-calc
                  CALL  0074,CH-ADD+1       Następny kod idzie do A.
                  JR    2D40,NXT-DGT-2      Kontynuuj pętlę z tym kodem.


List do administratora Serwisu Edukacyjnego Nauczycieli I LO

Twój email: (jeśli chcesz otrzymać odpowiedź)
Temat:
Uwaga: ← tutaj wpisz wyraz  ilo , inaczej list zostanie zignorowany

Poniżej wpisz swoje uwagi lub pytania dotyczące tego rozdziału (max. 2048 znaków).

Liczba znaków do wykorzystania: 2048

 

W związku z dużą liczbą listów do naszego serwisu edukacyjnego nie będziemy udzielać odpowiedzi na prośby rozwiązywania zadań, pisania programów zaliczeniowych, przesyłania materiałów czy też tłumaczenia zagadnień szeroko opisywanych w podręcznikach.



   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2017 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.