Remove erased function arguments
This commit is contained in:
38
TODO.md
38
TODO.md
@@ -1,7 +1,13 @@
|
|||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
|
- [ ] Remove erased args from primitive functions
|
||||||
|
- [x] Remove erased fields from constructor data
|
||||||
|
- [ ] Teach magic nat / magic enum about erased args
|
||||||
|
- [ ] Update LiftLambda.newt for arg removal changes
|
||||||
- [ ] Add error for non-linear names in pattern matching (currently it picks one)
|
- [ ] Add error for non-linear names in pattern matching (currently it picks one)
|
||||||
|
- We probably should handle forced values. Idris requires them to have the same name.
|
||||||
|
- [ ] Functions with erased-only arguments still get called with `()` - do we want this or should they be constants?
|
||||||
- [x] Take the parens off of FC to make vscode happy
|
- [x] Take the parens off of FC to make vscode happy
|
||||||
- [x] Magic to make Bool a boolean
|
- [x] Magic to make Bool a boolean
|
||||||
- [ ] Look into using holes for errors (https://types.pl/@AndrasKovacs/115401455046442009)
|
- [ ] Look into using holes for errors (https://types.pl/@AndrasKovacs/115401455046442009)
|
||||||
@@ -9,14 +15,20 @@
|
|||||||
- I've been wanting to try holes for parse errors too.
|
- I've been wanting to try holes for parse errors too.
|
||||||
- [ ] in-scope type at point in vscode
|
- [ ] in-scope type at point in vscode
|
||||||
- So the idea here is that the references will be via FC, we remember the type at declaration and then point the usage back to the declaration (FC -> FC). We could dump all of this. (If we're still doing json.)
|
- So the idea here is that the references will be via FC, we remember the type at declaration and then point the usage back to the declaration (FC -> FC). We could dump all of this. (If we're still doing json.)
|
||||||
|
- This information _could_ support renaming, too (but there may be indentation issues).
|
||||||
- Do we want to (maybe later) keep the scope as a FC? We could do scope at point then.
|
- Do we want to (maybe later) keep the scope as a FC? We could do scope at point then.
|
||||||
- But ideally we'd switch to a server/repl, so we don't have to mess around with serializing stuff.
|
- But ideally we'd switch to a server/repl, so we don't have to mess around with serializing stuff.
|
||||||
- [ ] LSP and/or more editor support
|
- [ ] LSP and/or more editor support
|
||||||
|
- [ ] refactor to query based? E.g. importing a module
|
||||||
- [ ] would be nice to have "add missing cases" and "case split"
|
- [ ] would be nice to have "add missing cases" and "case split"
|
||||||
- [x] Probably need ranges for FC
|
- [x] Probably need ranges for FC
|
||||||
- [ ] leave an interactive process running
|
- [ ] leave an interactive process running
|
||||||
- [ ] collect metadata or run through the serialization data
|
- [ ] restart mid file (we could save state per top level decl)
|
||||||
- [ ] rename in editor for top level functions (and maybe stuff in scope probably need LSP first)
|
- [ ] rename in editor (need to accumulate all names and what they reference)
|
||||||
|
- [ ] who calls X? We can only do this scoped to the current context for now. Someday whole source dir. #lsp
|
||||||
|
- [ ] Pretty print
|
||||||
|
- Can we format code? Maybe pull nearby comments or attach them like FC to tokens?
|
||||||
|
- We would need to address stack and laziness issues in prettier printer (or make it merely pretty)
|
||||||
- [ ] Look into descriptions, etc.
|
- [ ] Look into descriptions, etc.
|
||||||
- Can generating descriptions help with automatic "show" implementations
|
- Can generating descriptions help with automatic "show" implementations
|
||||||
- We lost debug printing when switching to numeric tags
|
- We lost debug printing when switching to numeric tags
|
||||||
@@ -32,8 +44,7 @@
|
|||||||
- [ ] Raw is duplicated between Lib.Syntax and Lib.Compile, but not detected
|
- [ ] Raw is duplicated between Lib.Syntax and Lib.Compile, but not detected
|
||||||
- [ ] Maybe add qualified names to surface syntax and allow / detect conflicts on reference
|
- [ ] Maybe add qualified names to surface syntax and allow / detect conflicts on reference
|
||||||
- [ ] Add `export` keywords
|
- [ ] Add `export` keywords
|
||||||
- [ ] vscode - run newt when switching editors
|
- [x] vscode - run newt when switching editors
|
||||||
- [ ] who calls X? We can only do this scoped to the current context for now. Someday whole source dir. #lsp
|
|
||||||
- [ ] case split
|
- [ ] case split
|
||||||
- We could fake this up:
|
- We could fake this up:
|
||||||
- given a name and a point in the editor
|
- given a name and a point in the editor
|
||||||
@@ -51,12 +62,15 @@
|
|||||||
- [x] fix string highlighting
|
- [x] fix string highlighting
|
||||||
- [x] implement tail call optimization
|
- [x] implement tail call optimization
|
||||||
- [x] implement magic nat
|
- [x] implement magic nat
|
||||||
|
- [ ] Consider splitting desugar/check
|
||||||
|
- We can only check physical syntax at the moment, which has been inconvenient in a couple of spots where we want to check generated code. E.g. solutions to auto implicits.
|
||||||
- [ ] record update can't elaborate if type is unsolved meta
|
- [ ] record update can't elaborate if type is unsolved meta
|
||||||
- need to postpone elab until meta is known. Create fresh meta for the term to return and have postponed elab fill it in later.
|
- need to postpone elab until meta is known. Create fresh meta for the term to return and have postponed elab fill it in later.
|
||||||
- [ ] drop erased args on types and top level functions
|
- [x] drop erased args on types and top level functions
|
||||||
- [ ] can I do some inlining without blowing up code size?
|
- [x] can I do some inlining without blowing up code size?
|
||||||
- [ ] Maybe tag some functions as inline
|
- [x] Maybe tag some functions as inline
|
||||||
- [ ] Eq Nat is not tail recursive because of the call to `==`
|
- [x] Eq Nat is not tail recursive because of the call to `==`
|
||||||
|
- [ ] Eq Nat does things the hard way, can we turn it into `==`?
|
||||||
- [x] use hint table for auto solving. (I think walking the `toList` is a big chunk of performance in `Elab.newt`.)
|
- [x] use hint table for auto solving. (I think walking the `toList` is a big chunk of performance in `Elab.newt`.)
|
||||||
- [x] implement string enum (or number, but I'm using strings for tags at the moment)
|
- [x] implement string enum (or number, but I'm using strings for tags at the moment)
|
||||||
- [x] use monaco input method instead of lean's
|
- [x] use monaco input method instead of lean's
|
||||||
@@ -102,10 +116,13 @@
|
|||||||
- The mini version would be recurse on `{`, pop on `}` (and expect caller to handle), fail if we get to the top with a tokens remaining.
|
- The mini version would be recurse on `{`, pop on `}` (and expect caller to handle), fail if we get to the top with a tokens remaining.
|
||||||
- [ ] mutual recursion in where?
|
- [ ] mutual recursion in where?
|
||||||
- need to scan sigs and then defs, will have to make sure Compile.idr puts them all in scope before processing each.
|
- need to scan sigs and then defs, will have to make sure Compile.idr puts them all in scope before processing each.
|
||||||
|
- we probably want this, just haven't gotten around to it.
|
||||||
|
- LetRec would have to be extended to have multiple names.
|
||||||
- [x] Move on to next decl in case of error
|
- [x] Move on to next decl in case of error
|
||||||
- [x] for parse error, seek to col 0 token and process next decl
|
- [x] for parse error, seek to col 0 token and process next decl
|
||||||
- [x] record update sugar
|
- [x] record update sugar
|
||||||
- [x] Change `Ord` to be more like Idris - LT / EQ / GT (and entail equality)
|
- [x] Change `Ord` to be more like Idris - LT / EQ / GT (and entail equality)
|
||||||
|
- [ ] Consider making `<` independent of `Ord`, so we get the `<` oper in the javascript.
|
||||||
- [x] Keep a `compare` function on `SortedMap` (like lean)
|
- [x] Keep a `compare` function on `SortedMap` (like lean)
|
||||||
- `emptyMap` helper defaults to `compare` from `Ord a`
|
- `emptyMap` helper defaults to `compare` from `Ord a`
|
||||||
- [x] keymap for monaco
|
- [x] keymap for monaco
|
||||||
@@ -253,16 +270,19 @@
|
|||||||
- [x] check quantity
|
- [x] check quantity
|
||||||
- [x] erase in output
|
- [x] erase in output
|
||||||
- [ ] remove erased top level arguments
|
- [ ] remove erased top level arguments
|
||||||
|
- maybe have something shaped like `List Bool` for `arity`
|
||||||
- [x] top level at point in vscode
|
- [x] top level at point in vscode
|
||||||
- [ ] repl
|
- [ ] repl
|
||||||
- [x] don't match forced constructors at runtime
|
- [x] don't match forced constructors at runtime
|
||||||
- I think we got this by not switching for single cases
|
- I think we got this by not switching for single cases
|
||||||
- [x] magic nat (codegen as number with appropriate pattern matching)
|
- [x] magic nat (codegen as number with appropriate pattern matching)
|
||||||
- [ ] magic tuple? (codegen as array)
|
- [ ] magic tuple? (codegen as array)
|
||||||
|
- Seems like this would be tricky as soon as the user starts peeling off the tail or consing them
|
||||||
- [ ] magic newtype? (drop them in codegen)
|
- [ ] magic newtype? (drop them in codegen)
|
||||||
- [x] vscode: syntax highlighting for String
|
- [x] vscode: syntax highlighting for String
|
||||||
- [ ] add `pop` or variant of `pfunc` that maps to an operator, giving the js operator and precedence on RHS
|
- [ ] add `poper` or variant of `pfunc` that maps to an operator, giving the js operator and precedence on RHS
|
||||||
- This has now been hard-coded in codegen, but a syntax or something would be better.
|
- This has now been hard-coded in codegen, but a syntax or something would be better.
|
||||||
|
- We want to drop implicit / erased args - i.e. pick the right two args for the native operator, see jsEq
|
||||||
- [ ] consider moving caselet, etc. desugaring out of the parser
|
- [ ] consider moving caselet, etc. desugaring out of the parser
|
||||||
- [-] pattern matching lambda
|
- [-] pattern matching lambda
|
||||||
- `\case` is sufficient
|
- `\case` is sufficient
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ import Prelude
|
|||||||
|
|
||||||
pfunc fs : JSObject := `require('fs')`
|
pfunc fs : JSObject := `require('fs')`
|
||||||
pfunc getArgs : List String := `arrayToList(String, process.argv)`
|
pfunc getArgs : List String := `arrayToList(String, process.argv)`
|
||||||
pfunc readFile uses (MkIORes) : (fn : String) -> IO String := `(fn) => (w) => Prelude_MkIORes(null, require('fs').readFileSync(fn, 'utf8'), w)`
|
pfunc readFile uses (MkIORes) : (fn : String) -> IO String := `(fn) => (w) => Prelude_MkIORes(require('fs').readFileSync(fn, 'utf8'), w)`
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ pfunc _%_ : Int → Int → Int := `(x,y) => x % y`
|
|||||||
-- should have a few more foreign functions and do this in newt
|
-- should have a few more foreign functions and do this in newt
|
||||||
pfunc divide uses (_,_) : String → String × String := `(s) => {
|
pfunc divide uses (_,_) : String → String × String := `(s) => {
|
||||||
let l = s.length/2|0
|
let l = s.length/2|0
|
||||||
return Prelude__$2C_(undefined, undefined, s.slice(0,l), s.slice(l))
|
return Prelude__$2C_(s.slice(0,l), s.slice(l))
|
||||||
}`
|
}`
|
||||||
|
|
||||||
step : List (Int × Int) → List (Int × Int)
|
step : List (Int × Int) → List (Int × Int)
|
||||||
|
|||||||
1176
bootstrap/newt.js
1176
bootstrap/newt.js
File diff suppressed because one or more lines are too long
@@ -5,11 +5,11 @@ import Prelude
|
|||||||
-- We should test this at some point
|
-- We should test this at some point
|
||||||
|
|
||||||
ptype IORef : U → U
|
ptype IORef : U → U
|
||||||
pfunc primNewIORef uses (MkIORes) : ∀ a. a → IO (IORef a) := `(_, a) => (w) => Prelude_MkIORes(null, [a], w)`
|
pfunc primNewIORef uses (MkIORes) : ∀ a. a → IO (IORef a) := `(_, a) => (w) => Prelude_MkIORes([a], w)`
|
||||||
pfunc primReadIORef uses (MkIORes) : ∀ a. IORef a → IO a := `(_, ref) => (w) => Prelude_MkIORes(null, ref[0], w)`
|
pfunc primReadIORef uses (MkIORes) : ∀ a. IORef a → IO a := `(_, ref) => (w) => Prelude_MkIORes(ref[0], w)`
|
||||||
pfunc primWriteIORef uses (MkIORes MkUnit) : ∀ a. IORef a → a → IO Unit := `(_, ref, a) => (w) => {
|
pfunc primWriteIORef uses (MkIORes MkUnit) : ∀ a. IORef a → a → IO Unit := `(_, ref, a) => (w) => {
|
||||||
ref[0] = a
|
ref[0] = a
|
||||||
return Prelude_MkIORes(null,Prelude_MkUnit,w)
|
return Prelude_MkIORes(Prelude_MkUnit,w)
|
||||||
}`
|
}`
|
||||||
|
|
||||||
newIORef : ∀ io a. {{HasIO io}} → a → io (IORef a)
|
newIORef : ∀ io a. {{HasIO io}} → a → io (IORef a)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import Lib.Prettier
|
|||||||
import Lib.CompileExp
|
import Lib.CompileExp
|
||||||
import Lib.TopContext
|
import Lib.TopContext
|
||||||
import Lib.LiftWhere
|
import Lib.LiftWhere
|
||||||
import Lib.LiftLambda
|
-- import Lib.LiftLambda -- NOW needs update for arg erasure
|
||||||
import Lib.TCO
|
import Lib.TCO
|
||||||
import Lib.Ref2
|
import Lib.Ref2
|
||||||
import Lib.Erasure
|
import Lib.Erasure
|
||||||
@@ -109,14 +109,17 @@ freshName' nm env =
|
|||||||
env' = push env (Var nm')
|
env' = push env (Var nm')
|
||||||
in (nm', env')
|
in (nm', env')
|
||||||
|
|
||||||
freshNames : List String -> JSEnv -> (List String × JSEnv)
|
freshNames : List (Quant × String) -> JSEnv -> (List String × JSEnv)
|
||||||
freshNames nms env = go nms env Lin
|
freshNames nms env = go nms env Lin
|
||||||
where
|
where
|
||||||
go : List Name -> JSEnv -> SnocList Name -> (List String × JSEnv)
|
go : List (Quant × String) -> JSEnv -> SnocList Name -> (List String × JSEnv)
|
||||||
go Nil env acc = (acc <>> Nil, env)
|
go Nil env acc = (acc <>> Nil, env)
|
||||||
go (n :: ns) env acc =
|
go ((Many, n) :: ns) env acc =
|
||||||
let (n', env') = freshName' n env
|
let (n', env') = freshName' n env
|
||||||
in go ns env' (acc :< n')
|
in go ns env' (acc :< n')
|
||||||
|
go ((Zero, n) :: ns) env acc =
|
||||||
|
let env' = push env JUndefined
|
||||||
|
in go ns env' acc
|
||||||
|
|
||||||
-- These expressions are added to the environment rather than assigned to a name
|
-- These expressions are added to the environment rather than assigned to a name
|
||||||
simpleJSExp : JSExp → Bool
|
simpleJSExp : JSExp → Bool
|
||||||
@@ -175,23 +178,39 @@ termToJS env (CLetRec nm t u) f =
|
|||||||
in case termToJS env' t (JAssign nm') of
|
in case termToJS env' t (JAssign nm') of
|
||||||
(JAssign _ exp) => JSnoc (JConst nm' exp) (termToJS env' u f)
|
(JAssign _ exp) => JSnoc (JConst nm' exp) (termToJS env' u f)
|
||||||
t' => JSnoc (JLet nm' t') (termToJS env' u f)
|
t' => JSnoc (JLet nm' t') (termToJS env' u f)
|
||||||
termToJS env (CConstr ix _ args) f = go args 0 (\ args => f $ LitObject (("tag", LitInt (cast ix)) :: args))
|
termToJS env (CConstr ix _ args qs) f = go args qs 0 (\ args => f $ LitObject (("tag", LitInt (cast ix)) :: args))
|
||||||
where
|
where
|
||||||
go : ∀ e. List CExp -> Int -> (List (String × JSExp) -> JSStmt e) -> JSStmt e
|
go : ∀ e. List CExp -> List Quant -> Int -> (List (String × JSExp) -> JSStmt e) -> JSStmt e
|
||||||
go Nil ix k = k Nil
|
go (t :: ts) (Many :: qs) ix k = termToJS env t $ \ t' => go ts qs (ix + 1) $ \ args => k $ ("h\{show ix}", t') :: args
|
||||||
go (t :: ts) ix k = termToJS env t $ \ t' => go ts (ix + 1) $ \ args => k $ ("h\{show ix}", t') :: args
|
go (t :: ts) (q :: qs) ix k = go ts qs (ix + 1) $ \ args => k args
|
||||||
termToJS env (CAppRef nm args etas) f = termToJS env (CRef nm) (\ t' => (argsToJS env t' args Lin f))
|
go _ _ ix k = k Nil
|
||||||
|
termToJS env (CAppRef nm args quants) f = termToJS env (CRef nm) (\ t' => (argsToJS env t' args quants Lin f))
|
||||||
where
|
where
|
||||||
etaExpand : JSEnv -> Nat -> SnocList JSExp -> JSExp -> JSExp
|
etaExpand : JSEnv -> List Quant -> SnocList JSExp -> JSExp -> JSExp
|
||||||
etaExpand env Z args tm = Apply tm (args <>> Nil)
|
etaExpand env Nil args tm = Apply tm (args <>> Nil)
|
||||||
etaExpand env (S etas) args tm =
|
etaExpand env (q :: qs) args tm =
|
||||||
let nm' = freshName "eta" env
|
let nm' = freshName "eta" env
|
||||||
env' = push env (Var nm')
|
env' = push env (Var nm')
|
||||||
in JLam (nm' :: Nil) $ JReturn $ etaExpand (push env (Var nm')) etas (args :< Var nm') tm
|
in case q of
|
||||||
|
Many => JLam (nm' :: Nil) $ JReturn $ etaExpand (push env (Var nm')) qs (args :< Var nm') tm
|
||||||
|
_ => JLam (nm' :: Nil) $ JReturn $ etaExpand (push env (Var nm')) qs args tm
|
||||||
|
|
||||||
argsToJS : ∀ e. JSEnv -> JSExp -> List CExp -> SnocList JSExp -> (JSExp -> JSStmt e) -> JSStmt e
|
apply : ∀ e. JSEnv → JSExp → (List CExp) → (JSExp → JSStmt e) → JSStmt e
|
||||||
argsToJS env tm Nil acc k = k (etaExpand env (cast etas) acc tm)
|
apply env tm Nil k = k tm
|
||||||
argsToJS env tm (x :: xs) acc k = termToJS env x (\ x' => argsToJS (incr env) tm xs (acc :< x') k)
|
apply env tm (x :: xs) k = termToJS env x $ \ x' => apply env (Apply tm (x' :: Nil)) xs k
|
||||||
|
|
||||||
|
argsToJS : ∀ e. JSEnv -> JSExp -> List CExp -> List Quant -> SnocList JSExp -> (JSExp -> JSStmt e) -> JSStmt e
|
||||||
|
argsToJS env tm Nil qs acc k = k (etaExpand env qs acc tm)
|
||||||
|
argsToJS env tm (x :: xs) (Many :: qs) acc k = termToJS env x (\ x' => argsToJS (incr env) tm xs qs (acc :< x') k)
|
||||||
|
argsToJS env tm (x :: xs) (q :: qs) acc k = argsToJS (incr env) tm xs qs acc k
|
||||||
|
-- REVIEW For now, functions whose arguments are all erased still get (), but no-arg functions don't
|
||||||
|
argsToJS env tm (x :: xs) Nil acc k = case quants of
|
||||||
|
Nil => apply env tm (x :: xs) k
|
||||||
|
_ => apply env (Apply tm (acc <>> Nil)) (x :: xs) k
|
||||||
|
argsToJS env tm (x :: xs) Nil Lin k = apply env tm (x :: xs) k
|
||||||
|
argsToJS env tm (x :: xs) Nil acc k = apply env (Apply tm (acc <>> Nil)) (x :: xs) k
|
||||||
|
-- backwards too...
|
||||||
|
-- termToJS env x $ \ x' => argsToJS env tm xs Nil acc $ \ tm' => k $ Apply tm' (x' :: Nil)
|
||||||
|
|
||||||
termToJS env (CApp t arg) f = termToJS env t (\ t' => termToJS env arg (\arg' => f (Apply t' (arg' :: Nil))))
|
termToJS env (CApp t arg) f = termToJS env t (\ t' => termToJS env arg (\arg' => f (Apply t' (arg' :: Nil))))
|
||||||
|
|
||||||
@@ -411,13 +430,14 @@ sortedNames defs qn = map snd $ filter (not ∘ fst) $ go Nil Nil (True, qn)
|
|||||||
getNames deep acc (CLam _ t) = getNames deep acc t
|
getNames deep acc (CLam _ t) = getNames deep acc t
|
||||||
-- top level 0-ary function, doesn't happen
|
-- top level 0-ary function, doesn't happen
|
||||||
getNames deep acc (CFun _ t) = if deep then getNames deep acc t else acc
|
getNames deep acc (CFun _ t) = if deep then getNames deep acc t else acc
|
||||||
-- 0-ary call is not deep invocation
|
|
||||||
getNames deep acc (CAppRef nm Nil 0) = (True, nm) :: acc
|
getNames deep acc (CAppRef nm args qs) =
|
||||||
-- full call is deep ref to the head, arguments may be applied by `nm`
|
if length' args == length' qs
|
||||||
getNames deep acc (CAppRef nm ts 0) = foldl (getNames True) ((True, nm) :: acc) ts
|
then case args of
|
||||||
-- non-zero are closures
|
Nil => (True, nm) :: acc
|
||||||
getNames deep acc (CAppRef nm ts _) = foldl (getNames deep) ((deep, nm) :: acc) ts
|
ts => foldl (getNames True) ((True, nm) :: acc) ts
|
||||||
-- True is needed for an issue in the parser. symbol -> keyword -> indented
|
else
|
||||||
|
foldl (getNames deep) ((deep, nm) :: acc) args
|
||||||
-- TODO look at which cases generate CApp
|
-- TODO look at which cases generate CApp
|
||||||
getNames deep acc (CApp t u) = getNames True (getNames deep acc u) t
|
getNames deep acc (CApp t u) = getNames True (getNames deep acc u) t
|
||||||
getNames deep acc (CCase t alts) = foldl (getNames deep) acc $ t :: map getBody alts
|
getNames deep acc (CCase t alts) = foldl (getNames deep) acc $ t :: map getBody alts
|
||||||
@@ -425,7 +445,7 @@ sortedNames defs qn = map snd $ filter (not ∘ fst) $ go Nil Nil (True, qn)
|
|||||||
getNames deep acc (CRef qn) = (deep, qn) :: acc
|
getNames deep acc (CRef qn) = (deep, qn) :: acc
|
||||||
getNames deep acc (CLet _ t u) = getNames deep (getNames deep acc t) u
|
getNames deep acc (CLet _ t u) = getNames deep (getNames deep acc t) u
|
||||||
getNames deep acc (CLetRec _ t u) = getNames deep (getNames deep acc t) u
|
getNames deep acc (CLetRec _ t u) = getNames deep (getNames deep acc t) u
|
||||||
getNames deep acc (CConstr _ _ ts) = foldl (getNames deep) acc ts
|
getNames deep acc (CConstr _ _ ts _) = foldl (getNames deep) acc ts
|
||||||
-- if the CRaw is called, then the deps are called
|
-- if the CRaw is called, then the deps are called
|
||||||
getNames deep acc (CRaw _ deps) = map (_,_ deep) deps ++ acc
|
getNames deep acc (CRaw _ deps) = map (_,_ deep) deps ++ acc
|
||||||
-- wrote these out so I get an error when I add a new constructor
|
-- wrote these out so I get an error when I add a new constructor
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ data CExp : U where
|
|||||||
CBnd : Int -> CExp
|
CBnd : Int -> CExp
|
||||||
-- How is CLam different from CFun with one arg?
|
-- How is CLam different from CFun with one arg?
|
||||||
CLam : Name -> CExp -> CExp
|
CLam : Name -> CExp -> CExp
|
||||||
CFun : List Name -> CExp -> CExp
|
CFun : List (Quant × Name) -> CExp -> CExp
|
||||||
CAppRef : QName -> List CExp -> Int -> CExp
|
CAppRef : QName -> List CExp -> List Quant -> CExp
|
||||||
CApp : CExp -> CExp -> CExp
|
CApp : CExp -> CExp -> CExp
|
||||||
CCase : CExp -> List CAlt -> CExp
|
CCase : CExp -> List CAlt -> CExp
|
||||||
CRef : QName -> CExp
|
CRef : QName -> CExp
|
||||||
@@ -38,7 +38,7 @@ data CExp : U where
|
|||||||
CLetRec : Name -> CExp -> CExp -> CExp
|
CLetRec : Name -> CExp -> CExp -> CExp
|
||||||
CErased : CExp
|
CErased : CExp
|
||||||
-- Data / type constructor
|
-- Data / type constructor
|
||||||
CConstr : Nat → Name -> List CExp -> CExp
|
CConstr : Nat → Name → List CExp → List Quant → CExp
|
||||||
-- Raw javascript for `pfunc`
|
-- Raw javascript for `pfunc`
|
||||||
CRaw : String -> List QName -> CExp
|
CRaw : String -> List QName -> CExp
|
||||||
-- Need this for magic Nat
|
-- Need this for magic Nat
|
||||||
@@ -48,9 +48,9 @@ data CExp : U where
|
|||||||
-- I'm counting Lam in the term for arity. This matches what I need in
|
-- I'm counting Lam in the term for arity. This matches what I need in
|
||||||
-- code gen.
|
-- code gen.
|
||||||
|
|
||||||
lamArity : Tm -> Nat
|
lamArity : Tm -> List Quant
|
||||||
lamArity (Lam _ _ _ _ t) = S (lamArity t)
|
lamArity (Lam _ _ _ quant t) = quant :: (lamArity t)
|
||||||
lamArity _ = Z
|
lamArity _ = Nil
|
||||||
|
|
||||||
-- It would be nice to be able to declare these
|
-- It would be nice to be able to declare these
|
||||||
compilePrimOp : String → List CExp → Maybe CExp
|
compilePrimOp : String → List CExp → Maybe CExp
|
||||||
@@ -62,46 +62,45 @@ compilePrimOp "Prelude._&&_" (x :: y :: Nil) = Just (CPrimOp "&&" x y)
|
|||||||
compilePrimOp "Prelude._||_" (x :: y :: Nil) = Just (CPrimOp "||" x y)
|
compilePrimOp "Prelude._||_" (x :: y :: Nil) = Just (CPrimOp "||" x y)
|
||||||
-- Assumes Bool is in the right order!
|
-- Assumes Bool is in the right order!
|
||||||
compilePrimOp "Prelude.jsEq" (_ :: x :: y :: Nil) = Just (CPrimOp "==" x y)
|
compilePrimOp "Prelude.jsEq" (_ :: x :: y :: Nil) = Just (CPrimOp "==" x y)
|
||||||
compilePrimOp "Prelude.jsLt" (_ :: x :: y :: Nil) = Just (CPrimOp "<" x y)
|
|
||||||
compilePrimOp "Prelude.divInt" (x :: y :: Nil) = Just (CPrimOp "|" (CPrimOp "/" x y) (CLit $ LInt 0))
|
compilePrimOp "Prelude.divInt" (x :: y :: Nil) = Just (CPrimOp "|" (CPrimOp "/" x y) (CLit $ LInt 0))
|
||||||
compilePrimOp _ _ = Nothing
|
compilePrimOp _ _ = Nothing
|
||||||
|
|
||||||
-- This is how much we want to curry at top level
|
-- This is how much we want to curry at top level
|
||||||
-- leading lambda Arity is used for function defs and metas
|
-- leading lambda Arity is used for function defs and metas
|
||||||
-- TODO - figure out how this will work with erasure
|
-- TODO - figure out how this will work with erasure
|
||||||
arityForName : {{Ref2 Defs St}} → FC -> QName -> M Nat
|
arityForName : {{Ref2 Defs St}} → FC -> QName -> M (List Quant)
|
||||||
arityForName fc nm = do
|
arityForName fc nm = do
|
||||||
defs <- getRef Defs
|
defs <- getRef Defs
|
||||||
case lookupMap' nm defs of
|
case lookupMap' nm defs of
|
||||||
Nothing => error fc "Name \{show nm} not in scope"
|
Nothing => error fc "Name \{show nm} not in scope"
|
||||||
(Just Axiom) => pure Z
|
(Just Axiom) => pure Nil
|
||||||
(Just (TCon arity strs)) => pure $ cast arity
|
(Just (PrimOp _)) => pure $ Many :: Many :: Nil
|
||||||
(Just (DCon _ _ k str)) => pure $ cast k
|
(Just (TCon arity strs)) => pure $ replicate' (cast arity) Many
|
||||||
|
(Just (DCon _ _ arity str)) => pure arity
|
||||||
(Just (Fn t)) => pure $ lamArity t
|
(Just (Fn t)) => pure $ lamArity t
|
||||||
(Just (PrimTCon arity)) => pure $ cast arity
|
(Just (PrimTCon arity)) => pure $ replicate' (cast arity) Many
|
||||||
(Just (PrimFn t arity used)) => pure arity
|
(Just (PrimFn t arity used)) => pure $ replicate' arity Many
|
||||||
|
where
|
||||||
|
|
||||||
|
|
||||||
any : ∀ a. (a → Bool) → List a → Bool
|
any : ∀ a. (a → Bool) → List a → Bool
|
||||||
any f Nil = False
|
any f Nil = False
|
||||||
any f (x :: xs) = if f x then True else any f xs
|
any f (x :: xs) = if f x then True else any f xs
|
||||||
|
|
||||||
|
-- NOW so we stuff quant and the args in here and sort it out later?
|
||||||
|
|
||||||
-- apply an expression at an arity to a list of args
|
-- apply an expression at an arity to a list of args
|
||||||
-- CAppRef will specify any missing args, for eta conversion later
|
-- CAppRef will specify any missing args, for eta conversion later
|
||||||
-- and any extra args get individual CApp.
|
-- and any extra args get individual CApp.
|
||||||
apply : QName -> List CExp -> SnocList CExp -> Nat -> M CExp
|
apply : QName -> List CExp -> List Quant -> M CExp
|
||||||
-- out of args, make one up (fix that last arg)
|
-- out of args, make one up (fix that last arg)
|
||||||
apply t Nil acc (S k) =
|
apply qn args quants = pure $ CAppRef qn args quants
|
||||||
pure $ CAppRef t (acc <>> Nil) (1 + cast k)
|
-- go (CAppRef qn args quants) args quants
|
||||||
apply t (x :: xs) acc (S k) = apply t xs (acc :< x) k
|
|
||||||
-- once we hit zero, we fold the rest
|
|
||||||
apply t ts acc Z = case acc of
|
|
||||||
-- drop zero arg call
|
|
||||||
Lin => go (CRef t) ts
|
|
||||||
_ => go (CAppRef t (acc <>> Nil) 0) ts
|
|
||||||
where
|
where
|
||||||
go : CExp -> List CExp -> M CExp
|
go : CExp -> List CExp -> List Quant → M CExp
|
||||||
go t Nil = pure t
|
go t (arg :: args) (q :: qs) = go t args qs
|
||||||
go t (arg :: args) = go (CApp t arg) args
|
go t Nil _ = pure t
|
||||||
|
go t (arg :: args) Nil = go (CApp t arg) args Nil
|
||||||
|
|
||||||
lookupDef : {{Ref2 Defs St}} → FC → QName → M Def
|
lookupDef : {{Ref2 Defs St}} → FC → QName → M Def
|
||||||
lookupDef fc nm = do
|
lookupDef fc nm = do
|
||||||
@@ -123,8 +122,7 @@ compileTerm t@(Ref fc nm@(QN _ tag)) = do
|
|||||||
defs <- getRef Defs
|
defs <- getRef Defs
|
||||||
case arity of
|
case arity of
|
||||||
-- we don't need to curry functions that take one argument
|
-- we don't need to curry functions that take one argument
|
||||||
(S Z) => pure $ CRef nm
|
Nil =>
|
||||||
Z =>
|
|
||||||
case the (Maybe Def) $ lookupMap' nm defs of
|
case the (Maybe Def) $ lookupMap' nm defs of
|
||||||
Just (DCon ix EnumCon _ _) => pure $ CLit $ LInt $ cast ix
|
Just (DCon ix EnumCon _ _) => pure $ CLit $ LInt $ cast ix
|
||||||
Just (DCon ix FalseCon _ _) => pure $ CLit $ LBool False
|
Just (DCon ix FalseCon _ _) => pure $ CLit $ LBool False
|
||||||
@@ -133,7 +131,7 @@ compileTerm t@(Ref fc nm@(QN _ tag)) = do
|
|||||||
Just (DCon _ SuccCon _ _) =>
|
Just (DCon _ SuccCon _ _) =>
|
||||||
pure $ CLam "x" $ CPrimOp "+" (CLit $ LInt 1) (CBnd 0)
|
pure $ CLam "x" $ CPrimOp "+" (CLit $ LInt 1) (CBnd 0)
|
||||||
_ => pure $ CRef nm
|
_ => pure $ CRef nm
|
||||||
_ => apply nm Nil Lin arity
|
_ => apply nm Nil arity
|
||||||
|
|
||||||
compileTerm (Meta fc k) = error fc "Compiling meta \{show k}"
|
compileTerm (Meta fc k) = error fc "Compiling meta \{show k}"
|
||||||
compileTerm (Lam _ nm _ _ t) = CLam nm <$> compileTerm t
|
compileTerm (Lam _ nm _ _ t) = CLam nm <$> compileTerm t
|
||||||
@@ -150,7 +148,7 @@ compileTerm tm@(App _ _ _) = case funArgs tm of
|
|||||||
| Just cexp => pure cexp
|
| Just cexp => pure cexp
|
||||||
case the (Maybe Def) $ lookupMap' nm defs of
|
case the (Maybe Def) $ lookupMap' nm defs of
|
||||||
Just (DCon _ SuccCon _ _) => applySucc args'
|
Just (DCon _ SuccCon _ _) => applySucc args'
|
||||||
_ => apply nm args' Lin arity
|
_ => apply nm args' arity
|
||||||
-- REVIEW maybe we want a different constructor for non-Ref applications?
|
-- REVIEW maybe we want a different constructor for non-Ref applications?
|
||||||
(t, args) => do
|
(t, args) => do
|
||||||
debug $ \ _ => "apply other \{render 90 $ pprint Nil t}"
|
debug $ \ _ => "apply other \{render 90 $ pprint Nil t}"
|
||||||
@@ -166,7 +164,7 @@ compileTerm (UU _) = pure $ CRef (QN Nil "U")
|
|||||||
compileTerm (Pi _ nm icit rig t u) = do
|
compileTerm (Pi _ nm icit rig t u) = do
|
||||||
t' <- compileTerm t
|
t' <- compileTerm t
|
||||||
u' <- compileTerm u
|
u' <- compileTerm u
|
||||||
pure $ CAppRef (QN primNS "PiType") (t' :: CLam nm u' :: Nil) 0
|
pure $ CAppRef (QN primNS "PiType") (t' :: CLam nm u' :: Nil) (Many :: Many :: Nil)
|
||||||
compileTerm (Case fc t alts) = do
|
compileTerm (Case fc t alts) = do
|
||||||
t' <- compileTerm t
|
t' <- compileTerm t
|
||||||
alts' <- for alts $ \case
|
alts' <- for alts $ \case
|
||||||
@@ -240,27 +238,44 @@ compileTerm (Erased _) = pure CErased
|
|||||||
compileFun : {{Ref2 Defs St}} → Tm -> M CExp
|
compileFun : {{Ref2 Defs St}} → Tm -> M CExp
|
||||||
compileFun tm = go tm Lin
|
compileFun tm = go tm Lin
|
||||||
where
|
where
|
||||||
go : Tm -> SnocList String -> M CExp
|
go : Tm -> SnocList (Quant × String) -> M CExp
|
||||||
go (Lam _ nm _ _ t) acc = go t (acc :< nm)
|
go (Lam _ nm _ quant t) acc = go t (acc :< (quant, nm))
|
||||||
go tm Lin = compileTerm tm
|
go tm Lin = compileTerm tm
|
||||||
go tm args = CFun (args <>> Nil) <$> compileTerm tm
|
go tm args = CFun (args <>> Nil) <$> compileTerm tm
|
||||||
|
|
||||||
|
compilePop : QName → M CExp
|
||||||
|
compilePop qn = do
|
||||||
|
top <- getTop
|
||||||
|
let (Just def) = lookup qn top | _ => error emptyFC "\{show qn} not found"
|
||||||
|
pure $ CErased -- FIXME - not implemented
|
||||||
|
|
||||||
-- What are the Defs used for above? (Arity for name)
|
-- What are the Defs used for above? (Arity for name)
|
||||||
compileDCon : Nat → QName → ConInfo → Int → CExp
|
compileDCon : Nat → QName → ConInfo → List Quant → CExp
|
||||||
compileDCon ix (QN _ nm) EnumCon 0 = CLit $ LInt $ cast ix
|
compileDCon ix (QN _ nm) EnumCon Nil = CLit $ LInt $ cast ix
|
||||||
compileDCon ix (QN _ nm) TrueCon 0 = CLit $ LBool True
|
compileDCon ix (QN _ nm) TrueCon Nil = CLit $ LBool True
|
||||||
compileDCon ix (QN _ nm) FalseCon 0 = CLit $ LBool False
|
compileDCon ix (QN _ nm) FalseCon Nil = CLit $ LBool False
|
||||||
compileDCon ix (QN _ nm) info 0 = CConstr ix nm Nil
|
compileDCon ix (QN _ nm) info Nil = CConstr ix nm Nil Nil
|
||||||
compileDCon ix (QN _ nm) info arity =
|
compileDCon ix (QN _ nm) info arity =
|
||||||
let args = map (\k => "h\{show k}") (range 0 arity) in
|
-- so we're fully applying this here, but dropping the args later?
|
||||||
CFun args $ CConstr ix nm $ map (\k => CBnd $ arity - k - 1) (range 0 arity)
|
-- The weird thing is that lambdas need the
|
||||||
|
let args = mkArgs Z arity
|
||||||
|
alen = length' arity
|
||||||
|
in CFun args $ CConstr ix nm (map (\k => CBnd $ alen - k - 1) (range 0 alen)) arity
|
||||||
|
where
|
||||||
|
mkArgs : Nat → List Quant → List (Quant × String)
|
||||||
|
mkArgs k (quant :: args) = (quant, "h\{show k}") :: mkArgs (S k) args
|
||||||
|
mkArgs k Nil = Nil
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- probably want to drop the Ref2 when we can
|
-- probably want to drop the Ref2 when we can
|
||||||
defToCExp : {{Ref2 Defs St}} → (QName × Def) -> M (QName × CExp)
|
defToCExp : {{Ref2 Defs St}} → (QName × Def) -> M (QName × CExp)
|
||||||
defToCExp (qn, Axiom) = pure $ (qn, CErased)
|
defToCExp (qn, Axiom) = pure $ (qn, CErased)
|
||||||
|
defToCExp (qn, (PrimOp _)) = (_,_ qn) <$> compilePop qn
|
||||||
defToCExp (qn, DCon ix info arity _) = pure $ (qn, compileDCon ix qn info arity)
|
defToCExp (qn, DCon ix info arity _) = pure $ (qn, compileDCon ix qn info arity)
|
||||||
-- FIXME need a number if we ever add typecase.
|
-- We're not using these are runtime at the moment, no typecase
|
||||||
defToCExp (qn, TCon arity _) = pure $ (qn, compileDCon Z qn NormalCon arity)
|
-- we need to sort out tag number if we do that
|
||||||
defToCExp (qn, PrimTCon arity) = pure $ (qn, compileDCon Z qn NormalCon arity)
|
defToCExp (qn, TCon arity conNames) = pure $ (qn, compileDCon Z qn NormalCon (replicate' (cast arity) Many))
|
||||||
|
defToCExp (qn, PrimTCon arity) = pure $ (qn, compileDCon Z qn NormalCon (replicate' (cast arity) Many))
|
||||||
defToCExp (qn, PrimFn src _ deps) = pure $ (qn, CRaw src deps)
|
defToCExp (qn, PrimFn src _ deps) = pure $ (qn, CRaw src deps)
|
||||||
defToCExp (qn, Fn tm) = (_,_ qn) <$> compileFun tm
|
defToCExp (qn, Fn tm) = (_,_ qn) <$> compileFun tm
|
||||||
|
|||||||
@@ -165,10 +165,10 @@ contextMatches ctx ty = go (zip ctx.env ctx.types)
|
|||||||
modifyTop [ metaCtx := mc]
|
modifyTop [ metaCtx := mc]
|
||||||
go xs)
|
go xs)
|
||||||
|
|
||||||
getArity : Tm -> Int
|
getArity : Tm -> List Quant
|
||||||
getArity (Pi x str icit rig t u) = 1 + getArity u
|
getArity (Pi x str icit rig t u) = rig :: getArity u
|
||||||
-- Ref or App (of type constructor) are valid
|
-- Ref or App (of type constructor) are valid
|
||||||
getArity _ = 0
|
getArity _ = Nil
|
||||||
|
|
||||||
-- Makes the arg for `solve` when we solve an auto
|
-- Makes the arg for `solve` when we solve an auto
|
||||||
makeSpine : Int -> List BD -> SnocList Val
|
makeSpine : Int -> List BD -> SnocList Val
|
||||||
@@ -727,7 +727,7 @@ getConstructors ctx scfc (VRef fc nm _) = do
|
|||||||
lookupDCon nm = do
|
lookupDCon nm = do
|
||||||
top <- getTop
|
top <- getTop
|
||||||
case lookup nm top of
|
case lookup nm top of
|
||||||
(Just (MkEntry _ name type (DCon _ _ k str) _)) => pure (name, k, type)
|
(Just (MkEntry _ name type (DCon _ _ k str) _)) => pure (name, length' k, type)
|
||||||
Just _ => error fc "Internal Error: \{show nm} is not a DCon"
|
Just _ => error fc "Internal Error: \{show nm} is not a DCon"
|
||||||
Nothing => error fc "Internal Error: DCon \{show nm} not found"
|
Nothing => error fc "Internal Error: DCon \{show nm} not found"
|
||||||
getConstructors ctx scfc tm = do
|
getConstructors ctx scfc tm = do
|
||||||
|
|||||||
@@ -418,16 +418,16 @@ populateConInfo entries =
|
|||||||
setInfo x _ = x
|
setInfo x _ = x
|
||||||
|
|
||||||
checkEnum : TopEntry → Maybe TopEntry
|
checkEnum : TopEntry → Maybe TopEntry
|
||||||
checkEnum (MkEntry fc nm dty (DCon ix _ 0 hn) flags) = Just $ MkEntry fc nm dty (DCon ix EnumCon 0 hn) flags
|
checkEnum (MkEntry fc nm dty (DCon ix _ Nil hn) flags) = Just $ MkEntry fc nm dty (DCon ix EnumCon Nil hn) flags
|
||||||
checkEnum _ = Nothing
|
checkEnum _ = Nothing
|
||||||
|
|
||||||
isZero : TopEntry → Bool
|
isZero : TopEntry → Bool
|
||||||
isZero (MkEntry fc nm dty (DCon _ _ 0 hn) flags) = True
|
isZero (MkEntry fc nm dty (DCon _ _ Nil hn) flags) = True
|
||||||
isZero _ = False
|
isZero _ = False
|
||||||
|
|
||||||
-- TODO - handle indexes, etc
|
-- TODO - handle indexes, etc
|
||||||
isSucc : TopEntry → Bool
|
isSucc : TopEntry → Bool
|
||||||
isSucc (MkEntry fc nm dty@(Pi _ _ _ _ (Ref _ a) (Ref _ b)) (DCon _ _ 1 hn) _) = a == b
|
isSucc (MkEntry fc nm dty@(Pi _ _ _ _ (Ref _ a) (Ref _ b)) (DCon _ _ (Many :: Nil) hn) _) = a == b
|
||||||
isSucc _ = False
|
isSucc _ = False
|
||||||
|
|
||||||
processData : List String → FC → String → Raw → List Decl → M Unit
|
processData : List String → FC → String → Raw → List Decl → M Unit
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ tailNames (CCase _ alts) = join $ map altTailNames alts
|
|||||||
altTailNames (CLitAlt _ exp) = tailNames exp
|
altTailNames (CLitAlt _ exp) = tailNames exp
|
||||||
tailNames (CLet _ _ t) = tailNames t
|
tailNames (CLet _ _ t) = tailNames t
|
||||||
tailNames (CLetRec _ _ t) = tailNames t
|
tailNames (CLetRec _ _ t) = tailNames t
|
||||||
tailNames (CConstr _ _ args) = Nil
|
tailNames (CConstr _ _ args _) = Nil
|
||||||
tailNames (CBnd _) = Nil
|
tailNames (CBnd _) = Nil
|
||||||
tailNames (CFun _ tm) = tailNames tm
|
tailNames (CFun _ tm) = tailNames tm
|
||||||
tailNames (CLam _ _) = Nil
|
tailNames (CLam _ _) = Nil
|
||||||
@@ -43,14 +43,16 @@ tailNames (CPrimOp _ _ _) = Nil
|
|||||||
-- rewrite tail calls to return an object
|
-- rewrite tail calls to return an object
|
||||||
rewriteTailCalls : List QName → CExp → CExp
|
rewriteTailCalls : List QName → CExp → CExp
|
||||||
rewriteTailCalls nms tm = case tm of
|
rewriteTailCalls nms tm = case tm of
|
||||||
CAppRef nm args 0 =>
|
CAppRef nm args qs =>
|
||||||
case getTag (S Z) nm nms of
|
if length' args == length' qs
|
||||||
Just ix => CConstr ix (show nm) args
|
then case getTag (S Z) nm nms of
|
||||||
Nothing => CConstr Z "return" (tm :: Nil)
|
Just ix => CConstr ix (show nm) args $ map (const Many) args
|
||||||
|
Nothing => CConstr Z "return" (tm :: Nil) (Many :: Nil)
|
||||||
|
else CConstr Z "return" (tm :: Nil) (Many :: Nil)
|
||||||
CLetRec nm t u => CLetRec nm t $ rewriteTailCalls nms u
|
CLetRec nm t u => CLetRec nm t $ rewriteTailCalls nms u
|
||||||
CLet nm t u => CLet nm t $ rewriteTailCalls nms u
|
CLet nm t u => CLet nm t $ rewriteTailCalls nms u
|
||||||
CCase sc alts => CCase sc $ map rewriteAlt alts
|
CCase sc alts => CCase sc $ map rewriteAlt alts
|
||||||
tm => CConstr Z "return" (tm :: Nil)
|
tm => CConstr Z "return" (tm :: Nil) (Many :: Nil)
|
||||||
where
|
where
|
||||||
getTag : Nat → QName → List QName → Maybe Nat
|
getTag : Nat → QName → List QName → Maybe Nat
|
||||||
getTag t nm Nil = Nothing
|
getTag t nm Nil = Nothing
|
||||||
@@ -71,15 +73,17 @@ doOptimize fns = do
|
|||||||
let nms = map fst fns
|
let nms = map fst fns
|
||||||
let alts = map (mkAlt nms) $ enumerate splitFuns
|
let alts = map (mkAlt nms) $ enumerate splitFuns
|
||||||
recName <- mkRecName nms
|
recName <- mkRecName nms
|
||||||
let recfun = CFun ("arg" :: Nil) $ CCase (CBnd 0) alts
|
let recfun = CFun ((Many, "arg") :: Nil) $ CCase (CBnd 0) alts
|
||||||
wrapped <- traverse (mkWrap recName) (enumerate fns)
|
wrapped <- traverse (mkWrap recName) (enumerate fns)
|
||||||
pure $ (recName, recfun) :: wrapped
|
pure $ (recName, recfun) :: wrapped
|
||||||
where
|
where
|
||||||
mkWrap : QName → Nat × QName × CExp → M (QName × CExp)
|
mkWrap : QName → Nat × QName × CExp → M (QName × CExp)
|
||||||
mkWrap recName (ix, qn, CFun args _) = do
|
mkWrap recName (ix, qn, CFun args _) = do
|
||||||
let arglen = length' args
|
let arglen = length' args
|
||||||
let arg = CConstr (S ix) (show qn) $ map (\k => CBnd (arglen - k - 1)) (range 0 arglen)
|
let conargs = map (\k => CBnd (arglen - k - 1)) (range 0 arglen)
|
||||||
let body = CAppRef bouncer (CRef recName :: arg :: Nil) 0
|
let conquant = map (const Many) conargs
|
||||||
|
let arg = CConstr (S ix) (show qn) conargs conquant
|
||||||
|
let body = CAppRef bouncer (CRef recName :: arg :: Nil) (Many :: Many :: Nil)
|
||||||
pure $ (qn, CFun args body)
|
pure $ (qn, CFun args body)
|
||||||
mkWrap _ (qn, _) = error emptyFC "error in mkWrap: \{show qn} not a CFun"
|
mkWrap _ (qn, _) = error emptyFC "error in mkWrap: \{show qn} not a CFun"
|
||||||
|
|
||||||
@@ -87,10 +91,10 @@ doOptimize fns = do
|
|||||||
mkRecName Nil = error emptyFC "INTERNAL ERROR: Empty List in doOptimize"
|
mkRecName Nil = error emptyFC "INTERNAL ERROR: Empty List in doOptimize"
|
||||||
mkRecName (QN ns nm :: _) = pure $ QN ns "REC_\{nm}"
|
mkRecName (QN ns nm :: _) = pure $ QN ns "REC_\{nm}"
|
||||||
|
|
||||||
mkAlt : List QName → (Nat × QName × List Name × CExp) -> CAlt
|
mkAlt : List QName → (Nat × QName × List (Quant × Name) × CExp) -> CAlt
|
||||||
mkAlt nms (ix, qn, args, tm) = CConAlt (S ix) (show qn) NormalCon args (rewriteTailCalls nms tm)
|
mkAlt nms (ix, qn, args, tm) = CConAlt (S ix) (show qn) NormalCon (map snd args) (rewriteTailCalls nms tm)
|
||||||
|
|
||||||
splitFun : (QName × CExp) → M (QName × List Name × CExp)
|
splitFun : (QName × CExp) → M (QName × List (Quant × Name) × CExp)
|
||||||
splitFun (qn, CFun args body) = pure (qn, args, body)
|
splitFun (qn, CFun args body) = pure (qn, args, body)
|
||||||
splitFun (qn, _) = error emptyFC "TCO error: \{show qn} not a function"
|
splitFun (qn, _) = error emptyFC "TCO error: \{show qn} not a function"
|
||||||
|
|
||||||
|
|||||||
@@ -357,11 +357,13 @@ instance Show ConInfo where
|
|||||||
show ZeroCon = "[Z]"
|
show ZeroCon = "[Z]"
|
||||||
show EnumCon = "[E]"
|
show EnumCon = "[E]"
|
||||||
|
|
||||||
data Def = Axiom | TCon Int (List QName) | DCon Nat ConInfo Int QName | Fn Tm | PrimTCon Int
|
data Def = Axiom | TCon Int (List QName) | DCon Nat ConInfo (List Quant) QName | Fn Tm | PrimTCon Int
|
||||||
| PrimFn String Nat (List QName)
|
| PrimFn String Nat (List QName)
|
||||||
|
| PrimOp String
|
||||||
|
|
||||||
instance Show Def where
|
instance Show Def where
|
||||||
show Axiom = "axiom"
|
show Axiom = "axiom"
|
||||||
|
show (PrimOp op) = "PrimOp \{show op}"
|
||||||
show (TCon _ strs) = "TCon \{show strs}"
|
show (TCon _ strs) = "TCon \{show strs}"
|
||||||
show (DCon ix ci k tyname) = "DCon \{show ix} \{show k} \{show tyname} \{show ci}"
|
show (DCon ix ci k tyname) = "DCon \{show ix} \{show k} \{show tyname} \{show ci}"
|
||||||
show (Fn t) = "Fn \{show t}"
|
show (Fn t) = "Fn \{show t}"
|
||||||
@@ -439,13 +441,15 @@ record TopContext where
|
|||||||
record Context where
|
record Context where
|
||||||
constructor MkCtx
|
constructor MkCtx
|
||||||
lvl : Int
|
lvl : Int
|
||||||
-- shall we use lvl as an index?
|
-- Kovacs splits this into multiple fields
|
||||||
|
-- I was going to recombine them, but realized I'd have to regenerate env for eval
|
||||||
env : Env -- Values in scope
|
env : Env -- Values in scope
|
||||||
|
-- TODO add fc, maybe add BD and make this a proper type
|
||||||
types : List (String × Val) -- types and names in scope
|
types : List (String × Val) -- types and names in scope
|
||||||
-- so we'll try "bds" determines length of local context
|
-- so we'll try "bds" determines length of local context
|
||||||
bds : List BD -- bound or defined
|
bds : List BD -- bound or defined
|
||||||
|
|
||||||
-- FC to use if we don't have a better option
|
-- FC to use for errors if we don't have a better option
|
||||||
ctxFC : FC
|
ctxFC : FC
|
||||||
|
|
||||||
-- add a binding to environment
|
-- add a binding to environment
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ module Node
|
|||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
pfunc getArgs uses (arrayToList MkIORes) : IO (List String) := `(w) => Prelude_MkIORes(null, Prelude_arrayToList(null, process.argv.slice(1)), w)`
|
pfunc getArgs uses (arrayToList MkIORes) : IO (List String) := `(w) => Prelude_MkIORes( Prelude_arrayToList(null, process.argv.slice(1)), w)`
|
||||||
pfunc readFile uses (MkIORes Left Right) : (fn : String) -> IO (Either String String) := `(fn) => (w) => {
|
pfunc readFile uses (MkIORes Left Right) : (fn : String) -> IO (Either String String) := `(fn) => (w) => {
|
||||||
let fs = require('fs')
|
let fs = require('fs')
|
||||||
let result
|
let result
|
||||||
try {
|
try {
|
||||||
let content = fs.readFileSync(fn, 'utf8')
|
let content = fs.readFileSync(fn, 'utf8')
|
||||||
result = Prelude_Right(null, null, content)
|
result = Prelude_Right(content)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
result = Prelude_Left(null, null, e+'')
|
result = Prelude_Left(e+'')
|
||||||
}
|
}
|
||||||
return Prelude_MkIORes(null, result, w)
|
return Prelude_MkIORes(result, w)
|
||||||
}`
|
}`
|
||||||
|
|
||||||
-- I wonder if I should automatically `uses` the constructors in the types
|
-- I wonder if I should automatically `uses` the constructors in the types
|
||||||
@@ -21,11 +21,11 @@ pfunc writeFile uses (MkIORes MkUnit) : String → String → IO (Either String
|
|||||||
let result
|
let result
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(fn, content, 'utf8')
|
fs.writeFileSync(fn, content, 'utf8')
|
||||||
result = Prelude_Right(null, null, Prelude_MkUnit)
|
result = Prelude_Right( Prelude_MkUnit)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
result = Prelude_Left(null, null, e+"")
|
result = Prelude_Left(e+"")
|
||||||
}
|
}
|
||||||
return Prelude_MkIORes(null, result, w)
|
return Prelude_MkIORes(result, w)
|
||||||
}`
|
}`
|
||||||
|
|
||||||
-- maybe System.exit or something, like the original putStrLn msg >> exitFailure
|
-- maybe System.exit or something, like the original putStrLn msg >> exitFailure
|
||||||
|
|||||||
@@ -297,9 +297,9 @@ pfunc aget : ∀ a. Array a → Int → a := `(a, arr, ix) => arr[ix]`
|
|||||||
pfunc aempty : ∀ a. Unit → Array a := `() => []`
|
pfunc aempty : ∀ a. Unit → Array a := `() => []`
|
||||||
|
|
||||||
pfunc arrayToList uses (Nil _::_) : ∀ a. Array a → List a := `(a,arr) => {
|
pfunc arrayToList uses (Nil _::_) : ∀ a. Array a → List a := `(a,arr) => {
|
||||||
let rval = Prelude_Nil(null)
|
let rval = Prelude_Nil()
|
||||||
for (let i = arr.length - 1;i >= 0; i--) {
|
for (let i = arr.length - 1;i >= 0; i--) {
|
||||||
rval = Prelude__$3A$3A_(a, arr[i], rval)
|
rval = Prelude__$3A$3A_(arr[i], rval)
|
||||||
}
|
}
|
||||||
return rval
|
return rval
|
||||||
}`
|
}`
|
||||||
@@ -315,9 +315,9 @@ pfunc p_strTail : (s : String) → String := `(s) => s[0]`
|
|||||||
pfunc trim : String → String := `s => s.trim()`
|
pfunc trim : String → String := `s => s.trim()`
|
||||||
pfunc split uses (Nil _::_) : String → String → List String := `(s, by) => {
|
pfunc split uses (Nil _::_) : String → String → List String := `(s, by) => {
|
||||||
let parts = s.split(by)
|
let parts = s.split(by)
|
||||||
let rval = Prelude_Nil(null)
|
let rval = Prelude_Nil()
|
||||||
parts.reverse()
|
parts.reverse()
|
||||||
parts.forEach(p => { rval = Prelude__$3A$3A_(null, p, rval) })
|
parts.forEach(p => { rval = Prelude__$3A$3A_(p, rval) })
|
||||||
return rval
|
return rval
|
||||||
}`
|
}`
|
||||||
|
|
||||||
@@ -330,6 +330,14 @@ pfunc intToNat : Int → Nat := `(n) => n>0?n:0`
|
|||||||
pfunc fastConcat uses (listToArray) : List String → String := `(xs) => Prelude_listToArray(null, xs).join('')`
|
pfunc fastConcat uses (listToArray) : List String → String := `(xs) => Prelude_listToArray(null, xs).join('')`
|
||||||
pfunc replicate uses (natToInt) : Nat → Char → String := `(n,c) => c.repeat(Prelude_natToInt(n))`
|
pfunc replicate uses (natToInt) : Nat → Char → String := `(n,c) => c.repeat(Prelude_natToInt(n))`
|
||||||
|
|
||||||
|
-- TODO this should be replicate and the chars thing should have a different name
|
||||||
|
replicate' : ∀ a. Nat → a → List a
|
||||||
|
replicate' {a} n x = go n Nil
|
||||||
|
where
|
||||||
|
go : Nat → List a → List a
|
||||||
|
go Z xs = xs
|
||||||
|
go (S k) xs = go k (x :: xs)
|
||||||
|
|
||||||
-- I don't want to use an empty type because it would be a proof of void
|
-- I don't want to use an empty type because it would be a proof of void
|
||||||
ptype World
|
ptype World
|
||||||
|
|
||||||
@@ -377,7 +385,7 @@ instance HasIO IO where
|
|||||||
|
|
||||||
pfunc primPutStrLn uses (MkIORes MkUnit) : String → IO Unit := `(s) => (w) => {
|
pfunc primPutStrLn uses (MkIORes MkUnit) : String → IO Unit := `(s) => (w) => {
|
||||||
console.log(s)
|
console.log(s)
|
||||||
return Prelude_MkIORes(null,Prelude_MkUnit,w)
|
return Prelude_MkIORes(Prelude_MkUnit,w)
|
||||||
}`
|
}`
|
||||||
|
|
||||||
putStrLn : ∀ io. {{HasIO io}} → String → io Unit
|
putStrLn : ∀ io. {{HasIO io}} → String → io Unit
|
||||||
@@ -403,8 +411,8 @@ pfunc chr : Int → Char := `(c) => String.fromCharCode(c)`
|
|||||||
|
|
||||||
pfunc unpack uses (Nil _::_) : String → List Char
|
pfunc unpack uses (Nil _::_) : String → List Char
|
||||||
:= `(s) => {
|
:= `(s) => {
|
||||||
let acc = Prelude_Nil(null)
|
let acc = Prelude_Nil()
|
||||||
for (let i = s.length - 1; 0 <= i; i--) acc = Prelude__$3A$3A_(null, s[i], acc)
|
for (let i = s.length - 1; 0 <= i; i--) acc = Prelude__$3A$3A_(s[i], acc)
|
||||||
return acc
|
return acc
|
||||||
}`
|
}`
|
||||||
|
|
||||||
@@ -628,20 +636,20 @@ instance Div Double where x / y = divDouble x y
|
|||||||
ptype IOArray : U → U
|
ptype IOArray : U → U
|
||||||
|
|
||||||
pfunc newArray uses (MkIORes) : ∀ a. Int → a → IO (IOArray a) :=
|
pfunc newArray uses (MkIORes) : ∀ a. Int → a → IO (IOArray a) :=
|
||||||
`(_, n, v) => (w) => Prelude_MkIORes(null, Prelude_Array(n).fill(v),w)`
|
`(_, n, v) => (w) => Prelude_MkIORes(Prelude_Array(n).fill(v),w)`
|
||||||
pfunc arrayGet : ∀ a. IOArray a → Int → IO a := `(_, arr, ix) => w => Prelude_MkIORes(null, arr[ix], w)`
|
pfunc arrayGet : ∀ a. IOArray a → Int → IO a := `(_, arr, ix) => w => Prelude_MkIORes(arr[ix], w)`
|
||||||
pfunc arraySet uses (MkIORes MkUnit) : ∀ a. IOArray a → Int → a → IO Unit := `(_, arr, ix, v) => w => {
|
pfunc arraySet uses (MkIORes MkUnit) : ∀ a. IOArray a → Int → a → IO Unit := `(_, arr, ix, v) => w => {
|
||||||
arr[ix] = v
|
arr[ix] = v
|
||||||
return Prelude_MkIORes(null, Prelude_MkUnit, w)
|
return Prelude_MkIORes(Prelude_MkUnit, w)
|
||||||
}`
|
}`
|
||||||
pfunc arraySize uses (MkIORes) : ∀ a. IOArray a → IO Int := `(_, arr) => w => Prelude_MkIORes(null, arr.length, w)`
|
pfunc arraySize uses (MkIORes) : ∀ a. IOArray a → IO Int := `(_, arr) => w => Prelude_MkIORes(arr.length, w)`
|
||||||
|
|
||||||
pfunc ioArrayToList uses (Nil _::_ MkIORes) : ∀ a. IOArray a → IO (List a) := `(a,arr) => w => {
|
pfunc ioArrayToList uses (Nil _::_ MkIORes) : ∀ a. IOArray a → IO (List a) := `(a,arr) => w => {
|
||||||
let rval = Prelude_Nil(null)
|
let rval = Prelude_Nil()
|
||||||
for (let i = arr.length - 1;i >= 0; i--) {
|
for (let i = arr.length - 1;i >= 0; i--) {
|
||||||
rval = Prelude__$3A$3A_(a, arr[i], rval)
|
rval = Prelude__$3A$3A_(arr[i], rval)
|
||||||
}
|
}
|
||||||
return Prelude_MkIORes(null, rval, w)
|
return Prelude_MkIORes(rval, w)
|
||||||
}`
|
}`
|
||||||
|
|
||||||
pfunc listToIOArray uses (MkIORes) : ∀ a. List a → IO (Array a) := `(a,list) => w => {
|
pfunc listToIOArray uses (MkIORes) : ∀ a. List a → IO (Array a) := `(a,list) => w => {
|
||||||
@@ -650,7 +658,7 @@ pfunc listToIOArray uses (MkIORes) : ∀ a. List a → IO (Array a) := `(a,list)
|
|||||||
rval.push(list.h1)
|
rval.push(list.h1)
|
||||||
list = list.h2
|
list = list.h2
|
||||||
}
|
}
|
||||||
return Prelude_MkIORes(null,rval,w)
|
return Prelude_MkIORes(rval,w)
|
||||||
}`
|
}`
|
||||||
|
|
||||||
class Cast a b where
|
class Cast a b where
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pfunc checksum uses (MkIORes) : String → IO String := `(a) => (w) => {
|
|||||||
for (let i = 0; i < arr.length; i++) {
|
for (let i = 0; i < arr.length; i++) {
|
||||||
val = ((val * 33) + arr[i]) | 0
|
val = ((val * 33) + arr[i]) | 0
|
||||||
}
|
}
|
||||||
return Prelude_MkIORes(null, ""+val, w);
|
return Prelude_MkIORes(""+val, w);
|
||||||
}`
|
}`
|
||||||
|
|
||||||
-- this was an experiment, prepping for dumping module information
|
-- this was an experiment, prepping for dumping module information
|
||||||
@@ -27,7 +27,7 @@ pfunc dumpModFile uses (MkIORes MkUnit): String → ModFile → IO Unit := `(fn,
|
|||||||
let enc = EncFile.encode(a)
|
let enc = EncFile.encode(a)
|
||||||
fs.writeFileSync(fn, enc)
|
fs.writeFileSync(fn, enc)
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
return Prelude_MkIORes(null, Prelude_MkUnit, w)
|
return Prelude_MkIORes(Prelude_MkUnit, w)
|
||||||
}`
|
}`
|
||||||
|
|
||||||
|
|
||||||
@@ -47,9 +47,9 @@ pfunc readModFile uses (MkIORes Just Nothing): String → IO (Maybe ModFile) :=
|
|||||||
let {DecFile} = require('./serializer')
|
let {DecFile} = require('./serializer')
|
||||||
let data = fs.readFileSync(fn)
|
let data = fs.readFileSync(fn)
|
||||||
let dec = DecFile.decode(data)
|
let dec = DecFile.decode(data)
|
||||||
return Prelude_MkIORes(null, Prelude_Just(null, dec), w)
|
return Prelude_MkIORes(Prelude_Just(dec), w)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Prelude_MkIORes(null, Prelude_Nothing, w)
|
return Prelude_MkIORes(Prelude_Nothing(), w)
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
(1 _ {"tag":0,"h0":null,"h1":null,"h2":2,"h3":0} {"tag":0,"h0":null})
|
|
||||||
{"tag":0,"h0":null}
|
|
||||||
(1 _ {"tag":0,"h0":null,"h1":null,"h2":2,"h3":3} {"tag":0,"h0":null})
|
|
||||||
(1 _ {"tag":0,"h0":null,"h1":null,"h2":1,"h3":3} (1 _ {"tag":0,"h0":null,"h1":null,"h2":2,"h3":0} {"tag":0,"h0":null}))
|
|
||||||
(1 _ {"tag":0,"h0":null,"h1":null,"h2":0,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":1,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":2,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":3,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":4,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":5,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":6,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":7,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":8,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":9,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":10,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":11,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":12,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":13,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":14,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":16,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":17,"h3":0} (1 _ {"tag":0,"h0":null,"h1":null,"h2":20,"h3":0} {"tag":0,"h0":null}))))))))))))))))))
|
|
||||||
{"tag":0,"h0":null,"h1":{"tag":0,"h0":null,"h1":null,"h2":0,"h3":0}}
|
|
||||||
{"tag":0,"h0":null,"h1":{"tag":0,"h0":null,"h1":null,"h2":20,"h3":0}}
|
|
||||||
ohne 4
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 1
|
|
||||||
(1 _ 0 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 5
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 7
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 2
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 9
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 3
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 10
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 6
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 0
|
|
||||||
(1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 11
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 12
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 13
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 20
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 14
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 16
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 17
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 8 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
ohne 8
|
|
||||||
(1 _ 0 (1 _ 1 (1 _ 2 (1 _ 3 (1 _ 4 (1 _ 5 (1 _ 6 (1 _ 7 (1 _ 9 (1 _ 10 (1 _ 11 (1 _ 12 (1 _ 13 (1 _ 14 (1 _ 16 (1 _ 17 (1 _ 20 {"tag":0,"h0":null})))))))))))))))))
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user