@@ -82,6 +82,78 @@ module Eval =
8282 | _ -> false
8383
8484 let rec private patternMatch ( pat : Pattern ) ( value : Value ) : Env option =
85+ let mergeBindings ( left : Env ) ( right : Env ) : Env option =
86+ let mutable ok = true
87+ let mutable merged = left
88+ for KeyValue( k, v) in right do
89+ match merged.TryFind k with
90+ | Some existing when not ( valueEquals existing v) ->
91+ ok <- false
92+ | Some _ -> ()
93+ | None -> merged <- Map.add k v merged
94+ if ok then Some merged else None
95+
96+ let rec matchMapClauses ( hasExplicitClauses : bool ) ( clauses : ( Pattern * Pattern ) list ) ( tailPattern : Pattern option ) ( remaining : Map < string , Value >) ( envAcc : Env ) : Env option =
97+ let applyTail () =
98+ match tailPattern with
99+ | Some tail ->
100+ match patternMatch tail ( VStringMap remaining) with
101+ | Some tailEnv -> mergeBindings envAcc tailEnv
102+ | None -> None
103+ | None ->
104+ if hasExplicitClauses || remaining.IsEmpty then Some envAcc else None
105+
106+ match clauses with
107+ | [] -> applyTail ()
108+ | ( keyPattern, valuePattern) :: rest ->
109+ match keyPattern with
110+ | PVar ( name, _) when not ( envAcc.ContainsKey name) ->
111+ if remaining.IsEmpty then None
112+ else
113+ let head = remaining |> Seq.head
114+ let key = head.Key
115+ let value = head.Value
116+ let nextRemaining = remaining.Remove key
117+ match patternMatch keyPattern ( VString key), patternMatch valuePattern value with
118+ | Some keyEnv, Some valueEnv ->
119+ match mergeBindings envAcc keyEnv with
120+ | Some merged1 ->
121+ match mergeBindings merged1 valueEnv with
122+ | Some merged2 -> matchMapClauses hasExplicitClauses rest tailPattern nextRemaining merged2
123+ | None -> None
124+ | None -> None
125+ | _ -> None
126+ | PVar ( name, _) ->
127+ match envAcc.TryFind name with
128+ | Some ( VString targetKey) when remaining.ContainsKey targetKey ->
129+ let value = remaining.[ targetKey]
130+ match patternMatch valuePattern value with
131+ | Some valueEnv ->
132+ match mergeBindings envAcc valueEnv with
133+ | Some merged -> matchMapClauses hasExplicitClauses rest tailPattern ( remaining.Remove targetKey) merged
134+ | None -> None
135+ | None -> None
136+ | _ -> None
137+ | _ ->
138+ let tryKey ( kv : System.Collections.Generic.KeyValuePair < string , Value >) : ( string * Env ) option =
139+ match patternMatch keyPattern ( VString kv.Key) with
140+ | Some keyEnv ->
141+ match mergeBindings envAcc keyEnv with
142+ | Some merged1 ->
143+ match patternMatch valuePattern kv.Value with
144+ | Some valueEnv ->
145+ match mergeBindings merged1 valueEnv with
146+ | Some merged2 -> Some ( kv.Key, merged2)
147+ | None -> None
148+ | None -> None
149+ | None -> None
150+ | None -> None
151+
152+ remaining
153+ |> Seq.tryPick tryKey
154+ |> Option.bind ( fun ( matchedKey , mergedEnv ) ->
155+ matchMapClauses hasExplicitClauses rest tailPattern ( remaining.Remove matchedKey) mergedEnv)
156+
85157 match pat, value with
86158 | PWildcard _, _ -> Some Map.empty
87159 | PVar ( name, _), v -> Some ( Map.ofList [ name, v ])
@@ -109,22 +181,8 @@ module Eval =
109181 | Some next -> Some ( Map.fold ( fun state k v -> Map.add k v state) acc next)
110182 | None -> None
111183 | _ -> None)
112- | PMapEmpty _, VStringMap values when values.IsEmpty ->
113- Some Map.empty
114- | PMapCons ( keyPattern, valuePattern, tailPattern, _), VStringMap values when not values.IsEmpty ->
115- let key , value =
116- values
117- |> Seq.head
118- |> fun kv -> kv.Key, kv.Value
119- let tail = VStringMap ( values.Remove key)
120- match patternMatch keyPattern ( VString key), patternMatch valuePattern value, patternMatch tailPattern tail with
121- | Some keyEnv, Some valueEnv, Some tailEnv ->
122- Some
123- ( Map.empty
124- |> Map.fold ( fun acc k v -> Map.add k v acc) keyEnv
125- |> Map.fold ( fun acc k v -> Map.add k v acc) valueEnv
126- |> Map.fold ( fun acc k v -> Map.add k v acc) tailEnv)
127- | _ -> None
184+ | PMap ( clauses, tailPattern, _), VStringMap values ->
185+ matchMapClauses ( not clauses.IsEmpty) clauses tailPattern values Map.empty
128186 | PSome ( p, _), VOption ( Some v) ->
129187 patternMatch p v
130188 | PNone _, VOption None -> Some Map.empty
0 commit comments