summaryrefslogtreecommitdiff
path: root/lambda-calcul/haskell/src/Minilang/Lambda.hs
blob: d2236580204b9e0a141276a70a80ba4d18c17419 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
module Minilang.Lambda where

import Data.Bifunctor (second)
import Minilang.Lambda.DeBruijn (eval, eval', fromDeBruijn, toDeBruijn)
import Minilang.Lambda.Eval (Env, Term)
import Minilang.Lambda.Infer (Context, TypeError, infer)
import Minilang.Lambda.Parser (AST (..), desugar)
import Minilang.Lambda.Unify (Type (..))
import Minilang.REPL.Types (Language (..))

-- | Top-level evaluator
-- Load a list of expressions into given `Env` and `Context`, returning an extended
-- `Env` and `Context` with declarations bound and the list of evaluated top-level
-- terms along with their types.
loadProgram ::
  Language ->
  Env ->
  Context ->
  [AST] ->
  Either TypeError ([(Term, Type)], Env, Context)
loadProgram language env context exprs =
  fmap (\(res, e, c) -> (reverse res, e, c)) result
  where
    result =
      foldl
        ( \acc expr ->
            case acc of
              Left typeError -> Left typeError
              Right (results, env', context') ->
                case runExpr language expr env' context' of
                  Left typeError -> Left typeError
                  Right (Nothing, env'', context'') ->
                    Right (results, env'', context'')
                  Right (Just res, env'', context'') ->
                    Right (res : results, env'', context'')
        )
        (Right ([], env, context))
        exprs

    runExpr language (Def ident body) env context =
      let term = desugar body
       in case language of
            Typed ->
              case infer term of
                Left typeError -> Left typeError
                Right typ ->
                  Right (Nothing, (ident, term) : env, context)
            Untyped ->
              Right (Nothing, (ident, term) : env, context)
    runExpr language expr env context =
      let term = desugar expr
          env' = second toDeBruijn <$> env
          v = fromDeBruijn $ eval' env' (toDeBruijn term)
       in case language of
            Typed ->
              case infer term of
                Left typeError -> Left typeError
                Right typ ->
                  Right (Just (v, typ), env, context)
            Untyped ->
              Right (Just (v, TyVar "<?>"), env, context)