================================================================================ Matching specific values ================================================================================ match command.split(): case ["quit"]: print("Goodbye!") quit_game() case ["look"]: current_room.describe() case ["get", obj]: character.get(obj, current_room) case ["go", direction]: current_room = current_room.neighbor(direction) # The rest of your commands go here -------------------------------------------------------------------------------- (module (match_statement (call (attribute (identifier) (identifier)) (argument_list)) (block (case_clause (case_pattern (list_pattern (case_pattern (string (string_start) (string_content) (string_end))))) (block (expression_statement (call (identifier) (argument_list (string (string_start) (string_content) (string_end))))) (expression_statement (call (identifier) (argument_list))))) (case_clause (case_pattern (list_pattern (case_pattern (string (string_start) (string_content) (string_end))))) (block (expression_statement (call (attribute (identifier) (identifier)) (argument_list))))) (case_clause (case_pattern (list_pattern (case_pattern (string (string_start) (string_content) (string_end))) (case_pattern (dotted_name (identifier))))) (block (expression_statement (call (attribute (identifier) (identifier)) (argument_list (identifier) (identifier)))))) (case_clause (case_pattern (list_pattern (case_pattern (string (string_start) (string_content) (string_end))) (case_pattern (dotted_name (identifier))))) (block (expression_statement (assignment (identifier) (call (attribute (identifier) (identifier)) (argument_list (identifier))))))) (comment)))) ================================================================================ Matching multiple values ================================================================================ match command.split(): case ["drop", *objects]: for obj in objects: character.drop(obj, current_room) -------------------------------------------------------------------------------- (module (match_statement (call (attribute (identifier) (identifier)) (argument_list)) (block (case_clause (case_pattern (list_pattern (case_pattern (string (string_start) (string_content) (string_end))) (case_pattern (splat_pattern (identifier))))) (block (for_statement (identifier) (identifier) (block (expression_statement (call (attribute (identifier) (identifier)) (argument_list (identifier) (identifier))))))))))) ================================================================================ Adding a wild card ================================================================================ match command.split(): # ^ conditional case ["quit"]: ... # Code omitted for brevity case ["go", direction]: pass case ["drop", *objects]: pass case _: print(f"Sorry, I couldn't understand {command!r}") -------------------------------------------------------------------------------- (module (match_statement (call (attribute (identifier) (identifier)) (argument_list)) (block (comment) (case_clause (case_pattern (list_pattern (case_pattern (string (string_start) (string_content) (string_end))))) (block (expression_statement (ellipsis)) (comment))) (case_clause (case_pattern (list_pattern (case_pattern (string (string_start) (string_content) (string_end))) (case_pattern (dotted_name (identifier))))) (block (pass_statement))) (case_clause (case_pattern (list_pattern (case_pattern (string (string_start) (string_content) (string_end))) (case_pattern (splat_pattern (identifier))))) (block (pass_statement))) (case_clause (case_pattern) (block (expression_statement (call (identifier) (argument_list (string (string_start) (string_content) (interpolation (identifier) (type_conversion)) (string_end)))))))))) ================================================================================ Or patterns ================================================================================ match command.split(): case ["north"] | ["go", "north"]: current_room = current_room.neighbor("north") case ["get", obj] | ["pick", "up", obj] | ["pick", obj, "up"]: pass -------------------------------------------------------------------------------- (module (match_statement (call (attribute (identifier) (identifier)) (argument_list)) (block (case_clause (case_pattern (union_pattern (list_pattern (case_pattern (string (string_start) (string_content) (string_end)))) (list_pattern (case_pattern (string (string_start) (string_content) (string_end))) (case_pattern (string (string_start) (string_content) (string_end)))))) (block (expression_statement (assignment (identifier) (call (attribute (identifier) (identifier)) (argument_list (string (string_start) (string_content) (string_end)))))))) (case_clause (case_pattern (union_pattern (list_pattern (case_pattern (string (string_start) (string_content) (string_end))) (case_pattern (dotted_name (identifier)))) (list_pattern (case_pattern (string (string_start) (string_content) (string_end))) (case_pattern (string (string_start) (string_content) (string_end))) (case_pattern (dotted_name (identifier)))) (list_pattern (case_pattern (string (string_start) (string_content) (string_end))) (case_pattern (dotted_name (identifier))) (case_pattern (string (string_start) (string_content) (string_end)))))) (block (pass_statement)))))) ================================================================================ As patterns ================================================================================ match command.split(): case ["go", ("north" | "south" | "east" | "west") as direction]: current_room = current_room.neighbor(direction) -------------------------------------------------------------------------------- (module (match_statement (call (attribute (identifier) (identifier)) (argument_list)) (block (case_clause (case_pattern (list_pattern (case_pattern (string (string_start) (string_content) (string_end))) (case_pattern (as_pattern (case_pattern (tuple_pattern (case_pattern (union_pattern (string (string_start) (string_content) (string_end)) (string (string_start) (string_content) (string_end)) (string (string_start) (string_content) (string_end)) (string (string_start) (string_content) (string_end)))))) (identifier))))) (block (expression_statement (assignment (identifier) (call (attribute (identifier) (identifier)) (argument_list (identifier)))))))))) ================================================================================ Actually not match ================================================================================ match = 2 match, a = 2, 3 match: int = secret x, match = 2, "hey, what's up?" *match, last = [1, 2, 3] def foo(**match): pass -------------------------------------------------------------------------------- (module (expression_statement (assignment (identifier) (integer))) (expression_statement (assignment (pattern_list (identifier) (identifier)) (expression_list (integer) (integer)))) (expression_statement (assignment (identifier) (type (identifier)) (identifier))) (expression_statement (assignment (pattern_list (identifier) (identifier)) (expression_list (integer) (string (string_start) (string_content) (string_end))))) (expression_statement (assignment (pattern_list (list_splat_pattern (identifier)) (identifier)) (list (integer) (integer) (integer)))) (function_definition (identifier) (parameters (dictionary_splat_pattern (identifier))) (block (pass_statement)))) ================================================================================ Match is match but not pattern matching ================================================================================ a = [match] match = [match] -------------------------------------------------------------------------------- (module (expression_statement (assignment (identifier) (list (identifier)))) (expression_statement (assignment (identifier) (list (identifier))))) ================================================================================ Match kwargs ================================================================================ field = call(match=r".*\.txt$") -------------------------------------------------------------------------------- (module (expression_statement (assignment (identifier) (call (identifier) (argument_list (keyword_argument (identifier) (string (string_start) (string_content) (string_end)))))))) ================================================================================ Match kwargs 2 ================================================================================ field = match(match=match, match) -------------------------------------------------------------------------------- (module (expression_statement (assignment (identifier) (call (identifier) (argument_list (keyword_argument (identifier) (identifier)) (identifier)))))) ================================================================================ Case used as identifier ================================================================================ a = [case] case = [case] just_in_case = call_me(case=True) -------------------------------------------------------------------------------- (module (expression_statement (assignment (identifier) (list (identifier)))) (expression_statement (assignment (identifier) (list (identifier)))) (expression_statement (assignment (identifier) (call (identifier) (argument_list (keyword_argument (identifier) (true))))))) ================================================================================ If guards ================================================================================ match 0: case 0 if False: x = False case 0 if True: x = True -------------------------------------------------------------------------------- (module (match_statement (integer) (block (case_clause (case_pattern (integer)) (if_clause (false)) (block (expression_statement (assignment (identifier) (false))))) (case_clause (case_pattern (integer)) (if_clause (true)) (block (expression_statement (assignment (identifier) (true)))))))) ================================================================================ Literals ================================================================================ match xxx: case 3 | -3: pass case "something": pass case "something" "else": pass case 1.0 | -1.0: pass case True | False: pass case None: pass -------------------------------------------------------------------------------- (module (match_statement (identifier) (block (case_clause (case_pattern (union_pattern (integer) (integer))) (block (pass_statement))) (case_clause (case_pattern (string (string_start) (string_content) (string_end))) (block (pass_statement))) (case_clause (case_pattern (concatenated_string (string (string_start) (string_content) (string_end)) (string (string_start) (string_content) (string_end)))) (block (pass_statement))) (case_clause (case_pattern (union_pattern (float) (float))) (block (pass_statement))) (case_clause (case_pattern (union_pattern (true) (false))) (block (pass_statement))) (case_clause (case_pattern (none)) (block (pass_statement)))))) ================================================================================ Comma separated cases ================================================================================ match (0, 1, 2): case 0,1: x = 0 case 0, *x: x = 0 -------------------------------------------------------------------------------- (module (match_statement (tuple (integer) (integer) (integer)) (block (case_clause (case_pattern (integer)) (case_pattern (integer)) (block (expression_statement (assignment (identifier) (integer))))) (case_clause (case_pattern (integer)) (case_pattern (splat_pattern (identifier))) (block (expression_statement (assignment (identifier) (integer)))))))) ================================================================================ Case terminating in comma ================================================================================ match x,: case *x,: y = 0 -------------------------------------------------------------------------------- (module (match_statement (identifier) (block (case_clause (case_pattern (splat_pattern (identifier))) (block (expression_statement (assignment (identifier) (integer)))))))) ================================================================================ Multiple match patterns ================================================================================ match ..., ...: case a, b: return locals() -------------------------------------------------------------------------------- (module (match_statement (ellipsis) (ellipsis) (block (case_clause (case_pattern (dotted_name (identifier))) (case_pattern (dotted_name (identifier))) (block (return_statement (call (identifier) (argument_list)))))))) ================================================================================ Match match, case case ================================================================================ match = case = 0 match match: case case: x = 0 -------------------------------------------------------------------------------- (module (expression_statement (assignment (identifier) (assignment (identifier) (integer)))) (match_statement (identifier) (block (case_clause (case_pattern (dotted_name (identifier))) (block (expression_statement (assignment (identifier) (integer)))))))) ================================================================================ Walrus match (Issue #150) ================================================================================ if match := re.fullmatch(r"(-)?(\d+:)?\d?\d:\d\d(\.\d*)?", time, flags=re.ASCII): return 42 -------------------------------------------------------------------------------- (module (if_statement (named_expression (identifier) (call (attribute (identifier) (identifier)) (argument_list (string (string_start) (string_content) (string_end)) (identifier) (keyword_argument (identifier) (attribute (identifier) (identifier)))))) (block (return_statement (integer))))) ================================================================================ Matching objects ================================================================================ match event.get(): case Click(position=(x, y)): handle_click_at(x, y) case KeyPress(key_name="Q") | Quit(): game.quit() case KeyPress(key_name="up arrow"): game.go_north() ... case KeyPress(): pass # Ignore other keystrokes case other_event: raise ValueError(f"Unrecognized event: {other_event}") -------------------------------------------------------------------------------- (module (match_statement (call (attribute (identifier) (identifier)) (argument_list)) (block (case_clause (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (keyword_pattern (identifier) (tuple_pattern (case_pattern (dotted_name (identifier))) (case_pattern (dotted_name (identifier)))))))) (block (expression_statement (call (identifier) (argument_list (identifier) (identifier)))))) (case_clause (case_pattern (union_pattern (class_pattern (dotted_name (identifier)) (case_pattern (keyword_pattern (identifier) (string (string_start) (string_content) (string_end))))) (class_pattern (dotted_name (identifier))))) (block (expression_statement (call (attribute (identifier) (identifier)) (argument_list))))) (case_clause (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (keyword_pattern (identifier) (string (string_start) (string_content) (string_end)))))) (block (expression_statement (call (attribute (identifier) (identifier)) (argument_list))) (expression_statement (ellipsis)))) (case_clause (case_pattern (class_pattern (dotted_name (identifier)))) (block (pass_statement) (comment))) (case_clause (case_pattern (dotted_name (identifier))) (block (raise_statement (call (identifier) (argument_list (string (string_start) (string_content) (interpolation (identifier)) (string_end)))))))))) ================================================================================ Positional arguments ================================================================================ match event.get(): case Click((x, y)): handle_click_at(x, y) -------------------------------------------------------------------------------- (module (match_statement (call (attribute (identifier) (identifier)) (argument_list)) (block (case_clause (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (tuple_pattern (case_pattern (dotted_name (identifier))) (case_pattern (dotted_name (identifier))))))) (block (expression_statement (call (identifier) (argument_list (identifier) (identifier))))))))) ================================================================================ Constants and enums ================================================================================ match event.get(): case Click((x, y), button=Button.LEFT): # This is a left click handle_click_at(x, y) case Click(): pass # ignore other clicks -------------------------------------------------------------------------------- (module (match_statement (call (attribute (identifier) (identifier)) (argument_list)) (block (case_clause (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (tuple_pattern (case_pattern (dotted_name (identifier))) (case_pattern (dotted_name (identifier))))) (case_pattern (keyword_pattern (identifier) (dotted_name (identifier) (identifier)))))) (comment) (block (expression_statement (call (identifier) (argument_list (identifier) (identifier)))))) (case_clause (case_pattern (class_pattern (dotted_name (identifier)))) (block (pass_statement) (comment)))))) ================================================================================ Dict mappings ================================================================================ for action in actions: match action: case {"text": message, "color": c}: ui.set_text_color(c) ui.display(message) case {"sleep": duration}: ui.wait(duration) case {"sound": url, "format": "ogg"}: ui.play(url) case {a.b: c}: action() case {"sound": _, "format": _}: warning("Unsupported audio format") -------------------------------------------------------------------------------- (module (for_statement (identifier) (identifier) (block (match_statement (identifier) (block (case_clause (case_pattern (dict_pattern (string (string_start) (string_content) (string_end)) (case_pattern (dotted_name (identifier))) (string (string_start) (string_content) (string_end)) (case_pattern (dotted_name (identifier))))) (block (expression_statement (call (attribute (identifier) (identifier)) (argument_list (identifier)))) (expression_statement (call (attribute (identifier) (identifier)) (argument_list (identifier)))))) (case_clause (case_pattern (dict_pattern (string (string_start) (string_content) (string_end)) (case_pattern (dotted_name (identifier))))) (block (expression_statement (call (attribute (identifier) (identifier)) (argument_list (identifier)))))) (case_clause (case_pattern (dict_pattern (string (string_start) (string_content) (string_end)) (case_pattern (dotted_name (identifier))) (string (string_start) (string_content) (string_end)) (case_pattern (string (string_start) (string_content) (string_end))))) (block (expression_statement (call (attribute (identifier) (identifier)) (argument_list (identifier)))))) (case_clause (case_pattern (dict_pattern (dotted_name (identifier) (identifier)) (case_pattern (dotted_name (identifier))))) (block (expression_statement (call (identifier) (argument_list))))) (case_clause (case_pattern (dict_pattern (string (string_start) (string_content) (string_end)) (case_pattern) (string (string_start) (string_content) (string_end)) (case_pattern))) (block (expression_statement (call (identifier) (argument_list (string (string_start) (string_content) (string_end)))))))))))) ================================================================================ Builtin classes ================================================================================ for action in actions: match action: case {"text": str(message), "color": str(c)}: ui.set_text_color(c) ui.display(message) case {"sleep": float(duration)}: ui.wait(duration) case {"sound": str(url), "format": "ogg"}: ui.play(url) case {"sound": _, "format": _}: warning("Unsupported audio format") -------------------------------------------------------------------------------- (module (for_statement (identifier) (identifier) (block (match_statement (identifier) (block (case_clause (case_pattern (dict_pattern (string (string_start) (string_content) (string_end)) (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (dotted_name (identifier))))) (string (string_start) (string_content) (string_end)) (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (dotted_name (identifier))))))) (block (expression_statement (call (attribute (identifier) (identifier)) (argument_list (identifier)))) (expression_statement (call (attribute (identifier) (identifier)) (argument_list (identifier)))))) (case_clause (case_pattern (dict_pattern (string (string_start) (string_content) (string_end)) (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (dotted_name (identifier))))))) (block (expression_statement (call (attribute (identifier) (identifier)) (argument_list (identifier)))))) (case_clause (case_pattern (dict_pattern (string (string_start) (string_content) (string_end)) (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (dotted_name (identifier))))) (string (string_start) (string_content) (string_end)) (case_pattern (string (string_start) (string_content) (string_end))))) (block (expression_statement (call (attribute (identifier) (identifier)) (argument_list (identifier)))))) (case_clause (case_pattern (dict_pattern (string (string_start) (string_content) (string_end)) (case_pattern) (string (string_start) (string_content) (string_end)) (case_pattern))) (block (expression_statement (call (identifier) (argument_list (string (string_start) (string_content) (string_end)))))))))))) ================================================================================ Complex case patterns on classes ================================================================================ match x: case Something(): # no args foo1() case Something.Else(): # more complex class name foo2() case Point2D(0, 1, 2): # three args foo3() case Point3D(x=0, y=0, z=0): # kw args foo4() case Point3D(34, x=0, y=0, z=0): # positional + kw args foo5() case Point2D(0, 1, 2,): # three args + trail comma foo6() case Point3D(x=0, y=0, z=0,): # kw args + trail comma foo7() case Point3D(34, x=0, y=0, z=0,): # positional + kw args + trail comma foo8() -------------------------------------------------------------------------------- (module (match_statement (identifier) (block (case_clause (case_pattern (class_pattern (dotted_name (identifier)))) (comment) (block (expression_statement (call (identifier) (argument_list))))) (case_clause (case_pattern (class_pattern (dotted_name (identifier) (identifier)))) (comment) (block (expression_statement (call (identifier) (argument_list))))) (case_clause (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (integer)) (case_pattern (integer)) (case_pattern (integer)))) (comment) (block (expression_statement (call (identifier) (argument_list))))) (case_clause (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (keyword_pattern (identifier) (integer))) (case_pattern (keyword_pattern (identifier) (integer))) (case_pattern (keyword_pattern (identifier) (integer))))) (comment) (block (expression_statement (call (identifier) (argument_list))))) (case_clause (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (integer)) (case_pattern (keyword_pattern (identifier) (integer))) (case_pattern (keyword_pattern (identifier) (integer))) (case_pattern (keyword_pattern (identifier) (integer))))) (comment) (block (expression_statement (call (identifier) (argument_list))))) (case_clause (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (integer)) (case_pattern (integer)) (case_pattern (integer)))) (comment) (block (expression_statement (call (identifier) (argument_list))))) (case_clause (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (keyword_pattern (identifier) (integer))) (case_pattern (keyword_pattern (identifier) (integer))) (case_pattern (keyword_pattern (identifier) (integer))))) (comment) (block (expression_statement (call (identifier) (argument_list))))) (case_clause (case_pattern (class_pattern (dotted_name (identifier)) (case_pattern (integer)) (case_pattern (keyword_pattern (identifier) (integer))) (case_pattern (keyword_pattern (identifier) (integer))) (case_pattern (keyword_pattern (identifier) (integer))))) (comment) (block (expression_statement (call (identifier) (argument_list)))))))) ================================================================================ Complex case patterns on complex numbers ================================================================================ match x: case -3 + 5j: pass case -3 + 5j as b2: pass case 3j as b1, -3 + 5j as b2: pass case -3. + 5j: pass case 3 - 5.j: pass -------------------------------------------------------------------------------- (module (match_statement (identifier) (block (case_clause (case_pattern (complex_pattern (integer) (integer))) (block (pass_statement))) (case_clause (case_pattern (as_pattern (case_pattern (complex_pattern (integer) (integer))) (identifier))) (block (pass_statement))) (case_clause (case_pattern (as_pattern (case_pattern (integer)) (identifier))) (case_pattern (as_pattern (case_pattern (complex_pattern (integer) (integer))) (identifier))) (block (pass_statement))) (case_clause (case_pattern (complex_pattern (float) (integer))) (block (pass_statement))) (case_clause (case_pattern (complex_pattern (integer) (float))) (block (pass_statement)))))) ================================================================================ Maybe sequence pattern right hand side precedence validation ================================================================================ match x: case a1, *a2, a3: pass -------------------------------------------------------------------------------- (module (match_statement (identifier) (block (case_clause (case_pattern (dotted_name (identifier))) (case_pattern (splat_pattern (identifier))) (case_pattern (dotted_name (identifier))) (block (pass_statement))))))