;; Kathi Fisler ;; Powerpoint exercise ;; Stage 4 : macro front-end ;; February 2, 2003 ;;;;;;;;;;;;;;; THE INTERFACE LANGUAGE ;;;;;;;;;;;;;;;;;;;;;;; ;; print-string : string -> void ;; prints string and a newline to the screen (define (print-string str) (printf "~a~n" str)) ;; print-newline : -> void ;; prints a newline on the screen (define (print-newline) (printf "~n")) ;; print-unnumbered-strings : list[string] -> void ;; prints a list of strings to the screen, each prefixed with a - (define (print-unnumbered-strings strlist) (for-each (lambda (str) (printf "- ~a~n" str)) strlist)) ;; print-numbered-strings : list[string] -> void ;; prints a list of strings to the screen, each prefixed with ;; a number (in consecutive increasing order) (define (print-numbered-strings strlist label) (cond [(empty? strlist) void] [(cons? strlist) (begin (printf "~a. ~a~n" label (first strlist)) (print-numbered-strings (rest strlist) (+ 1 label)))])) ;; await-click : -> void ;; mimics a mouse click by waiting for the user to type a character (define (await-click) (read)) ;;;;;;;;;; INTERFACE HELPERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; print-slide-title : string -> void ;; displays title of slide on screen (define (print-slide-title title-str) (print-string (string-append "Title: " title-str)) (print-newline)) ;; print-slide-body : slide-body -> void ;; displays contents of body on screen (define (print-slide-body body) (cond [(string? body) (print-string body)] [(pointlist? body) (cond [(pointlist-numbered? body) (print-numbered-strings (pointlist-points body) 1)] [else (print-unnumbered-strings (pointlist-points body))])])) ;; print-slide : slide -> void ;; displays contents of slide on screen (define (print-slide aslide) (begin (print-string "------------------------------") (print-slide-title (slide-title aslide)) (print-slide-body (slide-body aslide)) (print-string "------------------------------"))) ;; end-show : -> void ;; displays end of show message on screen (define (end-show) (print-string "End of show")) ;;;;;;;;;;;; THE DATA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; a slide is a (make-slide string slide-body) (define-struct slide (title body)) ;; a slide-body is either ;; - a string (paragraph), or ;; - a (make-pointlist list[string] boolean) (define-struct pointlist (points numbered?)) ;; A cmd is ;; - (make-display (-> slide)) ;; - (make-timecond (time->boolean) section section) (define-struct display (slide)) (define-struct timecond (time-limit within-time over-time)) ;; A talk is a list of sections (define-struct talk (sects)) ;; A section is a list of commands (define-struct section (cmds)) ;;;;;;;;;;;;;;; LANGUAGE HELPERS ;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; pointlist-numbered : list[string] -> pointlist ;; create numbered pointlist with given points (define (pointlist-numbered points) (make-pointlist points true)) ;; pointlist-bulleted : list[string] -> pointlist ;; create non-numbered pointlist with given points (define (pointlist-bulleted points) (make-pointlist points false)) ;; disp-slide : slide -> display ;; gives another name for make-display for readability (define disp-slide make-display) ;;;;;;;;;;;;;;;; MACROS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; macro to wrap lambda around a slide specification (define-syntax myslide (syntax-rules () [(myslide title body) (lambda () (make-slide title body))])) ;; macro to wrap list and section structure around a sequence of commands (define-syntax mytalk (syntax-rules () [(mytalk cmd1 ...) (make-talk (list (make-section (list cmd1 ...))))])) ;; macro to move slide specifications into talk (define-syntax talk-with-slides (syntax-rules () [(talk-with-slides ((slide name1 title1 body1) ...) cmd1 ...) (let ([name1 (myslide title1 body1)] ...) (mytalk cmd1 ...))])) ;; macro to simplify specification of timeconds ;; note this has two cases: you can leave the second list off in ;; the program and the macro will insert the empty section (define-syntax time-branch (syntax-rules () [(time-branch test cmdlist) (make-timecond test (make-section cmdlist) (make-section empty))] [(time-branch test cmdlist1 cmdlist2) (make-timecond test (make-section cmdlist1) (make-section cmdlist2))])) ;;;;;;;;;;;;;;;; INTERPRETER ;;;;;;;;;;;;;;;;;;;;;;;;;; (define start-time 0) (define example-index 0) ;; elapsed-time : -> number ;; returns the elapsed seconds since the recorded start time (define (elapsed-time) (- (current-seconds) start-time)) ;; make-next-example-title : -> string ;; creates string from "Example" and the current example index ;; EFFECTS: increments example-index (define (make-next-example-title) (begin (set! example-index (+ 1 example-index)) (format "Example ~a" example-index))) ;; run-cmd : cmd -> void ;; executes the given command (define (run-cmd cmd) (cond [(display? cmd) (begin (print-slide ((display-slide cmd))) (await-click))] [(timecond? cmd) (cond [((timecond-time-limit cmd) (elapsed-time)) (run-section (timecond-within-time cmd))] [else (run-section (timecond-over-time cmd))])])) ;; run-cmdlist : list[cmd] -> void ;; executes every command in a list (define (run-cmdlist cmd-lst) (cond [(empty? cmd-lst) void] [(cons? cmd-lst) (begin (run-cmd (first cmd-lst))) (run-cmdlist (rest cmd-lst))])) ;; run-sections : list[section] -> void ;; executes all the commands in the given section list (define (run-sections sect-lst) (cond [(empty? sect-lst) void] [(cons? sect-lst) (begin (run-section (first sect-lst)) (run-sections (rest sect-lst)))])) ;; run-section : section -> void ;; executes all the commands in the given section (define (run-section asect) (run-cmdlist (section-cmds asect))) ;; run-talk : talk -> void ;; executes the commands in a talk then displays end-of-show message (define (run-talk a-talk) (begin (set! example-index 0) (set! start-time (current-seconds)) (run-sections (talk-sects a-talk)) (end-show))) ;;;;;;;;;;;;;;;;;;;;;;;; THE TALKS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; talk1 : uses new pointlist helpers (define talk1 (let ([make-intro-slide (lambda () (make-slide "Hand Evals in DrScheme" "Hand evaluation helps you learn how Scheme reduces programs to values"))] [make-arith-eg-slide (lambda () (make-slide (make-next-example-title) (pointlist-bulleted (list "(+ (* 2 3) 6)" "(+ 6 6)" "12"))))] [make-func-eg-slide (lambda () (make-slide (make-next-example-title) (pointlist-bulleted (list "(define (foo x) (+ x 3))" "(* (foo 5) 4)" "(* (+ 5 3) 4)" "(* 8 4)" "32"))))] [make-summary-slide (lambda () (make-slide "Summary: How to Hand Eval" (pointlist-numbered (list "Find the innermost expression" "Evaluate one step" "Repeat until have a value"))))]) (make-talk (list (make-section (list (make-display make-intro-slide) (make-timecond (lambda (time-in-talk) (> 5 time-in-talk)) (make-section (list (make-display make-arith-eg-slide))) (make-section empty)) (make-display make-func-eg-slide) (make-display make-summary-slide))))))) ;; talk2 : uses pointlist helpers and myslide macro (define talk2 (let ([make-intro-slide (myslide "Hand Evals in DrScheme" "Hand evaluation helps you learn how Scheme reduces programs to values")] [make-arith-eg-slide (myslide (make-next-example-title) (pointlist-bulleted (list "(+ (* 2 3) 6)" "(+ 6 6)" "12")))] [make-func-eg-slide (myslide (make-next-example-title) (pointlist-bulleted (list "(define (foo x) (+ x 3))" "(* (foo 5) 4)" "(* (+ 5 3) 4)" "(* 8 4)" "32")))] [make-summary-slide (myslide "Summary: How to Hand Eval" (pointlist-numbered (list "Find the innermost expression" "Evaluate one step" "Repeat until have a value")))]) (make-talk (list (make-section (list (make-display make-intro-slide) (make-timecond (lambda (time-in-talk) (> 5 time-in-talk)) (make-section (list (make-display make-arith-eg-slide))) (make-section empty)) (make-display make-func-eg-slide) (make-display make-summary-slide))))))) ;; talk3 : uses pointlist helpers, myslide macro, and mytalk macro (define talk3 (let ([make-intro-slide (myslide "Hand Evals in DrScheme" "Hand evaluation helps you learn how Scheme reduces programs to values")] [make-arith-eg-slide (myslide (make-next-example-title) (pointlist-bulleted (list "(+ (* 2 3) 6)" "(+ 6 6)" "12")))] [make-func-eg-slide (myslide (make-next-example-title) (pointlist-bulleted (list "(define (foo x) (+ x 3))" "(* (foo 5) 4)" "(* (+ 5 3) 4)" "(* 8 4)" "32")))] [make-summary-slide (myslide "Summary: How to Hand Eval" (pointlist-numbered (list "Find the innermost expression" "Evaluate one step" "Repeat until have a value")))]) (mytalk (make-display make-intro-slide) (make-timecond (lambda (time-in-talk) (> 5 time-in-talk)) (make-section (list (make-display make-arith-eg-slide))) (make-section empty)) (make-display make-func-eg-slide) (make-display make-summary-slide)))) ;; talk4 : uses talk-with-slides macro (define talk4 (talk-with-slides ((slide intro-slide "Hand Evals in DrScheme" "Hand evaluation helps you learn how Scheme reduces programs to values") (slide arith-eg-slide (make-next-example-title) (pointlist-bulleted (list "(+ (* 2 3) 6)" "(+ 6 6)" "12"))) (slide func-eg-slide (make-next-example-title) (pointlist-bulleted (list "(define (foo x) (+ x 3))" "(* (foo 5) 4)" "(* (+ 5 3) 4)" "(* 8 4)" "32"))) (slide summary-slide "Summary: How to Hand Eval" (pointlist-numbered (list "Find the innermost expression" "Evaluate one step" "Repeat until have a value")))) (make-display intro-slide) (make-timecond (lambda (time-in-talk) (> 5 time-in-talk)) (make-section (list (make-display arith-eg-slide))) (make-section empty)) (make-display func-eg-slide) (make-display summary-slide))) ;; talk5 : clean-up command names and the timecond syntax (define talk5 (talk-with-slides ((slide intro-slide "Hand Evals in DrScheme" "Hand evaluation helps you learn how Scheme reduces programs to values") (slide arith-eg-slide (make-next-example-title) (pointlist-bulleted (list "(+ (* 2 3) 6)" "(+ 6 6)" "12"))) (slide func-eg-slide (make-next-example-title) (pointlist-bulleted (list "(define (foo x) (+ x 3))" "(* (foo 5) 4)" "(* (+ 5 3) 4)" "(* 8 4)" "32"))) (slide summary-slide "Summary: How to Hand Eval" (pointlist-numbered (list "Find the innermost expression" "Evaluate one step" "Repeat until have a value")))) (disp-slide intro-slide) (time-branch (lambda (time-in-talk) (> 5 time-in-talk)) (list (disp-slide arith-eg-slide))) (disp-slide func-eg-slide) (disp-slide summary-slide)))