I tried to program a Lisp-like sexpr for writing macros, as suggested by 
mratsim (Mamy Ratsimbazafy). Since I used symbol for tagging symbols, as in 
Ratsimbazafy's DSL, the compiler issued a warning that symbol is deprecated. It 
seems that the Nim compiler confused my use of the symbol identifier with 
something else that existed in a previous avatar of Nim. I am not sure how to 
fix this kind of bug, but I hoped it can be done, in order to liberate the 
symbol keyword for the user. By the way, my program is far from satisfactory, 
and I hope that you people can help me to improve its design and functionality, 
since it can help people with Lisp mind settings to write macros in Nim.

First, the misplaced warning:
    
    
    › make APP=cons
    nim c -o:cons.x -d:danger --hints:off --nimcache:lixo cons.nim
    /Users/ed/nim/tutorial/src/cons.nim(18, 20) Warning: Deprecated since 
version 0.18.1; All functionality is defined on 'NimNode'.; symbol is 
deprecated [Deprecated]
    CC: stdlib_formatfloat.nim
    CC: stdlib_system.nim
    CC: stdlib_parseutils.nim
    CC: stdlib_strutils.nim
    CC: stdlib_os.nim
    CC: cons.nim
    
    
    Run

> Now, the program that caused the warning:
    
    
    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: symbol: 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, symbol: `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.symbol
      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.symbol
         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