Skip to content

Example API for supporting various types #2

@alehander92

Description

@alehander92

As I promised in irc, here is a test file visualizing how I imagine such support for general object types and seq

I think the examples preserve fully the existing DSL, just adding three new patterns:
field: pattern, @[patterns] and *pattern

import unittest, macros

type
  H = enum HInt, HString

  A = ref object
    case kind: H:
    of HInt:
      i: int
    of HString:
      s: string
    players: seq[A]

proc hInt(i: int): A =
  A(kind: HInt, i: i, players: @[])

proc hString(s: string): A =
  A(kind: HString, s: s, players: @[])

macro matchLit*(typ: typed, litType: typed, f: untyped): untyped =
  discard


macro matchArgs*(typ: typed, f: untyped): untyped =
  discard

macro match*(obj: typed, args: varargs[untyped]): untyped =
  discard

macro matchtest(s: untyped, test: untyped): untyped =
  result = quote:
    test `s`:
      var expected {.inject.} = false
      `test`
      checkpoint "didn't match variant"
      check expected

template succeed: untyped =
  expected {.inject.} = true

suite "plan":
  matchtest "match variant field":
    var a = A(kind: HInt, i: 0)

    a.match:
    of HInt(i: `i`):
      check i == 0
      succeed
    else:
      discard

  matchtest "match variant literal":
    A.matchLit int, hInt
    A.matchLit string, hString

    var a = A(kind: HInt, i: 0)
    var b = A(kind: HString, s: "e")

    a.match:
    of 0:
      succeed
    else:
      discard

    b.match:
    of "f":
      discard
    of "e":
      succeed
    else:
      discard

  matchtest "match variant args with auto":
    A.matchArgs players

    var a = A(kind: HInt, i: 0, players: @[A(kind: HInt, i: 2, players: @[]), A(kind: HInt, i: 4, players: @[])])
    a.match:
    of HInt(HInt(2), HInt(4)):
      succeed
    else:
      discard

  matchtest "match normal objects":
    type
      Obj = object
        a*: int
        b*: int

    var a = Obj(a: 0, b: 0)
    a.match:
    of Obj(a: `a`, b: 0):
      check a == 0
      succeed
    else:
      discard

  matchtest "match seq":
    var a = @[0, 1, 2]
    a.match:
    of @[0]:
      discard
    of @[0, 1, `last`]:
      check last == 2
      succeed
    else:
      discard

    a.match:
    of @[`first`]:
      discard
    of @[0, *`last`]:
      check last == @[1, 2]
      succeed
    else:
      discard

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions