aboutsummaryrefslogtreecommitdiff
path: root/racket/types.rkt
blob: 6ca29e6bdd2c048ae48593d879509a0a27c70644 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#lang racket

(provide blank-exn? make-blank-exn mal-exn? make-mal-exn mal-exn-val
         malfunc malfunc? malfunc-fn
         malfunc-ast malfunc-env malfunc-params malfunc-macro? malfunc-meta
         _partition _equal? _printf
         nil _nil? _keyword _keyword?
         _to_list _sequential? _count _empty? _nth _first _rest _map
         _assoc _dissoc _get
         atom atom? atom-val set-atom-val!)

(define-struct (blank-exn exn:fail:user) ())
(define-struct (mal-exn exn:fail:user) [val])

(define nil%
  (class object%
    (super-new)))

(define nil (new nil%))

(define (_nil? obj)
  (eq? nil obj))

(struct malfunc [fn ast env params macro? meta]
        #:property prop:procedure (struct-field-index fn))

;; General functions

;; From: http://stackoverflow.com/questions/8725832/how-to-split-list-into-evenly-sized-chunks-in-racket-scheme/8731622#8731622
(define (_partition n xs)
  (if (null? xs)
      '()
      (let ((first-chunk (take xs n))
            (rest (drop xs n)))
        (cons first-chunk (_partition n rest)))))

(define (_equal? a b)
  (cond
    [(and (list? a) (vector? b))
     (equal? a (vector->list b))]
    [(and (vector? a) (list? b))
     (equal? (vector->list a) b)]
    [else (equal? a b)]))

;; printf with flush
(define _printf (lambda a (apply printf a) (flush-output)))

;; Keywords
(define (_keyword str)
  (string-append "\u029e" str))

(define (_keyword? k)
  (and (string? k) (regexp-match? #px"^\u029e" k)))


;; Lists and vectors

(define (_to_list a)
  (if (vector? a) (vector->list a) a))

(define (_sequential? seq)
  (or (vector? seq) (list? seq)))

(define (_count seq)
  (cond [(_nil? seq)    0]
        [(vector? seq) (vector-length seq)]
        [else          (length seq)]))

(define (_empty? seq)
  (eq? 0 (_count seq)))

(define (_nth seq idx)
    (cond [(>= idx (_count seq)) (raise "nth: index out of range")]
          [(vector? seq) (vector-ref seq idx)]
          [else          (list-ref seq idx)]))

(define (_first seq)
  (cond [(vector? seq) (if (_empty? seq) nil (vector-ref seq 0))]
        [else          (if (_empty? seq) nil (list-ref seq 0))]))

(define (_rest seq)
  (cond [(vector? seq) (if (_empty? seq) '() (rest (vector->list seq)))]
        [else          (if (_empty? seq) '() (rest seq))]))

(define (_map f seq)
  (cond [(vector? seq) (vector-map f seq)]
        [else          (map f seq)]))

;; Hash maps
(define _assoc
  (lambda args
    (let ([new-hm (hash-copy (first args))]
          [pairs (_partition 2 (rest args))])
      (map (lambda (k_v)
             (hash-set! new-hm (first k_v) (second k_v))) pairs)
      new-hm)))

(define _dissoc
  (lambda args
    (let ([new-hm (hash-copy (first args))])
      (map (lambda (k) (hash-remove! new-hm k)) (rest args))
      new-hm)))

(define (_get hm k)
    (cond [(_nil? hm) nil]
          [(dict-has-key? hm k) (hash-ref hm k)]
          [else nil]))

;; Atoms
(struct atom [val] #:mutable)