From 3baa6d87f9e0be009c5b23f0702da368ceab13a3 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Sat, 12 Mar 2016 23:33:54 -0400 Subject: - Added a REPL mode. --- src/lux.clj | 10 ++++-- src/lux/analyser.clj | 12 ++++++++ src/lux/analyser/base.clj | 4 +++ src/lux/base.clj | 2 +- src/lux/compiler.clj | 25 ++++++++------- src/lux/compiler/lux.clj | 5 +-- src/lux/optimizer.clj | 7 +++-- src/lux/repl.clj | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 121 insertions(+), 21 deletions(-) create mode 100644 src/lux/repl.clj (limited to 'src') diff --git a/src/lux.clj b/src/lux.clj index f1f43b7af..40e8a0d24 100644 --- a/src/lux.clj +++ b/src/lux.clj @@ -8,19 +8,23 @@ (:require [lux.base :as & :refer [|let |do return fail return* fail* |case]] [lux.compiler.base :as &compiler-base] [lux.compiler :as &compiler] + [lux.repl :as &repl] :reload-all) (:import (java.io File))) (defn -main [& args] (|case (&/->list args) - (&/$Cons "compile" (&/$Cons program-module (&/$Nil))) + (&/$Cons program-module (&/$Nil)) (time (&compiler/compile-program &/$Release program-module)) - (&/$Cons "compile" (&/$Cons "release" (&/$Cons program-module (&/$Nil)))) + (&/$Cons program-module (&/$Cons "release" (&/$Nil))) (time (&compiler/compile-program &/$Release program-module)) - (&/$Cons "compile" (&/$Cons "debug" (&/$Cons program-module (&/$Nil)))) + (&/$Cons program-module (&/$Cons "debug" (&/$Nil))) (time (&compiler/compile-program &/$Debug program-module)) + (&/$Nil) + (&repl/repl) + _ (println "Can't understand command."))) diff --git a/src/lux/analyser.clj b/src/lux/analyser.clj index 42d92b859..44c173864 100644 --- a/src/lux/analyser.clj +++ b/src/lux/analyser.clj @@ -711,3 +711,15 @@ (defn analyse [eval! compile-module compile-token] (|do [asts &parser/parse] (&/flat-map% (partial analyse-ast eval! compile-module compile-token &/$VoidT) asts))) + +(defn clean-output [?var analysis] + (|do [:let [[[?output-type ?output-cursor] ?output-term] analysis] + =output-type (&type/clean ?var ?output-type)] + (return (&&/|meta =output-type ?output-cursor ?output-term)))) + +(defn repl-analyse [eval! compile-module compile-token] + (|do [asts &parser/parse] + (&type/with-var + (fn [?var] + (|do [outputs (&/flat-map% (partial analyse-ast eval! compile-module compile-token ?var) asts)] + (&/map% (partial clean-output ?var) outputs)))))) diff --git a/src/lux/analyser/base.clj b/src/lux/analyser/base.clj index 130f238da..bb835a524 100644 --- a/src/lux/analyser/base.clj +++ b/src/lux/analyser/base.clj @@ -160,6 +160,10 @@ (|let [[[type _] _] analysis] type)) +(defn expr-term [analysis] + (|let [[[type _] term] analysis] + term)) + (defn with-type [new-type analysis] (|let [[[type cursor] adt] analysis] (&/T [(&/T [new-type cursor]) adt]))) diff --git a/src/lux/base.clj b/src/lux/base.clj index 56a59e31b..901011bb1 100644 --- a/src/lux/base.clj +++ b/src/lux/base.clj @@ -734,7 +734,7 @@ (T [;; "lux;info" (default-compiler-info mode) ;; "lux;source" - $None + $Nil ;; "lux;cursor" (T ["" -1 -1]) ;; "lux;modules" diff --git a/src/lux/compiler.clj b/src/lux/compiler.clj index ec8786ecc..1b852f789 100644 --- a/src/lux/compiler.clj +++ b/src/lux/compiler.clj @@ -36,10 +36,10 @@ ClassWriter MethodVisitor))) -;; [Utils/Compilers] +;; [Resources] (def ^:private !source->last-line (atom nil)) -(defn ^:private compile-expression [syntax] +(defn compile-expression [syntax] (|let [[[?type [_file-name _line _column]] ?form] syntax] (|do [^MethodVisitor *writer* &/get-writer :let [debug-label (new Label) @@ -434,7 +434,7 @@ )) )) -(defn ^:private compile-token [syntax] +(defn compile-token [syntax] (|case syntax (&o/$def ?name ?body ?meta) (&&lux/compile-def compile-expression ?name ?body ?meta) @@ -449,7 +449,14 @@ (&&host/compile-jvm-class compile-expression ?name ?super-class ?interfaces ?anns ?inheritance-modifier ?fields ?methods ??env ??ctor-args) )) -(defn ^:private eval! [expr] +(defn init! [] + (reset! !source->last-line {}) + (.mkdirs (java.io.File. &&/output-dir)) + (doto (.getDeclaredMethod java.net.URLClassLoader "addURL" (into-array [java.net.URL])) + (.setAccessible true) + (.invoke (ClassLoader/getSystemClassLoader) (to-array [(-> (new java.io.File "./resources") .toURI .toURL)])))) + +(defn eval! [expr] (&/with-eval (|do [module &/get-module-name id &/gen-id @@ -480,7 +487,7 @@ (.get nil) return)))) -(defn ^:private compile-module [name] +(defn compile-module [name] (let [file-name (str name ".lux")] (|do [file-content (&&io/read-file file-name) :let [file-hash (hash file-content)]] @@ -548,14 +555,6 @@ )) )) -(defn ^:private init! [] - (reset! !source->last-line {}) - (.mkdirs (java.io.File. &&/output-dir)) - (doto (.getDeclaredMethod java.net.URLClassLoader "addURL" (into-array [java.net.URL])) - (.setAccessible true) - (.invoke (ClassLoader/getSystemClassLoader) (to-array [(-> (new java.io.File "./resources") .toURI .toURL)])))) - -;; [Resources] (defn compile-program [mode program-module] (init!) (let [m-action (&/map% compile-module (&/|list "lux" program-module))] diff --git a/src/lux/compiler/lux.clj b/src/lux/compiler/lux.clj index 8f784cc11..3b0ae5b29 100644 --- a/src/lux/compiler/lux.clj +++ b/src/lux/compiler/lux.clj @@ -156,7 +156,7 @@ _ (|do [:let [=value-type (&a/expr-type* ?body)] - ^ClassWriter *writer* &/get-writer + ;; ^ClassWriter *writer* &/get-writer [file-name _ _] &/cursor :let [datum-sig "Ljava/lang/Object;" def-name (&host/def-name ?name) @@ -187,7 +187,8 @@ (.visitMaxs 0 0) (.visitEnd))]] (return nil))) - :let [_ (.visitEnd *writer*)] + ;; :let [_ (.visitEnd *writer*)] + :let [_ (.visitEnd =class)] _ (&&/save-class! def-name (.toByteArray =class)) :let [def-class (&&/load-class! class-loader (&host-generics/->class-name current-class)) [def-type is-type?] (|case (&a-meta/meta-get &a-meta/type?-tag ?meta) diff --git a/src/lux/optimizer.clj b/src/lux/optimizer.clj index 48db1e2cf..6f4fd27bd 100644 --- a/src/lux/optimizer.clj +++ b/src/lux/optimizer.clj @@ -154,7 +154,8 @@ ("jvm-lshr" 1) ("jvm-lushr" 1)) -(defn ^:private optimize-token [analysis] +;; [Exports] +(defn optimize-token [analysis] "(-> Analysis Optimized)" (|case analysis (&-base/$bool value) @@ -543,9 +544,11 @@ (&-base/$jvm-lushr value) (return ($jvm-lushr value)) + + _ + (assert false (prn-str 'optimize-token (&/adt->text analysis))) )) -;; [Exports] (defn optimize [eval! compile-module compile-token] (|do [analyses (&analyser/analyse eval! compile-module compile-token)] (&/map% optimize-token analyses))) diff --git a/src/lux/repl.clj b/src/lux/repl.clj new file mode 100644 index 000000000..138eb695f --- /dev/null +++ b/src/lux/repl.clj @@ -0,0 +1,77 @@ +;; Copyright (c) Eduardo Julian. All rights reserved. +;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +;; If a copy of the MPL was not distributed with this file, +;; You can obtain one at http://mozilla.org/MPL/2.0/. + +(ns lux.repl + (:require clojure.core.match + clojure.core.match.array + (lux [base :as & :refer [|let |do return* return fail fail* |case]] + [type :as &type] + [analyser :as &analyser] + [optimizer :as &optimizer] + [compiler :as &compiler]) + [lux.analyser.base :as &a-base] + [lux.analyser.module :as &module]) + (:import (java.io InputStreamReader + BufferedReader))) + +;; [Utils] +(def ^:private repl-module "REPL") + +(defn ^:private init [] + (do (println "Welcome to the REPL!") + (&compiler/init!) + (|case ((|do [_ (&compiler/compile-module "lux")] + (&module/enter-module repl-module)) + (&/init-state &/$Debug)) + (&/$Right ?state _) + (&/set$ &/$source &/$Nil ?state) + + (&/$Left ?message) + (assert false ?message)) + )) + +(defn ^:private repl-cursor [repl-line] + (&/T [repl-module repl-line 0])) + +;; [Values] +(defn repl [] + (with-open [input (->> System/in (new InputStreamReader) (new BufferedReader))] + (loop [state (init) + repl-line 0] + (let [_ (.print System/out "> ") + line (.readLine input) + line* (&/|list (&/T [(repl-cursor repl-line) line])) + state* (&/update$ &/$source + (fn [_source] (&/|++ _source line*)) + state)] + (|case ((|do [analysed-tokens (&analyser/repl-analyse &compiler/eval! &compiler/compile-module &compiler/compile-token) + optimized-tokens (->> analysed-tokens + (&/|map &a-base/expr-term) + (&/map% &optimizer/optimize-token)) + :let [optimized-tokens* (&/->list (map (fn [analysis optim] + (|let [[[_type _cursor] _term] analysis] + (&a-base/|meta _type _cursor optim))) + (&/->seq analysed-tokens) + (&/->seq optimized-tokens)))] + eval-values (&/map% &compiler/eval! optimized-tokens*) + :let [outputs (map (fn [analysis value] + (|let [[[_type _cursor] _term] analysis] + [_type value])) + (&/->seq analysed-tokens) + (&/->seq eval-values))]] + (return outputs)) + state*) + (&/$Right state** outputs) + (do (doseq [[_type _value] outputs] + (.println System/out (str "=> " (&type/show-type _type) "\n" (pr-str _value) "\n"))) + (recur state** (inc repl-line))) + + (&/$Left ^String ?message) + (if (or (= "[Reader Error] EOF" ?message) + (.startsWith ?message "[Parser Error] Unbalanced ")) + (recur state* (inc repl-line)) + (assert false ?message)) + )) + ))) -- cgit v1.2.3