Skip to content

Commit e25d16f

Browse files
author
Thomas Mahler
committed
get rid of old compiler
1 parent e4ba80d commit e25d16f

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

src/CCC/CompilerNaive.hs

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
{-# LANGUAGE GADTs #-}
2+
{-# LANGUAGE LambdaCase #-}
3+
{-# LANGUAGE ScopedTypeVariables #-}
4+
5+
-- | Naive (explicit CatExpr) compilation — no NBE.
6+
module CCC.CompilerNaive
7+
( compileNumExprNaive,
8+
compileEnvironmentNaive,
9+
tryCompileVarNaive,
10+
compileNumericBindingsNaive,
11+
) where
12+
13+
import CCC.CatExpr (CatExpr (..))
14+
import CCC.Cat (fanC)
15+
import CCC.Compiler (RVal (..), IntArgs (..), SomeIntArgs (..),
16+
compileRecBuiltin, collectLams, mkIntArgs,
17+
buildRecFun, argProjections, tupleFromExprs,
18+
expectRInt)
19+
import Parser (Environment, Expr (..))
20+
21+
-- | Naive CCC compilation: builds explicit CatExpr nodes directly.
22+
-- Unlike compileNumExpr (which uses NBE with Haskell closures for
23+
-- beta-reduction), this compiles into the RVal domain from a unit
24+
-- context, producing explicit Comp/fanC/Apply nodes at every step.
25+
--
26+
-- For first-order integer programs (no higher-order function passing),
27+
-- the output is identical to the NBE version — NBE only gains an
28+
-- advantage for higher-order terms where it can beta-reduce at compile time.
29+
compileNumExprNaive :: Environment -> Expr -> CatExpr () Integer
30+
compileNumExprNaive env expr =
31+
case compileNaive env [] expr of
32+
Right (RInt e) -> e
33+
Right _ -> error "Naive compilation: expected integer result"
34+
Left err -> error ("Naive compilation failed: " ++ err)
35+
36+
-- Direct CatExpr compilation (no NBE).
37+
-- Uses the same RVal machinery as compileRecExpr but starts from any context.
38+
-- Builtins are RFun closures (primitives), user-level code builds explicit nodes.
39+
--
40+
-- Key difference from compileExpr (NBE):
41+
-- NBE: Lam → Haskell closure; App → Haskell application (beta-reduces)
42+
-- Naive: Lam → RFun closure; App → RFun application (same node building)
43+
-- For first-order programs, both produce identical CatExpr output because
44+
-- builtins build the same Comp/fanC nodes. The difference appears only
45+
-- with higher-order terms where NBE can beta-reduce at compile time.
46+
compileNaive :: forall c. Environment -> [(String, RVal c)] -> Expr -> Either String (RVal c)
47+
compileNaive env local = \case
48+
Int i -> Right (RInt (IntConst i))
49+
Var name ->
50+
case lookup name local of
51+
Just v -> Right v
52+
Nothing -> compileNaiveVar name
53+
App fixHead stepExpr
54+
| isNaiveFixOp env local fixHead -> compileNaiveFix env stepExpr
55+
Lam param body ->
56+
Right (RFun (\arg -> compileNaive env ((param, arg) : local) body))
57+
App f x -> do
58+
fVal <- compileNaive env local f
59+
xVal <- compileNaive env local x
60+
applyNaiveVal fVal xVal
61+
where
62+
compileNaiveVar name =
63+
case lookup name env of
64+
Just expr -> compileNaive env local expr
65+
Nothing -> case compileRecBuiltin name of
66+
Just v -> Right v
67+
Nothing -> Left ("Unbound variable: " ++ name)
68+
69+
applyNaiveVal (RFun fn) x = fn x
70+
applyNaiveVal _ _ = Left "Cannot apply non-function value"
71+
72+
isNaiveFixOp :: Environment -> [(String, RVal c)] -> Expr -> Bool
73+
isNaiveFixOp env local = go []
74+
where
75+
go _ (Int _) = False
76+
go _ (Lam _ _) = False
77+
go _ (App _ _) = False
78+
go seen (Var name)
79+
| name `elem` map fst local = False
80+
| name == "y" || name == "fix" = True
81+
| name `elem` seen = False
82+
| otherwise =
83+
case lookup name env of
84+
Just expr -> go (name : seen) expr
85+
Nothing -> False
86+
87+
compileNaiveFix :: forall c. Environment -> Expr -> Either String (RVal c)
88+
compileNaiveFix env = \case
89+
Lam fName stepExpr ->
90+
case collectLams stepExpr of
91+
(params, body) ->
92+
case mkIntArgs (length params) of
93+
Just (SomeIntArgs args) -> compileNaiveFixGeneric env args fName params body
94+
Nothing -> Left "fix expects at least one integer argument"
95+
_ -> Left "fix expects a lambda step function"
96+
97+
compileNaiveFixGeneric ::
98+
forall c input.
99+
Environment ->
100+
IntArgs input ->
101+
String ->
102+
[String] ->
103+
Expr ->
104+
Either String (RVal c)
105+
compileNaiveFixGeneric env args fName params body = buildCurried args []
106+
where
107+
buildCurried :: IntArgs remaining -> [CatExpr c Integer] -> Either String (RVal c)
108+
buildCurried OneArg acc =
109+
Right $ RFun $ \case
110+
RInt arg -> applyNaiveFix (acc ++ [arg])
111+
_ -> Left "fix expects Integer argument"
112+
buildCurried (MoreArgs rest) acc =
113+
Right $ RFun $ \case
114+
RInt arg -> buildCurried rest (acc ++ [arg])
115+
_ -> Left "fix expects Integer argument"
116+
117+
applyNaiveFix :: [CatExpr c Integer] -> Either String (RVal c)
118+
applyNaiveFix actualArgs = do
119+
paramTuple <- tupleFromExprs args actualArgs
120+
recFun <- buildRecFun args
121+
let fixLocal =
122+
(fName, recFun) :
123+
zipWith (\name proj -> (name, RInt proj)) params (argProjections args Snd)
124+
stepBody <- compileNaive env fixLocal body >>= expectRInt "Recursive body must compile to Integer"
125+
Right (RInt (Comp (Fix stepBody) paramTuple))
126+
127+
compileNaiveIntExpr :: Environment -> Expr -> Either String (CatExpr () Integer)
128+
compileNaiveIntExpr env expr =
129+
case compileNaive env [] expr of
130+
Right (RInt e) -> Right e
131+
Right _ -> Left "Expected integer expression"
132+
Left err -> Left err
133+
134+
-- | Compile an expression, extracting environment variables to morphisms.
135+
compileEnvironmentNaive :: Environment -> [(String, String)]
136+
compileEnvironmentNaive env = map compileBinding env
137+
where
138+
compileBinding (name, expr) =
139+
case compileNaive env [] expr of
140+
Right (RInt cat) -> (name, show cat)
141+
Right (RSel cat) -> (name, show cat)
142+
Right (RFun _) -> (name, "<lambda function>")
143+
Left err -> (name, "<compile error: " ++ err ++ ">")
144+
145+
-- | Try to compile an environment variable to a numeric morphism.
146+
tryCompileVarNaive :: Environment -> String -> Either String (CatExpr () Integer)
147+
tryCompileVarNaive env name =
148+
case lookup name env of
149+
Just expr ->
150+
case compileNaiveIntExpr env expr of
151+
Right cat -> Right cat
152+
Left err -> Left $ "Expected numeric value for '" ++ name ++ "', got: " ++ err
153+
Nothing -> Left $ "Variable '" ++ name ++ "' not found in environment"
154+
155+
-- | Compile all numeric definitions in an environment.
156+
compileNumericBindingsNaive :: Environment -> ([(String, String)], [String])
157+
compileNumericBindingsNaive env =
158+
let results = map (\(name, _expr) -> (name, tryCompileVarNaive env name)) env
159+
successes = [(n, show m) | (n, Right m) <- results]
160+
failures = [e | (_, Left e) <- results]
161+
in (successes, failures)

0 commit comments

Comments
 (0)