diff options
Diffstat (limited to 'src/lang')
-rw-r--r-- | src/lang/analyser.clj | 13 | ||||
-rw-r--r-- | src/lang/compiler.clj | 14 | ||||
-rw-r--r-- | src/lang/parser.clj | 13 |
3 files changed, 31 insertions, 9 deletions
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)] |