From 80642da4769deb601f4d07ecb5b108429fb76e08 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Wed, 28 Nov 2018 14:37:02 +0100 Subject: [PATCH] Added doc for each bf instruction --- main.rkt | 93 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/main.rkt b/main.rkt index 363766e..e0f7a8a 100644 --- a/main.rkt +++ b/main.rkt @@ -18,11 +18,11 @@ ; Interpretation: a data pointer in the brainf*ck language in a tape. ; A Program is a String of: -; - ">" -; - "<" -; - "+" -; - "-" -; - "." +; - ">" (tape-right) +; - "<" (tape-left) +; - "+" (add1) +; - "-" (sub1) +; - "." (out) ; - "," ; - "[" ; - "]" @@ -34,22 +34,24 @@ ; A World is a (make-world tape dp output program ip) where: ; - tape: Tape ; - dp: DataPointer +; - tape-len: Nat ; - output: String ; - program: Program ; - ip: InstructionPointer ; Interpretation: the current state of execution of a brainf*ck program. -(define-struct world [tape dp output program ip]) +(define-struct world [tape dp tape-len output program ip]) ; Template function for World (define (fn-for-world w) (... (world-tape w) (world-dp w) + (world-tape-len w) (world-output w) (world-program w) (world-ip w))) ; string->program: String -> Program -; Given a string, returns a bf program without any invalid character +; Given a string, returns a b(world-dp-len w)f 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 @@ -85,17 +87,17 @@ ; program->world: Program -> World ; Given a program, returns the corresponding initial world state. (define (program->world p) - (make-world (cons 0 '()) 0 "" p 0)) + (make-world (cons 0 '()) 0 1 "" p 0)) ; Tests for program->world -(check-expect (program->world "[->+<]") (make-world (list 0) 0 "" "[->+<]" 0)) +(check-expect (program->world "[->+<]") (make-world (list 0) 0 1 "" "[->+<]" 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)))])) + [else (cons (first tape) (tape-help (rest tape) (sub1 dp) alter))])) ; Tests for tape-help (check-expect (tape-help (list 0) 0 add1-byte) (list 1)) @@ -106,19 +108,88 @@ (define (exec-add1 w) (make-world (tape-help (world-tape w) (world-dp w) add1-byte) (world-dp w) + (world-tape-len 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 +; 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-tape-len w) (world-output w) (world-program w) (add1 (world-ip w)))) +; exec-tape-left: World -> World +; Given a world, returns a new world with the < instruction executed +(define (exec-tape-left w) + (if (zero? (world-dp w)) + (error "Can't access negative tape positions") + (make-world (world-tape w) + (sub1 (world-dp w)) + (world-tape-len w) + (world-output w) + (world-program w) + (add1 (world-ip w))))) + +; exec-tape-right: World -> World +; Given a world, returns a new world with the > instruction executed +(define (exec-tape-right w) + (local [(define end-of-tape (= (world-dp w) (sub1 (world-tape-len w))))] + (make-world + (if end-of-tape + (cons (world-tape w) 0) + (world-tape w)) + (add1 (world-dp w)) + (if end-of-tape + (add1 (world-tape-len w)) + (world-tape-len w)) + (world-output w) + (world-program w) + (add1 (world-ip w))))) + +; exec-out: World -> World +; Given a world, returns a new world with the . instruction executed +(define (exec-out w) + (make-world + (world-tape w) + (world-dp w) + (world-tape-len w) + (string-append + (world-output w) + (list->string + (list (integer->char (list-ref (world-tape w) (world-dp w)))))) + (world-program w) + (add1 (world-ip w)))) + +; find-first: 1String String Nat -> Nat +(define (find-first char string start) + (cond [(string=? (substring string start (add1 start)) char) start] + [else (find-first char string (add1 start))])) + +; exec-loop-start: World -> World +; Given a world, returns a new world with the [ instruction executed +(define (exec-loop-start w) + (local [(define jump (zero? (list-ref (world-tape w) (world-dp w))))] + (make-world + (world-tape w) + (world-dp w) + (world-tape-len w) + (world-output w) + (world-program w) + (add1 (if jump + (find-first "]" (world-program w) (world-ip w)) + (world-ip w)))))) + +; Tests for exec-out +(check-expect (exec-out (make-world (list 50) 0 1 "" ".[->+<]" 0)) + (make-world (list 50) 0 1 "2" ".[->+<]" 1)) +(check-expect (exec-out (make-world (list 65) 0 1 "" ".[->+<]" 0)) + (make-world (list 65) 0 1 "A" ".[->+<]" 1)) + ; main: Filename -> World ; Given a Filename, return the last world state of execution of the ; corresponding bf program in the file