Guest User

Untitled

a guest
Feb 26th, 2012
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scheme 8.58 KB | None | 0 0
  1. #lang racket
  2.  
  3. (require "stack.rkt")
  4. (provide do-function)
  5. (define all-types '(#\S #\C #\R #\N #\B))
  6.  
  7. (define (string-case key . objects)
  8.   (define (match-helper l)
  9.     (cond ((null? l) #f)
  10.           ((string=? (car l) key) #t)
  11.           (else (match-helper (cdr l)))
  12.           )
  13.     )
  14.   (define (match remaining)
  15.     (cond ((null? (cdr remaining)) (car remaining))
  16.           ((match-helper (caar remaining)) (cadar remaining))
  17.           (else (match (cdr remaining))))
  18.     )
  19.   (match objects)
  20.   )                          
  21.  
  22. (define (give-error msg . args)
  23.   (define (iter msg args)
  24.     (let ((m msg) (a args))
  25.       (cond ((null? msg) (for-each (lambda (a) (display a) (display ", ")) args))
  26.             ((null? args) (newline)(error (car msg)))
  27.             (else (display (car msg))
  28.                   (display (car args))
  29.                   (iter (cdr msg) (cdr args))))
  30.       )
  31.     )
  32.   (iter msg args)
  33.   )
  34.  
  35. (define (get-requirements token)
  36.   (case (car token)
  37.     ((#\O) (string-case (cdr token)
  38.              '(("neg") ((#\N)))
  39.              '((#\N) (#\N))
  40.              ))
  41.     ((#\M) '( (#\N #\B #\C) (#\N #\B #\C)))
  42.     ((#\V) (string-case (cdr token)
  43.              '(("not") ((#\B)))
  44.              '((#\B) (#\B))
  45.              ))
  46.     (else (string-case (cdr token)
  47.             '(("load") ((#\R)))
  48.             '(("save") ((#\R) (#\S #\C #\R #\N #\B)))
  49.             '(("ref") ((#\N)))
  50.             '(("concat") ((#\S) (#\S)))
  51.             '(("substr") ((#\N)(#\N)(#\S)))
  52.             '(("length" "toint" "tobool") ((#\S)))
  53.             '(("getchar") ((#\N) (#\S)))
  54.             '(("putchar") ((#\C) (#\N)(#\S)))
  55.             '(("tostring") ((#\N #\B)))
  56.             '(("drop" "dup") ((#\S #\C #\R #\N #\B)))
  57.             '(("swap") ((#\S #\C #\R #\N #\B) (#\S #\C #\R #\N #\B)))
  58.             '(("rot") ((#\S #\C #\R #\N #\B) (#\S #\C #\R #\N #\B) (#\S #\C #\R #\N #\B)))
  59.             '(("write") ((#\C)))
  60.             '()
  61.             ))
  62.     )
  63.   )
  64.  
  65. (define (match token)
  66.  
  67.   (define (match-reqs reqs token)
  68.     (cond ((null? reqs) #f)
  69.           ((char=? (car reqs) token) #t)
  70.           (else (match-reqs (cdr reqs) token))
  71.           )
  72.     )
  73.  
  74.   (define (match-each token-reqs tokens)
  75.     (cond ((null? token-reqs) #f)
  76.           ((match-reqs (car token-reqs) (caar tokens))
  77.            (match-each (cdr token-reqs) (cdr tokens)))
  78.           (else (cons token-reqs tokens)))
  79.     )
  80.   (define requirements (get-requirements token))
  81.   (define inputs (map (lambda (t) (pop)) requirements))
  82.   (let ((match-error? (match-each requirements inputs)))
  83.     (if match-error?
  84.         (give-error '("Runtime error: " " expects " ", got " "runtime error")
  85.                     (cdr token) requirements inputs)
  86.         inputs)
  87.     )
  88.   )
  89.  
  90. (define (get-vals tokens)
  91.   (map (lambda (t)
  92.          (if (pair? (cdr t))
  93.              (cadr t)
  94.              (cdr t)))
  95.          tokens))
  96.  
  97. (define (do-function token)
  98.    
  99.   (let* ((inputs (match token))
  100.          (args (get-vals inputs))
  101.          (is (lambda (a) (string=? a (cdr token))))
  102.          (next-arg (lambda ()
  103.                     (let ((return (car args)))
  104.                       (set! args (cdr args))
  105.                       return))))
  106.     (case (car token)
  107.       ((#\O) (cond
  108.                ((is "+") (push (cons #\N (+ (next-arg) (next-arg)))))
  109.                ((is "-") (push (let ((a (next-arg)) (b (next-arg)))
  110.                                  (cons #\N (- b a)))))
  111.                ((is "*") (push (cons #\N (* (next-arg) (next-arg)))))
  112.                ((is "/") (let ((a (next-arg)) (b (next-arg)))
  113.                            (push (cons #\N (quotient b a)))
  114.                            (push (cons #\N (remainder b a)))))
  115.                ((is "neg") (push (cons #\N (* -1 (next-arg)))))
  116.                ))
  117.       ((#\M) (let ((y (next-arg)) (x (next-arg)))
  118.                (cond ((and (char? x) (char? y))
  119.                       (set! x (char->integer x))
  120.                       (set! y (char->integer y)))
  121.                      ((and (boolean? x) (boolean? y))
  122.                       (set! x (if x 1 0))
  123.                       (set! y (if y 1 0)))
  124.                      ((and (number? x) (number? y)) '())
  125.                      (else (give-error '("Runtime error: " " expects two arguments of same type, got " " and " "runtime error")
  126.                                        (cdr token) x y)))
  127.                (cond
  128.                  ((is "<") (push (cons #\B (< x y))))
  129.                  ((is ">") (push (cons #\B (> x y))))
  130.                  ((is ">=") (push (cons #\B (>= x y))))
  131.                  ((is "<=") (push (cons #\B (<= x y))))
  132.                  ((is "=") (push (cons #\B (= x y))))
  133.                  ((is "!=") (push (cons #\B (not (= x y)))))
  134.                )))
  135.       ((#\V) (cond
  136.                ((is "and") (push (cons #\B (and (next-arg) (next-arg)))))
  137.                ((is "or") (push (cons #\B (or (next-arg) (next-arg)))))
  138.                ((is "not") (push (cons #\B (not (next-arg)))))
  139.                ))
  140.       ((#\F) (cond
  141.                ((is "concat") (let ((y (next-arg)) (x (next-arg)))
  142.                                 (push (cons #\S (string-append x y)))))
  143.                ((is "substr") (let* ((l (next-arg)) (p (next-arg)) (s (next-arg)) (len (string-length s)))
  144.                                 (cond ((> p (- len 1))
  145.                                        (give-error '("Runtime error: start position at " " invalid for string \"" "\"" "runtime error")
  146.                                                    p s ""))
  147.                                       ((< len (+ p l))
  148.                                        (push (cons #\S (substring s p))))
  149.                                       (else (push (cons #\S (substring s p (+ p l))))))))
  150.                ((is "length") (push (cons #\N (string-length (next-arg)))))
  151.                ((is "getchar") (let ((i (next-arg))(s (next-arg)))
  152.                                  (if (> (+ i 1) (string-length s))
  153.                                      (give-error '("Runtime error: position " " exceeds length of string \"" "\"" "runtime error")
  154.                                                  i s "")
  155.                                      (push (cons #\C (string-ref s i))))))
  156.                ((is "putchar") (let ((c (next-arg)) (i (next-arg)) (s (next-arg)))
  157.                                 (if (< i (string-length s))
  158.                                     (begin (string-set! s i c)
  159.                                     (push (cons #\S s)))
  160.                                     (give-error '("Runtime error: position " " exceeds length of string\"" "\"" "runtime error")
  161.                                                 i s ""))))
  162.                ((is "tostring") (let ((i (next-arg)))
  163.                                   (cond ((boolean? i)
  164.                                          (if i
  165.                                              (push (cons #\S "true"))
  166.                                              (push (cons #\S "false"))))
  167.                                         (else (push (cons #\S (number->string i)))))))
  168.                ((is "toint") (let ((i (next-arg)))
  169.                                (if (string->number i)
  170.                                    (push (cons #\N (string->number i)))
  171.                                    (give-error '("Runtime error: string \"" "\" does not represent a number" "runtime error")
  172.                                                i ""))))
  173.                ((is "tobool") (let ((i (next-arg)))
  174.                                 (cond ((string=? i "true") (push (cons #\B #t)))
  175.                                       ((string=? i "false") (push (cons #\B #f)))
  176.                                       (else (give-error '("Runtime error: String \"" "\" does not represent a boolean value" "runtime error")
  177.                                                         i "")))))
  178.                ((is "drop") '())
  179.                ((is "dup") (let ((a (car inputs)))
  180.                              (push a)
  181.                              (push a)))
  182.                ((is "swap") (let ((a (car inputs)) (b (cadr inputs)))
  183.                               (push a)
  184.                               (push b)))
  185.                ((is "rot") (let ((a (car inputs)) (b (cadr inputs)) (c (caddr inputs)))
  186.                              (push a)
  187.                              (push c)
  188.                              (push b)))
  189.                ((is "read") (push (cons #\C (read-char))))
  190.                ((is "write") (display (next-arg)))
  191.                ((is "save") (save (next-arg) (cdr inputs)))
  192.                ((is "load") (push (load (next-arg))))
  193.                ((is "ref") (push (cons #\R (next-arg))))
  194.                ))
  195.                
  196.       ))
  197.   )
Advertisement
Add Comment
Please, Sign In to add comment