aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEduardo Julian2016-07-26 23:26:17 -0400
committerEduardo Julian2016-07-26 23:26:17 -0400
commit1ec61a0e6046afc3f408efbfc238391a0cac5bbf (patch)
treeb422ab70088497e09f95c4f85ca5b12c9bab84fc /src
parent65f6e162eecc6d754e2ccae83957f6ccb7b0bb70 (diff)
- A module's hash is also stored in the Compiler state and in the cached classes, to check for inconsistencies in the dependencies when loading cached modules.
Diffstat (limited to 'src')
-rw-r--r--src/lux/analyser/module.clj39
-rw-r--r--src/lux/compiler.clj17
-rw-r--r--src/lux/compiler/base.clj4
-rw-r--r--src/lux/compiler/cache.clj151
-rw-r--r--src/lux/repl.clj2
5 files changed, 114 insertions, 99 deletions
diff --git a/src/lux/analyser/module.clj b/src/lux/analyser/module.clj
index 4124503bd..dac7a3870 100644
--- a/src/lux/analyser/module.clj
+++ b/src/lux/analyser/module.clj
@@ -17,14 +17,17 @@
;; [Utils]
(deftuple
- ["module-aliases"
+ ["module-hash"
+ "module-aliases"
"defs"
"imports"
"tags"
"types"])
-(def ^:private +init+
- (&/T [;; "lux;module-aliases"
+(defn ^:private new-module [hash]
+ (&/T [;; lux;module-hash
+ hash
+ ;; "lux;module-aliases"
(&/|table)
;; "lux;defs"
(&/|table)
@@ -197,21 +200,11 @@
(return true))
(return false))))
-(def imports
- (|do [module &/get-module-name]
- (fn [state]
- (return* state (->> state (&/get$ &/$modules) (&/|get module) (&/get$ $imports))))))
-
-(defn create-module [name]
- "(-> Text (Lux Null))"
- (fn [state]
- (return* (&/update$ &/$modules #(&/|put name +init+ %) state) nil)))
-
-(defn enter-module [name]
- "(-> Text (Lux Null))"
+(defn create-module [name hash]
+ "(-> Text Hash-Code (Lux Null))"
(fn [state]
(return* (->> state
- (&/update$ &/$modules #(&/|put name +init+ %))
+ (&/update$ &/$modules #(&/|put name (new-module hash) %))
(&/set$ &/$envs (&/|list (&/env name))))
nil)))
@@ -225,10 +218,20 @@
state))
))
- tags-by-module $tags "(-> Text (Lux (List (, Text (, Int (List Text) Type)))))"
- types-by-module $types "(-> Text (Lux (List (, Text (, (List Text) Type)))))"
+ tags-by-module $tags "(-> Text (Lux (List (, Text (, Int (List Text) Type)))))"
+ types-by-module $types "(-> Text (Lux (List (, Text (, (List Text) Type)))))"
+ module-hash $module-hash "(-> Text (Lux Int))"
)
+(def imports
+ (|do [module &/get-module-name
+ _imports (fn [state]
+ (return* state (->> state (&/get$ &/$modules) (&/|get module) (&/get$ $imports))))]
+ (&/map% (fn [_module]
+ (|do [_hash (module-hash _module)]
+ (return (&/T [_module _hash]))))
+ _imports)))
+
(defn ensure-undeclared-tags [module tags]
(|do [tags-table (tags-by-module module)
_ (&/map% (fn [tag]
diff --git a/src/lux/compiler.clj b/src/lux/compiler.clj
index a5d7f7115..ef7fe9b1a 100644
--- a/src/lux/compiler.clj
+++ b/src/lux/compiler.clj
@@ -159,7 +159,7 @@
(if module-exists?
(fail "[Compiler Error] Can't redefine a module!")
(|do [_ (&&cache/delete name)
- _ (&a-module/enter-module 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)
@@ -194,7 +194,12 @@
(&/fold str "")))
.visitEnd)
(-> (.visitField (+ Opcodes/ACC_PUBLIC Opcodes/ACC_FINAL Opcodes/ACC_STATIC) &/imports-field "Ljava/lang/String;" nil
- (->> imports (&/|interpose &&/import-separator) (&/fold str "")))
+ (->> 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
@@ -205,10 +210,10 @@
(&/|interpose &&/tag-group-separator)
(&/fold str "")))
.visitEnd)
- (.visitEnd))
- ]
- _ (&/flag-compiled-module name)]
- (&&/save-class! &/module-class-name (.toByteArray =class)))
+ (.visitEnd))]
+ _ (&/flag-compiled-module name)
+ _ (&&/save-class! &/module-class-name (.toByteArray =class))]
+ (return file-hash))
?state)
(&/$Left ?message)
diff --git a/src/lux/compiler/base.clj b/src/lux/compiler/base.clj
index 5c50191fe..6f3bee1d6 100644
--- a/src/lux/compiler/base.clj
+++ b/src/lux/compiler/base.clj
@@ -44,11 +44,13 @@
(def exported-separator " ")
(def def-separator "\t")
-(def import-separator "\t")
(def tag-separator " ")
(def type-separator "\t")
(def tag-group-separator "\n")
+(def field-separator "\t")
+(def entry-separator "\n")
+
;; [Utils]
(defn ^:private write-file [^String file-name ^bytes data]
(do (assert (not (.exists (File. file-name))) (str "Can't overwrite file: " file-name))
diff --git a/src/lux/compiler/cache.clj b/src/lux/compiler/cache.clj
index 27bf56411..e573410d7 100644
--- a/src/lux/compiler/cache.clj
+++ b/src/lux/compiler/cache.clj
@@ -77,84 +77,89 @@
(swap! !classes assoc (str module* "." real-name) bytecode))))
(let [->regex (fn [text] (re-pattern (java.util.regex.Pattern/quote text)))
- import-separator-re (->regex &&/import-separator)
+ entry-separator-re (->regex &&/entry-separator)
+ field-separator-re (->regex &&/field-separator)
type-separator-re (->regex &&/type-separator)
tag-separator-re (->regex &&/tag-separator)
def-separator-re (->regex &&/def-separator)
tag-group-separator-re (->regex &&/tag-group-separator)]
(defn load [source-dirs module module-hash compile-module]
"(-> (List Text) Text Int (-> Text (Lux (,))) (Lux Bool))"
- (|do [loader &/loader
- !classes &/classes
- already-loaded? (&a-module/exists? module)
- _modules &/modules
- :let [redo-cache (|do [_ (delete module)
- _ (compile-module source-dirs module)]
- (return false))]]
+ (|do [already-loaded? (&a-module/exists? module)]
(if already-loaded?
- (return true)
- (if (cached? module)
- (let [module* (&host-generics/->class-name module)
- 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))
- _ (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) import-separator-re)]
- (|do [loads (&/map% (fn [_import]
- (|do [content (&&io/read-file source-dirs (str _import ".lux"))
- _ (load source-dirs _import (hash content) compile-module)]
- (&/cached-module? _import)))
- (if (= [""] imports)
- &/$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)]
- (if (= "" all-tags)
- &/$Nil
- (-> all-tags
- (string/split tag-group-separator-re)
- (->> (map (fn [_group]
- (let [[_type _tags] (string/split _group type-separator-re)]
- (&/T [_type (&/->list (string/split (or _tags "") tag-separator-re))])))))
- &/->list)))]
- (|do [_ (&a-module/enter-module 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-type (|case (&a-meta/meta-get &a-meta/type?-tag def-meta)
- (&/$Some (&/$BoolM true))
- &type/Type
-
- _
- (get-field &/type-field def-class))
- def-value (get-field &/value-field def-class)]
- (&a-module/define module _name def-type def-meta def-value))
- (let [[_ __module __name] (re-find #"^(.*);(.*)$" _alias)
- def-class (&&/load-class! loader (str (&host-generics/->class-name __module) "." (&host/def-name __name)))
- def-type (get-field &/type-field def-class)
- def-meta (&/|list (&/T [&a-meta/alias-tag (&/$IdentM (&/T [__module __name]))]))
- def-value (get-field &/value-field def-class)]
- (&a-module/define module _name def-type def-meta def-value)))
- ))
- (if (= [""] defs)
+ (return module-hash)
+ (|let [redo-cache (|do [_ (delete module)]
+ (compile-module source-dirs module))]
+ (if (cached? module)
+ (|do [loader &/loader
+ !classes &/classes
+ :let [module* (&host-generics/->class-name module)
+ 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))
+ _ (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)]
+ (|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"))
+ :let [file-hash (hash file-content)
+ __hash (Integer/parseInt _hash)]
+ _ (load source-dirs _module file-hash compile-module)
+ cached? (&/cached-module? _module)
+ :let [consistent-cache? (= file-hash __hash)]]
+ (return (and cached?
+ consistent-cache?)))))
+ (if (= [""] imports)
&/$Nil
- (&/->list defs)))
- _ (&/map% (fn [group]
- (|let [[_type _tags] group]
- (|do [[was-exported? =type] (&a-module/type-def module _type)]
- (&a-module/declare-tags module _tags was-exported? =type))))
- tag-groups)]
- (return true)))
- redo-cache)))
- (do (reset! !classes old-classes)
- redo-cache)))
- redo-cache)))))
+ (&/->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)]
+ (if (= "" all-tags)
+ &/$Nil
+ (-> all-tags
+ (string/split tag-group-separator-re)
+ (->> (map (fn [_group]
+ (let [[_type _tags] (string/split _group type-separator-re)]
+ (&/T [_type (&/->list (string/split (or _tags "") tag-separator-re))])))))
+ &/->list)))]
+ (|do [_ (&a-module/create-module module module-hash)
+ _ (&/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-type (|case (&a-meta/meta-get &a-meta/type?-tag def-meta)
+ (&/$Some (&/$BoolM true))
+ &type/Type
+
+ _
+ (get-field &/type-field def-class))
+ def-value (get-field &/value-field def-class)]
+ (&a-module/define module _name def-type def-meta def-value))
+ (let [[_ __module __name] (re-find #"^(.*);(.*)$" _alias)
+ def-class (&&/load-class! loader (str (&host-generics/->class-name __module) "." (&host/def-name __name)))
+ def-type (get-field &/type-field def-class)
+ def-meta (&/|list (&/T [&a-meta/alias-tag (&/$IdentM (&/T [__module __name]))]))
+ def-value (get-field &/value-field def-class)]
+ (&a-module/define module _name def-type def-meta def-value)))
+ ))
+ (if (= [""] defs)
+ &/$Nil
+ (&/->list defs)))
+ _ (&/map% (fn [group]
+ (|let [[_type _tags] group]
+ (|do [[was-exported? =type] (&a-module/type-def module _type)]
+ (&a-module/declare-tags module _tags was-exported? =type))))
+ tag-groups)]
+ (return module-hash)))
+ redo-cache)))
+ (do (reset! !classes old-classes)
+ redo-cache)))
+ redo-cache))))))
diff --git a/src/lux/repl.clj b/src/lux/repl.clj
index 0c4202650..0ffbdc1af 100644
--- a/src/lux/repl.clj
+++ b/src/lux/repl.clj
@@ -22,7 +22,7 @@
(defn ^:private init []
(do (&compiler/init!)
(|case ((|do [_ (&compiler/compile-module "lux")]
- (&module/enter-module repl-module))
+ (&module/create-module repl-module 0))
(&/init-state &/$Debug))
(&/$Right ?state _)
(do (println)