Skip to content

Instantly share code, notes, and snippets.

@JLHwung
Last active December 25, 2022 03:01
Show Gist options
  • Save JLHwung/d2b64364dc63757282cef182367b4e84 to your computer and use it in GitHub Desktop.
Save JLHwung/d2b64364dc63757282cef182367b4e84 to your computer and use it in GitHub Desktop.
AST examples for ESTree pattern-matching proposal

Note: The ExpressionStatement and Program node are omitted in the examples.

1. Object Match Pattern and "else" Match Clause

match (x) {
    when ({ colour: "#000000" }) { "yes" }
    else {
        "no"
    }
}
{
    "type": "MatchExpression",
    "discriminant": { "type": "Identifier", "name": "x" },
    "id": null,
    "clauses": [{
        "type": "MatchClause",
        "test": {
            "type": "ObjectMatchPattern",
            "properties": [{
                "type": "Property",
                "key": { "type": "StringLiteral", "value": "colour" },
                "value": { "type": "StringLiteral", "value": "#000000" },
                "kind": "init",
                "method": false
            }]
        },
        "consequent": {
            "type": "BlockStatement",
            "body": [{
                "type": "ExpressionStatement",
                "expression": { "type": "StringLiteral", "value": "yes" }
            }]
        },
        "guard": null,
        "id": null
    }, {
        "type": "MatchClause",
        "test": null,
        "consequent": {
            "type": "BlockStatement",
            "body": [{
                "type": "ExpressionStatement",
                "expression": { "type": "StringLiteral", "value": "no" }
            }]
        },
        "guard": null,
        "id": null
    }]
}

2. Matchable as RHS, Array Match Pattern and Null Match Pattern

match (f()) as [x, y] {
    when ([_, _, 200]) { "foo"; }
    else {
        process(x, y)
    }
}
{
    "type": "MatchExpression",
    "discriminant": {
        "type": "CallExpression",
        "callee": { "type": "Identifier", "name": "f" },
        "arguments": []
    },
    "id": {
        "type": "ArrayPattern",
        "elements": [
            { "type": "Identifier", "name": "x" },
            { "type": "Identifier", "name": "y" }
        ]
    },
    "clauses": [{
        "type": "MatchClause",
        "test": {
            "type": "ArrayMatchPattern",
            "elements": [
                { "type": "NullMatchPattern" },
                { "type": "NullMatchPattern" },
                { "type": "Literal", "value": 20 }
            ]
        },
        "consequent": {
            "type": "BlockStatement",
            "body": [{
                "type": "ExpressionStatement",
                "expression": { "type": "StringLiteral", "value": "foo" }
            }]
        },
        "guard": null,
        "id": null
    }, {
        "type": "MatchClause",
        "test": null,
        "consequent": {
            "type": "BlockStatement",
            "body": [{
                "type": "CallExpression",
                "callee": { "type": "Identifier", "name": "process" },
                "arguments": [
                    { "type": "Identifier", "name": "x" },
                    { "type": "Identifier", "name": "y" }
                ]
            }]
        },
        "guard": null,
        "id": null
    }]
}

3. Match Clause "as" RHS and guard condition

match (x) {
    when (/(?<x>\d+)/) as { groups: { y } } if (isEmpty(y)) {}
}
{
    "type": "MatchExpression",
    "discriminant": { "type": "Identifier", "name": "x" },
    "id": null,
    "clauses": [{
        "type": "MatchClause",
        "test": {
            "type": "Literal",
            "regex": { "pattern": "(?<x>\\d+)", "flags": "" }
        },
        "consequent": {
            "type": "BlockStatement",
            "body": []
        },
        "guard": {
            "type": "CallExpression",
            "callee": { "type": "Identifier", "name": "isEmpty" },
            "arguments": [
                { "type": "Identifier", "name": "y" }
            ]
        },
        "id": {
            "type": "ObjectPattern",
            "properties": [{
                "type": "Property",
                "key": { "type": "Identifier", "name": "groups" },
                "value": {
                    "type": "ObjectPattern",
                    "properties": [{
                        "type": "Property",
                        "key": { "type": "Identifier", "name": "y" }
                    }]
                },
                "kind": "init",
                "method": false
            }]
        }
    }]
}

4 "if" Match Clause and Binary Match Pattern

match (x) {
    if(isEmpty(x)) {}
    when({ status: 200 | 201 }) {}
}
{
    "type": "MatchExpression",
    "discriminant": { "type": "Identifier", "name": "x" },
    "id": null,
    "clauses": [{
        "type": "MatchClause",
        "test": {
            "type": "Literal",
            "regex": { "pattern": "(?<x>\\d+)", "flags": "" }
        },
        "consequent": {
            "type": "BlockStatement",
            "body": []
        },
        "guard": {
            "type": "CallExpression",
            "callee": { "type": "Identifier", "name": "isEmpty" },
            "arguments": [{ "type": "Identifier", "name": "x" }]
        },
        "id": null,
    }, {
        "type": "MatchClause",
        "test": {
            "type": "ObjectMatchPattern",
            "properties": [{
                "type": "Property",
                "key": { "type": "StringLiteral", "value": "status" },
                "value": {
                    "type": "BinaryMatchPattern",
                    "operator": "or",
                    "left": { "type": "Literal", "value": 200 },
                    "right": { "type": "Literal", "value": 201 }
                },
                "kind": "init",
                "method": false
            }]
        },
        "consequent": {
            "type": "BlockStatement",
            "body": []
        },
        "guard": null,
        "id": null
    }]
}

5 RegExp as Match Pattern, "with" additional Match Pattern and As Match Pattern

match (x) {
    when ({
        input: (/(?<x>\d+(?<d>[NSEW]))/ with [_, 200, _]) as { groups: { d } } 
    }) {}
}
{
    "type": "MatchExpression",
    "discriminant": { "type": "Identifier", "name": "x" },
    "id": null,
    "clauses": [{
        "type": "MatchClause",
        "test": {
            "type": "ObjectMatchPattern",
            "properties": [{
                "type": "Property",
                "key": { "type": "StringLiteral", "value": "input" },
                "value": {
                    "type": "AsMatchPattern",
                    "test": {
                        "type": "BinaryMatchPattern",
                        "operator": "with",
                        "left": { 
                            "type": "Literal",
                            "regex": { "pattern": "(?<x>\\d+(?<d>[NSEW]))", "flags": "" }
                        },
                        "right": {
                            "type": "ArrayMatchPattern",
                            "elements": [
                                { "type": "NullMatchPattern" },
                                { "type": "Literal", "value": 20 },
                                { "type": "NullMatchPattern" }
                            ]
                        }
                    },
                    "id": {
                        "type": "ObjectPattern",
                        "properties": [{
                            "type": "Property",
                            "key": { "type": "Identifier", "name": "groups" },
                            "value": {
                                "type": "ObjectPattern",
                                "properties": [{
                                    "type": "Property",
                                    "key": { "type": "Identifier", "name": "d" }
                                }]
                            },
                            "kind": "init",
                            "method": false
                        }]
                    }
                },
                "kind": "init",
                "method": false
            }]
        },
        "consequent": {
            "type": "BlockStatement",
            "body": []
        },
        "guard": null,
        "id": null
    }]
}

6 Expression Match Pattern

match (token) {
  when (^LF | ^CR) {}
}
{
    "type": "MatchExpression",
    "discriminant": { "type": "Identifier", "name": "x" },
    "id": null,
    "clauses": [{
        "type": "MatchClause",
        "test": {
            "type": "BinaryMatchPattern",
            "operator": "or",
            "left": { 
                "type": "ExpressionMatchPattern",
                "expression": { "type": "Identifier", "name": "LF" }
            },
            "right": { 
                "type": "ExpressionMatchPattern",
                "expression": { "type": "Identifier", "name": "CR" }
            }
        },
        "consequent": {
            "type": "BlockStatement",
            "body": []
        },
        "guard": null,
        "id": null
    }]
}

7. Expression Match Pattern and computed Object Match Pattern

match (action) {
    when (["take", ...{ [computed]: -200 }]) {}
}
{
    "type": "MatchExpression",
    "discriminant": { "type": "Identifier", "name": "action" },
    "id": null,
    "clauses": [{
        "type": "MatchClause",
        "test": {
            "type": "ArrayMatchPattern",
            "elements": [
                { "type": "Literal", "value": "take" },
                {
                    "type": "RestMatchElement",
                    "argument": {
                        "type": "ObjectMatchPattern",
                        "properties": [{
                            "type": "Property",
                            "key": { "type": "Identifier", "name": "computed" },
                            "computed": true,
                            "value": {
                                "type": "UnaryExpression",
                                "operator": "-",
                                "prefix": true,
                                "argument": { "type": "Literal", "value": 200 }
                            },
                            "kind": "init",
                            "method": false
                        }]
                    }
                }]
        },
        "consequent": {
            "type": "BlockStatement",
            "body": []
        },
        "guard": null,
        "id": null
    }]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment