working. checkpoint before messing with parser
This commit is contained in:
10
eg/ex.newt
10
eg/ex.newt
@@ -8,4 +8,12 @@ id = \ a => \ x => x
|
|||||||
-- errors aren't cutting to the top
|
-- errors aren't cutting to the top
|
||||||
-- I think we need the errors to be fatal if anything is consumed (since the nearest alt)
|
-- I think we need the errors to be fatal if anything is consumed (since the nearest alt)
|
||||||
|
|
||||||
foo
|
List : U -> U
|
||||||
|
List = \ A => (L : U) -> L -> (A -> L -> L) -> L
|
||||||
|
|
||||||
|
-- need more sugar for lambdas
|
||||||
|
nil : (A : U) -> (L : U) -> L -> (A -> L -> L) -> L
|
||||||
|
nil = \ A => \ L => \ n => \ f => n
|
||||||
|
|
||||||
|
Bool : U
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ authors = "Steve Dunham"
|
|||||||
-- langversion
|
-- langversion
|
||||||
|
|
||||||
-- packages to add to search path
|
-- packages to add to search path
|
||||||
depends = contrib, base
|
depends = contrib, base, elab-util
|
||||||
|
|
||||||
-- modules to install
|
-- modules to install
|
||||||
-- modules =
|
-- modules =
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ import Lib.Parser.Impl
|
|||||||
import Data.Vect
|
import Data.Vect
|
||||||
import Data.String
|
import Data.String
|
||||||
import Lib.TT
|
import Lib.TT
|
||||||
|
import Lib.TopContext
|
||||||
import Syntax
|
import Syntax
|
||||||
|
|
||||||
-- cribbed this, it avoids MonadError String m => everywhere
|
-- cribbed this, it avoids MonadError String m => everywhere
|
||||||
parameters {0 m : Type -> Type} {auto _ : MonadError String m}
|
parameters {0 m : Type -> Type} {auto _ : MonadError String m} (top : TopContext)
|
||||||
export
|
export
|
||||||
infer : Context -> Raw -> m (Tm, Val)
|
infer : Context -> Raw -> m (Tm, Val)
|
||||||
|
|
||||||
@@ -33,7 +34,7 @@ parameters {0 m : Type -> Type} {auto _ : MonadError String m}
|
|||||||
|
|
||||||
infer ctx (RVar nm) = go 0 ctx.types
|
infer ctx (RVar nm) = go 0 ctx.types
|
||||||
where
|
where
|
||||||
go : Nat -> List (String, Val) -> m (Tm, Val)
|
go : Nat -> Vect n (String, Val) -> m (Tm, Val)
|
||||||
go i [] = throwError "\{show nm} not in scope \{show $ map fst ctx.types}"
|
go i [] = throwError "\{show nm} not in scope \{show $ map fst ctx.types}"
|
||||||
go i ((x, ty) :: xs) = if x == nm then pure $ (Bnd i, ty)
|
go i ((x, ty) :: xs) = if x == nm then pure $ (Bnd i, ty)
|
||||||
else go (i + 1) xs
|
else go (i + 1) xs
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ import Data.List
|
|||||||
-- exercises. There is some fill in the parser stuff that may show
|
-- exercises. There is some fill in the parser stuff that may show
|
||||||
-- the future.
|
-- the future.
|
||||||
|
|
||||||
|
-- kovacs desugars the (a b c : Foo) during parsing (foldr)
|
||||||
|
|
||||||
|
-- We need to allow A -> B -> C in functions
|
||||||
|
-- We need to handle A -> (A -> B) -> C
|
||||||
|
|
||||||
ident = token Ident
|
ident = token Ident
|
||||||
|
|
||||||
parens : Parser a -> Parser a
|
parens : Parser a -> Parser a
|
||||||
@@ -51,7 +56,7 @@ lit = do
|
|||||||
t <- token Number
|
t <- token Number
|
||||||
pure $ RLit (LInt (cast t))
|
pure $ RLit (LInt (cast t))
|
||||||
|
|
||||||
-- I can haz arrows
|
-- typeExpr is term with arrows.
|
||||||
export typeExpr : Parser Raw
|
export typeExpr : Parser Raw
|
||||||
export term : (Parser Raw)
|
export term : (Parser Raw)
|
||||||
|
|
||||||
@@ -64,7 +69,7 @@ atom = withPos (RU <$ keyword "U"
|
|||||||
<|> RVar <$> ident
|
<|> RVar <$> ident
|
||||||
<|> lit
|
<|> lit
|
||||||
<|> RHole <$ keyword "_")
|
<|> RHole <$ keyword "_")
|
||||||
<|> parens term
|
<|> parens typeExpr
|
||||||
|
|
||||||
-- Argument to a Spine
|
-- Argument to a Spine
|
||||||
pArg : Parser (Icit,Raw)
|
pArg : Parser (Icit,Raw)
|
||||||
@@ -112,7 +117,7 @@ letExpr = do
|
|||||||
commit
|
commit
|
||||||
alts <- startBlock $ someSame $ letAssign
|
alts <- startBlock $ someSame $ letAssign
|
||||||
keyword' "in"
|
keyword' "in"
|
||||||
scope <- term
|
scope <- typeExpr
|
||||||
|
|
||||||
pure $ foldl (\ acc, (n,v) => RLet n RHole v acc) scope alts
|
pure $ foldl (\ acc, (n,v) => RLet n RHole v acc) scope alts
|
||||||
where
|
where
|
||||||
@@ -121,7 +126,7 @@ letExpr = do
|
|||||||
name <- ident
|
name <- ident
|
||||||
-- TODO type assertion
|
-- TODO type assertion
|
||||||
keyword "="
|
keyword "="
|
||||||
t <- term
|
t <- typeExpr
|
||||||
pure (name,t)
|
pure (name,t)
|
||||||
|
|
||||||
pLetArg : Parser (Icit, String, Maybe Raw)
|
pLetArg : Parser (Icit, String, Maybe Raw)
|
||||||
@@ -138,7 +143,7 @@ lamExpr = do
|
|||||||
commit
|
commit
|
||||||
(icit, name, ty) <- pLetArg
|
(icit, name, ty) <- pLetArg
|
||||||
keyword "=>"
|
keyword "=>"
|
||||||
scope <- term
|
scope <- typeExpr
|
||||||
-- TODO optional type
|
-- TODO optional type
|
||||||
pure $ RLam name icit scope
|
pure $ RLam name icit scope
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ public export
|
|||||||
Semigroup Doc where x <+> y = Seq x (Seq (Text " ") y)
|
Semigroup Doc where x <+> y = Seq x (Seq (Text " ") y)
|
||||||
|
|
||||||
-- Match System.File so we don't get warnings
|
-- Match System.File so we don't get warnings
|
||||||
|
public export
|
||||||
infixl 5 </>
|
infixl 5 </>
|
||||||
|
|
||||||
export
|
export
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
-- I'm not sure this is related, or just a note to self (Presheaves on Porpoise)
|
-- I'm not sure this is related, or just a note to self (Presheaves on Porpoise)
|
||||||
|
|
||||||
-- maybe watch https://www.youtube.com/watch?v=3gef0_NFz8Q
|
-- maybe watch https://www.youtube.com/watch?v=3gef0_NFz8Q
|
||||||
-- or drop the indices for now.
|
-- or drop the indices for now.
|
||||||
|
|
||||||
@@ -7,9 +8,12 @@
|
|||||||
module Lib.TT
|
module Lib.TT
|
||||||
-- For SourcePos
|
-- For SourcePos
|
||||||
import Lib.Parser.Impl
|
import Lib.Parser.Impl
|
||||||
|
|
||||||
import Control.Monad.Error.Interface
|
import Control.Monad.Error.Interface
|
||||||
import Data.Fin
|
import Data.Fin
|
||||||
import Data.List
|
import Data.List
|
||||||
|
import Data.Vect
|
||||||
|
import Data.SortedMap
|
||||||
|
|
||||||
public export
|
public export
|
||||||
Name : Type
|
Name : Type
|
||||||
@@ -107,7 +111,8 @@ public export
|
|||||||
($$) : Closure -> Val -> Val
|
($$) : Closure -> Val -> Val
|
||||||
($$) (MkClosure env tm) u = eval (u :: env) tm
|
($$) (MkClosure env tm) u = eval (u :: env) tm
|
||||||
|
|
||||||
infixl 8 $$
|
public export
|
||||||
|
infixl 8 $$
|
||||||
|
|
||||||
export
|
export
|
||||||
vapp : Val -> Val -> Val
|
vapp : Val -> Val -> Val
|
||||||
@@ -152,30 +157,69 @@ conv : (lvl : Nat) -> Val -> Val -> Bool
|
|||||||
-- Types = List (Name, Lazy Val)
|
-- Types = List (Name, Lazy Val)
|
||||||
|
|
||||||
|
|
||||||
|
{-
|
||||||
|
smalltt
|
||||||
|
|
||||||
|
smalltt gets into weird haskell weeds in eval - shifting top level to the left
|
||||||
|
and tagging meta vs top with a bit.
|
||||||
|
|
||||||
|
I think something subtle is going on with laziness on Elaboration.hs:300
|
||||||
|
yeah, and define is even inlined.
|
||||||
|
|
||||||
|
So it has a top context, and clears out almost everything for processing a def in
|
||||||
|
a different kind of context.
|
||||||
|
|
||||||
|
we very much need an idea of local context for metas. I don't want to abstract over
|
||||||
|
the entire program.
|
||||||
|
|
||||||
|
So I guess we have top and local then?
|
||||||
|
|
||||||
|
With haskell syntax. I think we can have Axiom for claims and rewrite to def later.
|
||||||
|
|
||||||
|
Hmm, so given ezoo, if I'm going simple, I could keep BDs short, and use the normal
|
||||||
|
context. (Zoo4.lean:222) I'd probably still need an undefined/axiom marker as a value?
|
||||||
|
|
||||||
|
ok, so with just one context, Env is List Val and we're getting Tm back from type checking.
|
||||||
|
|
||||||
|
Can I get val back? Do we need to quote? What happens if we don't?
|
||||||
|
|
||||||
|
-}
|
||||||
|
|
||||||
|
data BD = Bound | Defined
|
||||||
|
|
||||||
|
-- we'll use this for typechecking, but need to keep a TopContext around too.
|
||||||
public export
|
public export
|
||||||
record Context where
|
record Context where
|
||||||
constructor MkCtx
|
constructor MkCtx
|
||||||
|
lvl : Nat
|
||||||
|
-- shall we use lvl as an index?
|
||||||
env : Env -- Values in scope
|
env : Env -- Values in scope
|
||||||
types : List (String, Val) -- types and names in scope
|
types : Vect lvl (String, Val) -- types and names in scope
|
||||||
-- bds : List BD -- bind or define
|
-- so we'll try "bds" determines length of local context
|
||||||
-- lvl = length types
|
bds : List BD -- bound or defined
|
||||||
|
|
||||||
pos : SourcePos -- the last SourcePos that we saw
|
pos : SourcePos -- the last SourcePos that we saw
|
||||||
|
|
||||||
export
|
export
|
||||||
empty : Context
|
empty : Context
|
||||||
empty = MkCtx [] [] (0,0)
|
empty = MkCtx 0 [] [] [] (0,0)
|
||||||
|
|
||||||
export partial
|
export partial
|
||||||
Show Context where
|
Show Context where
|
||||||
show ctx = "Context \{show $ map fst $ ctx.types}"
|
show ctx = "Context \{show $ map fst $ ctx.types}"
|
||||||
|
|
||||||
-- Kovacs Small-TT has locals and globals, lets do that.
|
|
||||||
|
|
||||||
||| add a binding to environment
|
||| add a binding to environment
|
||||||
export
|
export
|
||||||
extend : Context -> String -> Val -> Context
|
extend : Context -> String -> Val -> Context
|
||||||
extend (MkCtx env types pos) name ty =
|
extend (MkCtx lvl env types bds pos) name ty =
|
||||||
MkCtx (VVar (length env) :: env) ((name, ty) :: types) pos
|
MkCtx (S lvl) (VVar lvl :: env) ((name, ty) :: types) (Bound :: bds) pos
|
||||||
|
|
||||||
|
-- I guess we define things as values?
|
||||||
|
export
|
||||||
|
define : Context -> String -> Val -> Val -> Context
|
||||||
|
define (MkCtx lvl env types bds pos) name val ty =
|
||||||
|
MkCtx (S lvl) (val :: env) ((name, ty) :: types) (Defined :: bds) pos
|
||||||
|
|
||||||
|
|
||||||
update : Context -> String -> Tm -> Context
|
update : Context -> String -> Tm -> Context
|
||||||
-- oof
|
-- oof
|
||||||
@@ -184,7 +228,7 @@ lookup : {0 m : Type -> Type} -> {auto _ : MonadError String m} ->
|
|||||||
Context -> String -> m Val
|
Context -> String -> m Val
|
||||||
lookup ctx nm = go ctx.types
|
lookup ctx nm = go ctx.types
|
||||||
where
|
where
|
||||||
go : List (String,Val) -> m Val
|
go : Vect n (String,Val) -> m Val
|
||||||
go [] = throwError "Name \{nm} not in scope"
|
go [] = throwError "Name \{nm} not in scope"
|
||||||
go ((n, ty) :: xs) = if n == nm then pure ty else go xs
|
go ((n, ty) :: xs) = if n == nm then pure ty else go xs
|
||||||
|
|
||||||
|
|||||||
69
src/Lib/TopContext.idr
Normal file
69
src/Lib/TopContext.idr
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
module Lib.TopContext
|
||||||
|
|
||||||
|
import Data.String
|
||||||
|
import Lib.TT
|
||||||
|
|
||||||
|
|
||||||
|
public export
|
||||||
|
data Def = Axiom | TCon (List String) | DCon Nat | Fn Tm
|
||||||
|
|
||||||
|
Show Def where
|
||||||
|
show Axiom = "axiom"
|
||||||
|
show (TCon strs) = "TCon \{show strs}"
|
||||||
|
show (DCon k) = "DCon \{show k}"
|
||||||
|
show (Fn t) = "Fn \{show t}"
|
||||||
|
|
||||||
|
||| entry in the top level context
|
||||||
|
public export
|
||||||
|
record TopEntry where
|
||||||
|
constructor MkEntry
|
||||||
|
name : String
|
||||||
|
type : Tm
|
||||||
|
def : Def
|
||||||
|
|
||||||
|
-- FIXME snoc
|
||||||
|
|
||||||
|
export
|
||||||
|
Show TopEntry where
|
||||||
|
show (MkEntry name type def) = "\{show name} : \{show type} := \{show def}"
|
||||||
|
|
||||||
|
||| Top level context.
|
||||||
|
||| Most of the reason this is separate is to have a different type
|
||||||
|
||| `Def` for the entries.
|
||||||
|
|||
|
||||||
|
||| The price is that we have names in addition to levels. Do we want to
|
||||||
|
||| expand these during conversion?
|
||||||
|
public export
|
||||||
|
record TopContext where
|
||||||
|
constructor MkTop
|
||||||
|
-- We'll add a map later?
|
||||||
|
defs : List TopEntry
|
||||||
|
|
||||||
|
|
||||||
|
export
|
||||||
|
lookup : String -> TopContext -> Maybe TopEntry
|
||||||
|
lookup nm top = go top.defs
|
||||||
|
where
|
||||||
|
go : List TopEntry -> Maybe TopEntry
|
||||||
|
go [] = Nothing
|
||||||
|
go (entry :: xs) = if entry.name == nm then Just entry else go xs
|
||||||
|
|
||||||
|
-- Maybe pretty print?
|
||||||
|
export
|
||||||
|
Show TopContext where
|
||||||
|
show (MkTop defs) = "\nContext:\n [\{ joinBy "\n" $ map show defs}]"
|
||||||
|
|
||||||
|
public export
|
||||||
|
empty : TopContext
|
||||||
|
empty = MkTop []
|
||||||
|
|
||||||
|
public export
|
||||||
|
claim : TopContext -> String -> Tm -> TopContext
|
||||||
|
claim tc name ty = { defs $= (MkEntry name ty Axiom ::) } tc
|
||||||
|
|
||||||
|
-- TODO update existing, throw, etc.
|
||||||
|
|
||||||
|
public export
|
||||||
|
addDef : TopContext -> String -> Tm -> Tm -> TopContext
|
||||||
|
addDef tc name tm ty = { defs $= (MkEntry name ty (Fn tm) ::) } tc
|
||||||
|
|
||||||
37
src/Main.idr
37
src/Main.idr
@@ -2,6 +2,8 @@ module Main
|
|||||||
|
|
||||||
import Control.App
|
import Control.App
|
||||||
import Data.String
|
import Data.String
|
||||||
|
import Data.Vect
|
||||||
|
import Data.List
|
||||||
import Control.Monad.Error.Interface
|
import Control.Monad.Error.Interface
|
||||||
import Control.Monad.Error.Either
|
import Control.Monad.Error.Either
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
@@ -12,6 +14,7 @@ import Lib.Prettier
|
|||||||
import Lib.Token
|
import Lib.Token
|
||||||
import Lib.Tokenizer
|
import Lib.Tokenizer
|
||||||
import Lib.TT
|
import Lib.TT
|
||||||
|
import Lib.TopContext
|
||||||
import Syntax
|
import Syntax
|
||||||
import Syntax
|
import Syntax
|
||||||
import System
|
import System
|
||||||
@@ -20,38 +23,46 @@ import System.File
|
|||||||
|
|
||||||
{-
|
{-
|
||||||
|
|
||||||
|
- [ ] Replace on define
|
||||||
|
- [ ] more sugar on lambdas
|
||||||
|
|
||||||
|
|
||||||
Currently working through checking of decl / def
|
Currently working through checking of decl / def
|
||||||
|
|
||||||
Running check is awkward. I need a monad stack.
|
Running check is awkward. I need a monad stack.
|
||||||
Main2.idr has an older App attempt without the code below. Retrofit.
|
Main2.idr has an older App attempt without the code below. Retrofit.
|
||||||
|
|
||||||
|
App isn't compatible with javascript (without a way to short circuit
|
||||||
|
the fork foreign function.)
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
|
||||||
M : Type -> Type
|
M : Type -> Type
|
||||||
M = (StateT Context (EitherT String IO))
|
M = (StateT TopContext (EitherT String IO))
|
||||||
|
|
||||||
processDecl : Decl -> M ()
|
processDecl : Decl -> M ()
|
||||||
processDecl (TypeSig nm tm) = do
|
processDecl (TypeSig nm tm) = do
|
||||||
ctx <- get
|
ctx <- get
|
||||||
putStrLn "TypeSig \{nm} \{show tm}"
|
putStrLn "TypeSig \{nm} \{show tm}"
|
||||||
ty <- check ctx tm VU
|
ty <- check ctx empty tm VU
|
||||||
putStrLn "got \{show ty}"
|
putStrLn "got \{show ty}"
|
||||||
let vty = eval ctx.env ty
|
|
||||||
putStrLn "--- \{show $ quote 0 vty}"
|
put $ claim ctx nm ty
|
||||||
put $ extend ctx nm vty
|
|
||||||
|
|
||||||
processDecl (Def nm raw) = do
|
processDecl (Def nm raw) = do
|
||||||
putStrLn "def \{show nm}"
|
putStrLn "def \{show nm}"
|
||||||
ctx <- get
|
ctx <- get
|
||||||
let Just ty = lookup nm ctx.types
|
let Just entry = lookup nm ctx
|
||||||
| Nothing => printLn "skip def \{nm} without Decl"
|
| Nothing => printLn "skip def \{nm} without Decl"
|
||||||
putStrLn "check \{nm} = \{show raw} at \{show $ quote 0 ty}"
|
let (MkEntry name ty Axiom) := entry
|
||||||
Right tm <- pure $ the (Either String Tm) (check ctx raw ty)
|
-- FIXME error
|
||||||
|
| _ => printLn "\{nm} already defined"
|
||||||
|
putStrLn "check \{nm} = \{show raw} at \{show $ ty}"
|
||||||
|
let vty = eval empty ty
|
||||||
|
Right tm <- pure $ the (Either String Tm) (check ctx empty raw vty)
|
||||||
| Left err => printLn err
|
| Left err => printLn err
|
||||||
putStrLn "got \{show tm}"
|
putStrLn "got \{show tm}"
|
||||||
-- XXXXX here I need to update the environment
|
put (addDef ctx nm tm ty)
|
||||||
-- I may want to rework things to have a top environment with names,
|
|
||||||
-- then levels / indices for local stuff.
|
|
||||||
|
|
||||||
|
|
||||||
processDecl decl = putStrLn "skip \{show decl}"
|
processDecl decl = putStrLn "skip \{show decl}"
|
||||||
|
|
||||||
@@ -81,6 +92,6 @@ main' = do
|
|||||||
|
|
||||||
main : IO ()
|
main : IO ()
|
||||||
main = do
|
main = do
|
||||||
foo <- runEitherT $ runStateT TT.empty $ main'
|
foo <- runEitherT $ runStateT empty $ main'
|
||||||
putStrLn "done"
|
putStrLn "done"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user