Skip to content

Commit

Permalink
Support pattern matching on Var
Browse files Browse the repository at this point in the history
  • Loading branch information
tekknolagi committed Nov 22, 2023
1 parent e6fcb32 commit 203b124
Showing 1 changed file with 36 additions and 4 deletions.
40 changes: 36 additions & 4 deletions scrapscript.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,12 +542,13 @@ class MatchError(Exception):
pass


def match(obj: Object, pattern: Object) -> bool:
def match(obj: Object, pattern: Object) -> bool | Env:
if isinstance(pattern, Int):
return isinstance(obj, Int) and obj.value == pattern.value
if isinstance(pattern, String):
return isinstance(obj, String) and obj.value == pattern.value
# TODO: Handle match condition with var pattern
if isinstance(pattern, Var):
return {pattern.name: obj}
raise NotImplementedError("TODO: match")


Expand Down Expand Up @@ -605,8 +606,14 @@ def eval(env: Env, exp: Object) -> Object:
# TODO(max): Implement MatchClosure
arg = eval(env, exp.arg)
for case in callee.func.cases:
if match(arg, case.pattern):
return eval(env, case.body)
m = match(arg, case.pattern)
if isinstance(m, bool):
if m:
return eval(env, case.body)
else:
continue
assert isinstance(m, dict)
return eval({**env, **m}, case.body)
raise MatchError("no matching cases")
else:
raise TypeError(f"attempted to apply a non-function of type {type(callee.func).__name__}")
Expand Down Expand Up @@ -1497,6 +1504,31 @@ def test_simple_int_match(self) -> None:
Int(3),
)

def test_match_var_binds_var(self) -> None:
self.assertEqual(
self._run(
"""
id 3
. id =
| x -> x
"""
),
Int(3),
)

def test_match_var_binds_first_arm(self) -> None:
self.assertEqual(
self._run(
"""
id 3
. id =
| x -> x
| y -> y * 2
"""
),
Int(3),
)

def test_pipe(self) -> None:
self.assertEqual(self._run("1 |> (a -> a + 2)"), Int(3))

Expand Down

0 comments on commit 203b124

Please sign in to comment.