Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import macros
- {.experimental.}
- proc `-`(a: pointer, b: pointer): int =
- cast[int](a) - cast[int](b)
- proc `+`(a: pointer, b: int): pointer =
- cast[pointer](cast[int](a) + cast[int](b))
- macro structural(con, inter, fieldDefs): untyped =
- let dummySym = genSym(nskVar, "dummy")
- let vtableType = newNimNode(nnkTupleTy)
- let vtableVal = newNimNode(nnkPar)
- let conTests = newNimNode(nnkStmtList)
- for fieldDef in fieldDefs.children:
- let fname = fieldDef[0]
- let ftype = fieldDef[1][0]
- var a = newNimNode(nnkIdentDefs)
- a.add(fname)
- a.add(quote do: tuple[offs: int, tmark: `ftype`])
- a.add(newEmptyNode())
- vtableType.add(a)
- var b = newNimNode(nnkExprColonExpr)
- b.add(fname)
- b.add(quote do: (addr(`dummySym`.`fname`) - addr(`dummySym`[]), `dummySym`.`fname`))
- vtableVal.add(b)
- conTests.add(quote do: T.`fname` is `ftype`)
- let node = quote do:
- type
- `con` = concept g, type T
- `conTests`
- `inter` = object
- base: pointer
- vtable: ptr[`vtableType`]
- converter conToInt[T: not typedesc and `con`](x: var T): `inter` =
- var vt {.global.} = (proc(): `vtableType` =
- var `dummySym` = T()
- return `vtableVal`
- )()
- `inter`(
- base: addr x[],
- vtable: addr vt
- )
- let node2 = quote("@") do:
- template `.`(x: @inter, field: untyped): untyped =
- cast[ptr[(@vtableType).field.tmark]](x.base + x.vtable.field.offs)[]
- let node3 = newStmtList()
- node3.add(node)
- node3.add(node2)
- node3
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement