atarionline.pl ABC czyli Atari Basic Compiler - Forum Atarum

Jeśli chcesz wziąć udział w dyskusjach na forum - zaloguj się. Jeżeli nie masz loginu - poproś o członkostwo.

  • :
  • :

Vanilla 1.1.4 jest produktem Lussumo. Więcej informacji: Dokumentacja, Forum.

    • 1:
       
      CommentAuthormgr_inz_rafal
    • CommentTime14 Nov 2012 zmieniony
     
    OK, jest pierwsza wersja pętelek. Na razie z dwoma ograniczeniami:
    1. Gramatyka nie pozwala na pominięcie słowa STEP
    2. STEP ujemny nie działa (trzeba zrobić odwrotne porównanie niż w dodatnim, a już dziś mi się nie chce) :)

    Spostrzegawczy jednak zauważą, że umiejscowienie kilku FOR lub NEXT w jednej linii wymagało dorobienia obsługi GOTO do środka linijki :)

    Oto przykładowy kod i wynik.
    10 FOR A = 1 TO 5 STEP 1
    20 FOR B = 2 TO 7 STEP 2:FOR C = 2 TO 14 STEP 5
    30 PRINT A*B*C
    40 NEXT C
    50 NEXT B:NEXT A
    60 PRINT 666

    • 2: CommentAuthormono
    • CommentTime14 Nov 2012 zmieniony
     
    Weź pod uwagę rozkaz POP. Ma znaczenie w pętlach FOR/NEXT i skokach GOSUB do podprocedur.
    Skoki liczone możesz realizować za pomocą
    jmp (addr)

    Miej na uwadze też TRAP, które funkcjonuje jak wyjątek w językach C++-podobnych.

    Edit: Opis działania ->link<- str. 42/43.
    • 3:
       
      CommentAuthorpirx
    • CommentTime14 Nov 2012
     
    >Niestety to rozwiązanie nie działa dla wyrażeń (np. GOTO X * 10), bo ich wartość nie jest znana w czasie kompilacji

    Ha! Po tylu latach zrozumiałem, czemu w mojej instrukcji do Atari Basic z 800XL było napisane, że GOTO X*1000 i GOSUB X*1000 są "not good for compilation"! (o ile pamiętam)
  1.  
    @mono
    Tak, pamiętam o POP. Jeśli chodzi o jmp (addr) to trochę się boję buga związanego z ostatnim bajtem strony, dlatego wolę stosować PHA, PHA, RTS.

    A może MADS pilnuje tego jmp?

    TRAP i ON ERROR GOTO/GOSUB będzie mi spędzać sen z powiek trochę później, jak już porobię podstawy. Podobnie jak inne rzeczy, których nigdy w BASIC nie rozumiałem, np. STATUS czy XIO :) Póki co żyję nadzieją, że da się to jakoś prosto zmapować na wywołania OSu albo, że kiedyś będziecie mi w stanie to wytłumaczyć :)

    @pirx
    Są good, jeśli kompilator jest good :) A moim zdaniem robienie kompilatora "pół-BASICA" mija się z celem. Jak wspierać to wszystko co się da i co będę umiał zrobić :)
    • 5: CommentAuthormono
    • CommentTime14 Nov 2012
     
    ->link<-
    STATUS i XIO, jak również OPEN, CLOSE, GET, PUT, INPUT, PRINT, LPRINT, LOCATE, POINT, NOTE, to odwołania do CIO w OS. Gorzej będzie z LOAD, SAVE, CLOAD, CSAVE, ENTER i LIST.
    • 6:
       
      CommentAuthorxeen
    • CommentTime14 Nov 2012
     
    wydaje mi się, że w przypadku takiego "cross'a" te komendy (load, save, cload itp) nie są za bardzo użyteczne.
    "very nice to have", co najwyżej, jak dla mnie.
    • 7: CommentAuthormono
    • CommentTime14 Nov 2012
     
    Jeszcze RUN. RUN jest często używany w programach wieloplikowych. Można w sumie za pomocą RUN ładować i uruchamiać skompilowany program w BASICu.
    • 8:
       
      CommentAuthormgr_inz_rafal
    • CommentTime16 Nov 2012 zmieniony
     
    Odnośnie POP mam małą sprawę.
    Generalnie byłoby to trywialne w implementacji gdyby nie fakt, że BASIC wymusza podanie identyfikatora pętli po NEXT, co może w dość dziwny sposób zaburzyć przebieg programu. Np.
    10 FOR J=1 TO 5
    20 FOR I=1 TO 3
    30 PRINT I*J
    40 NEXT J

    Chcąc to skompilować musiałbym zorganizować sobie osobne miejsce w pamięci do przechowywania NAZW (zmiennych sterujących) pętli zmapowanych na odpowiednie adresy powrotu. Następnie, po każdym NEXT szukać odpowiedniej nazwy pętli i wykonywać adekwatny skok.

    I teraz rodzi się gniew :)

    Z jednej strony chciałbym zachować dużą kompatybilność, a z drugiej nie wiem, po kiego grzyba wspierać tak dziwne konstrukcje, których implementacja zburzy wewnętrzną elegancję mojego kompilatora :)

    No cóż, pewnie i tak zrobię, żeby działało, ale jeśli ktoś dorzuci parę argumentów ZA stosowaniem takiej konstrukcji jak powyżej, to na pewno będzie mi łatwiej :)
    • 9: CommentAuthormono
    • CommentTime16 Nov 2012 zmieniony
     
    A czemu dynamicznie? Nie można statycznie określić gdzie jest początek pętli a gdzie koniec? Nawet stosu mieć nie musisz, jak to jest w basicu...
    Przed takim NEXTem powinien się oczywiście pojawić POP, ale jeśli programista zapomni, to w BASICu się wysypie, a u Ciebie nie :)

    Edit: Taki POP: NEXT J z wnętrza pętli sterowanej I to takie goto z C... niby nieładne, ale jak już ktoś tak zaprogramował. FOR/NEXT w BASICu mają tę zaletę, że adres powrotu odkładany jest na stos (może się zdarzyć w środku linii) więc nie trzeba szukać linii (od początku programu), jak to jest w przypadku [ON]GOTO/GOSUB co jest straszliwie wolne (tzn. NEXT jest znacznie szybsze).
  2.  
    Muszę to sobie jeszcze raz na spokojnie rozrysować... Teraz mam skoki w pętlach na statycznych labelkach i działa OK, pod warunkiem, że FOR/NEXT zawsze do siebie pasują. Poniższy program kompiluje się i działa dobrze, ale myk polega na tym, że kompilator po prostu ignoruje POP :)
    10 FOR J=1 TO 5
    20 FOR I=1 TO 3
    30 PRINT I*J
    35 IF I = 2 THEN POP:GOTO 50
    40 NEXT I
    50 NEXT J

    Właśnie fakt, że nie muszę nic przy POP robić trochę mnie zdziwił i zacząłem drążyć temat - może całkiem niepotrzebnie.

    Przeanalizuję jeszcze sytuację na spokojnie, bo chciałbym też uniknąć sytuacji, że ktoś w swoim programie polega na tej specyficznej właściwości BASICa i po kompilacji nie uzyska zamierzonego efektu.

    A przy NEXT mogli sobie pozwolić na skok bezpośrednio pod adres, bo zawsze wiadomo gdzie skoczyć. A w GOTO/GOSUB zdecydowali się na obsługę słynnych już skoków w linijki liczone w trakcie działania programu (GOTO X*10).

    Ale... Cały czas nie rozumiem, dlaczego w BASICu zdecydowano się na podawanie nazwy zmiennej sterującej po NEXT. Tzn. rozumiem jak to działa, ale nie mogę wygenerować żadnego akademickiego przykładu, w którym takie rozwiązanie miałoby przewagę nad anonimowym NEXT, skaczącym po prostu do początku najgłębszego FORa.
    • 11: CommentAuthorrudla
    • CommentTime16 Nov 2012
     
    Specifying the loop variable in next enhances readability and error checking. (With variable name specified, interpreter may easily detect incorrectly nested loops).

    Atari Basic does not do the checking correctly, but it should.
    • 12: CommentAuthormono
    • CommentTime16 Nov 2012
     
    Pewnie nazwa zmiennej jest dlatego, że basic nie ma instrukcji opuszczenia pętli (c break). Nextów do tej samej zmiennej też zresztą w jednej pętli możesz mieć wiele (c continue).
    • 13: CommentAuthorBluki
    • CommentTime16 Nov 2012
     
    Ja tak jak Rudla uważam, że w celu lepszej czytelności programu, a przy okazji ułatwienia odszukiwania błędów. Przecież Microsoft BASIC potrzebuje samego NEXT, bez parametrów.
  3.  
    Bardzo cieszę się z Waszych opinii :) Głównie dlatego, że mam podobne przemyślenia, a dodatkowo ułatwi mi to pracę oraz nie narazi kompilatora na utratę wewnętrznej harmonii.

    W bieżącej wersji właśnie tak podszedłem do tematu i zgłaszam błąd kompilacji jeśli wykryję niezgodność FORa z NEXTem. Poniżej przykład.

    Jeśli więc mogę założyć, że taki kod jak poniżej powstaje głównie z powodu błędów programisty, a nie celowo, to jestem spokojny.

    Kod:
    10 FOR I = 1 TO 5
    20 FOR J = 1 TO 3
    30 PRINT I*J
    40 NEXT I
    50 NEXT J
    60 PRINT 666


    Kompilacja:
    Now compiling...
    Variable "I" not used yet. Spawning new one...
    FOR LOOP "I" with BORDER at $6bd0 and STEP at $6ba0
    line: 10 compiled
    Variable "J" not used yet. Spawning new one...
    FOR LOOP "J" with BORDER at $6bd6 and STEP at $6ba6
    line: 20 compiled
    Variable "I" found...
    Variable "J" found...
    Creating temporary variable at location $70c...
    line: 30 compiled
    NEXT: Current loop: "J" - next statement = "I"
    ERROR: FOR/NEXT identifier mismatch
    ****** compilation failed
    • 15: CommentAuthorxxl
    • CommentTime16 Nov 2012
     
    swietny projekt. bardzo ambitny.

    mam pytanie - a jesli bedzie wiecej niz jeden NEXT dla FOR? przykladowo w petli bedzie rozgalezienie i czesc kodu wraz NEXT bedzie gdzie indziej. nie wiem czy to jest mozliwe w Atar Basic - tak pytam.
    • 16: CommentAuthorrudla
    • CommentTime16 Nov 2012
     
    The example with switched I and J reports error in Basic at line 50.
    It seems that when some loop ends (I), nested loops are automatically terminated too (J).

    Basic then reports error at line 50, because there is no active loop with variable J.
    • 17:
       
      CommentAuthormgr_inz_rafal
    • CommentTime17 Nov 2012 zmieniony
     

    xxl:

    mam pytanie - a jesli bedzie wiecej niz jeden NEXT dla FOR?

    Na razie się wysypie, ale wydaje się być proste do ogarnięcia, bo powinno dać się zrobić na statycznych labelkach. W Atari Basic jest to jak najbardziej możliwe.

    Natomiast obawiam się innego scenariusza - jakiś wyskok z pętli za pomocą GOTO, potem np. GOSUB i nagle 100 linijek dalej NEXT :) Tego raczej nie da się skompilować, choć w Atari Basic może działać...

    @rudla
    Seems you're right. I will, however, stick to the strict checking of FOR/NEXT consistency at compile time anyway, to reach some decent compromise.

    PS. I'm glad that they didn't decide to allow NEXT VAR$ :)
    • 18: CommentAuthorBluki
    • CommentTime17 Nov 2012
     
    Warto pamiętać, że są pewne zasady programowania. Innymi słowy: choć BASIC na to pozwala, to pewnych konstrukcji nie należy stosować, pomimo że działają. Głównie z powodu utraty przejrzystości programu, co w konsekwencji może doprowadzić do utraty kontroli nad programem.
    W konkretnym przypadku GOTO na zewnątrz pętli FOR-NEXT powinno być traktowane jako trwałe opuszczenie tej pętli (bez ponownego skoku do NEXT). Wyjście z pętli, wykonanie czegoś i powrót do NEXT – tylko przez GOSUB. Dlatego jakimiś dziwnymi „łamańcami” nie należy się przejmować, bo i tak wszystkich się nie przewidzi.

    To tylko takie moje zdanie.

    Na marginesie: Atari BASIC akceptuje instrukcję GOTO i GO TO.
    • 19:
       
      CommentAuthormgr_inz_rafal
    • CommentTime17 Nov 2012 zmieniony
     

    Bluki:

    Innymi słowy: choć BASIC na to pozwala, to pewnych konstrukcji nie należy stosować, pomimo że działają.
    Problem polega na tym, że nigdy nie wiesz, czy ktoś takiego powiedzmy "błędu" BASICa jakoś kreatywnie nie zastosował i nie oparł na nim jakiegoś triku. No ale potwierdza się powiedzenie, że diabeł tkwi w szczegółach i nawet BASIC nie musi być taki całkiem do końca "prosty" :)

    W konkretnym przypadku GOTO na zewnątrz pętli FOR-NEXT powinno być traktowane jako trwałe opuszczenie tej pętli
    To co proponujesz jest chyba "niekompilowalne", a przynajmniej nie w trywialny sposób. Musiałbym jakoś sprawdzać "nad którymi" linijkami leci GOTO i interpretować to, co w nich jest...

    Zresztą, w Atari Basic poniższy program jest jak najbardziej prawidłowy. I może by się nawet skompilował, ale łatwo wyobrazić sobie całą masę zakręconych konstrukcji, dla których wsparcie w kompilatorze będzie niemożliwe (czyt. możliwe, ale korzyści z kompilacji będą mniejsze niż zwykła interpretacja kodu).
    10 FOR I=1 TO 10
    15 PRINT I
    20 GOTO 100
    30 END
    100 NEXT I


    Na marginesie: Atari BASIC akceptuje instrukcję GOTO i GO TO.
    Dzięki za info - nie wiedziałem... Na szczęście to tylko prosty tweak w gramatyce :)
    • 20: CommentAuthorBluki
    • CommentTime17 Nov 2012
     
    Z tą "gramatyką", to tak nie do końca - token GOTO to 0A, a GO TO - 0B (hex).

    Pisałem o zasadzie używania GOTO w interpreterze, innych rozwiązań kompilator nie musi uwzględniać - to miałem na myśli.
  4.  
    Tak długo jak GOTO i GO TO nie różnią się działaniem mogę obydwa parsować jako to samo. No chyba, że czymś się różnią, ale wtedy zabieram się za kurs BASICa, a nie za kompilator :)
    • 22: CommentAuthormono
    • CommentTime17 Nov 2012 zmieniony
     
    Niczym. Podobnie jak DIM i COM, lub jak ? i PRINT.
    • 23:
       
      CommentAuthormgr_inz_rafal
    • CommentTime20 Nov 2012 zmieniony
     
    OK, wracając do FOR... Zezwalając na kilka NEXTów w środku muszę wyłączyć kontrolę spójności pętli, dlatego też dorobiłem do kompilatora przełącznik, który pozwoli użytkownikowi zdecydować jakie zachowanie bardziej mu odpowiada.

    I tak, dla przykładowego programu:
    10 FOR I = 1 TO 2
    20 FOR J = 1 TO 5
    30 IF J = 3 THEN GOTO 37
    31 PRINT I*J
    32 GOTO 40
    37 PRINT 37
    38 NEXT J
    40 NEXT J
    50 NEXT I
    60 PRINT 666
    dostaniemy albo poprawny wynik (obrazek) albo błąd kompilacji:
    NEXT: Current loop: "I" - next statement = "J"
    ERROR: FOR/NEXT identifier mismatch


    • 24: CommentAuthorrudla
    • CommentTime20 Nov 2012
     
    Is that example correct? I mean what is the meaning of this program? Does not it report error when run in Atari Basic?
    • 25:
       
      CommentAuthormgr_inz_rafal
    • CommentTime20 Nov 2012 zmieniony
     
    It is correct because it executes the FOR/NEXT statements in the correct order. I don't care much about the meaning :)

    Yet for the compiler it is not possible to determine the execution path that the program will follow at compile time, therefore FOR/NEXT consistency checking must be disabled.

    Here's the output from Atari Basic:
    • 26:
       
      CommentAuthormgr_inz_rafal
    • CommentTime21 Nov 2012 zmieniony
     
    Czy w Atari Basic jest jakiś znany bug związany z liczbą "-0"?

    Robię przymiarki do operatorów logicznych i w jednym z eksperymentów dostałem taki wynik:


    Po pierwsze: dlaczego "NOT -0 = 0"? Zwłaszcza, że "0 AND -0 = 0"...

    Po drugie, co to za emotka w 30 linijce listingu? :)

    PS. Jak dla mnie "NOT -0" to ewidentnie powinno być 1.
    • 27: CommentAuthorBluki
    • CommentTime21 Nov 2012 zmieniony
     
    Wygląda na błąd interpretera.



    NOT -0 nie równa się w tym przypadku 0, tylko NOT "dzikie wyrażenie" = 0.
  5.  
    OK, w takim razie ja pożyczę sposób interpretacji tego wyrażenia z TBXL i Basic XE :)
    • 29: CommentAuthormono
    • CommentTime21 Nov 2012 zmieniony
     
    Ciekawe.
    Z analizy kodu procedury FPASC ($D8E6 a więc pakiet liczb FP a nie sam BASIC) wynika, że wykładnik liczby -0 jest równy 128. Wg Zientary od linii 890 następuje prosta zamiana wykładnika na dwie cyfry (FP może być co najwyżej 2-cyfrowa) więc starsza cyfra to 12 :) co powoduje wypisanie tego < ('0'+12='<'). Dalej 8 czyli najmłodsza cyfra 128. Czyli niby błąd po stronie FP, ale...
    BASIC parsując wyrażenia zazwyczaj zapisuje liczby ujemne, jako token znaku "-" oraz samą liczbę, jako dodatnią (polecam sprawdzić wynik działania ? FRE(0), ? FRE(1) i ? FRE(-1)). Wygląda na to, że jest błąd w tablicy parsowania składni SXTAB ($A605), ale gdzie konkretnie trzeba by się zastanowić.
    Gratuluję znalezienia błędu BASICa, którego nie ma w atariki :)
    • 30: CommentAuthormono
    • CommentTime21 Nov 2012 zmieniony
     

    mgr_inz_rafal:

    Po pierwsze: dlaczego "NOT -0 = 0"? Zwłaszcza, że "0 AND -0 = 0"...

    No właśnie z powyższego powodu. Obliczanie wartości logicznej z wyrażenia (tutaj z liczby -0) sprawdza czy liczba FP jest 0 (bajt cechy i znaku liczby = 0), czy jednak nie i wtedy 1.
    • 31:
       
      CommentAuthorjhusak
    • CommentTime21 Nov 2012 zmieniony
     
    Ech, zazdroszczę (i zapewne nie tylko ja) Wam tej dociekliwości :)
    Nie tylko, że nie bo nie, no bo jak nie jak tak, tylko dogłębna analiza!

    Uczmy się od mgr_inz_rafal i mono!!!

    Z drugiej strony jeśli pisałbym kompilator, to jednak nie implementowałbym błędów z pełną świadomością - zapewne programiści atari basic nie opierają się na tych błędach w celu uzyskania jakichś tam korzyści.
    • 32:
       
      CommentAuthormgr_inz_rafal
    • CommentTime21 Nov 2012 zmieniony
     

    mono:

    Wygląda na to, że jest błąd w tablicy parsowania składni SXTAB ($A605), ale gdzie konkretnie trzeba by się zastanowić.
    Jutro na spokojnie poczytam Twojego posta, bo dziś już nie mam siły na myślenie :)

    Na szybko wydaje się jednak, że coś jest skopane w okolicach instrukcji NOT. Linijka 10 listuje się normalnie, więc to nie problem z samym "-0".

    Wygląda też na to, że twórcy TBXL i Basic XE odkryli (i poprawili) ten problem przede mną, tylko pewnie nie chciało im się aktualizować Atariki :) Może wystarczy porównać tablicę parsowania tych języków z tą obecną w Atari BASIC... Ale to na jakiś wolniejszy weekend :)

    jhusak:

    Z drugiej strony jeśli pisałbym kompilator, to jednak nie implementowałbym błędów z pełną świadomością
    Correct. Takich ewidentnie skwaszonych rzeczy nie będę implementował w kompilatorze. Ale kto wie, może trafi się w końcu subtelny błąd, który wielu programistów traktowało jako celowe zachowanie i zaczęli na nim "polegać" - wtedy, dla kompatybilności - trzeba będzie kompilować to błędne działanie.
    • 33:
       
      CommentAuthorjhusak
    • CommentTime21 Nov 2012 zmieniony
     
    A co do 0 and -0 to wszystko w porządku, bo drugie 0 czy -0 nie wpływa na całkowity wynik and, nic z tego nie można wywnioskować.

    Z tego, co wydaje mi się, 0 jest traktowane jako zero tylko wtedy, gdy wszystkie 6 bajtów liczby = 0. Więc wówczas jest to błąd parsowania liczby, która '-' traktuje jako znak ZAWSZE ustawiany (czyli obsadzony bit znaku <> '-' jest prefiksem liczby) co generuje błąd, bo niema tam przypadku -0.

    Zero powinno być <> pięć bajtów mantysy jest równych 0, a cecha dowolna.
    • 34: CommentAuthormono
    • CommentTime22 Nov 2012
     
    @jhusak: no właśnie nie - odpowiedni wycinek:
    0770 ;eXecute NOT operator
    0780 ;
    0790 XNOT JSR GETVAR
    0800 LDA FR0
    0810 ;
    0820 ;RESuLT One
    0830 ;
    0840 RESLTO BEQ ONEP
    0850 ;
    0860 ;result ZERO
    0870 ;
    0880 ZERO LDA #$00
    0890 TAY
    0900 BEQ STRES
    0910 ;
    0920 ;result ONE Positive
    0930 ;
    0940 ONEP LDA #$40
    0950 ;

    FR0 to cecha (ze nakiem) i znak liczby.
  6.  

    mono:

    Gratuluję znalezienia błędu BASICa, którego nie ma w atariki :)
    Już ktoś dodał :)
    • 36:
       
      CommentAuthormgr_inz_rafal
    • CommentTime29 Nov 2012 zmieniony
     
    Na dzisiaj przygotowałem cały zestaw operatorów logicznych. Poniżej kod oraz obrazki z Atari Basic oraz z kompilatora.
    10 IF 5>6 AND (0 OR 3=3) THEN PRINT 1
    20 IF 5>6 AND 0 OR 3=3 THEN PRINT 2
    30 IF 5> NOT 6 THEN PRINT 3
    40 IF 5<>3 THEN PRINT NOT 3 + NOT 0
    50 A=5
    60 IF A=5 THEN A=A + NOT 0
    70 PRINT A
    80 DIM STEFAN(10)
    90 STEFAN( NOT 0)=666
    100 PRINT STEFAN(A - 5)


    Atari Basic:


    ABC:


    PS. 12 zmiennych tymczasowych :)
    • 37:
       
      CommentAuthormgr_inz_rafal
    • CommentTime30 Nov 2012 zmieniony
     
    Hej,
    Poniższa konstrukcja zgłasza błąd. Znacie przyczynę, bo wydaje się, że nie ma tutaj żadnych przeciwwskazań do działania?
    10 DIM T(5)
    20 FOR T(3)=4 TO 8:NEXT T(3)
    • 38: CommentAuthorwieczor
    • CommentTime30 Nov 2012
     
    Chyba nie znam języka w którym element tablicy może być używany jako iterator :)
    • 39:
       
      CommentAuthormgr_inz_rafal
    • CommentTime30 Nov 2012 zmieniony
     
    No chociażby C
    int main ()
    {
    int a[17];
    for (a[4] = 5; a[4] < 8; ++a[4])
    {}
    }
    • 40: CommentAuthorwieczor
    • CommentTime30 Nov 2012
     
    I to się kompiluje? Nigdy czegoś takiego nie próbowałem :) No, w Basicu najwyrazniej nie mozna :D Nie w tym :D
  7.  
    W C nawet dużo ciekawsze rzeczy się kompilują :)

    Polecam ioccc.org.
    • 42: CommentAuthormono
    • CommentTime30 Nov 2012
     
    Wygląda to znów na ograniczenie nałożone przez tablicę kontroli składni, bo sama procedura NUMVAR służąca do określenia rodzaju zmiennej numerycznej potrafi rozpoznać, że ma do czynienia ze mienną tablicową.
    Gramatyka Panie, gramatyka...
    • 43:
       
      CommentAuthorjhusak
    • CommentTime30 Nov 2012
     
    Jak sama nazwa wskazuje: zmienna sterująca pętli for, a nie l-wartość sterująca.
  8.  
    Jak nazwa wskazuje "zmienna", czyli l-wartość :)
    • 45:
       
      CommentAuthormgr_inz_rafal
    • CommentTime3 Dec 2012 zmieniony
     
    Dzisiaj przedstawiam dokończonego PRINTa. Dodałem obsługę stringów oraz przecinka i średnika.

    Np. tabliczka mnożenia:
    10 FOR I = 1 TO 9
    20 FOR J = 1 TO 9
    30 PRINT I;"*";J,"= ";I*J
    40 NEXT J
    45 PRINT "---"
    50 NEXT I
    60 PRINT 666




    I jeszcze programistyczny klasyk, czyli trójkąt z gwiazdek:
    10 FOR I = 15 TO 1 STEP -1
    20 FOR J = 1 TO I
    30 PRINT "*";
    40 NEXT J
    50 PRINT
    60 NEXT I
    70 PRINT 666


    • 46:
       
      CommentAuthormgr_inz_rafal
    • CommentTime3 Dec 2012 zmieniony
     
    I jeszcze od razu pytanie o tabulator. Jak BASIC ma domyślnie ustawione Tab Stopy?

    Poniżej dwa obrazki powstałe z takiego kodu:
    10 PRINT 1,2,3,4,5,6,7,8,9
    Pierwszy to Atari Basic, a drugi to program skompilowany.

    Obsługa przecinka to u mnie po prostu wypisanie znaku 127, ale może coś jeszcze trzeba zrobić? Mieszanie w komórce 201 ($D9) nie daje efektów.

    • 47: CommentAuthormono
    • CommentTime3 Dec 2012 zmieniony
     
    Są dwa skoki tabulatora (niezależne od siebie):
    1. Realizowany przez "," w instrukcji PRINT.
    2. TAB edytora (CHR$(127)).
    Pierwszy ustalony jest podczas startu BASICa na 10 w rejestrze PTABW ($C9) i przepisywany do tymczasowego licznika AUXBR w procedurze PRINT. Modyfikacja PTABW np za pomocą POKE wpływa na działanie PRINT.
    Drugi jest efektem wykonania kodu sterującego edytora ekranowego i zależy od pozycji tabulacji ustalanych w tablicy TABMAP ($2A3..$2A7) lub bezpośrednio w edytorze za pomocą klawiszy Shift+TAB (CHR$(158)), Ctrl+TAB (CHR$(159)).

    Edit: IMHO zamiast używać edytora powinieneś rysować tyle spacji ile wskazuje PTABW.
    • 48:
       
      CommentAuthormgr_inz_rafal
    • CommentTime3 Dec 2012 zmieniony
     
    Ale wartość PTABW nie zmienia się dynamicznie podczas PRINTa, nie?

    W takim razie rysując po prostu 10 (domyślnie) spacji, uzyskał bym inny output niż w AtariBasic dla poniższego programu. Basic raz wypisał 7 spacji, a w linijce pod spodem już tylko 6.

    • 49: CommentAuthormono
    • CommentTime3 Dec 2012 zmieniony
     
    Nie zmienia się dynamicznie. Punktem w którym kończy się malować spacje jest wielokrotność PTABW (ustalana w tymczasowym rejestrze AUXBR od etykiety COM w procedurze XPRINT ->link<- ). Tab wykraczający poza szerokość ekranu ląduje na lewym marginesie następnego wiersza.
    Z kolei PTABW można zmieniać między PRINTami. Resetowany na 10 jest bodajże tylko przy NEW i po starcie BASICa.
    • 50:
       
      CommentAuthormgr_inz_rafal
    • CommentTime4 Dec 2012 zmieniony
     
    OK, obszedłem problem za pomocą przydatnej komórki $55 i rysuję tyle spacji ile brakuje do wielokrotności 10.

    Efekt jest jeszcze trochę inny (obrazek) niż daje XPRINT - liczby są idealnie jedna pod drugą. Właściwie nawet ładniej niż w Atari Basic, więc chyba tak zostawię :)

    PS. Kto inicjuje PTABW? Jak odpalam .xex to jest tam 0, a nie domyślne $a.