Hi, mratsin.
Thank you for the link to your work. By studying your first example, I was able
to create a Lisp like AST, however I could not discover a way to convert it to
a Nim AST. Could you take a look at my program, and suggest a way of converting
it into a functional Nim macro? By the way, I changed symbol to symb, since the
compiler issues a warning against using symbol.
import os, strutils, macros
type
SExprKind = enum
IntScalar, FloatScalar, St, Sym, consp
SExpr = ref object
case kind: SExprKind
of IntScalar: intVal: int
of FloatScalar: floatVal: float
of Sym: symb: string
of St: str: string
of consp: car, cdr: SExpr
template mI(a:int): SExpr=
SExpr(kind: IntScalar, intVal: a)
template sy(s: string): SExpr=
SExpr(kind: Sym, symb: `s`)
template mS(s:string): SExpr=
SExpr(kind: St, str: s)
template car(s:SExpr) : SExpr=
if s == nil: s
else: s.car
template cdr(s:SExpr) : Sexpr=
if s == nil: s
else: s.cdr
template cons(x:SExpr, y:SExpr) : SExpr=
SExpr(kind: consp, car: x, cdr: y)
proc `$`*(se: SExpr): string =
case se.kind
of IntScalar: result= $se.intVal
of FloatScalar: result = $se.floatVal
of ST: result = '"' & se.str & '"'
of Sym: result = se.symb
of consp:
result.add("(")
var r = se
if r != nil:
result.add($r.car)
r= r.cdr
while r != nil:
result.add(indent($r.car, 2))
r= r.cdr
result.add(")")
proc walkAST(e:SExpr): NimNode =
case e.kind:
of Sym: return newIdentNode e.symb
of IntScalar: return newLit e.intVal
else: return newLit "Erro"
let ii{.compileTime.} = "i".sy.walkAST
macro iter(jj: untyped, c1: untyped, c2: untyped, stm: untyped): untyped=
let
jx= jj.strVal
p= int(c1.intVal)
result= nnkStmtList.newTree(
nnkForStmt.newTree(jx.sy.walkAST,
infix(p.mI.walkAST, "..", c2), stm))
proc main() =
iter(j, 2, paramStr(1).parseInt):
echo j, cons("hi".sy, cons(cons("world".sy, nil), nil))
main()
Run