aboutsummaryrefslogtreecommitdiff
path: root/src/lux/optimizer.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/lux/optimizer.clj')
-rw-r--r--src/lux/optimizer.clj182
1 files changed, 125 insertions, 57 deletions
diff --git a/src/lux/optimizer.clj b/src/lux/optimizer.clj
index 755c4aae2..5c30dc44f 100644
--- a/src/lux/optimizer.clj
+++ b/src/lux/optimizer.clj
@@ -101,6 +101,71 @@
;; branch's body.
("ExecPM" 1))
+(defn de-meta
+ "(-> Optimized Optimized)"
+ [optim]
+ (|let [[meta optim-] optim]
+ (|case optim-
+ ($variant idx is-last? value)
+ ($variant idx is-last? (de-meta value))
+
+ ($tuple elems)
+ ($tuple (&/|map de-meta elems))
+
+ ($case value [_pm _bodies])
+ ($case (de-meta value)
+ (&/T [_pm (&/|map de-meta _bodies)]))
+
+ ($function _register-offset arity scope captured body*)
+ ($function _register-offset
+ arity
+ scope
+ (&/|map (fn [capture]
+ (|let [[_name [_meta ($captured _scope _idx _source)]] capture]
+ (&/T [_name ($captured _scope _idx (de-meta _source))])))
+ captured)
+ (de-meta body*))
+
+ ($ann value-expr type-expr)
+ (de-meta value-expr)
+
+ ($apply func args)
+ ($apply (de-meta func)
+ (&/|map de-meta args))
+
+ ($captured scope idx source)
+ ($captured scope idx (de-meta source))
+
+ ($proc proc-ident args special-args)
+ ($proc proc-ident (&/|map de-meta args) special-args)
+
+ ($loop _register-offset _inits _body)
+ ($loop _register-offset
+ (&/|map de-meta _inits)
+ (de-meta _body))
+
+ ($iter _iter-register-offset args)
+ ($iter _iter-register-offset
+ (&/|map de-meta args))
+
+ ($let _value _register _body)
+ ($let (de-meta _value)
+ _register
+ (de-meta _body))
+
+ ($record-get _value _path)
+ ($record-get (de-meta _value)
+ _path)
+
+ ($if _test _then _else)
+ ($if (de-meta _test)
+ (de-meta _then)
+ (de-meta _else))
+
+ _
+ optim-
+ )))
+
;; This function does a simple transformation from the declarative
;; model of PM of the analyser, to the operational model of PM of the
;; optimizer.
@@ -797,7 +862,7 @@
(|case optim-
($apply [meta-0 ($var (&/$Local 0))] _args)
(if (= arity (&/|length _args))
- (&/T [meta ($iter 0 _args)])
+ (&/T [meta ($iter 1 _args)])
optim)
($case _value [_pattern _bodies])
@@ -880,99 +945,102 @@
false
)))
-(defn ^:private pm-loop-transform [register-offset pattern]
+(defn ^:private pm-loop-transform [register-offset direct? pattern]
(|case pattern
($BindPM _var-id)
- ($BindPM (+ register-offset _var-id))
+ ($BindPM (+ register-offset (if direct?
+ (- _var-id 2)
+ (- _var-id 1))))
($SeqPM _left-pm _right-pm)
- ($SeqPM (pm-loop-transform register-offset _left-pm)
- (pm-loop-transform register-offset _right-pm))
+ ($SeqPM (pm-loop-transform register-offset direct? _left-pm)
+ (pm-loop-transform register-offset direct? _right-pm))
($AltPM _left-pm _right-pm)
- ($AltPM (pm-loop-transform register-offset _left-pm)
- (pm-loop-transform register-offset _right-pm))
+ ($AltPM (pm-loop-transform register-offset direct? _left-pm)
+ (pm-loop-transform register-offset direct? _right-pm))
_
pattern
))
-(defn ^:private loop-transform [register-offset body]
- (|let [[meta body-] body]
+;; This function must be run STRICTLY before shift-function body, as
+;; the transformation assumes that SFB will be invoke after it.
+(defn ^:private loop-transform [register-offset direct? body]
+ (|let [adjust-direct (fn [register]
+ ;; The register must be decreased once, since
+ ;; it will be re-increased in
+ ;; shift-function-body.
+ ;; The decrease is meant to keep things stable.
+ (if direct?
+ ;; And, if this adjustment is done
+ ;; directly during a loop-transform (and
+ ;; not indirectly if transforming an inner
+ ;; loop), then it must be decreased again
+ ;; because the 0/self var will no longer
+ ;; exist in the loop's context.
+ (- register 2)
+ (- register 1)))
+ [meta body-] body]
(|case body-
($variant idx is-last? value)
- (&/T [meta ($variant idx is-last? (loop-transform register-offset value))])
+ (&/T [meta ($variant idx is-last? (loop-transform register-offset direct? value))])
($tuple elems)
- (&/T [meta ($tuple (&/|map (partial loop-transform register-offset) elems))])
+ (&/T [meta ($tuple (&/|map (partial loop-transform register-offset direct?) elems))])
($case value [_pm _bodies])
- (&/T [meta ($case (loop-transform register-offset value)
- (&/T [(pm-loop-transform register-offset _pm)
- (&/|map (partial loop-transform register-offset)
+ (&/T [meta ($case (loop-transform register-offset direct? value)
+ (&/T [(pm-loop-transform register-offset direct? _pm)
+ (&/|map (partial loop-transform register-offset direct?)
_bodies)]))])
-
- ($function _register-offset arity scope captured body*)
- (&/T [meta ($function _register-offset
- arity
- scope
- (&/|map (fn [entry]
- (|let [[_name _captured] entry]
- (|case _captured
- ;; [_meta ($captured _scope _idx [_ ($var (&/$Local _l-idx))])]
- ;; (&/T [_meta ($var (&/$Local (+ register-offset (dec _l-idx))))])
-
- [_meta ($captured _scope _idx _source)]
- (&/T [_name _source])
- )))
- captured)
- body*)])
+ ;; Functions are ignored because they'll be handled properly at shift-function-body
+
($ann value-expr type-expr)
- (&/T [meta ($ann (loop-transform register-offset value-expr)
+ (&/T [meta ($ann (loop-transform register-offset direct? value-expr)
type-expr)])
($var (&/$Local idx))
- ;; First, it's decreased because the var index is 1-based (since
- ;; 0 is reserved for self-reference).
+ ;; The index must be decreased once, because the var index is
+ ;; 1-based (since 0 is reserved for self-reference).
+ ;; Then it must be decreased again, since it will be increased
+ ;; in the shift-function-body call.
;; Then, I add the offset to ensure the var points to the right register.
- (&/T [meta ($var (&/$Local (+ register-offset (dec idx))))])
+ (&/T [meta ($var (&/$Local (-> (adjust-direct idx)
+ (+ register-offset))))])
($apply func args)
- (&/T [meta ($apply (loop-transform register-offset func)
- (&/|map (partial loop-transform register-offset) args))])
+ (&/T [meta ($apply (loop-transform register-offset direct? func)
+ (&/|map (partial loop-transform register-offset direct?) args))])
- ;; ($captured scope idx [_ ($var (&/$Local _l-idx))])
- ;; (&/T [meta ($var (&/$Local (+ register-offset (dec _l-idx))))])
-
- ($captured scope idx source)
- source
+ ;; Captured-vars are ignored because they'll be handled properly at shift-function-body
($proc proc-ident args special-args)
- (&/T [meta ($proc proc-ident (&/|map (partial loop-transform register-offset) args) special-args)])
+ (&/T [meta ($proc proc-ident (&/|map (partial loop-transform register-offset direct?) args) special-args)])
($loop _register-offset _inits _body)
- (&/T [meta ($loop (+ register-offset _register-offset)
- (&/|map (partial loop-transform register-offset) _inits)
- (loop-transform register-offset _body))])
+ (&/T [meta ($loop (+ register-offset (adjust-direct _register-offset))
+ (&/|map (partial loop-transform register-offset direct?) _inits)
+ (loop-transform register-offset direct? _body))])
($iter _iter-register-offset args)
- (&/T [meta ($iter (+ register-offset _iter-register-offset)
- (&/|map (partial loop-transform register-offset) args))])
+ (&/T [meta ($iter (+ register-offset (adjust-direct _iter-register-offset))
+ (&/|map (partial loop-transform register-offset direct?) args))])
($let _value _register _body)
- (&/T [meta ($let (loop-transform register-offset _value)
- (+ register-offset _register)
- (loop-transform register-offset _body))])
+ (&/T [meta ($let (loop-transform register-offset direct? _value)
+ (+ register-offset (adjust-direct _register))
+ (loop-transform register-offset direct? _body))])
($record-get _value _path)
- (&/T [meta ($record-get (loop-transform register-offset _value)
+ (&/T [meta ($record-get (loop-transform register-offset direct? _value)
_path)])
($if _test _then _else)
- (&/T [meta ($if (loop-transform register-offset _test)
- (loop-transform register-offset _then)
- (loop-transform register-offset _else))])
+ (&/T [meta ($if (loop-transform register-offset direct? _test)
+ (loop-transform register-offset direct? _then)
+ (loop-transform register-offset direct? _else))])
_
body
@@ -980,8 +1048,8 @@
(defn ^:private inline-loop [meta register-offset scope captured args body]
(->> body
+ (loop-transform register-offset true)
(shift-function-body scope (&/|tail scope) true)
- (loop-transform register-offset)
($loop register-offset args)
(list meta)
(&/T)))
@@ -1033,8 +1101,8 @@
(|let [=func (pass-0 top-level-func? func)
=args (&/|map (partial pass-0 top-level-func?) args)]
(|case =func
- [_ (&a/$ann [_ ($function _register-offset _arity _scope _captured _body)]
- _)]
+ [_ ($ann [_ ($function _register-offset _arity _scope _captured _body)]
+ _)]
(if (and (= _arity (&/|length =args))
(not (contains-self-reference? _body)))
(inline-loop meta _register-offset _scope _captured =args _body)