Skip to content

Commit 8560b55

Browse files
committed
Implement wildcard match pattern (LPWildcard)
Add LPWildcard case to LetPattern types across the codebase. The wildcard pattern `_` now properly matches any value without binding it to a variable, distinguishing it from a regular variable named "_". Changes: - Added LPWildcard to LetPattern in all type definitions (ProgramTypes, RuntimeTypes, WrittenTypes, and Darklang language tools) - Updated parser to recognize `_` as LPWildcard instead of LPVariable - Updated type converters to handle LPWildcard conversion - Updated interpreter to match wildcards without extracting bindings - Added binary serialization support for LPWildcard - Updated pretty printers and semantic tokens for wildcard display - Added comprehensive tests for wildcard patterns in tuples and let bindings - Fixed symbol threading in ProgramTypesToRuntimeTypes to preserve symbols from previous patterns when processing wildcards Closes #5460
1 parent 161c14e commit 8560b55

File tree

22 files changed

+72
-10
lines changed

22 files changed

+72
-10
lines changed

backend/src/LibExecution/Interpreter.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ let rec checkAndExtractLetPattern
2929

3030
match pat, dv with
3131
| LPVariable extractTo, dv -> true, [ (extractTo, dv) ]
32+
| LPWildcard, _ -> true, []
3233
| LPUnit, DUnit -> true, []
3334
| LPTuple(first, second, theRest), DTuple(firstVal, secondVal, theRestVal) ->
3435
match r first firstVal, r second secondVal with

backend/src/LibExecution/ProgramTypes.fs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ type LetPattern =
203203
/// `let x = 1`
204204
| LPVariable of id * name : string
205205

206-
// /// `let _ignored = 1`
207-
// | LPIgnored
206+
/// `let _ = 1`
207+
| LPWildcard of id
208208

209209
// /// let (x) = 1
210210
//| LPParens of inner : LetPattern
@@ -223,6 +223,7 @@ module LetPattern =
223223
let rec symbolsUsed (pattern : LetPattern) : Set<string> =
224224
match pattern with
225225
| LPVariable(_, name) -> Set.singleton name
226+
| LPWildcard _ -> Set.empty
226227
| LPTuple(_, first, second, rest) ->
227228
Set.unionMany
228229
[ symbolsUsed first
@@ -233,6 +234,7 @@ module LetPattern =
233234
let toID (pattern : LetPattern) : id =
234235
match pattern with
235236
| LPVariable(id, _)
237+
| LPWildcard id
236238
| LPTuple(id, _, _, _)
237239
| LPUnit id -> id
238240

backend/src/LibExecution/ProgramTypesToDarkTypes.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ module LetPattern =
327327
let (caseName, fields) =
328328
match p with
329329
| PT.LPVariable(id, name) -> "LPVariable", [ DInt64(int64 id); DString name ]
330+
| PT.LPWildcard id -> "LPWildcard", [ DInt64(int64 id) ]
330331
| PT.LPUnit id -> "LPUnit", [ DInt64(int64 id) ]
331332
| PT.LPTuple(id, first, second, theRest) ->
332333
"LPTuple",
@@ -342,6 +343,7 @@ module LetPattern =
342343
match d with
343344
| DEnum(_, _, [], "LPVariable", [ DInt64 id; DString name ]) ->
344345
PT.LPVariable(uint64 id, name)
346+
| DEnum(_, _, [], "LPWildcard", [ DInt64 id ]) -> PT.LPWildcard(uint64 id)
345347
| DEnum(_, _, [], "LPUnit", [ DInt64 id ]) -> PT.LPUnit(uint64 id)
346348
| DEnum(_,
347349
_,

backend/src/LibExecution/ProgramTypesToRuntimeTypes.fs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,9 @@ module LetPattern =
178178
(p : PT.LetPattern)
179179
: (RT.LetPattern * Map<string, RT.Register> * int) =
180180
match p with
181-
| PT.LPUnit _ -> RT.LPUnit, Map.empty, rc
181+
| PT.LPUnit _ -> RT.LPUnit, symbols, rc
182+
183+
| PT.LPWildcard _ -> RT.LPWildcard, symbols, rc
182184

183185
| PT.LPTuple(_, first, second, theRest) ->
184186
let first, symbols, rc = toRT symbols rc first

backend/src/LibExecution/RTQueryCompiler.fs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ and executeInstruction
421421
=
422422
match p with
423423
| RT.LPVariable extractTo -> st.withReg (extractTo, srcVal)
424+
| RT.LPWildcard -> st
424425
| RT.LPUnit -> st
425426
| RT.LPTuple(first, second, rest) ->
426427
// For tuples, extract elements if srcVal is a literal tuple
@@ -559,7 +560,9 @@ let compileLambda
559560
let lambdaParamReg =
560561
match lambdaImpl.patterns.head with
561562
| RT.LPVariable reg -> reg
562-
| _ -> 0 // Default to 0 if not a simple variable pattern
563+
| RT.LPWildcard -> 0
564+
| RT.LPUnit -> 0
565+
| RT.LPTuple _ -> 0
563566

564567
let initialState =
565568
// Start with DBRow in the lambda parameter register

backend/src/LibExecution/RuntimeTypes.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,8 @@ type LetPattern =
291291
/// `let x = 1`
292292
| LPVariable of extractTo : Register
293293

294-
// /// `let _ = 1`
295-
// | LPIgnored
294+
/// `let _ = 1`
295+
| LPWildcard
296296

297297
/// `let (x, y) = (1, 2)`
298298
| LPTuple of first : LetPattern * second : LetPattern * theRest : List<LetPattern>

backend/src/LibExecution/RuntimeTypesToDarkTypes.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ module LetPattern =
319319
let (caseName, fields) =
320320
match p with
321321
| LPVariable reg -> "LPVariable", [ DInt32 reg ]
322+
| LPWildcard -> "LPWildcard", []
322323
| LPUnit -> "LPUnit", []
323324
| LPTuple(first, second, theRest) ->
324325
"LPTuple",
@@ -331,6 +332,7 @@ module LetPattern =
331332
let rec fromDT (d : Dval) : LetPattern =
332333
match d with
333334
| DEnum(_, _, [], "LPVariable", [ DInt32 reg ]) -> LPVariable(reg)
335+
| DEnum(_, _, [], "LPWildcard", []) -> LPWildcard
334336
| DEnum(_, _, [], "LPUnit", []) -> LPUnit
335337
| DEnum(_, _, [], "LPTuple", [ first; second; DList(_vtTODO, theRest) ]) ->
336338
LPTuple(fromDT first, fromDT second, List.map fromDT theRest)

backend/src/LibParser/FSharpToWrittenTypes.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ module LetPattern =
167167

168168
match pat with
169169
| SynPat.Paren(subPat, _) -> mapPat subPat
170-
| SynPat.Wild(_) -> WT.LPVariable(gid (), "_")
170+
| SynPat.Wild(_) -> WT.LPWildcard(gid ())
171171
| SynPat.Named(SynIdent(name, _), _, _, _) -> WT.LPVariable(gid (), name.idText)
172172
| SynPat.Const(SynConst.Unit, _) -> WT.LPUnit(gid ())
173173

@@ -689,7 +689,7 @@ module Expr =
689689

690690
// Sequential code: (a; b) -> let _ = a in b
691691
| SynExpr.Sequential(_, _, a, b, _) ->
692-
WT.ELet(id, WT.LPVariable(gid (), "_"), c a, c b)
692+
WT.ELet(id, WT.LPWildcard(gid ()), c a, c b)
693693

694694

695695
// Pipes (|>)

backend/src/LibParser/WrittenTypes.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ type UnresolvedEnumTypeName = List<string>
5353
type LetPattern =
5454
| LPUnit of id
5555
| LPVariable of id * name : string
56+
| LPWildcard of id
5657
| LPTuple of
5758
id *
5859
first : LetPattern *

backend/src/LibParser/WrittenTypesToProgramTypes.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ module LetPattern =
128128
// Track this as a local binding to prevent resolving it as a global
129129
localBindings = Set.add varName context.localBindings }
130130
(newContext, PT.LPVariable(id, varName))
131+
| WT.LPWildcard id -> (context, PT.LPWildcard id)
131132
| WT.LPTuple(id, first, second, theRest) ->
132133
let (context1, first') = toPT context first
133134
let (context2, second') = toPT context1 second

0 commit comments

Comments
 (0)