Merge pull request #400 from asarhaddon/improve-mal-impl-macro-no-meta
[jackhill/mal.git] / yorick / types.i
1 require, "hash.i"
2
3 struct MalError {
4 string message
5 pointer obj
6 }
7
8 struct MalNil {
9 int val
10 }
11
12 MAL_NIL = MalNil()
13
14 struct MalTrue {
15 int val
16 }
17
18 MAL_TRUE = MalTrue()
19
20 struct MalFalse {
21 int val
22 }
23
24 MAL_FALSE = MalFalse()
25
26 struct MalNumber {
27 int val
28 }
29
30 func new_number(s)
31 {
32 return MalNumber(val=atoi(s))
33 }
34
35 struct MalSymbol {
36 string val
37 pointer meta
38 }
39
40 struct MalString {
41 string val
42 pointer meta
43 }
44
45 struct MalKeyword {
46 string val
47 pointer meta
48 }
49
50 struct MalList {
51 pointer val
52 pointer meta
53 }
54
55 struct MalVector {
56 pointer val
57 pointer meta
58 }
59
60 func count(obj) { return numberof(*obj.val); }
61
62 func rest(obj) {
63 seq = count(obj) <= 1 ? [] : ((*obj.val)(2:))
64 return MalList(val=&seq)
65 }
66
67 struct MalHashmap {
68 pointer val
69 pointer meta
70 }
71
72 func hashmap_obj_to_key(obj) {
73 if (structof(obj) == MalString) return "str:" + obj.val
74 else if (structof(obj) == MalSymbol) return "sym:" + obj.val
75 else if (structof(obj) == MalKeyword) return "key:" + obj.val
76 else error, "Unsupported obj type for hash key"
77 }
78
79 func hashmap_key_to_obj(key) {
80 type_str = strpart(key, 1:4)
81 val = strpart(key, 5:)
82 if (type_str == "str:") return MalString(val=val)
83 else if (type_str == "sym:") return MalSymbol(val=val)
84 else if (type_str == "key:") return MalKeyword(val=val)
85 else error, "Unsupported key type"
86 }
87
88 func array_to_hashmap(seq)
89 {
90 if (numberof(seq) % 2 != 0) return MalError(message="Odd number of elements in hashmap")
91 h = hash_new()
92 for (i = 1; i <= numberof(seq); i += 2) {
93 hash_set, h, hashmap_obj_to_key(*seq(i)), *seq(i + 1)
94 }
95 return MalHashmap(val=&h)
96 }
97
98 struct MalNativeFunction {
99 string val
100 pointer meta
101 }
102
103 struct MalFunction {
104 pointer env
105 pointer binds
106 pointer ast
107 int macro
108 pointer meta
109 }
110
111 struct MalAtom {
112 pointer val
113 pointer meta
114 }
115
116 func is_macro(obj) { return (structof(obj) == MalFunction && obj.macro); }
117
118 struct MalAtomVal {
119 pointer val
120 }
121
122 func new_boolean(b) {
123 if (b) return MAL_TRUE
124 return MAL_FALSE
125 }
126
127 func equal_seq(seq_a, seq_b) {
128 if (numberof(seq_a) != numberof(seq_b)) return 0
129 for (i = 1; i <= numberof(seq_a); ++i) {
130 if (!equal(*seq_a(i), *seq_b(i))) return 0
131 }
132 return 1
133 }
134
135 func equal_hash(hm_a, hm_b) {
136 if (numberof(*hm_a.keys) != numberof(*hm_b.keys)) return 0
137 for (i = 1; i <= numberof(*hm_a.keys); ++i) {
138 key_a = (*hm_a.keys)(i)
139 val_a = *((*hm_a.vals)(i))
140 val_b = hash_get(hm_b, key_a)
141 if (is_void(val_b) || !equal(val_a, val_b)) return 0
142 }
143 return 1
144 }
145
146 func equal(a, b) {
147 ta = structof(a)
148 tb = structof(b)
149 if (ta == MalNil) return tb == MalNil
150 else if (ta == MalTrue) return tb == MalTrue
151 else if (ta == MalFalse) return tb == MalFalse
152 else if (ta == MalNumber) return tb == MalNumber && a.val == b.val
153 else if (ta == MalSymbol) return tb == MalSymbol && a.val == b.val
154 else if (ta == MalString) return tb == MalString && a.val == b.val
155 else if (ta == MalKeyword) return tb == MalKeyword && a.val == b.val
156 else if (ta == MalList || ta == MalVector) {
157 return (tb == MalList || tb == MalVector) && equal_seq(*(a.val), *(b.val))
158 }
159 else if (ta == MalHashmap) return tb == MalHashmap && equal_hash(*a.val, *b.val)
160 else return 0
161 }
162
163 func streplaceall(s, pattern, subst)
164 {
165 return streplace(s, strfind(pattern, s, n=999), subst)
166 }