summaryrefslogtreecommitdiff
path: root/src/jester/operators/lambdas.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/jester/operators/lambdas.clj')
-rw-r--r--src/jester/operators/lambdas.clj78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/jester/operators/lambdas.clj b/src/jester/operators/lambdas.clj
new file mode 100644
index 0000000..2243809
--- /dev/null
+++ b/src/jester/operators/lambdas.clj
@@ -0,0 +1,78 @@
+(ns jester.operators.lambdas
+ (:require [jester.types :refer [type-variable]])
+ (:require [jester.expansion :refer [with-type
+ expand-use
+ define-simple-operator
+ define-syntax
+ with-temporary-parameter-type
+ *operators*
+ *syntax*
+ operator-type]]))
+
+(defn ^:private expand-fn [args body]
+ (let [args-vars (mapv #(do % (type-variable)) args)
+ body-var (type-variable)]
+ (letfn [(binding-params [args vars f]
+ (if (empty? args)
+ (f)
+ (with-temporary-parameter-type [(first args) (first vars)]
+ (binding-params (rest args) (rest vars) f))))]
+ (with-type `(fn [~@args]
+ ~(binding-params args args-vars #(expand-use body body-var)))
+ `(-> ~args-vars ~body-var)))))
+
+(define-syntax fn [[& args] body]
+ (expand-fn args body))
+
+(define-syntax fn* [[& args] body]
+ (expand-fn args body))
+
+(define-syntax var [name]
+ (when-not (symbol? name)
+ (throw (ex-info (str "Var name must be a symbol, not " (pr-str name))
+ {:invalid-name name})))
+ (if (contains? *operators* name)
+ (if-let [operator (get *operators* name)]
+ (with-type (:name operator)
+ (operator-type operator)))))
+
+(defmacro call [f & args]
+ (cons f args))
+
+(define-simple-operator call
+ (∀ [args return] (-> [(-> args return) & args] return)))
+
+(define-simple-operator apply
+ (∀ [args return] (-> [(-> args return) args] return)))
+
+(define-simple-operator apply1 clojure.core/apply
+ (∀ [arg1 args return] (-> [(-> [arg1 & args] return) arg1 args] return)))
+
+(define-simple-operator apply2 clojure.core/apply
+ (∀ [arg1 arg2 args return] (-> [(-> [arg1 arg2 & args] return) arg1 arg2 args] return)))
+
+(define-simple-operator apply3 clojure.core/apply
+ (∀ [arg1 arg2 arg3 args return] (-> [(-> [arg1 arg2 arg3 & args] return) arg1 arg2 arg3 args] return)))
+
+(define-simple-operator map
+ (∀ [a b] (-> [(-> [a] b) (list a)] (list b))))
+
+(define-simple-operator filter
+ (∀ [a] (-> [(-> [a] boolean) (list a)] (list a))))
+
+(define-simple-operator remove
+ (∀ [a] (-> [(-> [a] boolean) (list a)] (list a))))
+
+(define-simple-operator reduce
+ (∀ [item result] (-> [(-> [result item] result) result (list item)] result)))
+
+(defn zip [as bs]
+ (map vector as bs))
+
+(define-simple-operator zip
+ (∀ [a b] (-> [(list a) (list b)] (list [a b]))))
+
+(define-simple-operator zip1 jester.operators.lambdas/zip
+ (∀ [x1 y1] (-> [[x1] [y1]] [[x1 y1]])))
+(define-simple-operator zip2 jester.operators.lambdas/zip
+ (∀ [x1 x2 y1 y2] (-> [[x1 x2] [y1 y2]] [[x1 y1] [x2 y2]])))