Skip to content

Commit 9b998c6

Browse files
committed
Stash an old idea: Prepare for a pi-sigma calc
Start simply typed. Not planning to pursue this idea further.
1 parent d66e4ac commit 9b998c6

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed

PiSig.hs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
{-# LANGUAGE NamedFieldPuns #-}
2+
module PiSig where
3+
4+
-- loosely based on http://www.andres-loeh.de/LambdaPi/
5+
6+
import Control.Monad.Error
7+
8+
infixl 3 :@:
9+
10+
type BName = Int
11+
data FName = Global String | Local BName | Quote BName
12+
deriving (Show, Eq)
13+
14+
-- start simply typed
15+
data Ty = TyFree FName | TyArrow Ty Ty
16+
deriving (Show, Eq)
17+
data TermInfer = Ann TermCheck Ty | Bound BName | Free FName | TermInfer :@: TermCheck
18+
deriving (Show, Eq)
19+
data TermCheck = Infer TermInfer | Lam TermCheck
20+
deriving (Show, Eq)
21+
data Neutral = NFree FName | NApp Neutral Value
22+
deriving (Show, Eq)
23+
data Value = VNeut Neutral | VClo Closure
24+
deriving (Show, Eq)
25+
26+
data Code = CClo [Code] | CLit Value | CRef BName | CApp
27+
deriving (Show, Eq)
28+
type Env = [Value]
29+
type Closure = (Env, [Code])
30+
31+
data State = State {s_code :: [Code], s_env, s_stack :: Env, s_cont :: Maybe State}
32+
s_init codes = State {s_code = codes, s_env = [], s_stack = [], s_cont = Nothing}
33+
s_push st val = st{s_stack = val : s_stack st}
34+
s_pop st@State {s_stack = val : vals} = (val, st{s_stack = vals})
35+
s_lookup State {s_env} bname = s_env !! bname
36+
s_isFinal State {s_code = [], s_cont = Nothing} = True
37+
s_isFinal _ = False
38+
s_ret st
39+
| not (s_isFinal st) && null (s_code st) = s_cont st
40+
| otherwise = Just st
41+
s_next st@State {s_code = code : codes} = (code, st{s_code = codes})
42+
-- TODO: assert empty code implies empty stack?
43+
s_step State {s_code = [], s_stack = [val], s_cont = Just st'} = s_push st' val
44+
s_step st@State {s_code = code : codes} = exec code st{s_code = codes}
45+
46+
vfree n = VNeut (NFree n)
47+
vapp st (VNeut neutral) arg = s_push st $ VNeut (NApp neutral arg)
48+
vapp st (VClo (env, codes)) arg = State codes (arg : env) [] $ s_ret st
49+
50+
exec (CClo codes) st@State {s_env} = s_push st $ VClo (s_env, codes)
51+
exec (CLit val) st = s_push st val
52+
exec (CRef bname) st = s_push st $ s_lookup st bname
53+
exec CApp st = vapp st'' proc arg
54+
where
55+
(proc, st') = s_pop st
56+
(arg, st'') = s_pop st'
57+
58+
eval = dropWhile (not . s_isFinal) . iterate s_step
59+
60+
data Kind = Star
61+
deriving (Show)
62+
data Info = HasKind Kind | HasType Ty
63+
deriving (Show)
64+
type Context = [(FName, Info)]
65+
cxt_lookup cxt name = case lookup name cxt of
66+
Just info -> return info
67+
Nothing -> throwError "unknown identifier"
68+
69+
kind cxt (TyFree name) Star = do
70+
HasKind Star <- cxt_lookup cxt name
71+
return ()
72+
kind cxt (TyArrow tyProc tyArg) Star = kind cxt tyProc Star >> kind cxt tyArg Star
73+
74+
typeInfer level cxt (Ann term ty) =
75+
kind cxt ty Star >> typeCheck level cxt term ty >> return ty
76+
typeInfer level cxt (Free name) = do
77+
HasType ty <- cxt_lookup cxt name
78+
return ty
79+
typeInfer level cxt (proc :@: arg) = do
80+
tyProc <- typeInfer level cxt proc
81+
case tyProc of
82+
TyArrow tyArg tyRes -> typeCheck level cxt arg tyArg >> return tyRes
83+
_ -> throwError $ "applying non-proc type: " ++ show tyProc
84+
typeCheck level cxt (Infer term) ty = do
85+
ty' <- typeInfer level cxt term
86+
unless (ty == ty') $ throwError $ "expected type '" ++ show ty ++ "' but inferred: " ++ show ty'
87+
typeCheck level cxt (Lam term) (TyArrow tyArg tyRes) = typeCheck (level + 1)
88+
((Local level, HasType tyArg) : cxt) (substCheck 0 (Free (Local level)) term) tyRes
89+
typeCheck _ _ _ _ = throwError "type error"
90+
91+
substInfer = undefined -- level
92+
substCheck = undefined
93+
94+
quote level (VClo (env, codes)) = undefined
95+
quote level (VNeut neutral) = Infer (neutQuote level neutral)
96+
neutQuote level (NFree name) = boundFree level name
97+
neutQuote level (NApp neut arg) = neutQuote level neut :@: quote level arg
98+
99+
boundFree level (Quote depth) = Bound (level - depth - 1)
100+
boundFree level name = Free name

0 commit comments

Comments
 (0)