nimpylib
nimpylib copied to clipboard
Possible to use def outside of tonim:?
Hello! This is an amazing project, good job.
Whenever I try to do this I get Error: undeclared identifier: 'def'
Is this possible to define these outside of tonim:
given the current macro capabilities of nim?
If not, any tips to make this more ergonomic? or apply this to the entire file by default?
Thanks!!
@gnat this is what I came up with for a simple def
macro. It probably can't handle complex cases at all though, and you should really just use Nim's proc syntax as it's native. Nimpylib was meant as a half-joking project, not something people will use in real projects :)
import std/macros
proc genProc(define, body: NimNode): NimNode =
# Copy the defines (arguments, return type, proc name)
var define = define
var
startIdx = 1 # start index of arguments of the proc
stopIdx = define.len - 1 # end index
# First argument is the return type of the procedure
var args = @[newIdentNode("auto")]
# If it's a infix ->, it's a type hint for the return type
if define.kind == nnkInfix:
if define[0].strVal != "->":
error("expected a type hint arrow", define)
# Replace the return type
args[0] = define[^1]
define = define[1] # Discard the arrow
var procName = define[0]
# Loop over all arguments except the procedure name
for i in startIdx..stopIdx:
# Argument name
let arg = define[i]
# arg = 5
if arg.kind == nnkExprEqExpr:
args.add newIdentDefs(arg[0], newEmptyNode(), arg[1])
# arg: int or arg: int ~ 5
elif arg.kind == nnkExprColonExpr:
# With default value with ~
if arg[1].kind == nnkInfix and arg[1][0].strVal == "~":
args.add newIdentDefs(arg[0], arg[1][1], arg[1][2])
# No default value, just a type hint
else:
args.add newIdentDefs(arg[0], arg[1], newEmptyNode())
else:
# Just add argument: auto and hope for the best
args.add newIdentDefs(arg, ident("auto"), newEmptyNode())
# Convert a python "doc" comment into a nim doc comment
if body[0].kind == nnkTripleStrLit:
body[0] = newCommentStmtNode($body[0])
# Finally create a procedure and add it to result!
return newProc(procName, args, body, nnkProcDef)
macro def*(args, body: untyped): untyped =
result = genProc(args, body)
#echo repr result
def retStuff(a: string, b: int) -> string:
result = newStringOfCap(a.len * b)
for i in 0..<b:
result.add a
doAssert retStuff("hello", 3) == "hellohellohello"
def add(x, y):
"""
hello testing lol
"""
return x + y
doAssert add(3, 5) == 8
def add2(x, y: int ~ 8) -> int:
"""
hello testing lol
"""
return x + y
doAssert add2(3) == 11
Is this possible to define these outside of tonim: given the current macro capabilities of nim?
Sure, here
Also, I'm planning to implement raise ErrType(...)
and non-declaration-needed assignments in def
macro...