lib/lang.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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
import tables, strutils import ../core/parser, ../core/interpreter, ../core/utils minsym "exit": quit(0) minsym "symbols": var q = newSeq[TMinValue](0) for s in SYMBOLS.keys: q.add s.newVal i.push q.newVal minsym "sigils": var q = newSeq[TMinValue](0) for s in SIGILS.keys: q.add s.newVal i.push q.newVal minsym "debug?": i.push i.debugging.newVal minsym "debug": i.debugging = not i.debugging echo "Debugging: $1" % [$i.debugging] # Language constructs minsym "bind": var q2 = i.pop # new (can be a quoted symbol or a string) var q1 = i.pop # existing (auto-quoted) var symbol: string if not q1.isQuotation: q1 = @[q1].newVal if q2.isString: symbol = q2.strVal elif q2.isQuotation and q2.qVal.len == 1 and q2.qVal[0].kind == minSymbol: symbol = q2.qVal[0].symVal else: i.error errIncorrect, "The top quotation must contain only one symbol value" if SYMBOLS.hasKey(symbol): i.error errSystem, "Symbol '$1' already exists" % [symbol] minsym symbol: i.evaluating = true i.push q1.qVal i.evaluating = false minsym "unbind": var q1 = i.pop if q1.qVal.len == 1 and q1.qVal[0].kind == minSymbol: var symbol = q1.qVal[0].symVal SYMBOLS.del symbol else: i.error errIncorrect, "The top quotation must contain only one symbol value" minsigil "'": i.push(@[TMinValue(kind: minSymbol, symVal: i.pop.strVal)].newVal) minsym "sigil": var q1 = i.pop let q2 = i.pop if q1.isString: q1 = @[q1].newVal if q1.isQuotation and q2.isQuotation: if q1.qVal.len == 1 and q1.qVal[0].kind == minSymbol: var symbol = q1.qVal[0].symVal if symbol.len == 1: if SIGILS.hasKey(symbol): i.error errSystem, "Sigil '$1' already exists" % [symbol] minsigil symbol: i.evaluating = true i.push q2.qVal i.evaluating = false else: i.error errIncorrect, "A sigil can only have one character" else: i.error errIncorrect, "The top quotation must contain only one symbol value" else: i.error errIncorrect, "Two quotations are required on the stack" minsym "eval": let s = i.pop if s.isString: i.eval s.strVal else: i.error(errIncorrect, "A string is required on the stack") minsym "load": let s = i.pop if s.isString: i.load s.strVal else: i.error(errIncorrect, "A string is required on the stack") # Operations on the whole stack minsym "clear": while i.stack.len > 0: discard i.pop minsym "dump": echo i.dump minsym "stack": var s = i.stack i.push s # Operations on quotations or strings minsym "concat": var q1 = i.pop var q2 = i.pop if q1.isString and q2.isString: let s = q2.strVal & q1.strVal i.push newVal(s) elif q1.isQuotation and q2.isQuotation: let q = q2.qVal & q1.qVal i.push newVal(q) else: i.error(errIncorrect, "Two quotations or two strings are required on the stack") minsym "first": var q = i.pop if q.isQuotation: i.push q.qVal[0] elif q.isString: i.push newVal($q.strVal[0]) else: i.error(errIncorrect, "A quotation or a string is required on the stack") minsym "rest": var q = i.pop if q.isQuotation: i.push newVal(q.qVal[1..q.qVal.len-1]) elif q.isString: i.push newVal(q.strVal[1..q.strVal.len-1]) else: i.error(errIncorrect, "A quotation or a string is required on the stack") |