Skip to content

Commit 52eceba

Browse files
committed
Stash old idea: Add interpreter for a Direct Calc
Includes an attempt at typing. Not planning to pursue this further.
1 parent 9b998c6 commit 52eceba

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed

DirectCalc.hs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
{-# LANGUAGE NoMonomorphismRestriction, TupleSections #-}
2+
module DirectCalc where
3+
4+
import qualified Data.Map as M
5+
import Data.Maybe
6+
import Control.Monad.State
7+
import Control.Monad.Error
8+
9+
type Ident = String
10+
type Arity = Int
11+
type EnvKey = Arity
12+
type Env = [Value]
13+
data Name = Free Ident | Bound EnvKey
14+
deriving (Show, Eq, Ord)
15+
16+
data Term =
17+
Type | Arrow Term Term | Ann Term Term |
18+
Var Name | App Term Term | Lam Term
19+
deriving (Show, Eq)
20+
21+
data Neutral = NVar Ident | NApp Neutral Value
22+
deriving (Show, Eq)
23+
24+
type Closure = (Env, Term)
25+
data Value = VNeut Neutral | VClo Closure | VType | VArrow Value Value
26+
deriving (Show, Eq)
27+
28+
vvar (Free ident) env = VNeut $ NVar ident
29+
vvar (Bound key) env = env !! key
30+
vapp (VNeut neutral) arg = VNeut $ NApp neutral arg
31+
vapp (VClo (cenv, cbody)) arg = bigstep cbody $ arg : cenv
32+
33+
bigstep (Var name) env = vvar name env
34+
bigstep (App tproc targ) env = vapp proc arg
35+
where proc = bigstep tproc env
36+
arg = bigstep targ env
37+
bigstep (Lam body) env = VClo (env, body)
38+
39+
data TContext = TContext{tc_tvars :: M.Map EnvKey Term,
40+
tc_bvars :: M.Map Name [Term],
41+
tc_nextFresh :: EnvKey}
42+
tc_fresh = do
43+
cxt <- get
44+
let fresh = tc_nextFresh cxt
45+
put $ cxt{tc_nextFresh = fresh + 1}
46+
return $ Var $ Bound fresh
47+
tc_bvarFresh name = do
48+
fresh <- tc_fresh
49+
cxt <- get
50+
let tys = fresh : (maybe [] id $ M.lookup name $ tc_bvars cxt)
51+
put $ cxt{tc_bvars = M.insert name tys $ tc_bvars cxt}
52+
return fresh
53+
tc_find key = do
54+
cxt <- get
55+
let (term, tvars) = _find (tc_tvars cxt) key []
56+
put $ cxt{tc_tvars = tvars}
57+
return term
58+
where
59+
_find tvars key accKeys = case M.lookup key tvars of
60+
Just (Var (Bound next)) -> _find tvars next $ key : accKeys
61+
Just term -> (term, merge term)
62+
Nothing -> (vkey, merge vkey)
63+
where vkey = Var $ Bound key
64+
merge term = M.union tvars $ M.fromList $ map (, term) accKeys
65+
tc_assign key term = do
66+
cxt <- get
67+
put $ cxt{tc_tvars = M.insert key term $ tc_tvars cxt}
68+
69+
subterms (Arrow ta tb) = [ta, tb]
70+
subterms (App ta tb) = [ta, tb]
71+
subterms (Ann ta tb) = [ta, tb]
72+
subterms (Lam body) = [body]
73+
subterms _ = []
74+
75+
occurs name (Var vname) = name == vname
76+
occurs name term = any (occurs name) $ subterms term
77+
78+
sunify (Ann ta tb) other = liftM (Ann ta) $ sunify tb other
79+
sunify other ann@(Ann ta' tb') = sunify ann other
80+
sunify (Var (Free _)) _ = error "something went wrong"
81+
sunify tvar@(Var (Bound key)) other = do
82+
term <- tc_find key
83+
if tvar == term
84+
then if occurs (Bound key) term
85+
then throwError $ "occurs check failed: " ++ show (key, term)
86+
else tc_assign key term >> return term
87+
else sunify term other
88+
sunify other (Var name) = sunify (Var name) other
89+
sunify Type Type = return Type
90+
sunify (Arrow ta tb) (Arrow ta' tb') =
91+
liftM2 Arrow (sunify ta ta') $ sunify tb tb'
92+
-- TODO: reduce apps and inside lambdas for non-simple unify
93+
sunify (App ta tb) (App ta' tb') = liftM2 App (sunify ta ta') $ sunify tb tb'
94+
sunify (Lam body) (Lam body') = liftM Lam $ sunify body body'
95+
sunify ta tb = throwError $ "type mismatch: " ++ show (ta, tb)
96+
97+
--sunifyE lenv renv = undefined
98+
99+
sbvar name = do
100+
cxt <- get
101+
let bvars = tc_bvars cxt
102+
case M.lookup name bvars of
103+
Nothing -> tc_bvarFresh name
104+
Just (ty : tys) -> do
105+
final <- foldM sunify ty tys
106+
put $ cxt{tc_bvars = M.insert name [final] bvars}
107+
return final
108+
109+
bigtype Type = return Type
110+
bigtype (Arrow ta tb) = bigtype ta >> bigtype tb >> return Type
111+
bigtype (Ann term ty) =
112+
bigtype ty >>= sunify Type >> bigtype term >>= sunify ty >> return ty
113+
bigtype (Var name) = tc_bvarFresh name
114+
bigtype (Lam body) = do -- TODO: how to quantify? free var dependencies?
115+
tbody <- bigtype body
116+
targ <- sbvar $ Bound 0
117+
return $ Arrow targ tbody
118+
119+
{-bigtype (App proc arg) = (tyRes, env')-}
120+
{-where (tyProc, penv) = bigtype proc-}
121+
{-(tyArg, aenv) = bigtype arg-}
122+
{-tyRes = undefined -- create fresh var-}
123+
{-tenv = sunify tyProc $ Arrow tyArg tyRes-}
124+
{-env = sunifyE penv aenv-}
125+
{-env' = sunifyE env tenv-}
126+
127+
-- data TermD_ lterm rterm =

0 commit comments

Comments
 (0)