Created
February 21, 2015 04:57
-
-
Save frenchy64/98fff7c70145d6961e31 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns demo.core | |
(:require [clojure.core.typed :as t])) | |
;; Map vs Vector AST representation | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; * Maps | |
(t/defalias M (t/U '{:op ':if :test M :then M :else M} | |
'{:op ':do :e1 M :e2 M} | |
'{:op ':val :val t/Any})) | |
(t/ann ast [M -> M]) | |
(defmulti ast :op) | |
(defmethod ast :if [{:keys [test then else]}] | |
{:op :if :test test :then then :else else}) | |
(defmethod ast :do [{:keys [e1 e2]}] | |
{:op :do :e1 e1 :e2 e2}) | |
(defmethod ast :val [{:keys [val]}] | |
{:op :val :val val}) | |
(ast {:op :if | |
:test {:op :val :val 1} | |
:then {:op :do | |
:e1 {:op :val :val 2} | |
:e2 {:op :val :val 3}} | |
:else {:op :val :val 4}}) | |
;=> {:op :if | |
; :test {:op :val :val 1} | |
; :then {:op :do | |
; :e1 {:op :val :val 2} | |
; :e2 {:op :val :val 3}} | |
; :else {:op :val :val 4}} | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; * Vectors | |
(t/defalias E (t/U '[':if E E E] | |
'[':do E E] | |
'[':val t/Any])) | |
(t/ann variant [E -> E]) | |
(defmulti variant first) | |
(defmethod variant :if [[_ test then else]] | |
[:if test then else]) | |
(defmethod variant :do [[_ e1 e2]] | |
[:do e1 e2]) | |
(defmethod variant :val [[_ v]] | |
[:val v]) | |
(variant [:if [:val 1] [:do [:val 2] [:val 3]] [:val 4]]) | |
;=> [:if [:val 1] [:do [:val 2] [:val 3]] [:val 4]] | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; * Can't decide | |
(t/defalias C (t/U '{:op ':if :test C :then C :else C} | |
'[':do C C] | |
'{:op ':val :val t/Any})) | |
(t/ann change [M E -> C]) | |
(defmulti change (t/fn [m :- M, v :- E] | |
[(:op m) (first v)])) | |
(defmethod change [:if :if] [{:keys [test then else]} [_ vtest vthen velse]] | |
{:op :if | |
:test (change test vtest) | |
:then (change then vthen) | |
:else (change else velse)}) | |
(defmethod change [:do :do] [{:keys [e1 e2]} [_ ve1 ve2]] | |
[:do (change e1 ve1) (change e2 ve2)]) | |
(defmethod change [:val :val] [{:keys [val]} [_ vval]] | |
(assert (= val vval)) | |
{:op :val :val val}) | |
(change {:op :if | |
:test {:op :val :val 1} | |
:then {:op :do | |
:e1 {:op :val :val 2} | |
:e2 {:op :val :val 3}} | |
:else {:op :val :val 4}} | |
[:if [:val 1] [:do [:val 2] [:val 3]] [:val 4]]) | |
;=> {:op :if, :test {:op :val, :val 1}, :then [:do {:op :val, :val 2} {:op :val, :val 3}], :else {:op :val, :val 4}} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment