summaryrefslogtreecommitdiffstats
path: root/Elab.sml
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2025-01-22 19:45:12 -0800
committerRose Hogenson <rosehogenson@posteo.net>2025-05-18 08:11:25 -0700
commite5034d3a668fbf0a4367bb582d759ba82b5576a3 (patch)
treeb0b658d254fe6a710183e60e792bb068263e77df /Elab.sml
parentUse code generation for printing the AST (diff)
downloadsml-e5034d3a668fbf0a4367bb582d759ba82b5576a3.tar.zst
Support struct expressions
Diffstat (limited to 'Elab.sml')
-rw-r--r--Elab.sml47
1 files changed, 33 insertions, 14 deletions
diff --git a/Elab.sml b/Elab.sml
index 60760cd..74e331b 100644
--- a/Elab.sml
+++ b/Elab.sml
@@ -186,6 +186,7 @@ struct
in (patterns, occurrences, actions)
end
+ (* https://compiler.club/compiling-pattern-matching/ *)
fun compilePatternMatching (env : env) ([] : Syntax.pat list list, _ : Syntax.lexp list, _ : Syntax.lexp list) : Syntax.lexp =
raise Fail "nonexhaustive match"
| compilePatternMatching env (patterns as firstRow :: rows, occurrences, actions) =
@@ -245,12 +246,21 @@ struct
fun structBoundVars (decls : Syntax.dec list) : string list = List.concatMap declBoundVars decls
- fun bindStructType (name : string) (decls : Syntax.dec list) (Env env) : env =
+ fun bindStruct (name : string) (structEnv : env) (Env { vars, types, structTypes }) : env =
+ Env { vars = vars, types = types, structTypes = StringMap.insert name structEnv structTypes }
+
+ fun bindStructType (name : string) (decls : Syntax.dec list) (env : env) : env =
let
val structEnv =
foldl
(fn (Syntax.DDatatype (_, cons), env) => bindDataCons cons env
- | (Syntax.DStruct (name, decls), env) => bindStructType name decls env
+ | (Syntax.DStruct (name, Syntax.SStruct decls), env) => bindStructType name decls env
+ | (Syntax.DStruct (name, Syntax.SIdent ident), env) =>
+ let
+ fun lookup [name] env = lookupStructType name env
+ | lookup (name :: names) env = lookup names (lookupStructType name env)
+ | lookup _ _ = raise Fail "invalid struct identifier"
+ in lookup ident env end
| (_, env) => env)
emptyEnv
decls
@@ -260,7 +270,7 @@ struct
structEnv
(enumerate (structBoundVars decls))
in
- Env { vars = #vars env, types = #types env, structTypes = StringMap.insert name structEnv (#structTypes env) }
+ bindStruct name structEnv env
end
fun actionVector (env : env) (expr : Syntax.lexp) (arms : (Syntax.pat * Syntax.expr) list) : Syntax.lexp list =
@@ -313,8 +323,7 @@ struct
fun go env [i] acc = Syntax.LSelect (lookupVar i env, acc)
| go env (accessor :: accessors) acc =
let val env = lookupStructType accessor env
- in go env accessors (Syntax.LSelect (lookupVar accessor env, acc))
- end
+ in go env accessors (Syntax.LSelect (lookupVar accessor env, acc)) end
| go _ [] _ = raise Fail "go empty"
in go env accessors s
end
@@ -395,25 +404,35 @@ struct
]
, elab env (Syntax.ELet (decls, body))
)
- end
- end
- | Syntax.ELet (Syntax.DStruct (name, structDecls) :: decls, body) =>
+ end end
+ | Syntax.ELet (Syntax.DStruct (name, Syntax.SStruct structDecls) :: decls, body) =>
let
val names = structBoundVars structDecls
val tuple = elab env (Syntax.ELet (structDecls, Syntax.ETuple (map (fn n => Syntax.EIdent [n]) names)))
val v = GenSym.new ()
val env = bindStructType name structDecls env
val env = bindVar name v env
- in Syntax.LApp (Syntax.LFn (v, elab env (Syntax.ELet (decls, body))), tuple)
- end
+ in Syntax.LApp (Syntax.LFn (v, elab env (Syntax.ELet (decls, body))), tuple) end
+ | Syntax.ELet (Syntax.DStruct (name, Syntax.SIdent (structName :: accessors)) :: decls, body) =>
+ let
+ val s = Syntax.LVar (lookupVar structName env)
+ fun go env [] acc = (env, acc)
+ | go env (accessor :: accessors) acc =
+ go
+ (lookupStructType accessor env)
+ accessors
+ (Syntax.LSelect (lookupVar accessor env, acc))
+ val (structEnv, structExpr) = go (lookupStructType structName env) accessors s
+ val v = GenSym.new ()
+ val env = bindStruct name structEnv env
+ val env = bindVar name v env
+ in Syntax.LApp (Syntax.LFn (v, elab env (Syntax.ELet (decls, body))), structExpr) end
| Syntax.ELambda body =>
let val v = GenSym.new ()
- in Syntax.LFn (v, elabCase env (Syntax.LVar v) [body])
- end
+ in Syntax.LFn (v, elabCase env (Syntax.LVar v) [body]) end
| Syntax.ECase (expr, arms) =>
let val v = GenSym.new ()
- in Syntax.LApp (Syntax.LFn (v, elabCase env (Syntax.LVar v) arms), elab env expr)
- end
+ in Syntax.LApp (Syntax.LFn (v, elabCase env (Syntax.LVar v) arms), elab env expr) end
fun elaborate (p : Syntax.expr) : Syntax.lexp = elab emptyEnv p
end