all repos — min @ 323618c811ea88c8d4456cabbce6bfd8c9d728c6

A small but practical concatenative programming language.

lib/quotations.nim

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
import tables
import ../core/parser, ../core/interpreter, ../core/utils

# Operations on quotations

minsym "quote":
  let a = i.pop
  i.push MinValue(kind: minQuotation, qVal: @[a])

minsym "unquote":
  let q = i.pop
  if not q.isQuotation:
    i.error errNoQuotation
  for item in q.qVal:
   i.push item 

minsym "cons":
  var q = i.pop
  let v = i.pop
  if not q.isQuotation:
    i.error errNoQuotation
  q.qVal.add v
  i.push q

minsym "at":
  var index = i.pop
  var q = i.pop
  if index.isInt and q.isQuotation:
    i.push q.qVal[index.intVal]
  else:
    i.error errIncorrect, "An integer and a quotation are required on the stack"

minsym "map":
  let prog = i.pop
  let list = i.pop
  if prog.isQuotation and list.isQuotation:
    i.push newVal(newSeq[MinValue](0))
    for litem in list.qVal:
      i.push litem
      for pitem in prog.qVal:
        i.push pitem
      i.apply("swap") 
      i.apply("cons") 
  else:
    i.error(errIncorrect, "Two quotations are required on the stack")

minsym "times":
  let t = i.pop
  let prog = i.pop
  if t.isInt and prog.isQuotation:
    for c in 1..t.intVal:
      for pitem in prog.qVal:
        i.push pitem
  else:
    i.error errIncorrect, "An integer and a quotation are required on the stack"

minsym "ifte":
  let fpath = i.pop
  let tpath = i.pop
  let check = i.pop
  var stack = i.copystack
  if check.isQuotation and tpath.isQuotation and fpath.isQuotation:
    i.push check.qVal
    let res = i.pop
    i.stack = stack
    if res.isBool and res.boolVal == true:
      i.push tpath.qVal
    else:
      i.push fpath.qVal
  else:
    i.error(errIncorrect, "Three quotations are required on the stack")

minsym "while":
  let d = i.pop
  let b = i.pop
  if b.isQuotation and d.isQuotation:
    i.push b.qVal
    var check = i.pop
    while check.isBool and check.boolVal == true:
      i.push d.qVal
      i.push b.qVal
      check = i.pop
  else:
    i.error(errIncorrect, "Two quotations are required on the stack")

minsym "filter":
  let filter = i.pop
  let list = i.pop
  var res = newSeq[MinValue](0)
  if filter.isQuotation and list.isQuotation:
    for e in list.qVal:
      i.push e
      i.push filter.qVal
      var check = i.pop
      if check.isBool and check.boolVal == true:
        res.add e
    i.push res.newVal
  else:
    i.error(errIncorrect, "Two quotations are required on the stack")

minsym "linrec":
  var r2 = i.pop
  var r1 = i.pop
  var t = i.pop
  var p = i.pop
  if p.isQuotation and t.isQuotation and r1.isQuotation and r2.isQuotation:
    i.linrec(p, t, r1, r2)
  else:
    i.error(errIncorrect, "Four quotations are required on the stack")