Hi, martsim.
I tried to develop a Lisp like consp data structures for writing macros. I used
your Domain Specific Language as a starting point. The experiment is far from a
success, but I decided to share the results with you, maybe you can help me.
Here is what I got:
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(")")
let plus{.compileTime.}= "+".sy
proc walkAST(e:SExpr): NimNode =
case e.kind:
of Sym: return newIdentNode e.symb
of IntScalar: return newLit e.intVal
of consp:
if car(e) == plus:
var callTree = nnkCall.newTree()
callTree.add newIdentNode"+"
callTree.add e.cdr.car.walkAST
callTree.add e.cdr.cdr.car.walkAST
return callTree
else: return newLit "Erro"
macro def(id:untyped, x:untyped, y:untyped): untyped=
let ix= x.strVal.sy
let iy= y.strVal.sy
let body= cons(plus, cons(ix, cons(iy, nil))).walkAST
quote do:
proc `id`(`x`: int, `y`: int): int=
`body`
def(sum, cx, cy)
proc main() =
echo cons("hi".sy, cons(cons("world".sy, nil), nil))
echo sum(paramStr(1).parseInt, 8)
main()
Run