Fixed some whitespace issues and added init variables.

This commit is contained in:
Joey Payne 2015-07-05 22:15:14 -06:00
commit f3e7bee8e7

View file

@ -4,30 +4,52 @@ import strutils
{.hint[XDeclaredButNotUsed]: off.} {.hint[XDeclaredButNotUsed]: off.}
macro new*(obj: untyped): untyped {.immediate.}= macro new*(obj: untyped): untyped {.immediate.}=
## Creates a new instance of the class if obj.kind == nnkObjConstr or obj.kind == nnkCall:
## and calls the init() method on it var args: seq[NimNode] = @[]
if obj.kind == nnkObjConstr: var new_obj = copyNimTree(obj)
# Only if the node is an object constructor
template init_object(obj)= # delete the parameters from the object
var init_obj = obj # since we are going to use init() instead
when compiles(init_obj.init()): new_obj.del(1, len(new_obj)-1)
init_obj.init()
init_obj # create a symbol that we can use
result = getAst(init_object(obj)) var sym = genSym(nskVar, "init_obj")
# self = init_obj
var self_eq = newNimNode(nnkExprEqExpr).add(ident"self", sym)
args.add(self_eq)
for ch in obj.children:
if ch.kind == nnkExprColonExpr:
# some_arg = some_val
args.add(newNimNode(nnkExprEqExpr).add(ch[0], ch[1]))
# init(self=init_obj, some_arg=someval, ...)
var init_call = newCall(ident"init", args)
template new_object(symbol, obj_node, init_func)=
var symbol = obj_node
when compiles(init_func):
init_func
symbol
result = getAst(new_object(sym, new_obj, init_call))
else: else:
# Otherwise, just revert to system.new # otherwise, just call system.new on the object
template init_object(obj)= # since we don't care about it
template new_object(obj)=
var init_obj = obj var init_obj = obj
system.new(init_obj) system.new(init_obj)
result = getAst(new_object(obj))
result = getAst(init_object(obj))
macro class*(head: untyped, body: untyped): untyped= macro class*(head: untyped, body: untyped): untyped =
# object reference name inside methods. # object reference name inside methods.
# ie: self, self # ie: self, self
let obj_reference = "self" let obj_reference = "self"
var export_class: bool = false # whether or not to export the class to other modules var export_class: bool = false
var typeName, baseName: NimNode var typeName, baseName: NimNode
@ -54,7 +76,7 @@ macro class*(head: untyped, body: untyped): untyped=
# ----------- # -----------
# Infix # Infix
# Ident !"*" # Ident !"*"
# Ident !"Animal" # Ident !"Animal
# Prefix # Prefix
# Ident !"of" # Ident !"of"
# Ident !"RootObj" # Ident !"RootObj"
@ -116,6 +138,22 @@ macro class*(head: untyped, body: untyped): untyped=
# return `baseName`(self) # return `baseName`(self)
# result.add(super) # result.add(super)
template set_node_name(n2, proc_name, type_name)=
if n2.name.kind == nnkIdent:
proc_name = $(n2.name.toStrLit())
n2.name = ident(proc_name & type_name)
elif n2.name.kind == nnkPostFix:
if n2.name[1].kind == nnkIdent:
proc_name = $(n2.name[1].toStrLit())
n2.name[1] = ident(proc_name & type_name)
elif n2.name[1].kind == nnkAccQuoted:
proc_name = $(n2.name[1][0].toStrLit())
n2.name[1][0] = ident(proc_name & type_name)
elif n2.name.kind == nnkAccQuoted:
proc_name = $(n2.name[0].toStrLit())
n2.name[0] = ident(proc_name & type_name)
result.add(n2)
# Make forward declarations so that function order # Make forward declarations so that function order
# does not matter, just like in real OOP! # does not matter, just like in real OOP!
for node in body.children: for node in body.children:
@ -134,20 +172,7 @@ macro class*(head: untyped, body: untyped): untyped=
let type_name = $(typeName.toStrLit()) let type_name = $(typeName.toStrLit())
var proc_name = "" var proc_name = ""
if n2.name.kind == nnkIdent: set_node_name(n2, proc_name, type_name)
proc_name = $(n2.name.toStrLit())
n2.name = ident(proc_name & type_name)
elif n2.name.kind == nnkPostFix:
if n2.name[1].kind == nnkIdent:
proc_name = $(n2.name[1].toStrLit())
n2.name[1] = ident(proc_name & type_name)
elif n2.name[1].kind == nnkAccQuoted:
proc_name = $(n2.name[1][0].toStrLit())
n2.name[1][0] = ident(proc_name & type_name)
elif n2.name.kind == nnkAccQuoted:
proc_name = $(n2.name[0].toStrLit())
n2.name[0] = ident(proc_name & type_name)
result.add(n2)
else: else:
discard discard
@ -169,21 +194,7 @@ macro class*(head: untyped, body: untyped): untyped=
var proc_name = $(n2.name.toStrLit()) var proc_name = $(n2.name.toStrLit())
var is_assignment = proc_name.contains("=") var is_assignment = proc_name.contains("=")
if n2.name.kind == nnkIdent: set_node_name(n2, proc_name, type_name)
proc_name = $(n2.name.toStrLit())
n2.name = ident(proc_name & type_name)
elif n2.name.kind == nnkPostFix:
if n2.name[1].kind == nnkIdent:
proc_name = $(n2.name[1].toStrLit())
n2.name[1] = ident(proc_name & type_name)
elif n2.name[1].kind == nnkAccQuoted:
proc_name = $(n2.name[1][0].toStrLit())
n2.name[1][0] = ident(proc_name & type_name)
elif n2.name.kind == nnkAccQuoted:
proc_name = $(n2.name[0].toStrLit())
n2.name[0] = ident(proc_name & type_name)
result.add(n2)
# simply call the class method from here # simply call the class method from here
# proc procName= # proc procName=
@ -265,9 +276,16 @@ macro class*(head: untyped, body: untyped): untyped=
result.insert(0, type_decl) result.insert(0, type_decl)
class Animal* of RootObj: #exports the class. Need to use RootObj for exports class Animal of RootObj:
var name: string var
var age: int name: string
age: int
method init*(name: string, age: int)=
self.name = name
self.age = age
echo "I am a new Animal, ", self.name
method stuff(s:string): string = s method stuff(s:string): string = s
method vocalize: string = "..." method vocalize: string = "..."
method age_human_yrs: int = self.age # `self` is injected method age_human_yrs: int = self.age # `self` is injected
@ -282,11 +300,12 @@ class Cat of Animal:
self.vocalize_animal() & "meow" self.vocalize_animal() & "meow"
class Tiger of Cat: class Tiger of Cat:
method init()= method init(name: string="Bob", age: int)=
self.init_animal(name, age)
echo "I am a new tiger" echo "I am a new tiger"
method vocalize: string = method vocalize: string =
# no need for super.super! # no need for super.super!
self.vocalize_animal() & "Rawr!" & self.vocalize_cat() self.vocalize_animal() & "Rawr!"
if isMainModule: if isMainModule:
var animals: seq[Animal] = @[] var animals: seq[Animal] = @[]
@ -299,10 +318,13 @@ if isMainModule:
echo a.age_human_yrs() echo a.age_human_yrs()
# prints: # prints:
# I am a new Animal, Sparky
# I am a new Animal, Mitten
# I am a new Animal, Jean
# I am a new tiger # I am a new tiger
# Sparky says woof # Sparky says woof
# 70 # 70
# Mitten says ...meow # Mitten says ...meow
# 10 # 10
# Jean says ...Rawr!...meow # Jean says ...Rawr!
# 2 # 2