diff --git a/main.rkt b/main.rkt index 692ebfb..363766e 100644 --- a/main.rkt +++ b/main.rkt @@ -4,6 +4,9 @@ ; 2018-11-21 - Made by Claudio Maggioni - Tommaso Rodolfo Masera ; easybf +(require 2htdp/batch-io) +(require 2htdp/image) +(require 2htdp/universe) ; A Byte is an Int between 0 and 255 ; Interpretation: a byte in decimal notation. @@ -45,18 +48,87 @@ (world-program w) (world-ip w))) -; read-file: FileName -> String -; Given a filename, parses it and returns the content as a string. -(define (read-file fl) - ...) +; string->program: String -> Program +; Given a string, returns a bf program without any invalid character +(define (string->program s) + (local [; valid-char: 1String -> Boolean + ; Given a valid-char, returns #t if the character is a valid bf + ; instruction. + (define (valid-char? s) + (member? s '(">" "<" "+" "-" "," "." "[" "]")))] + (implode (filter valid-char? (explode s))))) + +; Tests for string->program +(check-expect (string->program "hello") "") +(check-expect (string->program "+world50-[]") "+-[]") +(check-expect (string->program "") "") + +; add1-byte: Byte -> Byte +; Given a byte, returns the byte+1 simulating overflows +(define (add1-byte b) + (modulo (add1 b) 256)) + +; Tests for add1-byte +(check-expect (add1-byte 255) 0) +(check-expect (add1-byte 254) 255) + +; sub1-byte: Byte -> Byte +; Given a byte, returns the byte-1 simulating underflows +(define (sub1-byte b) + (cond [(zero? b) 255] + [else (sub1 b)])) + +; Tests for sub1-byte +(check-expect (sub1-byte 0) 255) +(check-expect (sub1-byte 1) 0) + +; program->world: Program -> World +; Given a program, returns the corresponding initial world state. +(define (program->world p) + (make-world (cons 0 '()) 0 "" p 0)) + +; Tests for program->world +(check-expect (program->world "[->+<]") (make-world (list 0) 0 "" "[->+<]" 0)) + +; tape-help: Tape DP (Byte -> Byte) -> Tape +; Given a tape and a data pointer, returns the same tape with the data in the +; location of the data pointer altered by the function `alter`. +(define (tape-help tape dp alter) + (cond [(zero? dp) (cons (alter (first tape)) (rest tape))] + [else (cons (first tape) (tape-help (rest tape) (sub1 dp)))])) + +; Tests for tape-help +(check-expect (tape-help (list 0) 0 add1-byte) (list 1)) +(check-expect (tape-help (list 0 1 2 3) 2 sub1-byte) (list 0 1 1 3)) + +; exec-add1: World -> World +; Given a world, returns a new world with the + instruction executed +(define (exec-add1 w) + (make-world (tape-help (world-tape w) (world-dp w) add1-byte) + (world-dp w) + (world-output w) + (world-program w) + (add1 (world-ip w)))) + +; exec-sub1: World -> World +; Given a world, returns a new world with the + instruction executed +(define (exec-sub1 w) + (make-world (tape-help (world-tape w) (world-dp w) sub1-byte) + (world-dp w) + (world-output w) + (world-program w) + (add1 (world-ip w)))) + +; main: Filename -> World +; Given a Filename, return the last world state of execution of the +; corresponding bf program in the file +(define (main file) + (program->world (string->program (read-file file)))) ; TODO: -; - read-file: FileName -> String -; - string->program: String -> Program (filter of valid instructions) -; - program->world: Program -> World (compute initial world state) ; - big-bang: ; - - - - - - inital state (make-world (list 0) 0 "" 0) -; - - - - - - on-tick fetch, decode, execute +; - - - - - - on-tick fetch, decode, execute ; - - - - - - on-key for "," ; - - - - - - (on-mouse for stepper) -; - - - - - - (draw-scene for output and tape) \ No newline at end of file +; - - - - - - (draw-scene for output and tape)