Added equality
This commit is contained in:
parent
3633ff9ae9
commit
35fef5c605
2 changed files with 50 additions and 3 deletions
|
|
@ -115,7 +115,7 @@ A couple of limitations fo the `adt` macro:
|
|||
* field names must be unique across branches (that is, different variants cannot have two fields with the same name). This is actually a limitation of Nim.
|
||||
* the shortcut that groups field names by type does not seem to work, that is, in the above example one could not write `Rectangle(w, h: float)`.
|
||||
|
||||
In the future, Patty will also add a proper definition of equality and copy constructors. Also, some work needs to be done to make it easier to use the generated contructors with `ref` types, in particular for the important case of recursive algebraic data types.
|
||||
In the future, Patty may also add copy constructors. Also, some work needs to be done to make it easier to use the generated contructors with `ref` types, in particular for the important case of recursive algebraic data types.
|
||||
|
||||
Things that do not work (yet)
|
||||
-----------------------------
|
||||
|
|
|
|||
51
patty.nim
51
patty.nim
|
|
@ -1,4 +1,4 @@
|
|||
import macros
|
||||
import macros, sequtils
|
||||
|
||||
const enumSuffix = "E"
|
||||
|
||||
|
|
@ -109,14 +109,61 @@ proc defineConstructor(e, n: NimNode): NimNode {. compileTime .} =
|
|||
else:
|
||||
error("Invalid ADT case: " & $(toStrLit(n)))
|
||||
|
||||
proc eqFor(n: NimNode): NimNode {. compileTime .} =
|
||||
if n.kind == nnkObjConstr:
|
||||
result = newNimNode(nnkOfBranch).add(n[0] & enumSuffix)
|
||||
var comparisons: seq[NimNode] = @[]
|
||||
|
||||
for c in tail(n):
|
||||
comparisons.add(infix(newDotExpr(ident("a"), c[0]), "==", newDotExpr(ident("b"), c[0])))
|
||||
|
||||
let body = foldr(comparisons, infix(a, "and", b))
|
||||
|
||||
result.add(newStmtList(newNimNode(nnkReturnStmt).add(body)))
|
||||
elif n.kind == nnkIdent:
|
||||
result = newNimNode(nnkOfBranch).add(n & enumSuffix)
|
||||
result.add(newStmtList(newNimNode(nnkReturnStmt).add(ident("true"))))
|
||||
else:
|
||||
error("Invalid ADT case: " & $(toStrLit(n)))
|
||||
|
||||
|
||||
proc defineEquality(tp, body: NimNode): NimNode {. compileTime .} =
|
||||
# template compare(content, tp: NimNode) =
|
||||
# proc `==`(a, b: tp): bool =
|
||||
# if a.kind == b.kind: content
|
||||
# else: false
|
||||
var condition = newNimNode(nnkCaseStmt).add(newDotExpr(ident("a"), ident("kind")))
|
||||
for child in children(body):
|
||||
condition.add(eqFor(child))
|
||||
|
||||
var body = newNimNode(nnkIfExpr).add(
|
||||
newNimNode(nnkElifBranch).add(
|
||||
infix(newDotExpr(ident("a"), ident("kind")), "==", newDotExpr(ident("b"), ident("kind"))),
|
||||
condition
|
||||
),
|
||||
newNimNode(nnkElse).add(newStmtList(newNimNode(nnkReturnStmt).add(ident("false"))))
|
||||
)
|
||||
|
||||
result = newProc(
|
||||
name = ident("`==`"),
|
||||
params = [ident("bool"), newIdentDefs(ident("a"), tp), newIdentDefs(ident("b"), tp)],
|
||||
body = body
|
||||
)
|
||||
# result = getAst(compare(condition, tp))
|
||||
|
||||
macro adt*(e: expr, body: stmt): stmt {. immediate .} =
|
||||
result = newStmtList(defineTypes(e, body))
|
||||
result = newStmtList(defineTypes(e, body), defineEquality(e, body))
|
||||
|
||||
for child in children(body):
|
||||
result.add(defineConstructor(e, child))
|
||||
when defined(pattydebug):
|
||||
echo toStrLit(result)
|
||||
|
||||
adt Shape:
|
||||
Circle(r: float, x: float, y: float)
|
||||
Rectangle(w: float, h: float)
|
||||
Square(side: int)
|
||||
|
||||
macro match*(e: expr, body: stmt): stmt {. immediate .} =
|
||||
# A fresh symbol used to hold the evaluation of e
|
||||
let sym = genSym()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue