From de60ed1439575ec99cb27e2bdd127a5957db07bc Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Sun, 9 Oct 2016 18:28:37 -0400 Subject: - Replace _lux_imports with _lux_module by adding module annotations. --- src/lux/analyser.clj | 8 +-- src/lux/analyser/lux.clj | 48 +++++++------ src/lux/analyser/meta.clj | 3 +- src/lux/analyser/module.clj | 43 +++++++++++- src/lux/base.clj | 2 +- src/lux/compiler.clj | 160 ++++++++++++++++++++++++-------------------- src/lux/compiler/base.clj | 9 ++- src/lux/compiler/cache.clj | 18 ++--- src/lux/compiler/lux.clj | 16 ++--- src/lux/compiler/type.clj | 4 +- src/lux/type.clj | 16 ++--- 11 files changed, 196 insertions(+), 131 deletions(-) diff --git a/src/lux/analyser.clj b/src/lux/analyser.clj index f97a0ea08..40ed3ab28 100644 --- a/src/lux/analyser.clj +++ b/src/lux/analyser.clj @@ -156,12 +156,10 @@ (&/with-cursor cursor (&&lux/analyse-def analyse optimize eval! compile-def ?name ?value ?meta))) - "_lux_import" - (|let [(&/$Cons [_ (&/$TextS ?path)] - (&/$Cons [_ (&/$TextS ?alias)] - (&/$Nil))) parameters] + "_lux_module" + (|let [(&/$Cons ?meta (&/$Nil)) parameters] (&/with-cursor cursor - (&&lux/analyse-import analyse compile-module ?path ?alias))) + (&&lux/analyse-module analyse optimize eval! compile-module ?meta))) "_lux_program" (|let [(&/$Cons [_ (&/$SymbolS "" ?args)] diff --git a/src/lux/analyser/lux.clj b/src/lux/analyser/lux.clj index a05e96bca..208890d78 100644 --- a/src/lux/analyser/lux.clj +++ b/src/lux/analyser/lux.clj @@ -567,7 +567,7 @@ (|do [=value (&/without-repl-closure (&/with-scope ?name (&&/analyse-1+ analyse ?value))) - =meta (&&/analyse-1 analyse &type/DefMeta ?meta) + =meta (&&/analyse-1 analyse &type/Anns ?meta) ==meta (eval! (optimize =meta)) _ (&&module/test-type module-name ?name ==meta (&&/expr-type* =value)) _ (&&module/test-macro module-name ?name ==meta (&&/expr-type* =value)) @@ -575,26 +575,34 @@ (return &/$Nil)) ))) -(defn analyse-import [analyse compile-module path ex-alias] +(defn analyse-module [analyse optimize eval! compile-module ?meta] (|do [_ &/ensure-statement - current-module &/get-module-name - _ (if (= current-module path) - (&/fail-with-loc (str "[Analyser Error] Module can't import itself: " path)) - (return nil))] - (&/without-repl - (&/save-module - (|do [already-compiled? (&&module/exists? path) - active? (&/active-module? path) - _ (&/assert! (not active?) - (str "[Analyser Error] Can't import a module that is mid-compilation: " path " @ " current-module)) - _ (&&module/add-import path) - ?module-hash (if (not already-compiled?) - (compile-module path) - (&&module/module-hash path)) - _ (if (= "" ex-alias) - (return nil) - (&&module/alias current-module ex-alias path))] - (return &/$Nil)))))) + =anns (&&/analyse-1 analyse &type/Anns ?meta) + ==anns (eval! (optimize =anns)) + module-name &/get-module-name + _ (&&module/set-anns ==anns module-name) + _imports (&&module/fetch-imports ==anns) + current-module &/get-module-name] + (&/map% (fn [_import] + (|let [[path alias] _import] + (&/without-repl + (&/save-module + (|do [_ (if (= current-module path) + (&/fail-with-loc (str "[Analyser Error] Module can't import itself: " path)) + (return nil)) + already-compiled? (&&module/exists? path) + active? (&/active-module? path) + _ (&/assert! (not active?) + (str "[Analyser Error] Can't import a module that is mid-compilation: " path " @ " current-module)) + _ (&&module/add-import path) + ?module-hash (if (not already-compiled?) + (compile-module path) + (&&module/module-hash path)) + _ (if (= "" alias) + (return nil) + (&&module/alias current-module alias path))] + (return &/$Nil)))))) + _imports))) (defn ^:private coerce [new-type analysis] "(-> Type Analysis Analysis)" diff --git a/src/lux/analyser/meta.clj b/src/lux/analyser/meta.clj index 3f2016f27..831386f47 100644 --- a/src/lux/analyser/meta.clj +++ b/src/lux/analyser/meta.clj @@ -20,7 +20,7 @@ ;; [Values] (defn meta-get [ident dict] - "(-> Ident DefMeta (Maybe DefMetaValue))" + "(-> Ident Anns (Maybe Ann-Value))" (|case dict (&/$Cons [k v] dict*) (if (ident= k ident) @@ -42,4 +42,5 @@ macro?-tag "macro?" export?-tag "export?" tags-tag "tags" + imports-tag "imports" ) diff --git a/src/lux/analyser/module.clj b/src/lux/analyser/module.clj index ead4ffc67..a06988a3f 100644 --- a/src/lux/analyser/module.clj +++ b/src/lux/analyser/module.clj @@ -22,7 +22,8 @@ "defs" "imports" "tags" - "types"]) + "types" + "module-anns"]) (defn ^:private new-module [hash] (&/T [;; lux;module-hash @@ -36,7 +37,9 @@ ;; "lux;tags" (&/|table) ;; "lux;types" - (&/|table)] + (&/|table) + ;; module-anns + (&/|list)] )) ;; [Exports] @@ -166,6 +169,25 @@ (&/get$ $imports) (&/|any? (partial = imported-module)))) +(defn get-anns [module-name] + (fn [state] + (if-let [module (->> state + (&/get$ &/$modules) + (&/|get module-name))] + (return* state (&/get$ $module-anns module)) + ((&/fail-with-loc (str "[Analyser Error] Module does not exist: " module-name)) + state)))) + +(defn set-anns [anns module-name] + (fn [state] + (return* (->> state + (&/update$ &/$modules + (fn [ms] + (&/|update module-name + #(&/set$ $module-anns anns %) + ms)))) + nil))) + (defn find-def [module name] (|do [current-module &/get-module-name] (fn [state] @@ -350,3 +372,20 @@ test-type &type/Type &meta/type?-tag "type" test-macro &type/Macro &meta/macro?-tag "macro" ) + +(defn fetch-imports [meta] + (|case (&meta/meta-get &meta/imports-tag meta) + (&/$Some (&/$ListM _parts)) + (&/map% (fn [_part] + (|case _part + (&/$ListM (&/$Cons [(&/$TextM _module) + (&/$Cons [(&/$TextM _alias) + (&/$Nil)])])) + (return (&/T [_module _alias])) + + _ + (&/fail-with-loc "[Analyser Error] Wrong import syntax."))) + _parts) + + _ + (&/fail-with-loc "[Analyser Error] No import meta-data."))) diff --git a/src/lux/base.clj b/src/lux/base.clj index 5129fecb0..88d50002b 100644 --- a/src/lux/base.clj +++ b/src/lux/base.clj @@ -230,7 +230,7 @@ (def name-field "_name") (def hash-field "_hash") (def type-field "_type") -(def meta-field "_meta") +(def anns-field "_anns") (def value-field "_value") (def compiler-field "_compiler") (def imports-field "_imports") diff --git a/src/lux/compiler.clj b/src/lux/compiler.clj index 9443b188c..7bf53ada7 100644 --- a/src/lux/compiler.clj +++ b/src/lux/compiler.clj @@ -162,78 +162,94 @@ (partial &&host/compile-jvm-class compile-expression*) &&host/compile-jvm-interface]))) -(defn compile-module [source-dirs name] - (let [file-name (str name ".lux")] - (|do [file-content (&&io/read-file source-dirs file-name) - :let [file-hash (hash file-content)]] - (if (&&cache/cached? name) - (&&cache/load source-dirs name file-hash compile-module) - (let [compiler-step (&analyser/analyse &optimizer/optimize eval! (partial compile-module source-dirs) all-compilers)] - (|do [module-exists? (&a-module/exists? name)] - (if module-exists? - (fail "[Compiler Error] Can't redefine a module!") - (|do [_ (&&cache/delete name) - _ (&a-module/create-module name file-hash) - _ (&/flag-active-module name) - :let [=class (doto (new ClassWriter ClassWriter/COMPUTE_MAXS) - (.visit &host/bytecode-version (+ Opcodes/ACC_PUBLIC Opcodes/ACC_SUPER) - (str (&host/->module-class name) "/_") nil "java/lang/Object" nil) - (-> (.visitField (+ Opcodes/ACC_PUBLIC Opcodes/ACC_FINAL Opcodes/ACC_STATIC) &/hash-field "I" nil file-hash) - .visitEnd) - (-> (.visitField (+ Opcodes/ACC_PUBLIC Opcodes/ACC_FINAL Opcodes/ACC_STATIC) &/compiler-field "Ljava/lang/String;" nil &/compiler-version) - .visitEnd) - (.visitSource file-name nil))] - _ (if (= "lux" name) - (|do [_ &&host/compile-Function-class - _ &&host/compile-LuxRT-class] - (return nil)) - (return nil))] - (fn [state] - (|case ((&/with-writer =class - (&/exhaust% compiler-step)) - (&/set$ &/$source (&reader/from name file-content) state)) - (&/$Right ?state _) - (&/run-state (|do [defs &a-module/defs - imports &a-module/imports - tag-groups &&module/tag-groups - :let [_ (doto =class - (-> (.visitField (+ Opcodes/ACC_PUBLIC Opcodes/ACC_FINAL Opcodes/ACC_STATIC) &/defs-field "Ljava/lang/String;" nil - (->> defs - (&/|map (fn [_def] - (|let [[?name ?alias] _def] - (str ?name - &&/exported-separator - ?alias)))) - (&/|interpose &&/def-separator) - (&/fold str ""))) - .visitEnd) - (-> (.visitField (+ Opcodes/ACC_PUBLIC Opcodes/ACC_FINAL Opcodes/ACC_STATIC) &/imports-field "Ljava/lang/String;" nil - (->> imports - (&/|map (fn [import] - (|let [[_module _hash] import] - (str _module &&/field-separator _hash)))) - (&/|interpose &&/entry-separator) - (&/fold str ""))) - .visitEnd) - (-> (.visitField (+ Opcodes/ACC_PUBLIC Opcodes/ACC_FINAL Opcodes/ACC_STATIC) &/tags-field "Ljava/lang/String;" nil - (->> tag-groups - (&/|map (fn [group] - (|let [[type tags] group] - (->> tags (&/|interpose &&/tag-separator) (&/fold str "") - (str type &&/type-separator))))) - (&/|interpose &&/tag-group-separator) - (&/fold str ""))) - .visitEnd) - (.visitEnd))] - _ (&/flag-compiled-module name) - _ (&&/save-class! &/module-class-name (.toByteArray =class))] - (return file-hash)) - ?state) - - (&/$Left ?message) - (fail* ?message))))))) - )) - )) +(let [+field-flags+ (+ Opcodes/ACC_PUBLIC Opcodes/ACC_FINAL Opcodes/ACC_STATIC) + +datum-sig+ "Ljava/lang/Object;"] + (defn compile-module [source-dirs name] + (let [file-name (str name ".lux")] + (|do [file-content (&&io/read-file source-dirs file-name) + :let [file-hash (hash file-content)]] + (if (&&cache/cached? name) + (&&cache/load source-dirs name file-hash compile-module) + (let [compiler-step (&analyser/analyse &optimizer/optimize eval! (partial compile-module source-dirs) all-compilers)] + (|do [module-exists? (&a-module/exists? name)] + (if module-exists? + (fail "[Compiler Error] Can't redefine a module!") + (|do [_ (&&cache/delete name) + _ (&a-module/create-module name file-hash) + _ (&/flag-active-module name) + :let [module-class-name (str (&host/->module-class name) "/_") + =class (doto (new ClassWriter ClassWriter/COMPUTE_MAXS) + (.visit &host/bytecode-version (+ Opcodes/ACC_PUBLIC Opcodes/ACC_SUPER) + module-class-name nil "java/lang/Object" nil) + (-> (.visitField +field-flags+ &/hash-field "I" nil file-hash) + .visitEnd) + (-> (.visitField +field-flags+ &/compiler-field "Ljava/lang/String;" nil &/compiler-version) + .visitEnd) + (-> (.visitField +field-flags+ &/anns-field +datum-sig+ nil nil) + (doto (.visitEnd))) + (.visitSource file-name nil))] + _ (if (= "lux" name) + (|do [_ &&host/compile-Function-class + _ &&host/compile-LuxRT-class] + (return nil)) + (return nil))] + (fn [state] + (|case ((&/with-writer =class + (&/exhaust% compiler-step)) + (&/set$ &/$source (&reader/from name file-content) state)) + (&/$Right ?state _) + (&/run-state (|do [==anns (&a-module/get-anns name) + defs &a-module/defs + imports &a-module/imports + tag-groups &&module/tag-groups + :let [_ (doto =class + (-> (.visitField (+ Opcodes/ACC_PUBLIC Opcodes/ACC_FINAL Opcodes/ACC_STATIC) &/defs-field "Ljava/lang/String;" nil + (->> defs + (&/|map (fn [_def] + (|let [[?name ?alias] _def] + (str ?name + &&/exported-separator + ?alias)))) + (&/|interpose &&/def-separator) + (&/fold str ""))) + .visitEnd) + (-> (.visitField (+ Opcodes/ACC_PUBLIC Opcodes/ACC_FINAL Opcodes/ACC_STATIC) &/imports-field "Ljava/lang/String;" nil + (->> imports + (&/|map (fn [import] + (|let [[_module _hash] import] + (str _module &&/field-separator _hash)))) + (&/|interpose &&/entry-separator) + (&/fold str ""))) + .visitEnd) + (-> (.visitField (+ Opcodes/ACC_PUBLIC Opcodes/ACC_FINAL Opcodes/ACC_STATIC) &/tags-field "Ljava/lang/String;" nil + (->> tag-groups + (&/|map (fn [group] + (|let [[type tags] group] + (->> tags (&/|interpose &&/tag-separator) (&/fold str "") + (str type &&/type-separator))))) + (&/|interpose &&/tag-group-separator) + (&/fold str ""))) + .visitEnd))] + _ (&/with-writer (.visitMethod =class Opcodes/ACC_PUBLIC "" "()V" nil nil) + (|do [^MethodVisitor **writer** &/get-writer + :let [_ (.visitCode **writer**)] + _ (&&/compile-meta compile-expression ==anns) + :let [_ (.visitFieldInsn **writer** Opcodes/PUTSTATIC module-class-name &/anns-field +datum-sig+)] + :let [_ (doto **writer** + (.visitInsn Opcodes/RETURN) + (.visitMaxs 0 0) + (.visitEnd))]] + (return nil))) + :let [_ (.visitEnd =class)] + _ (&/flag-compiled-module name) + _ (&&/save-class! &/module-class-name (.toByteArray =class))] + (return file-hash)) + ?state) + + (&/$Left ?message) + (fail* ?message))))))) + )) + ))) (defn compile-program [mode program-module source-dirs] (init!) diff --git a/src/lux/compiler/base.clj b/src/lux/compiler/base.clj index 6f3bee1d6..14a223eed 100644 --- a/src/lux/compiler/base.clj +++ b/src/lux/compiler/base.clj @@ -9,12 +9,13 @@ [clojure.java.io :as io] [clojure.core.match :as M :refer [matchv]] clojure.core.match.array - (lux [base :as & :refer [|do return* return fail fail*]] + (lux [base :as & :refer [|let |do return* return fail fail*]] [type :as &type] [host :as &host]) (lux.analyser [base :as &a] [module :as &a-module]) - [lux.host.generics :as &host-generics]) + [lux.host.generics :as &host-generics] + (lux.compiler [type :as &&type])) (:import (org.objectweb.asm Opcodes Label ClassWriter @@ -105,3 +106,7 @@ wrap-double unwrap-double "java/lang/Double" "doubleValue" "D" Opcodes/DUP_X2 wrap-char unwrap-char "java/lang/Character" "charValue" "C" Opcodes/DUP_X1 ) + +(defn compile-meta [compile anns] + (|let [analysis (&&type/defmeta->analysis anns)] + (compile nil analysis))) diff --git a/src/lux/compiler/cache.clj b/src/lux/compiler/cache.clj index e573410d7..f2668f8b5 100644 --- a/src/lux/compiler/cache.clj +++ b/src/lux/compiler/cache.clj @@ -97,12 +97,12 @@ module-path (str &&/output-dir "/" module) class-name (str module* "._") old-classes @!classes - ^Class module-meta (do (swap! !classes assoc class-name (read-file (File. (str module-path "/_.class")))) - (&&/load-class! loader class-name)) + ^Class module-class (do (swap! !classes assoc class-name (read-file (File. (str module-path "/_.class")))) + (&&/load-class! loader class-name)) _ (install-all-classes-in-module !classes module* module-path)]] - (if (and (= module-hash (get-field &/hash-field module-meta)) - (= &/compiler-version (get-field &/compiler-field module-meta))) - (let [imports (string/split (get-field &/imports-field module-meta) entry-separator-re)] + (if (and (= module-hash (get-field &/hash-field module-class)) + (= &/compiler-version (get-field &/compiler-field module-class))) + (let [imports (string/split (get-field &/imports-field module-class) entry-separator-re)] (|do [loads (&/map% (fn [_import] (let [[_module _hash] (string/split _import field-separator-re)] (|do [file-content (&&io/read-file source-dirs (str _module ".lux")) @@ -117,8 +117,8 @@ &/$Nil (&/->list imports)))] (if (->> loads &/->seq (every? true?)) - (let [defs (string/split (get-field &/defs-field module-meta) def-separator-re) - tag-groups (let [all-tags (get-field &/tags-field module-meta)] + (let [defs (string/split (get-field &/defs-field module-class) def-separator-re) + tag-groups (let [all-tags (get-field &/tags-field module-class)] (if (= "" all-tags) &/$Nil (-> all-tags @@ -128,13 +128,15 @@ (&/T [_type (&/->list (string/split (or _tags "") tag-separator-re))]))))) &/->list)))] (|do [_ (&a-module/create-module module module-hash) + :let [module-anns (get-field &/anns-field module-class)] + _ (&a-module/set-anns module-anns module) _ (&/flag-cached-module module) _ (&a-module/set-imports imports) _ (&/map% (fn [_def] (let [[_name _alias] (string/split _def #" ")] (if (= nil _alias) (let [def-class (&&/load-class! loader (str module* "." (&host/def-name _name))) - def-meta (get-field &/meta-field def-class) + def-meta (get-field &/anns-field def-class) def-type (|case (&a-meta/meta-get &a-meta/type?-tag def-meta) (&/$Some (&/$BoolM true)) &type/Type diff --git a/src/lux/compiler/lux.clj b/src/lux/compiler/lux.clj index 38176d3ec..976bdfa15 100644 --- a/src/lux/compiler/lux.clj +++ b/src/lux/compiler/lux.clj @@ -232,10 +232,6 @@ (&&type/type->analysis ?def-type)))]] (compile nil ?def-type))) -(defn ^:private compile-def-meta [compile ?meta] - (|let [analysis (&&type/defmeta->analysis ?meta)] - (compile nil analysis))) - (defn ^:private de-ann [optim] (|case optim [_ (&o/$ann value-expr _)] @@ -284,7 +280,7 @@ (doto (.visitEnd))) (-> (.visitField field-flags &/type-field datum-sig nil nil) (doto (.visitEnd))) - (-> (.visitField field-flags &/meta-field datum-sig nil nil) + (-> (.visitField field-flags &/anns-field datum-sig nil nil) (doto (.visitEnd))) (-> (.visitField field-flags &/value-field datum-sig nil nil) (doto (.visitEnd))) @@ -295,8 +291,8 @@ :let [_ (.visitCode **writer**)] _ (compile-def-type compile ?body) :let [_ (.visitFieldInsn **writer** Opcodes/PUTSTATIC current-class &/type-field datum-sig)] - _ (compile-def-meta compile ?meta) - :let [_ (.visitFieldInsn **writer** Opcodes/PUTSTATIC current-class &/meta-field datum-sig)] + _ (&&/compile-meta compile ?meta) + :let [_ (.visitFieldInsn **writer** Opcodes/PUTSTATIC current-class &/anns-field datum-sig)] _ instancer :let [_ (.visitFieldInsn **writer** Opcodes/PUTSTATIC current-class &/value-field datum-sig)] :let [_ (doto **writer** @@ -367,7 +363,7 @@ (doto (.visitEnd))) (-> (.visitField field-flags &/type-field datum-sig nil nil) (doto (.visitEnd))) - (-> (.visitField field-flags &/meta-field datum-sig nil nil) + (-> (.visitField field-flags &/anns-field datum-sig nil nil) (doto (.visitEnd))) (-> (.visitField field-flags &/value-field datum-sig nil nil) (doto (.visitEnd))) @@ -377,8 +373,8 @@ :let [_ (.visitCode **writer**)] _ (compile-def-type compile ?body) :let [_ (.visitFieldInsn **writer** Opcodes/PUTSTATIC current-class &/type-field datum-sig)] - _ (compile-def-meta compile ?meta) - :let [_ (.visitFieldInsn **writer** Opcodes/PUTSTATIC current-class &/meta-field datum-sig)] + _ (&&/compile-meta compile ?meta) + :let [_ (.visitFieldInsn **writer** Opcodes/PUTSTATIC current-class &/anns-field datum-sig)] _ (compile nil ?body) :let [_ (.visitFieldInsn **writer** Opcodes/PUTSTATIC current-class &/value-field datum-sig)] :let [_ (doto **writer** diff --git a/src/lux/compiler/type.clj b/src/lux/compiler/type.clj index f80e32a57..b2b0f9cb9 100644 --- a/src/lux/compiler/type.clj +++ b/src/lux/compiler/type.clj @@ -107,7 +107,7 @@ )) (defn ^:private defmetavalue->analysis [dmv] - "(-> DefMetaValue Analysis)" + "(-> Ann-Value Analysis)" (|case dmv (&/$BoolM value) (variant$ #'&/$BoolM (bool$ value)) @@ -149,7 +149,7 @@ )) (defn defmeta->analysis [xs] - "(-> DefMeta Analysis)" + "(-> Anns Analysis)" (List$ (&/|map (fn [kv] (|let [[k v] kv] (tuple$ (&/|list (ident$ k) diff --git a/src/lux/type.clj b/src/lux/type.clj index 64b189949..05a353e85 100644 --- a/src/lux/type.clj +++ b/src/lux/type.clj @@ -114,9 +114,9 @@ ) &/$VoidT)))) -(def DefMetaValue - (&/$NamedT (&/T ["lux" "DefMetaValue"]) - (let [DefMetaValue (&/$AppT (&/$BoundT 0) (&/$BoundT 1))] +(def Ann-Value + (&/$NamedT (&/T ["lux" "Ann-Value"]) + (let [Ann-Value (&/$AppT (&/$BoundT 0) (&/$BoundT 1))] (&/$AppT (&/$UnivQ empty-env (&/$SumT ;; BoolM @@ -144,15 +144,15 @@ Ident (&/$SumT ;; ListM - (&/$AppT List DefMetaValue) + (&/$AppT List Ann-Value) ;; DictM - (&/$AppT List (&/$ProdT Text DefMetaValue))))))))))) + (&/$AppT List (&/$ProdT Text Ann-Value))))))))))) ) &/$VoidT)))) -(def DefMeta - (&/$NamedT (&/T ["lux" "DefMeta"]) - (&/$AppT List (&/$ProdT Ident DefMetaValue)))) +(def Anns + (&/$NamedT (&/T ["lux" "Anns"]) + (&/$AppT List (&/$ProdT Ident Ann-Value)))) (def Macro) -- cgit v1.2.3