finish for-next loops

This commit is contained in:
Matthew Butterick 2016-05-31 12:50:43 -07:00
parent 30fa41f05f
commit 481cbab336
7 changed files with 80 additions and 37 deletions

View File

@ -1,10 +1,10 @@
#lang racket/base #lang racket/base
(require racket/provide racket/list racket/string racket/format racket/match racket/port (require racket/provide racket/list racket/string racket/format racket/match racket/port
br/define br/syntax br/datum br/debug br/conditional br/define br/syntax br/datum br/debug br/conditional racket/function
(for-syntax racket/base racket/syntax br/syntax br/debug br/define)) (for-syntax racket/base racket/syntax br/syntax br/debug br/define))
(provide (except-out (all-from-out racket/base) define) (provide (except-out (all-from-out racket/base) define)
(all-from-out racket/list racket/string racket/format racket/match racket/port (all-from-out racket/list racket/string racket/format racket/match racket/port
br/syntax br/datum br/debug br/conditional) br/syntax br/datum br/debug br/conditional racket/function)
(for-syntax (all-from-out racket/base racket/syntax br/syntax br/debug)) (for-syntax (all-from-out racket/base racket/syntax br/syntax br/debug))
(for-syntax caller-stx shared-syntax with-shared-id with-calling-site-id) ; from br/define (for-syntax caller-stx shared-syntax with-shared-id with-calling-site-id) ; from br/define
(filtered-out (filtered-out

View File

@ -0,0 +1,19 @@
#lang br/demo/basic
1 PRINT TAB(32);"3D PLOT"
2 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
3 PRINT:PRINT:PRINT
5 DEF FNA(Z)=30*EXP(-Z*Z/100)
100 PRINT
110 FOR X=-30 TO 30 STEP 1.5
120 L=0
130 Y1=5*INT(SQR(900-X*X)/5)
140 FOR Y=Y1 TO -Y1 STEP -5
150 Z=INT(25+FNA(SQR(X*X+Y*Y))-.7*Y)
160 IF Z<=L THEN 190
170 L=Z
180 PRINT TAB(Z);"*";
190 NEXT Y
200 PRINT
210 NEXT X
300 END

View File

@ -0,0 +1,9 @@
#lang br/demo/basic
1 REM http://www.vintage-basic.net/bcg/amazing.bas
10 PRINT TAB(28);"AMAZING PROGRAM"
20 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
30 PRINT:PRINT:PRINT:PRINT
100 INPUT "WHAT ARE YOUR WIDTH AND LENGTH";H,V
102 IF H<>1 AND V<>1 THEN 110
104 PRINT "MEANINGLESS DIMENSIONS. TRY AGAIN.":GOTO 100

View File

@ -103,8 +103,8 @@
(define-macro expr (define-macro expr
[(_ COMP-EXPR) #'COMP-EXPR] [(_ COMP-EXPR) #'COMP-EXPR]
[(_ COMP-EXPR "AND" SUBEXPR) #'(basic:and COMP-EXPR SUBEXPR)] [(_ COMP-EXPR "and" SUBEXPR) #'(basic:and COMP-EXPR SUBEXPR)]
[(_ COMP-EXPR "OR" SUBEXPR) #'(basic:or COMP-EXPR SUBEXPR)]) [(_ COMP-EXPR "or" SUBEXPR) #'(basic:or COMP-EXPR SUBEXPR)])
(define-macro comp-expr (define-macro comp-expr
[(_ SUM) #'SUM] [(_ SUM) #'SUM]
@ -144,18 +144,20 @@
(define (RND num) (* (random) num)) (define (RND num) (* (random) num))
(define-macro basic:input (define-macro basic:input
[(_ PRINT-LIST _ID) [(_ (print-list . PL-ITEMS) ID ...)
#'(begin #'(begin
(basic:print (append PRINT-LIST (list ";"))) (basic:print (append (print-list . PL-ITEMS) (list ";")))
(basic:input _ID))] (basic:input ID) ...)]
[(_ ID) #'(set! ID (let* ([str (read-line)] [(_ ID ...) #'(begin
(set! ID (let* ([str (read-line)]
[num (string->number str)]) [num (string->number str)])
(or num str)))]) (or num str))) ...)])
(define (basic:goto where) where) (define (basic:goto where) where)
(define (basic:return) (car return-stack)) (define (basic:return) (car return-stack))
(define (basic:stop) (basic:end))
(define (basic:end) (raise-program-end-error)) (define (basic:end) (raise-program-end-error))
(define for-stack empty) (define for-stack empty)
@ -179,21 +181,21 @@
[else [else
(statement VAR "=" START-VALUE) (statement VAR "=" START-VALUE)
(call/cc (λ(for-k) (call/cc (λ(for-k)
(push-for-stack (λ () (push-for-stack (cons 'VAR
(define next-val (+ VAR STEP-VALUE)) (λ ()
(and (<= next-val END-VALUE) (define next-val (+ VAR STEP-VALUE))
(set! VAR next-val) (and (<= next-val END-VALUE)
(for-k)))))) (set! VAR next-val)
(for-k)))))))
(raise-line-end-error)]))]) (raise-line-end-error)]))])
(define (handle-next [stack-selector-proc car])
(unless (pair? for-stack)
(error 'next "for-stack is empty"))
(let ([for-thunk (cdr (stack-selector-proc for-stack))])
(unless (for-thunk)
(pop-for-stack))))
(define-macro basic:next (define-macro basic:next
[(_ VAR) [(_ VAR) #'(handle-next (λ(stack) (assq 'VAR stack)))] ; named `next` means find var in stack
;; todo: named `next` means find var in stack [(_) #'(handle-next)]) ; plain `next` implies var on top of stack
#'()]
[(_)
;; plain `next` implies var on top of stack
#'(if (pair? for-stack)
(let ([for-thunk (car for-stack)])
(unless (for-thunk)
(pop-for-stack)))
(error 'next "for-stack is empty"))])

View File

@ -4,20 +4,20 @@ basic-program : line*
line: NUMBER statement [/":" statement]* line: NUMBER statement [/":" statement]*
statement : "end" statement : "end" | "stop"
| "gosub" expr | "gosub" expr
| "goto" expr | "goto" expr
| "if" expr /"then" (statement | expr) [/"else" (statement | expr)] | "if" expr /"then" (statement | expr) [/"else" (statement | expr)]
| "input" [print-list /";"] ID | "input" [print-list /";"] ID [/"," ID]*
| ID "=" expr | [/"let"] ID "=" expr
| "print" [print-list] | "print" [print-list]
| "return" | "return"
| "for" ID /"=" value /"to" value [/"step" value] | "for" ID /"=" value /"to" value [/"step" value]
| "next" [ID] | "next" [ID]
print-list : expr [";" [print-list]] print-list : expr [[";"] [print-list]]
expr : comp-expr [("AND" | "OR") expr] expr : comp-expr [("and" | "or") expr]
comp-expr : sum [("=" | ">" | ">=" | "<" | "<=" | "<>") comp-expr] comp-expr : sum [("=" | ">" | ">=" | "<" | "<=" | "<>") comp-expr]
@ -28,7 +28,7 @@ product : [product ("*" | "/")] value
@value : ID @value : ID
| id-expr | id-expr
| /"(" expr /")" | /"(" expr /")"
| STRING
| NUMBER | NUMBER
| STRING
/id-expr : ID [/"(" expr [/"," expr]* /")"] /id-expr : ID [/"(" expr [/"," expr]* /")"]

View File

@ -1,6 +1,19 @@
#lang br/demo/basic #lang br/demo/basic
1 A = 2 10 PRINT TAB(30);"SINE WAVE"
10 PRINT A < 2 20 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
12 C$ = "string thing" 30 PRINT: PRINT: PRINT: PRINT: PRINT
15 PRINT A;: PRINT C$ 40 REMARKABLE PROGRAM BY DAVID AHL
50 B=0
100 REM START LONG LOOP
110 FOR T=0 TO 40 STEP .25
120 A=INT(26+25*SIN(T))
130 PRINT TAB(A);
140 IF B=1 THEN 180
150 PRINT "CREATIVE"
160 B=1
170 GOTO 200
180 PRINT "COMPUTING"
190 B=0
200 NEXT T
999 END

View File

@ -16,14 +16,14 @@
(lexer-src-pos (lexer-src-pos
[(eof) eof] [(eof) eof]
[(union #\tab #\space #\newline [(union #\tab #\space #\newline
(seq number " REM" (repetition 1 +inf.0 (char-complement #\newline)) #\newline)) (get-token input-port)] (seq number " REM" (repetition 0 +inf.0 (char-complement #\newline)) #\newline)) (get-token input-port)]
[(union "PRINT" "print" "FOR" "for" "TO" "to" "STEP" "step" "IF" "if" [(union "PRINT" "print" "FOR" "for" "TO" "to" "STEP" "step" "IF" "if"
"GOTO" "goto" "INPUT" "input" "LET" "let" "NEXT" "next" "GOTO" "goto" "INPUT" "input" "LET" "let" "NEXT" "next"
"RETURN" "return" "CLEAR" "clear" "LIST" "list" "RUN" "run" "RETURN" "return" "CLEAR" "clear" "LIST" "list" "RUN" "run"
"END" "end" "THEN" "then" "ELSE" "else" "GOSUB" "gosub" "END" "end" "THEN" "then" "ELSE" "else" "GOSUB" "gosub"
"AND" "and" "OR" "or" "AND" "and" "OR" "or" "STOP" "stop" "LET" "let"
";" "=" "(" ")" "+" "-" "*" "/" ";" "=" "(" ")" "+" "-" "*" "/"
"<=" ">=" "<>" "<" ">" "=" ":") (string-downcase lexeme)] "<=" ">=" "<>" "<" ">" "=" ":" ",") (string-downcase lexeme)]
[(union ",") (get-token input-port)] [(union ",") (get-token input-port)]
[number (token 'NUMBER (string->number lexeme))] [number (token 'NUMBER (string->number lexeme))]
[(seq (repetition 1 +inf.0 upper-case) (? "$")) (token 'ID (string->symbol lexeme))] [(seq (repetition 1 +inf.0 upper-case) (? "$")) (token 'ID (string->symbol lexeme))]