Skip to content

Commit 0f6dcd4

Browse files
committed
Add wildcard _ in tuple patterns for match
`match p of (0, _): ...; (_, 0): ...;` - per-field AND chain, wildcard fields skipped. Single-element `(expr)` treated as parenthesized expression, not tuple.
1 parent e73e990 commit 0f6dcd4

1 file changed

Lines changed: 81 additions & 12 deletions

File tree

compiler/pstatmnt.pas

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -434,25 +434,94 @@ implementation
434434

435435
function parse_branch_cond(has_subject:boolean;subject:tnode) : tnode;
436436
{ Parse pattern(s) for a branch. Subject mode supports comma-separated
437-
patterns (OR'd). }
437+
patterns (OR'd) and tuple patterns with _ wildcards. }
438438
var
439-
pat : tnode;
439+
pat,cond : tnode;
440+
fields : array of tnode;
441+
fieldcount,i,symidx : integer;
442+
sym : tsym;
443+
recdef : trecorddef;
440444
begin
441-
pat:=comp_expr([ef_accept_equal]);
442-
do_typecheckpass(pat);
443-
if has_subject then
445+
{ tuple pattern with potential _ wildcards }
446+
if has_subject and (current_scanner.token=_LKLAMMER) and
447+
assigned(subject.resultdef) and (subject.resultdef.typ=recorddef) and
448+
(df_tuple in subject.resultdef.defoptions) then
444449
begin
445-
result:=caddnode.create(equaln,subject.getcopy,pat);
446-
while try_to_consume(_COMMA) do
450+
consume(_LKLAMMER);
451+
fieldcount:=0;
452+
setlength(fields,8);
453+
repeat
454+
if fieldcount>=length(fields) then
455+
setlength(fields,fieldcount*2);
456+
if (current_scanner.token=_ID) and (current_scanner.pattern='_') then
457+
begin
458+
fields[fieldcount]:=nil;
459+
consume(_ID);
460+
end
461+
else
462+
begin
463+
fields[fieldcount]:=comp_expr([ef_accept_equal]);
464+
do_typecheckpass(fields[fieldcount]);
465+
end;
466+
inc(fieldcount);
467+
until not try_to_consume(_COMMA);
468+
{ single expression in parens = parenthesized expr, not tuple }
469+
if fieldcount=1 then
470+
begin
471+
consume(_RKLAMMER);
472+
if fields[0]=nil then
473+
result:=cordconstnode.create(1,pasbool1type,false)
474+
else
475+
result:=caddnode.create(equaln,subject.getcopy,fields[0]);
476+
exit;
477+
end;
478+
consume(_RKLAMMER);
479+
{ build per-field AND chain, skipping wildcards }
480+
recdef:=trecorddef(subject.resultdef);
481+
cond:=nil;
482+
i:=0;
483+
for symidx:=0 to recdef.symtable.symlist.count-1 do
447484
begin
448-
pat:=comp_expr([ef_accept_equal]);
449-
do_typecheckpass(pat);
450-
result:=caddnode.create(orn,result,
451-
caddnode.create(equaln,subject.getcopy,pat));
485+
sym:=tsym(recdef.symtable.symlist[symidx]);
486+
if sym.typ<>fieldvarsym then
487+
continue;
488+
if i>=fieldcount then
489+
break;
490+
if fields[i]<>nil then
491+
begin
492+
pat:=caddnode.create(equaln,
493+
csubscriptnode.create(tfieldvarsym(sym),subject.getcopy),
494+
fields[i]);
495+
if cond=nil then
496+
cond:=pat
497+
else
498+
cond:=caddnode.create(andn,cond,pat);
499+
end;
500+
inc(i);
452501
end;
502+
if cond=nil then
503+
cond:=cordconstnode.create(1,pasbool1type,false);
504+
result:=cond;
453505
end
454506
else
455-
result:=pat;
507+
begin
508+
{ normal pattern with optional comma-separated OR }
509+
pat:=comp_expr([ef_accept_equal]);
510+
do_typecheckpass(pat);
511+
if has_subject then
512+
begin
513+
result:=caddnode.create(equaln,subject.getcopy,pat);
514+
while try_to_consume(_COMMA) do
515+
begin
516+
pat:=comp_expr([ef_accept_equal]);
517+
do_typecheckpass(pat);
518+
result:=caddnode.create(orn,result,
519+
caddnode.create(equaln,subject.getcopy,pat));
520+
end;
521+
end
522+
else
523+
result:=pat;
524+
end;
456525
end;
457526

458527
var

0 commit comments

Comments
 (0)