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

Reply via email to