aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lang.clj1
-rw-r--r--src/lang/analyser.clj13
-rw-r--r--src/lang/compiler.clj14
-rw-r--r--src/lang/parser.clj13
4 files changed, 31 insertions, 10 deletions
diff --git a/src/lang.clj b/src/lang.clj
index a5aef4f6e..83862bb2f 100644
--- a/src/lang.clj
+++ b/src/lang.clj
@@ -52,7 +52,6 @@
;; TODO: Define functions as classes inheriting Function.
;; TODO: Add tuples.
- ;; TODO: Add let.
;; TODO: Add pattern-matching.
;; TODO: Do tail-call optimization.
;; TODO: Add macros.
diff --git a/src/lang/analyser.clj b/src/lang/analyser.clj
index 98543e13e..811cc93ea 100644
--- a/src/lang/analyser.clj
+++ b/src/lang/analyser.clj
@@ -24,6 +24,10 @@
(assoc-in [:defs (:name state) name] desc)
(assoc-in [:env :mappings name] (annotated [::global (:name state) name] (:type desc)))) nil]]))
+(def ^:private next-local-idx
+ (fn [state]
+ [::&util/ok [state (-> state :env :counter)]]))
+
(defn ^:private with-local [name type body]
(fn [state]
(let [=return (body (update-in state [:env] #(-> %
@@ -108,6 +112,14 @@
=else (analyse-form* ?else)]
(return (annotated [::if =test =then =else] ::&type/nothing))))
+(defanalyser analyse-let
+ [::&parser/let ?label ?value ?body]
+ (exec [=value (analyse-form* ?value)
+ idx next-local-idx
+ =body (with-local ?label =value
+ (analyse-form* ?body))]
+ (return (annotated [::let idx ?label =value =body] (:type =body)))))
+
(defanalyser analyse-defclass
[::&parser/defclass ?name ?fields]
(let [=members {:fields (into {} (for [[class field] ?fields]
@@ -176,6 +188,7 @@
analyse-dynamic-access
analyse-fn-call
analyse-if
+ analyse-let
analyse-defclass
analyse-definterface
analyse-def
diff --git a/src/lang/compiler.clj b/src/lang/compiler.clj
index a71a66b8b..8b73720c4 100644
--- a/src/lang/compiler.clj
+++ b/src/lang/compiler.clj
@@ -127,6 +127,19 @@
(assert (compile-form (assoc *state* :form ?else)) "CAN't COMPILE ELSE")
(.visitLabel *writer* end-label)))
+(defcompiler ^:private compile-let
+ [::&analyser/let ?idx ?label ?value ?body]
+ (let [start-label (new Label)
+ end-label (new Label)
+ ?idx (int ?idx)]
+ (.visitLocalVariable *writer* ?label (->java-sig (:type ?value)) nil start-label end-label ?idx)
+ (assert (compile-form (assoc *state* :form ?value)) "CAN't COMPILE LET-VALUE")
+ (doto *writer*
+ (.visitVarInsn Opcodes/ASTORE ?idx)
+ (.visitLabel start-label))
+ (assert (compile-form (assoc *state* :form ?body)) "CAN't COMPILE LET-BODY")
+ (.visitLabel *writer* end-label)))
+
(defcompiler ^:private compile-def
[::&analyser/def ?form ?body]
(match ?form
@@ -221,6 +234,7 @@
compile-dynamic-access
compile-ann-class
compile-if
+ compile-let
compile-def
compile-module
compile-defclass
diff --git a/src/lang/parser.clj b/src/lang/parser.clj
index 2d104be94..fd50a04fb 100644
--- a/src/lang/parser.clj
+++ b/src/lang/parser.clj
@@ -93,15 +93,10 @@
(return [::case =variant =branches])))
(defparser ^:private parse-let
- [::&lexer/list ([[::&lexer/ident "let"] [::&lexer/tuple ?bindings] ?expr] :seq)]
- (exec [=expr (apply-m parse-form (list ?expr))
- =bindings (do (assert (even? (count ?bindings)))
- (map-m (fn [[destruct expr]]
- (exec [=destruct (apply-m parse-form (list destruct))
- =expr (apply-m parse-form (list expr))]
- (return [::let-binding =destruct =expr])))
- (partition 2 ?bindings)))]
- (return [::let =bindings =expr])))
+ [::&lexer/list ([[::&lexer/ident "let"] [::&lexer/ident ?label] ?value ?body] :seq)]
+ (exec [=value (apply-m parse-form (list ?value))
+ =body (apply-m parse-form (list ?body))]
+ (return [::let ?label =value =body])))
(defparser ^:private parse-module
[::&lexer/list ([[::&lexer/ident "module"]] :seq)]