Last active
March 10, 2024 15:44
-
-
Save bucho666/b7e241b51d8e7a78c7c63c3ca2226e4c to your computer and use it in GitHub Desktop.
nim class macro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import macros | |
proc typeName(head: NimNode): NimNode = | |
if head.len == 0: head else: head[1] | |
proc baseName(head: NimNode): NimNode = | |
if head.len == 0: newIdentNode("RootObj") else: head[2] | |
proc isObjectDef(head: NimNode): bool = | |
head.len == 0 or head[2].kind == nnkIdent | |
proc buildObjectTypeDecl(head: NimNode): NimNode = | |
template typeDecl(a, b): untyped = | |
type a* = ref object of b | |
result = getAst(typeDecl(head.typeName, head.baseName)) | |
proc buildBasicTypeDecl(head: NimNode): NimNode = | |
result = newNimNode(nnkTypeSection) | |
result.add(newNimNode(nnkTypeDef)) | |
result[0].add(newIdentNode($head[1])) | |
result[0].add(newNimNode(nnkEmpty)) | |
result[0].add(head[2]) | |
proc buildTypeDecl(head: NimNode): NimNode = | |
if head.isObjectDef: | |
head.buildObjectTypeDecl | |
else: | |
head.buildBasicTypeDecl | |
macro class*(head, body: untyped): untyped = | |
result = newStmtList() | |
result.add(head.buildTypeDecl) | |
let | |
typeName = head.typeName | |
ctorName = newIdentNode("new" & $typeName) | |
var recList = newNimNode(nnkRecList) | |
for node in body.children: | |
case node.kind: | |
of nnkMethodDef, nnkProcDef, nnkIteratorDef: | |
if node.name.kind != nnkAccQuoted and node.name == ctorName: | |
node.params[0] = typeName | |
else: | |
node.params.insert(1, newIdentDefs(ident("self"), typeName)) | |
result.add(node) | |
of nnkVarSection: | |
if not head.isObjectDef: | |
error "Invalid node: " & node.lispRepr | |
for n in node.children: | |
recList.add(n) | |
else: | |
result.add(node) | |
if head.isObjectDef: | |
result[0][0][2][0][2] = recList |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import class | |
class Animal: | |
var name: string | |
var age: int | |
method vocalize: string {.base.} = | |
"..." | |
method age_human_yrs: int {.base.} = | |
self.age | |
class Dog of Animal: | |
method vocalize: string = | |
"woof" | |
method age_human_yrs: int = | |
self.age * 7 | |
class Cat of Animal: | |
method vocalize: string = | |
"meow" | |
class Rabbit of Animal: | |
proc newRabbit(name: string, age: int) = | |
result = Rabbit(name: name, age: age) | |
method vocalize: string = | |
"meep" | |
proc `$`: string = | |
"rabbit:" & self.name & ":" & $self.age | |
class Range: | |
var min, max: int | |
iterator items(): int = | |
for n in self.min..self.max: | |
yield n | |
class Point of tuple[x, y: int]: | |
proc newPoint(x, y: int) = | |
(x: x, y: y) | |
proc `$`():string = | |
"x:" & $self.x & " y:" & $self.y | |
class Main: | |
proc animalDemo() = | |
var animals: seq[Animal] = @[] | |
animals.add(Dog(name: "Sparky", age: 10)) | |
animals.add(Cat(name: "Mitten", age: 10)) | |
for a in animals: | |
echo a.vocalize() | |
echo a.age_human_yrs() | |
let r = newRabbit("Fluffy", 3) | |
echo r.vocalize() | |
echo r.age_human_yrs() | |
echo r | |
proc iteratorDemo() = | |
for n in Range(min:3, max:12): | |
echo n | |
proc tupleClassDemo() = | |
echo (x:1, y:2) | |
echo (3, 4) | |
echo newPoint(5, 6) | |
proc run() = | |
self.animalDemo | |
self.iteratorDemo | |
self.tupleClassDemo | |
Main().run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment