all repos — min @ cbf56e3665bf42ab3419e54c4356c7aeffaa0877

A small but practical concatenative programming language.

primitives.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
import tables, strutils
import interpreter

proc valueError(s: TMinValue, msg: string) =
  stderr.writeln("$1 [$2, $3] Error - $4" %[s.file, $s.first, $s.last, msg])
  quit(1)

proc peek(s: TMinStack, i = 1): TMinValue =
  return s[s.len-i]

proc expects(sym: string, reqs: openarray[string]) =
  var i = 0
  var a: TMinValue
  for r in reqs:
    inc(i)
    a = STACK.peek(i)
    if r != "any" and a.kind != TYPES[r]:
      a.valueError("$1: Value #$2 is not a $3" % [sym, $i, r])

template minsym(name: string, reqs: openarray[string], body: stmt): stmt =
  SYMBOLS[name] = proc (val: TMinValue) =
    let n_req = reqs.len
    let n_found = STACK.len
    if n_found < n_req:
      val.valueError("$1: Not enough values on the stack (required: $2, found: $3)." % [name, $n_req, $n_found])
    name.expects reqs
    body

proc alias(newname, oldname) =
  SYMBOLS[newname] = SYMBOLS[oldname]

proc printMinValue(a: TMinValue) =
  case a.kind:
    of minSymbol:
      stdout.write a.symVal
    of minString:
      stdout.write "\""&a.strVal&"\""
    of minInt:
      stdout.write a.intVal
    of minFloat:
      stdout.write a.floatVal
    of minQuotation:
      stdout.write "[ "
      for i in a.qVal:
        printMinValue i
        stdout.write " "
      stdout.write "]"

### SYMBOL DEFINITIONS ###

minsym "dup", ["any"]:
  STACK.add STACK.peek

minsym "pop", ["any"]:
  discard STACK.pop

minsym "swap", ["any", "any"]:
  let a = STACK.pop
  let b = STACK.pop
  STACK.add a
  STACK.add b

minsym "quote", ["any"]:
  let a = STACK.pop
  STACK.add TMinValue(kind: minQuotation, qVal: @[a])

minsym "i", []:
  discard

minsym "print", ["any"]:
  let a = STACK[STACK.len-1]
  printMinValue a
  echo ""

minsym "alias", ["quotation", "quotation"]:
  var q = STACK.pop
  var v = STACK.pop
  if q.qVal.len != 1 or q.qVal[0].kind != minSymbol:
    q.valueError("alias: First quoted symbol not found on the stack.")
  let newalias = q.qVal[0].symVal
  if v.qVal.len != 1 or v.qVal[0].kind != minSymbol:
    q.valueError("alias: Second quoted symbol '$1' not found on the stack")
  let orig = v.qVal[0].symVal
  if SYMBOLS.haskey orig:
    SYMBOLS[newalias] = SYMBOLS[orig]
  else:
    v.valueError("alias: Unknown symbol '$1'" % [orig])