diff options
author | Eduardo Julian | 2017-11-21 16:09:07 -0400 |
---|---|---|
committer | Eduardo Julian | 2017-11-21 16:09:07 -0400 |
commit | e37e3713e080606930a5f8442f03dabc4c26a7f9 (patch) | |
tree | ad772c1801af0d01dc105bccf85703f13b127e50 /new-luxc/source | |
parent | 3eabc421e559e7e2f903e06eb6b47a2ee0cd25b9 (diff) |
- Fixed some bugs.
- Some small refactoring.
Diffstat (limited to 'new-luxc/source')
-rw-r--r-- | new-luxc/source/luxc/lang/analysis/case.lux | 2 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/analysis/expression.lux | 15 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/analysis/function.lux | 6 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/analysis/procedure/common.lux | 2 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/analysis/reference.lux | 3 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/analysis/structure.lux | 61 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/synthesis/case.lux | 69 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/synthesis/expression.lux | 84 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/synthesis/loop.lux | 39 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/translation.lux | 92 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/translation/imports.jvm.lux | 1 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/translation/loop.jvm.lux | 58 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/translation/procedure/common.jvm.lux | 127 | ||||
-rw-r--r-- | new-luxc/source/luxc/lang/translation/runtime.jvm.lux | 4 |
14 files changed, 311 insertions, 252 deletions
diff --git a/new-luxc/source/luxc/lang/analysis/case.lux b/new-luxc/source/luxc/lang/analysis/case.lux index 4a28ce436..5d4c592aa 100644 --- a/new-luxc/source/luxc/lang/analysis/case.lux +++ b/new-luxc/source/luxc/lang/analysis/case.lux @@ -239,7 +239,7 @@ (^ [cursor (#;Form (list& [_ (#;Tag tag)] values))]) (&;with-cursor cursor (do macro;Monad<Meta> - [tag (macro;canonical tag) + [tag (macro;normalize tag) [idx group variantT] (macro;resolve-tag tag) _ (&;with-type-env (tc;check inputT variantT))] diff --git a/new-luxc/source/luxc/lang/analysis/expression.lux b/new-luxc/source/luxc/lang/analysis/expression.lux index 89fb3b93e..6abe8e62b 100644 --- a/new-luxc/source/luxc/lang/analysis/expression.lux +++ b/new-luxc/source/luxc/lang/analysis/expression.lux @@ -93,13 +93,14 @@ (case ?macro (#;Some macro) (do @ - [expansion (function [compiler] - (case (macroL;expand macro args compiler) - (#e;Success [compiler' output]) - (#e;Success [compiler' output]) - - (#e;Error error) - ((&;throw Macro-Expansion-Failed error) compiler)))] + [expansion (: (Meta (List Code)) + (function [compiler] + (case (macroL;expand macro args compiler) + (#e;Error error) + ((&;throw Macro-Expansion-Failed error) compiler) + + output + output)))] (case expansion (^ (list single)) (analyse single) diff --git a/new-luxc/source/luxc/lang/analysis/function.lux b/new-luxc/source/luxc/lang/analysis/function.lux index a2aa95c08..b4aa31c90 100644 --- a/new-luxc/source/luxc/lang/analysis/function.lux +++ b/new-luxc/source/luxc/lang/analysis/function.lux @@ -17,6 +17,7 @@ ["&;" inference]) [";L" variable #+ Variable]))) +(exception: #export Cannot-Analyse-Function) (exception: #export Invalid-Function-Type) (exception: #export Cannot-Apply-Function) @@ -27,7 +28,10 @@ [functionT macro;expected-type] (loop [expectedT functionT] (&;with-stacked-errors - (function [_] (Invalid-Function-Type (%type expectedT))) + (function [_] (Cannot-Analyse-Function (format " Type: " (%type expectedT) "\n" + "Function: " func-name "\n" + "Argument: " arg-name "\n" + " Body: " (%code body)))) (case expectedT (#;Named name unnamedT) (recur unnamedT) diff --git a/new-luxc/source/luxc/lang/analysis/procedure/common.lux b/new-luxc/source/luxc/lang/analysis/procedure/common.lux index 747e9f61d..489414c2a 100644 --- a/new-luxc/source/luxc/lang/analysis/procedure/common.lux +++ b/new-luxc/source/luxc/lang/analysis/procedure/common.lux @@ -273,6 +273,8 @@ (install "replace-all" (trinary Text Text Text Text)) (install "char" (binary Text Nat (type (Maybe Nat)))) (install "clip" (trinary Text Nat Nat (type (Maybe Text)))) + (install "upper" (unary Text Text)) + (install "lower" (unary Text Text)) ))) (def: (array-get proc) diff --git a/new-luxc/source/luxc/lang/analysis/reference.lux b/new-luxc/source/luxc/lang/analysis/reference.lux index 7475f269f..c660408de 100644 --- a/new-luxc/source/luxc/lang/analysis/reference.lux +++ b/new-luxc/source/luxc/lang/analysis/reference.lux @@ -21,7 +21,8 @@ _ (do @ - [_ (&;infer actualT)] + [_ (&;infer actualT) + def-name (macro;normalize def-name)] (wrap (code;symbol def-name)))))) (def: (analyse-variable var-name) diff --git a/new-luxc/source/luxc/lang/analysis/structure.lux b/new-luxc/source/luxc/lang/analysis/structure.lux index 19eebbc46..e6cd2dbad 100644 --- a/new-luxc/source/luxc/lang/analysis/structure.lux +++ b/new-luxc/source/luxc/lang/analysis/structure.lux @@ -20,10 +20,13 @@ (analysis ["&;" common] ["&;" inference])))) -(exception: #export Not-Variant-Type) -(exception: #export Not-Tuple-Type) +(exception: #export Invalid-Variant-Type) +(exception: #export Invalid-Tuple-Type) (exception: #export Not-Quantified-Type) +(exception: #export Cannot-Analyse-Variant) +(exception: #export Cannot-Analyse-Tuple) + (exception: #export Cannot-Infer-Numeric-Tag) (exception: #export Record-Keys-Must-Be-Tags) (exception: #export Cannot-Repeat-Tag) @@ -35,9 +38,9 @@ (do macro;Monad<Meta> [expectedT macro;expected-type] (&;with-stacked-errors - (function [_] (Not-Variant-Type (format " Type: " (%type expectedT) "\n" - "Value: " (%code valueC) "\n" - " Tag: " (%n tag)))) + (function [_] (Cannot-Analyse-Variant (format " Type: " (%type expectedT) "\n" + " Tag: " (%n tag) "\n" + "Expression: " (%code valueC)))) (case expectedT (#;Sum _) (let [flat (type;flatten-variant expectedT) @@ -70,9 +73,9 @@ ## Cannot do inference when the tag is numeric. ## This is because there is no way of knowing how many ## cases the inferred sum type would have. - (&;throw Cannot-Infer-Numeric-Tag (format " Tag: " (%n tag) "\n" - "Value: " (%code valueC) "\n" - " Type: " (%type expectedT))) + (&;throw Cannot-Infer-Numeric-Tag (format " Type: " (%type expectedT) "\n" + " Tag: " (%n tag) "\n" + "Expression: " (%code valueC))) )) (^template [<tag> <instancer>] @@ -95,9 +98,9 @@ (analyse-sum analyse tag valueC)) _ - (&;throw Not-Variant-Type (format " Type: " (%type expectedT) "\n" - " Tag: " (%n tag) "\n" - "Value: " (%code valueC))))) + (&;throw Invalid-Variant-Type (format " Type: " (%type expectedT) "\n" + " Tag: " (%n tag) "\n" + "Expression: " (%code valueC))))) _ (case (type;apply (list inputT) funT) @@ -109,9 +112,9 @@ (analyse-sum analyse tag valueC)))) _ - (&;throw Not-Variant-Type (format " Type: " (%type expectedT) "\n" - " Tag: " (%n tag) "\n" - "Value: " (%code valueC))))))) + (&;throw Invalid-Variant-Type (format " Type: " (%type expectedT) "\n" + " Tag: " (%n tag) "\n" + "Expression: " (%code valueC))))))) (def: (analyse-typed-product analyse membersC+) (-> &;Analyser (List Code) (Meta la;Analysis)) @@ -166,8 +169,8 @@ (do macro;Monad<Meta> [expectedT macro;expected-type] (&;with-stacked-errors - (function [_] (Not-Tuple-Type (format " Type: " (%type expectedT) "\n" - "Value: " (%code (` [(~@ membersC)]))))) + (function [_] (Cannot-Analyse-Tuple (format " Type: " (%type expectedT) "\n" + "Expression: " (%code (` [(~@ membersC)]))))) (case expectedT (#;Product _) (analyse-typed-product analyse membersC) @@ -215,8 +218,8 @@ (analyse-product analyse membersC)) _ - (&;throw Not-Tuple-Type (format " Type: " (%type expectedT) "\n" - "Value: " (%code (` [(~@ membersC)])))))) + (&;throw Invalid-Tuple-Type (format " Type: " (%type expectedT) "\n" + "Expression: " (%code (` [(~@ membersC)])))))) _ (case (type;apply (list inputT) funT) @@ -228,14 +231,14 @@ (analyse-product analyse membersC)))) _ - (&;throw Not-Tuple-Type (format " Type: " (%type expectedT) "\n" - "Value: " (%code (` [(~@ membersC)])))) + (&;throw Invalid-Tuple-Type (format " Type: " (%type expectedT) "\n" + "Expression: " (%code (` [(~@ membersC)])))) )))) (def: #export (analyse-tagged-sum analyse tag valueC) (-> &;Analyser Ident Code (Meta la;Analysis)) (do macro;Monad<Meta> - [tag (macro;canonical tag) + [tag (macro;normalize tag) [idx group variantT] (macro;resolve-tag tag) expectedT macro;expected-type] (case expectedT @@ -261,7 +264,7 @@ (case key [_ (#;Tag key)] (do macro;Monad<Meta> - [key (macro;canonical key)] + [key (macro;normalize key)] (wrap [key val])) _ @@ -281,22 +284,26 @@ (#;Cons [head-k head-v] _) (do macro;Monad<Meta> - [head-k (macro;canonical head-k) + [head-k (macro;normalize head-k) [_ tag-set recordT] (macro;resolve-tag head-k) #let [size-record (list;size record) size-ts (list;size tag-set)] _ (if (n.= size-ts size-record) (wrap []) (&;throw Record-Size-Mismatch - (format "Expected: " (|> size-ts nat-to-int %i) "\n" - " Actual: " (|> size-record nat-to-int %i) "\n" - " Type: " (%type recordT)))) + (format " Expected: " (|> size-ts nat-to-int %i) "\n" + " Actual: " (|> size-record nat-to-int %i) "\n" + " Type: " (%type recordT) "\n" + "Expression: " (%code (|> record + (list/map (function [[keyI valueC]] + [(code;tag keyI) valueC])) + code;record))))) #let [tuple-range (list;n.range +0 (n.dec size-ts)) tag->idx (dict;from-list ident;Hash<Ident> (list;zip2 tag-set tuple-range))] idx->val (monad;fold @ (function [[key val] idx->val] (do @ - [key (macro;canonical key)] + [key (macro;normalize key)] (case (dict;get key tag->idx) #;None (&;throw Tag-Does-Not-Belong-To-Record diff --git a/new-luxc/source/luxc/lang/synthesis/case.lux b/new-luxc/source/luxc/lang/synthesis/case.lux index dfe05e1bf..c35483dd8 100644 --- a/new-luxc/source/luxc/lang/synthesis/case.lux +++ b/new-luxc/source/luxc/lang/synthesis/case.lux @@ -13,45 +13,52 @@ (def: popPS ls;Path (' ("lux case pop"))) -(def: (path' outer-arity pattern) - (-> ls;Arity la;Pattern (List ls;Path)) +(def: (path' arity num-locals pattern) + (-> ls;Arity Nat la;Pattern [Nat (List ls;Path)]) (case pattern (^code ("lux case tuple" [(~@ membersP)])) (case membersP #;Nil - (list popPS) + [num-locals + (list popPS)] (#;Cons singletonP #;Nil) - (path' outer-arity singletonP) + (path' arity num-locals singletonP) (#;Cons _) (let [last-idx (n.dec (list;size membersP)) - [_ tuple-path] (list/fold (function [current-pattern [current-idx next]] - [(n.dec current-idx) - (|> (list (if (n.= last-idx current-idx) - (` ("lux case tuple right" (~ (code;nat current-idx)))) - (` ("lux case tuple left" (~ (code;nat current-idx)))))) - (list/compose (path' outer-arity current-pattern)) - (list/compose next))]) - [last-idx (list popPS)] - (list;reverse membersP))] - tuple-path)) + [_ output] (list/fold (: (-> la;Pattern [Nat [Nat (List ls;Path)]] [Nat [Nat (List ls;Path)]]) + (function [current-pattern [current-idx num-locals' next]] + (let [[num-locals'' current-path] (path' arity num-locals' current-pattern)] + [(n.dec current-idx) + num-locals'' + (|> (list (if (n.= last-idx current-idx) + (` ("lux case tuple right" (~ (code;nat current-idx)))) + (` ("lux case tuple left" (~ (code;nat current-idx)))))) + (list/compose current-path) + (list/compose next))]))) + [last-idx num-locals (list popPS)] + (list;reverse membersP))] + output)) (^code ("lux case variant" (~ [_ (#;Nat tag)]) (~ [_ (#;Nat num-tags)]) (~ memberP))) - (|> (list (if (n.= (n.dec num-tags) tag) - (` ("lux case variant right" (~ (code;nat tag)))) - (` ("lux case variant left" (~ (code;nat tag)))))) - (list/compose (path' outer-arity memberP)) - (list& popPS)) + (let [[num-locals' member-path] (path' arity num-locals memberP)] + [num-locals' (|> (list (if (n.= (n.dec num-tags) tag) + (` ("lux case variant right" (~ (code;nat tag)))) + (` ("lux case variant left" (~ (code;nat tag)))))) + (list/compose member-path) + (list& popPS))]) (^code ("lux case bind" (~ [_ (#;Nat register)]))) - (list popPS - (` ("lux case bind" (~ (code;nat (if (functionS;nested? outer-arity) - (|> register variableL;local (functionS;adjust-var outer-arity) variableL;local-register) - register)))))) + [(n.inc num-locals) + (list popPS + (` ("lux case bind" (~ (code;nat (if (functionS;nested? arity) + (n.+ (n.dec arity) register) + register))))))] _ - (list popPS pattern))) + [num-locals + (list popPS pattern)])) (def: (clean-unnecessary-pops paths) (-> (List ls;Path) (List ls;Path)) @@ -64,12 +71,14 @@ #;Nil paths)) -(def: #export (path outer-arity pattern body) - (-> ls;Arity la;Pattern ls;Synthesis ls;Path) - (|> (path' outer-arity pattern) clean-unnecessary-pops - (list/fold (function [pre post] - (` ("lux case seq" (~ pre) (~ post)))) - (` ("lux case exec" (~ body)))))) +(def: #export (path arity num-locals synthesize pattern bodyA) + (-> ls;Arity Nat (-> Nat la;Analysis ls;Synthesis) la;Pattern la;Analysis ls;Path) + (let [[num-locals' pieces] (path' arity num-locals pattern)] + (|> pieces + clean-unnecessary-pops + (list/fold (function [pre post] + (` ("lux case seq" (~ pre) (~ post)))) + (` ("lux case exec" (~ (synthesize num-locals' bodyA)))))))) (def: #export (weave leftP rightP) (-> ls;Path ls;Path ls;Path) diff --git a/new-luxc/source/luxc/lang/synthesis/expression.lux b/new-luxc/source/luxc/lang/synthesis/expression.lux index b9f5d56cc..aaa2cf2c7 100644 --- a/new-luxc/source/luxc/lang/synthesis/expression.lux +++ b/new-luxc/source/luxc/lang/synthesis/expression.lux @@ -59,33 +59,32 @@ (-> ls;Synthesis (List ls;Synthesis) ls;Synthesis) (` ("lux call" (~ funcS) (~@ argsS)))) -(def: (synthesize-case synthesize outer-arity inputA branchesA) - (-> (-> la;Analysis ls;Synthesis) - ls;Arity la;Analysis (List [la;Pattern la;Analysis]) +(def: (synthesize-case arity num-locals synthesize inputA branchesA) + (-> ls;Arity Nat (-> Nat la;Analysis ls;Synthesis) + la;Analysis (List [la;Pattern la;Analysis]) ls;Synthesis) - (let [inputS (synthesize inputA)] + (let [inputS (synthesize num-locals inputA)] (case (list;reverse branchesA) (^multi (^ (list [(^code ("lux case bind" (~ [_ (#;Nat input-register)]))) (^code ((~ [_ (#;Int var)])))])) (not (variableL;captured? var)) - (n.= input-register (int-to-nat var))) + (n.= input-register (variableL;local-register var))) inputS (^ (list [(^code ("lux case bind" (~ [_ (#;Nat register)]))) bodyA])) - (let$ (if (functionS;nested? outer-arity) - (|> register variableL;local (functionS;adjust-var outer-arity) variableL;local-register) + (let$ (if (functionS;nested? arity) + (n.+ (n.dec arity) register) register) inputS - (synthesize bodyA)) + (synthesize (n.inc num-locals) bodyA)) (^or (^ (list [(^code true) thenA] [(^code false) elseA])) (^ (list [(^code false) elseA] [(^code true) thenA]))) - (if$ inputS (synthesize thenA) (synthesize elseA)) + (if$ inputS (synthesize num-locals thenA) (synthesize num-locals elseA)) (#;Cons [lastP lastA] prevsPA) (let [transform-branch (: (-> la;Pattern la;Analysis ls;Path) - (function [pattern expr] - (caseS;path outer-arity pattern (synthesize expr)))) + (caseS;path arity num-locals synthesize)) pathS (list/fold caseS;weave (transform-branch lastP lastA) (list/map (product;uncurry transform-branch) prevsPA))] @@ -95,23 +94,20 @@ (undefined) ))) -(def: (synthesize-apply synthesize outer-arity num-locals exprA) - (-> (-> la;Analysis ls;Synthesis) ls;Arity Nat la;Analysis ls;Synthesis) +(def: (synthesize-apply synthesize num-locals exprA) + (-> (-> la;Analysis ls;Synthesis) Nat la;Analysis ls;Synthesis) (let [[funcA argsA] (functionS;unfold-apply exprA) funcS (synthesize funcA) argsS (list/map synthesize argsA)] (case funcS - (^multi (^ [_ (#;Form (list [_ (#;Text "lux function")] [_ (#;Nat _arity)] [_ (#;Tuple _env)] _bodyS))]) + (^multi (^code ("lux function" (~ [_ (#;Nat _arity)]) [(~@ _env)] (~ _bodyS))) (and (n.= _arity (list;size argsS)) (not (loopS;contains-self-reference? _bodyS))) [(s;run _env (p;some s;int)) (#e;Success _env)]) - (let [register-offset (if (functionS;top? outer-arity) - num-locals - (|> outer-arity n.inc (n.+ num-locals)))] - (` ("lux loop" (~ (code;nat register-offset)) [(~@ argsS)] - (~ (loopS;adjust _env register-offset _bodyS))))) + (` ("lux loop" (~ (code;nat (n.inc num-locals))) [(~@ argsS)] + (~ (loopS;adjust _env num-locals _bodyS)))) - (^ [_ (#;Form (list& [_ (#;Text "lux call")] funcS' argsS'))]) + (^code ("lux call" (~ funcS') (~@ argsS'))) (call$ funcS' (list/compose argsS' argsS)) _ @@ -119,58 +115,59 @@ (def: #export (synthesize expressionA) (-> la;Analysis ls;Synthesis) - (loop [outer-arity +0 + (loop [arity +0 resolver init-resolver direct? false num-locals +0 expressionA expressionA] (case expressionA (^code [(~ _left) (~ _right)]) - (` [(~@ (list/map (recur outer-arity resolver false num-locals) (la;unfold-tuple expressionA)))]) + (` [(~@ (list/map (recur arity resolver false num-locals) + (la;unfold-tuple expressionA)))]) (^or (^code ("lux sum left" (~ _))) (^code ("lux sum right" (~ _)))) (let [[tag last? value] (maybe;assume (la;unfold-variant expressionA))] - (variant$ tag last? (recur outer-arity resolver false num-locals value))) + (variant$ tag last? (recur arity resolver false num-locals value))) (^code ((~ [_ (#;Int var)]))) (if (variableL;local? var) - (if (functionS;nested? outer-arity) + (if (functionS;nested? arity) (if (variableL;self? var) - (call$ (var$ 0) (|> (list;n.range +1 (n.dec outer-arity)) + (call$ (var$ 0) (|> (list;n.range +1 (n.dec arity)) (list/map (|>. variableL;local code;int (~) () (`))))) - (var$ (functionS;adjust-var outer-arity var))) + (var$ (functionS;adjust-var arity var))) (var$ var)) (var$ (maybe;default var (dict;get var resolver)))) (^code ("lux case" (~ inputA) (~ [_ (#;Record branchesA)]))) - (synthesize-case (recur outer-arity resolver false num-locals) outer-arity inputA branchesA) + (synthesize-case arity num-locals (recur arity resolver false) inputA branchesA) (^multi (^code ("lux function" [(~@ scope)] (~ bodyA))) [(s;run scope (p;some s;int)) (#e;Success raw-env)]) - (let [inner-arity (if direct? - (n.inc outer-arity) - +1) + (let [function-arity (if direct? + (n.inc arity) + +1) env (list/map (function [closure] (case (dict;get closure resolver) (#;Some resolved) (if (and (variableL;local? resolved) - (functionS;nested? outer-arity) - (|> resolved variableL;local-register (n.>= outer-arity))) - (functionS;adjust-var outer-arity resolved) + (functionS;nested? arity) + (|> resolved variableL;local-register (n.>= arity))) + (functionS;adjust-var arity resolved) resolved) #;None (if (and (variableL;local? closure) - (functionS;nested? outer-arity)) - (functionS;adjust-var outer-arity closure) + (functionS;nested? arity)) + (functionS;adjust-var arity closure) closure))) raw-env) env-vars (: (List Variable) (case raw-env #;Nil (list) _ (|> (list;size raw-env) n.dec (list;n.range +0) (list/map variableL;captured)))) - resolver' (if (and (functionS;nested? inner-arity) + resolver' (if (and (functionS;nested? function-arity) direct?) (list/fold (function [[from to] resolver'] (dict;put from to resolver')) @@ -180,19 +177,20 @@ (dict;put var var resolver')) init-resolver env-vars))] - (case (recur inner-arity resolver' true num-locals bodyA) - (^ [_ (#;Form (list [_ (#;Text "lux function")] [_ (#;Nat arity')] env' bodyS'))]) - (let [arity (n.inc arity')] - (function$ arity env (prepare-body inner-arity arity bodyS'))) + (case (recur function-arity resolver' true function-arity bodyA) + (^ [_ (#;Form (list [_ (#;Text "lux function")] [_ (#;Nat unmerged-arity)] env' bodyS'))]) + (let [merged-arity (n.inc unmerged-arity)] + (function$ merged-arity env + (prepare-body function-arity merged-arity bodyS'))) bodyS - (function$ +1 env (prepare-body inner-arity +1 bodyS)))) + (function$ +1 env (prepare-body function-arity +1 bodyS)))) (^code ("lux apply" (~@ _))) - (synthesize-apply (recur outer-arity resolver false num-locals) outer-arity num-locals expressionA) + (synthesize-apply (recur arity resolver false num-locals) num-locals expressionA) (^code ((~ [_ (#;Text name)]) (~@ args))) - (procedure$ name (list/map (recur outer-arity resolver false num-locals) args)) + (procedure$ name (list/map (recur arity resolver false num-locals) args)) _ expressionA))) diff --git a/new-luxc/source/luxc/lang/synthesis/loop.lux b/new-luxc/source/luxc/lang/synthesis/loop.lux index 86c37a3f0..ac72e69b2 100644 --- a/new-luxc/source/luxc/lang/synthesis/loop.lux +++ b/new-luxc/source/luxc/lang/synthesis/loop.lux @@ -108,7 +108,7 @@ exprS ))) -(def: #export (adjust env outer-offset exprS) +(def: #export (adjust env offset exprS) (-> (List Variable) Register ls;Synthesis ls;Synthesis) (let [resolve-captured (: (-> Variable Variable) (function [var] @@ -116,13 +116,13 @@ (|> env (list;nth idx) maybe;assume))))] (loop [exprS exprS] (case exprS - (^ [_ (#;Form (list [_ (#;Nat tag)] last? valueS))]) + (^code ((~ [_ (#;Nat tag)]) (~ last?) (~ valueS))) (` ((~ (code;nat tag)) (~ last?) (~ (recur valueS)))) - [_ (#;Tuple members)] - [_ (#;Tuple (list/map recur members))] + (^code [(~@ members)]) + (` [(~@ (list/map recur members))]) - (^ [_ (#;Form (list [_ (#;Text "lux case")] inputS pathS))]) + (^code ("lux case" (~ inputS) (~ pathS))) (` ("lux case" (~ (recur inputS)) (~ (let [adjust' recur] (loop [pathS pathS] @@ -133,22 +133,25 @@ (["lux case alt"] ["lux case seq"]) + (^code ("lux case bind" (~ [_ (#;Nat register)]))) + (` ("lux case bind" (~ (code;nat (n.+ offset register))))) + (^ [_ (#;Form (list [_ (#;Text "lux case exec")] bodyS))]) (` ("lux case exec" (~ (adjust' bodyS)))) _ pathS)))))) - (^ [_ (#;Form (list [_ (#;Text "lux function")] arity [_ (#;Tuple environment)] bodyS))]) + (^code ("lux function" (~ arity) [(~@ environment)] (~ bodyS))) (` ("lux function" (~ arity) - (~ [_ (#;Tuple (list/map (function [_var] - (case _var - (^ [_ (#;Form (list [_ (#;Int var)]))]) - (` ((~ (code;int (resolve-captured var))))) - - _ - _var)) - environment))]) + [(~@ (list/map (function [_var] + (case _var + (^ [_ (#;Form (list [_ (#;Int var)]))]) + (` ((~ (code;int (resolve-captured var))))) + + _ + _var)) + environment))] (~ (recur bodyS)))) (^ [_ (#;Form (list& [_ (#;Text "lux call")] funcS argsS))]) @@ -163,10 +166,10 @@ (^ [_ (#;Form (list [_ (#;Int var)]))]) (if (variableL;captured? var) (` ((~ (code;int (resolve-captured var))))) - (` ((~ (code;int (|> outer-offset nat-to-int (i.+ var))))))) + (` ((~ (code;int (|> offset nat-to-int (i.+ var))))))) (^ [_ (#;Form (list [_ (#;Text "lux let")] [_ (#;Nat register)] inputS bodyS))]) - (` ("lux let" (~ (code;nat (n.+ outer-offset register))) + (` ("lux let" (~ (code;nat (n.+ offset register))) (~ (recur inputS)) (~ (recur bodyS)))) @@ -175,8 +178,8 @@ (~ (recur thenS)) (~ (recur elseS)))) - (^ [_ (#;Form (list [_ (#;Text "lux loop")] [_ (#;Nat inner-offset)] [_ (#;Tuple initsS)] bodyS))]) - (` ("lux loop" (~ (code;nat (n.+ outer-offset inner-offset))) + (^ [_ (#;Form (list [_ (#;Text "lux loop")] [_ (#;Nat loop-offset)] [_ (#;Tuple initsS)] bodyS))]) + (` ("lux loop" (~ (code;nat (n.+ offset loop-offset))) [(~@ (list/map recur initsS))] (~ (recur bodyS)))) diff --git a/new-luxc/source/luxc/lang/translation.lux b/new-luxc/source/luxc/lang/translation.lux index 33f74795a..fbecf2da5 100644 --- a/new-luxc/source/luxc/lang/translation.lux +++ b/new-luxc/source/luxc/lang/translation.lux @@ -7,10 +7,10 @@ (data ["e" error] [text "text/" Hash<Text>] text/format - (coll [list] + (coll [list "list/" Functor<List>] [dict])) [macro] - (lang [syntax] + (lang [syntax #+ Aliases] (type ["tc" check])) [host] [io #+ IO Process io] @@ -52,9 +52,12 @@ (wrap [annsI (:! Code annsV)]))) (def: (switch-compiler new-compiler) - (-> Compiler (Meta Unit)) + (-> Compiler (Meta Aliases)) (function [old-compiler] - (#e;Success [new-compiler []]))) + ((do macro;Monad<Meta> + [this macro;current-module] + (wrap (|> this (get@ #;module-aliases) (dict;from-list text;Hash<Text>) (: Aliases)))) + new-compiler))) (def: (ensure-valid-alias def-name annotations value) (-> Text Code Code (Meta Unit)) @@ -66,8 +69,8 @@ _ (&;throw Invalid-Alias def-name))) -(def: (translate translate-module code) - (-> (-> Text Compiler (Process Compiler)) Code (Meta Unit)) +(def: (translate translate-module aliases code) + (-> (-> Text Compiler (Process Compiler)) Aliases Code (Meta Aliases)) (case code (^code ((~ [_ (#;Symbol macro-name)]) (~@ args))) (do macro;Monad<Meta> @@ -76,15 +79,26 @@ (case ?macro (#;Some macro) (do @ - [expansion (function [compiler] - (case (macroL;expand macro args compiler) - (#e;Success [compiler' output]) - (#e;Success [compiler' output]) + [expansion (: (Meta (List Code)) + (function [compiler] + (case (macroL;expand macro args compiler) + (#e;Error error) + ((&;throw Macro-Expansion-Failed error) compiler) - (#e;Error error) - ((&;throw Macro-Expansion-Failed error) compiler))) - _ (monad;map @ (translate translate-module) expansion)] - (wrap [])) + output + output))) + expansion-aliases (monad;map @ (translate translate-module aliases) expansion)] + (if (dict;empty? aliases) + (loop [expansion-aliases expansion-aliases] + (case expansion-aliases + #;Nil + (wrap aliases) + + (#;Cons head tail) + (if (dict;empty? head) + (recur tail) + (wrap head)))) + (wrap aliases))) #;None (&;throw Unrecognized-Statement (%code code)))) @@ -100,7 +114,7 @@ [_ (ensure-valid-alias def-name annsV valueC) _ (&;with-scope (statementT;translate-def def-name Void id annsI annsV))] - (wrap [])) + (wrap aliases)) #;None (do @ @@ -114,10 +128,15 @@ (analyse valueC)))) valueT (&;with-type-env (tc;clean valueT)) + ## #let [_ (if (or (text/= "list/size" def-name)) + ## (log! (format "{" def-name "}\n" + ## " ANALYSIS: " (%code valueA) "\n" + ## "SYNTHESIS: " (%code (expressionS;synthesize valueA)))) + ## [])] valueI (expressionT;translate (expressionS;synthesize valueA)) _ (&;with-scope (statementT;translate-def def-name valueT valueI annsI annsV))] - (wrap [])))))) + (wrap aliases)))))) (^code ("lux module" (~ annsC))) (do macro;Monad<Meta> @@ -135,23 +154,24 @@ [[_ programA] (&;with-scope (&;with-type (type (io;IO Unit)) (analyse programC))) - programI (expressionT;translate (expressionS;synthesize programA))] - (statementT;translate-program program-args programI)) + programI (expressionT;translate (expressionS;synthesize programA)) + _ (statementT;translate-program program-args programI)] + (wrap aliases)) _ (&;throw Unrecognized-Statement (%code code)))) -(def: (exhaust action) - (All [a] (-> (Meta a) (Meta Unit))) +(def: (forgive-eof action) + (-> (Meta Unit) (Meta Unit)) (function [compiler] (case (action compiler) - (#e;Success [compiler' _]) - ((exhaust action) compiler') - (#e;Error error) (if (ex;match? syntax;End-Of-File error) (#e;Success [compiler []]) - (#e;Error error))))) + (#e;Error error)) + + output + output))) (def: prelude Text "lux") @@ -164,10 +184,10 @@ _ (moduleL;flag-compiled! module-name)] (wrap output))) -(def: (read current-module) - (-> Text (Meta Code)) +(def: (read current-module aliases) + (-> Text Aliases (Meta Code)) (function [compiler] - (case (syntax;read current-module (get@ #;source compiler)) + (case (syntax;read current-module aliases (get@ #;source compiler)) (#e;Error error) (#e;Error error) @@ -178,8 +198,7 @@ (def: (translate-module source-dirs target-dir module-name compiler) (-> (List File) File Text Compiler (Process Compiler)) (do io;Monad<Process> - [#let [_ (log! (format "{translate-module} " module-name))] - ## _ (&io;prepare-module target-dir module-name) + [## _ (&io;prepare-module target-dir module-name) [file-name file-content] (&io;read-module source-dirs module-name) #let [module-hash (text/hash file-content) translate-module (translate-module source-dirs target-dir)]] @@ -190,12 +209,15 @@ (with-active-compilation [module-name file-name file-content] - (exhaust - (do @ - [code (read module-name) - #let [[cursor _] code]] - (&;with-cursor cursor - (translate translate-module code)))))))] + (forgive-eof + (loop [aliases (: Aliases + (dict;new text;Hash<Text>))] + (do @ + [code (read module-name aliases) + #let [[cursor _] code] + aliases' (&;with-cursor cursor + (translate translate-module aliases code))] + (forgive-eof (recur aliases'))))))))] (wrap artifacts))) (#e;Success [compiler artifacts]) (do @ diff --git a/new-luxc/source/luxc/lang/translation/imports.jvm.lux b/new-luxc/source/luxc/lang/translation/imports.jvm.lux index c30f61225..be8b828cd 100644 --- a/new-luxc/source/luxc/lang/translation/imports.jvm.lux +++ b/new-luxc/source/luxc/lang/translation/imports.jvm.lux @@ -111,7 +111,6 @@ (do macro;Monad<Meta> [_ (moduleL;set-annotations annotations) current-module macro;current-module-name - #let [_ (log! (format "{translate-imports} " current-module))] imports (let [imports (|> (macro;get-tuple-ann (ident-for #;imports) annotations) (maybe;default (list)))] (case (s;run imports (p;some import)) diff --git a/new-luxc/source/luxc/lang/translation/loop.jvm.lux b/new-luxc/source/luxc/lang/translation/loop.jvm.lux index f5830bf9e..77d43a0e5 100644 --- a/new-luxc/source/luxc/lang/translation/loop.jvm.lux +++ b/new-luxc/source/luxc/lang/translation/loop.jvm.lux @@ -16,7 +16,18 @@ (translation [";T" common] [";T" runtime] [";T" reference]) - [";L" variable #+ Variable]))) + [";L" variable #+ Variable Register]))) + +(def: (constant? register changeS) + (-> Register ls;Synthesis Bool) + (case changeS + (^multi (^code ((~ [_ (#;Int var)]))) + (i.= (variableL;local register) + var)) + true + + _ + false)) (def: #export (translate-recur translate argsS) (-> (-> ls;Synthesis (Meta $;Inst)) @@ -24,23 +35,30 @@ (Meta $;Inst)) (do macro;Monad<Meta> [[@begin offset] hostL;anchor - argsI (monad;map @ (function [[register argS]] - (let [register' (|> register (n.+ offset))] - (: (Meta $;Inst) - (case argS - (^multi (^code ((~ [_ (#;Int var)]))) - (i.= (variableL;local register') - var)) - (wrap id) - - _ - (do @ - [argI (translate argS)] - (wrap (|>. argI - ($i;ASTORE register')))))))) - (list;zip2 (list;n.range +0 (n.dec (list;size argsS))) - argsS))] - (wrap (|>. ($i;fuse argsI) + #let [pairs (list;zip2 (list;n.range offset (|> (list;size argsS) n.dec (n.+ offset))) + argsS)] + ## It may look weird that first I compile the values separately, + ## and then I compile the stores/allocations. + ## It must be done that way in order to avoid a potential bug. + ## Let's say that you'll recur with 2 expressions: X and Y. + ## If Y depends on the value of X, and you don't compile values + ## and stores separately, then by the time Y is evaluated, it + ## will refer to the new value of X, instead of the old value, as + ## must be the case. + valuesI+ (monad;map @ (function [[register argS]] + (: (Meta $;Inst) + (if (constant? register argS) + (wrap id) + (translate argS)))) + pairs) + #let [storesI+ (list/map (function [[register argS]] + (: $;Inst + (if (constant? register argS) + id + ($i;ASTORE register)))) + (list;reverse pairs))]] + (wrap (|>. ($i;fuse valuesI+) + ($i;fuse storesI+) ($i;GOTO @begin))))) (def: #export (translate-loop translate offset initsS+ bodyS) @@ -50,12 +68,12 @@ (do macro;Monad<Meta> [@begin $i;make-label initsI+ (monad;map @ translate initsS+) - bodyI (hostL;with-anchor [@begin (n.inc offset)] + bodyI (hostL;with-anchor [@begin offset] (translate bodyS)) #let [initializationI (|> (list;enumerate initsI+) (list/map (function [[register initI]] (|>. initI - ($i;ASTORE (|> register n.inc (n.+ offset)))))) + ($i;ASTORE (n.+ offset register))))) $i;fuse)]] (wrap (|>. initializationI ($i;label @begin) diff --git a/new-luxc/source/luxc/lang/translation/procedure/common.jvm.lux b/new-luxc/source/luxc/lang/translation/procedure/common.jvm.lux index 0e17f99a6..6c1b18932 100644 --- a/new-luxc/source/luxc/lang/translation/procedure/common.jvm.lux +++ b/new-luxc/source/luxc/lang/translation/procedure/common.jvm.lux @@ -267,65 +267,61 @@ $;Method ($t;method (list $t;long $t;long) (#;Some $t;int) (list))) -(do-template [<name> <const> <wrapper>] +(do-template [<name> <const> <type>] [(def: (<name> _) Nullary - (|>. <const> <wrapper>))] + (|>. <const> ($i;wrap <type>)))] - [nat//min ($i;long 0) ($i;wrap #$;Long)] - [nat//max ($i;long -1) ($i;wrap #$;Long)] + [nat//min ($i;long 0) #$;Long] + [nat//max ($i;long -1) #$;Long] - [int//min ($i;long Long.MIN_VALUE) ($i;wrap #$;Long)] - [int//max ($i;long Long.MAX_VALUE) ($i;wrap #$;Long)] + [int//min ($i;long Long.MIN_VALUE) #$;Long] + [int//max ($i;long Long.MAX_VALUE) #$;Long] - [frac//smallest ($i;double Double.MIN_VALUE) ($i;wrap #$;Double)] - [frac//min ($i;double (f.* -1.0 Double.MAX_VALUE)) ($i;wrap #$;Double)] - [frac//max ($i;double Double.MAX_VALUE) ($i;wrap #$;Double)] - [frac//not-a-number ($i;double Double.NaN) ($i;wrap #$;Double)] - [frac//positive-infinity ($i;double Double.POSITIVE_INFINITY) ($i;wrap #$;Double)] - [frac//negative-infinity ($i;double Double.NEGATIVE_INFINITY) ($i;wrap #$;Double)] - - [deg//min ($i;long 0) ($i;wrap #$;Long)] - [deg//max ($i;long -1) ($i;wrap #$;Long)] + [frac//smallest ($i;double Double.MIN_VALUE) #$;Double] + [frac//min ($i;double (f.* -1.0 Double.MAX_VALUE)) #$;Double] + [frac//max ($i;double Double.MAX_VALUE) #$;Double] + [frac//not-a-number ($i;double Double.NaN) #$;Double] + [frac//positive-infinity ($i;double Double.POSITIVE_INFINITY) #$;Double] + [frac//negative-infinity ($i;double Double.NEGATIVE_INFINITY) #$;Double] + + [deg//min ($i;long 0) #$;Long] + [deg//max ($i;long -1) #$;Long] ) -(do-template [<name> <unwrap> <wrap> <op>] +(do-template [<name> <type> <op>] [(def: (<name> [subjectI paramI]) Binary - (|>. subjectI <unwrap> - paramI <unwrap> + (|>. subjectI ($i;unwrap <type>) + paramI ($i;unwrap <type>) <op> - <wrap>))] + ($i;wrap <type>)))] - [int//add ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LADD] - [int//sub ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LSUB] - [int//mul ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LMUL] - [int//div ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LDIV] - [int//rem ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LREM] + [int//add #$;Long $i;LADD] + [int//sub #$;Long $i;LSUB] + [int//mul #$;Long $i;LMUL] + [int//div #$;Long $i;LDIV] + [int//rem #$;Long $i;LREM] - [nat//add ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LADD] - [nat//sub ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LSUB] - [nat//mul ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LMUL] - [nat//div ($i;unwrap #$;Long) ($i;wrap #$;Long) - ($i;INVOKESTATIC hostL;runtime-class "div_nat" nat-method false)] - [nat//rem ($i;unwrap #$;Long) ($i;wrap #$;Long) - ($i;INVOKESTATIC hostL;runtime-class "rem_nat" nat-method false)] - - [frac//add ($i;unwrap #$;Double) ($i;wrap #$;Double) $i;DADD] - [frac//sub ($i;unwrap #$;Double) ($i;wrap #$;Double) $i;DSUB] - [frac//mul ($i;unwrap #$;Double) ($i;wrap #$;Double) $i;DMUL] - [frac//div ($i;unwrap #$;Double) ($i;wrap #$;Double) $i;DDIV] - [frac//rem ($i;unwrap #$;Double) ($i;wrap #$;Double) $i;DREM] - - [deg//add ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LADD] - [deg//sub ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LSUB] - [deg//mul ($i;unwrap #$;Long) ($i;wrap #$;Long) - ($i;INVOKESTATIC hostL;runtime-class "mul_deg" deg-method false)] - [deg//div ($i;unwrap #$;Long) ($i;wrap #$;Long) - ($i;INVOKESTATIC hostL;runtime-class "div_deg" deg-method false)] - [deg//rem ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LSUB] - [deg//scale ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LMUL] - [deg//reciprocal ($i;unwrap #$;Long) ($i;wrap #$;Long) $i;LDIV] + [nat//add #$;Long $i;LADD] + [nat//sub #$;Long $i;LSUB] + [nat//mul #$;Long $i;LMUL] + [nat//div #$;Long ($i;INVOKESTATIC hostL;runtime-class "div_nat" nat-method false)] + [nat//rem #$;Long ($i;INVOKESTATIC hostL;runtime-class "rem_nat" nat-method false)] + + [frac//add #$;Double $i;DADD] + [frac//sub #$;Double $i;DSUB] + [frac//mul #$;Double $i;DMUL] + [frac//div #$;Double $i;DDIV] + [frac//rem #$;Double $i;DREM] + + [deg//add #$;Long $i;LADD] + [deg//sub #$;Long $i;LSUB] + [deg//mul #$;Long ($i;INVOKESTATIC hostL;runtime-class "mul_deg" deg-method false)] + [deg//div #$;Long ($i;INVOKESTATIC hostL;runtime-class "div_deg" deg-method false)] + [deg//rem #$;Long $i;LSUB] + [deg//scale #$;Long $i;LMUL] + [deg//reciprocal #$;Long $i;LDIV] ) (do-template [<eq> <lt> <unwrap> <cmp>] @@ -382,11 +378,11 @@ ($i;INVOKEVIRTUAL <class> <method> ($t;method (list) (#;Some <outputT>) (list)) false) <post>))] - [text//size "java.lang.String" "length" lux-intI $t;int] - [text//hash "java.lang.Object" "hashCode" lux-intI $t;int] - [text//trim "java.lang.String" "trim" id $String] - [text//upper-case "java.lang.String" "toUpperCase" id $String] - [text//lower-case "java.lang.String" "toLowerCase" id $String] + [text//size "java.lang.String" "length" lux-intI $t;int] + [text//hash "java.lang.Object" "hashCode" lux-intI $t;int] + [text//trim "java.lang.String" "trim" id $String] + [text//upper "java.lang.String" "toUpperCase" id $String] + [text//lower "java.lang.String" "toLowerCase" id $String] ) (do-template [<name> <pre-subject> <pre-param> <op> <post>] @@ -676,18 +672,21 @@ (def: text-procs Bundle - (|> (dict;new text;Hash<Text>) - (install "text =" (binary text//eq)) - (install "text <" (binary text//lt)) - (install "text concat" (binary text//concat)) - (install "text index" (trinary text//index)) - (install "text size" (unary text//size)) - (install "text hash" (unary text//hash)) - (install "text replace-once" (trinary text//replace-once)) - (install "text replace-all" (trinary text//replace-all)) - (install "text char" (binary text//char)) - (install "text clip" (trinary text//clip)) - )) + (<| (prefix "text") + (|> (dict;new text;Hash<Text>) + (install "=" (binary text//eq)) + (install "<" (binary text//lt)) + (install "concat" (binary text//concat)) + (install "index" (trinary text//index)) + (install "size" (unary text//size)) + (install "hash" (unary text//hash)) + (install "replace-once" (trinary text//replace-once)) + (install "replace-all" (trinary text//replace-all)) + (install "char" (binary text//char)) + (install "clip" (trinary text//clip)) + (install "upper" (unary text//upper)) + (install "lower" (unary text//lower)) + ))) (def: array-procs Bundle diff --git a/new-luxc/source/luxc/lang/translation/runtime.jvm.lux b/new-luxc/source/luxc/lang/translation/runtime.jvm.lux index 87174b192..d2bb1645b 100644 --- a/new-luxc/source/luxc/lang/translation/runtime.jvm.lux +++ b/new-luxc/source/luxc/lang/translation/runtime.jvm.lux @@ -198,7 +198,6 @@ div-method ($t;method (list $t;long $t;long) (#;Some $t;long) (list)) upcastI ($i;INVOKESTATIC hostL;runtime-class "_toUnsignedBigInteger" upcast-method false) downcastI ($i;INVOKEVIRTUAL "java.math.BigInteger" "longValue" ($t;method (list) (#;Some $t;long) (list)) false)] - ## http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Long.java#215 (|>. ($d;method #$;Public $;staticM "_toUnsignedBigInteger" upcast-method (let [upcastI ($i;INVOKESTATIC "java.math.BigInteger" "valueOf" upcast-method false) discernI (function [@where] (|>. ($i;LLOAD +0) ($i;long 0) $i;LCMP ($i;IFGE @where))) @@ -220,14 +219,12 @@ ($i;LLOAD +0) upcastI $i;ARETURN)))) - ## http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Long.java?av=f#1267 ($d;method #$;Public $;staticM "compare_nat" compare-nat-method (let [shiftI (|>. ($i;GETSTATIC "java.lang.Long" "MIN_VALUE" $t;long) $i;LADD)] (|>. ($i;LLOAD +0) shiftI ($i;LLOAD +2) shiftI $i;LCMP $i;IRETURN))) - ## http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Long.java#1290 ($d;method #$;Public $;staticM "div_nat" div-method (let [is-param-largeI (function [@where] (|>. ($i;LLOAD +2) ($i;long 0) $i;LCMP ($i;IFLT @where))) is-subject-smallI (function [@where] (|>. ($i;LLOAD +0) ($i;long 0) $i;LCMP ($i;IFGT @where))) @@ -257,7 +254,6 @@ ## Less than ($i;label @is-zero) ($i;long 0) $i;LRETURN)))) - ## http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Long.java#1323 ($d;method #$;Public $;staticM "rem_nat" div-method (let [is-subject-largeI (function [@where] (|>. ($i;LLOAD +0) ($i;long 0) $i;LCMP ($i;IFLE @where))) is-param-largeI (function [@where] (|>. ($i;LLOAD +2) ($i;long 0) $i;LCMP ($i;IFLE @where))) |