|
9 | 9 | (seq? x) :seq |
10 | 10 | (vector? x) :vector |
11 | 11 | (symbol? x) :symbol |
12 | | - (number? x) :number))) |
| 12 | + (number? x) :number |
| 13 | + (keyword? x) :keyword))) |
13 | 14 |
|
14 | 15 | (defmulti analyze-seq (fn [x] |
15 | 16 | (let [f (first x)] |
|
51 | 52 | [body] |
52 | 53 | body) |
53 | 54 | analyzed-bodies (reduce |
54 | | - analyze-fn-body |
| 55 | + (partial analyze-fn-body name) |
55 | 56 | {} |
56 | 57 | arities)] |
57 | 58 | {:op :fn |
|
62 | 63 | :arities (vals analyzed-bodies)} |
63 | 64 | )) |
64 | 65 |
|
65 | | -(defn analyze-fn-body [acc [args & body]] |
| 66 | +(defn analyze-fn-body [fn-name acc [args & body]] |
66 | 67 | ; TODO: Add support for variadic fns |
67 | 68 | (let [arity (count args) |
| 69 | + new-env (assoc-in *env* [:locals fn-name] {:op :binding |
| 70 | + :type :fn-self |
| 71 | + :name fn-name |
| 72 | + :form fn-name |
| 73 | + :env *env*}) |
68 | 74 | new-env (reduce |
69 | 75 | (fn [acc idx] |
70 | 76 | (let [arg-name (nth args idx)] |
|
74 | 80 | :name arg-name |
75 | 81 | :form arg-name |
76 | 82 | :env *env*}))) |
77 | | - *env* |
| 83 | + new-env |
78 | 84 | (range (count args)))] |
79 | 85 | (assert (not (acc arity)) (str "Duplicate arity for " (cons args body))) |
80 | 86 | (assoc acc arity {:op :fn-body |
|
130 | 136 | (defmethod analyze-seq :default |
131 | 137 | [[sym & args :as form]] |
132 | 138 | (println form) |
133 | | - (let [resolved (resolve-in (the-ns (:ns *env*)) sym)] |
| 139 | + (let [resolved (and (symbol? sym) |
| 140 | + (resolve-in (the-ns (:ns *env*)) sym))] |
134 | 141 | (if (and resolved |
135 | 142 | (macro? @resolved)) |
136 | 143 | (analyze-form (apply @resolved args)) |
|
145 | 152 | (defmethod analyze-form :number |
146 | 153 | [x] |
147 | 154 | {:op :const |
| 155 | + :type :number |
| 156 | + :form x |
| 157 | + :env *env*}) |
| 158 | + |
| 159 | +(defmethod analyze-form :keyword |
| 160 | + [x] |
| 161 | + {:op :const |
| 162 | + :type :keyword |
148 | 163 | :form x |
149 | 164 | :env *env*}) |
150 | 165 |
|
|
156 | 171 | [x] |
157 | 172 | (if-let [local (get-in *env* [:locals x])] |
158 | 173 | local |
159 | | - {:op :global |
160 | | - :env *env* |
161 | | - :form x})) |
| 174 | + (maybe-var x))) |
| 175 | + |
| 176 | +(defmethod analyze-form :vector |
| 177 | + [x] |
| 178 | + (println "analyze " x) |
| 179 | + {:op :vector |
| 180 | + :children [:items] |
| 181 | + :items (mapv analyze-form x) |
| 182 | + :form x |
| 183 | + :env *env*}) |
| 184 | + |
| 185 | +(defn maybe-var [x] |
| 186 | + (let [resolved (resolve-in (the-ns (:ns *env*)) x)] |
| 187 | + (if resolved |
| 188 | + {:op :var |
| 189 | + :env *env* |
| 190 | + :ns (namespace resolved) |
| 191 | + :name (name resolved) |
| 192 | + :form x} |
| 193 | + {:op :var |
| 194 | + :env *env* |
| 195 | + :ns (name (:ns *env*)) |
| 196 | + :name (name x) |
| 197 | + :form x}))) |
162 | 198 |
|
163 | 199 |
|
164 | 200 | ;; ENV Functions |
|
190 | 226 | (selector node)) |
191 | 227 | post)) |
192 | 228 |
|
| 229 | +(defn post-walk [f ast] |
| 230 | + (walk f identity :children ast)) |
| 231 | + |
| 232 | +(defn clean-do [ast] |
| 233 | + (post-walk |
| 234 | + (fn [{:keys [op statements ret] :as do}] |
| 235 | + (println ">-- " op (count statements)) |
| 236 | + (if (and (= op :do) |
| 237 | + (= (count statements) 0)) |
| 238 | + (do (println "reducing ") ret) |
| 239 | + ast)) |
| 240 | + ast)) |
193 | 241 |
|
194 | 242 | (defn remove-env [ast] |
195 | 243 | (walk #(dissoc % :env) |
196 | 244 | identity |
197 | 245 | :children |
198 | 246 | ast)) |
199 | 247 |
|
200 | | -(let [form '((fn this [i max] |
201 | | - (if (-lt i max) |
202 | | - (this (-add i 1) |
203 | | - max) |
204 | | - i)) |
205 | | - 1000)] |
206 | | - (println (string-builder @(to-rpython (atom (string-builder)) 0 (remove-env (analyze form)))))) |
207 | | - |
208 | 248 | (defn write! [sb val] |
209 | 249 | (swap! sb conj! val) |
210 | 250 | sb) |
|
214 | 254 | (write! sb " "))) |
215 | 255 |
|
216 | 256 | (defmulti to-rpython (fn [sb offset node] |
| 257 | + (println (:op node)) |
217 | 258 | (:op node))) |
218 | 259 |
|
219 | 260 | (defmethod to-rpython :if |
|
223 | 264 | (let [offset (inc offset)] |
224 | 265 | (doseq [[nm form] [[:test test] |
225 | 266 | [:then then] |
226 | | - [:else else]]] |
| 267 | + [:els else]]] |
227 | 268 | (offset-spaces sb offset) |
228 | 269 | (write! sb (name nm)) |
229 | 270 | (write! sb "=") |
|
232 | 273 | (offset-spaces sb offset) |
233 | 274 | (write! sb ")"))) |
234 | 275 |
|
235 | | -(defmethod to-rpython :const |
| 276 | +(defmulti write-const (fn [sb offset const] |
| 277 | + (:type const))) |
| 278 | + |
| 279 | +(defmethod write-const :keyword |
236 | 280 | [sb offset {:keys [form]}] |
237 | | - (write! sb "i.Const(rt.wrap(") |
238 | | - (write! sb (str form)) |
239 | | - (write! sb "))")) |
| 281 | + (write! sb "kw(u\"") |
| 282 | + (when (namespace form) |
| 283 | + (write! sb (namespace form)) |
| 284 | + (write! sb "/")) |
| 285 | + (write! sb (name form)) |
| 286 | + (write! sb "\")")) |
| 287 | + |
| 288 | +(defmethod to-rpython :const |
| 289 | + [sb offset ast] |
| 290 | + (write! sb "i.Const(") |
| 291 | + (write-const sb offset ast) |
| 292 | + (write! sb ")")) |
| 293 | + |
| 294 | +(defmethod to-rpython :invoke |
| 295 | + [sb offset ast] |
| 296 | + (write! sb "i.Invoke(\n") |
| 297 | + (let [offset (inc offset)] |
| 298 | + (offset-spaces sb offset) |
| 299 | + (write! sb "args=[\n") |
| 300 | + (let [offset (inc offset)] |
| 301 | + (doseq [x `(~(:fn ast) ~@(:args ast))] |
| 302 | + (offset-spaces sb offset) |
| 303 | + (to-rpython sb offset x) |
| 304 | + (write! sb ",\n"))) |
| 305 | + (offset-spaces sb offset) |
| 306 | + (write! sb "],\n")) |
| 307 | + (offset-spaces sb offset) |
| 308 | + (write! sb ")")) |
| 309 | + |
| 310 | + |
| 311 | +(defmethod to-rpython :do |
| 312 | + [sb offset {:keys [ret statements]}] |
| 313 | + (write! sb "i.Do(\n") |
| 314 | + (let [offset (inc offset)] |
| 315 | + (offset-spaces sb offset) |
| 316 | + (write! sb "args=[\n") |
| 317 | + (let [offset (inc offset)] |
| 318 | + (doseq [x `(~@statements ~ret)] |
| 319 | + (offset-spaces sb offset) |
| 320 | + (to-rpython sb offset x) |
| 321 | + (write! sb ",\n"))) |
| 322 | + (offset-spaces sb offset) |
| 323 | + (write! sb "],\n")) |
| 324 | + (offset-spaces sb offset) |
| 325 | + (write! sb ")")) |
| 326 | + |
| 327 | + |
| 328 | +(defmethod to-rpython :fn |
| 329 | + [sb offset {:keys [name arities]}] |
| 330 | + (assert (= (count arities) 1)) |
| 331 | + (to-rpython-fn-body sb offset name (nth arities 0))) |
| 332 | + |
| 333 | +(defn to-rpython-fn-body |
| 334 | + [sb offset name {:keys [args body]}] |
| 335 | + (write! sb "i.Fn(args=[") |
| 336 | + (write! sb (->> args |
| 337 | + (map (fn [name] |
| 338 | + (str "kw(u\"" name "\")"))) |
| 339 | + (interpose ",") |
| 340 | + (apply str))) |
| 341 | + (write! sb "],name=kw(u\"") |
| 342 | + (write! sb (str name)) |
| 343 | + (write! sb "\"),\n") |
| 344 | + (let [offset (inc offset)] |
| 345 | + (offset-spaces sb offset) |
| 346 | + (write! sb "body=") |
| 347 | + (to-rpython sb offset body) |
| 348 | + (write! sb ",\n")) |
| 349 | + (offset-spaces sb offset) |
| 350 | + (write! sb ")")) |
| 351 | + |
| 352 | +(defmethod to-rpython :var |
| 353 | + [sb offset {:keys [ns name]}] |
| 354 | + (write! sb "i.Const(code.intern_var(") |
| 355 | + (write! sb "u\"") |
| 356 | + (write! sb ns) |
| 357 | + (write! sb "\", u\"") |
| 358 | + (write! sb name) |
| 359 | + (write! sb "\"))")) |
| 360 | + |
| 361 | +(defmethod to-rpython :binding |
| 362 | + [sb offset {:keys [name]}] |
| 363 | + (write! sb "i.Lookup(kw(u\"") |
| 364 | + (write! sb name) |
| 365 | + (write! sb "\"))")) |
| 366 | + |
| 367 | +(defmethod to-rpython :def |
| 368 | + [sb offset {:keys [name env val]}] |
| 369 | + (write! sb "i.Invoke(args=[\n") |
| 370 | + (write! sb (str "# (def " (:ns env) "/" name ")\n")) |
| 371 | + (let [offset (inc offset)] |
| 372 | + (offset-spaces sb offset) |
| 373 | + (write! sb "i.Const(code.intern_var(u\"pixie.stdlib\", u\"set-var-root!\")),\n") |
| 374 | + (offset-spaces sb offset) |
| 375 | + (write! sb "i.Const(code.intern_var(u\"") |
| 376 | + (write! sb (:ns env)) |
| 377 | + (write! sb "\",u\"") |
| 378 | + (write! sb name) |
| 379 | + (write! sb "\")),\n") |
| 380 | + (offset-spaces sb offset) |
| 381 | + (to-rpython sb offset val) |
| 382 | + (write! sb "])") |
| 383 | + )) |
| 384 | + |
| 385 | +(defmethod to-rpython :vector |
| 386 | + [sb offset {:keys [items]}] |
| 387 | + (write! sb "i.Invoke(args=[\n") |
| 388 | + (let [offset (inc offset)] |
| 389 | + (offset-spaces sb offset) |
| 390 | + (write! sb "i.Const(code.intern_var(u\"pixie.stdlib\", u\"vector\")),\n") |
| 391 | + (doseq [item items] |
| 392 | + (offset-spaces sb offset) |
| 393 | + (to-rpython sb offset item) |
| 394 | + (write! sb ",\n")) |
| 395 | + (offset-spaces sb offset) |
| 396 | + (write! sb "])"))) |
240 | 397 |
|
241 | 398 |
|
| 399 | +(let [form '(do (deftype Cons [head tail meta]))] |
| 400 | + (println (string-builder @(to-rpython (atom (string-builder)) 0 (clean-do (analyze form)))))) |
242 | 401 |
|
243 | | -(defmethod rpython-node) |
|
0 commit comments