all repos — min @ 8357584593a7963b548eff370c08031c9b089199

A small but practical concatenative programming language.

call operator now restoring original quotation.
h3rald h3rald@h3rald.com
Fri, 24 Jun 2016 11:34:56 +0200
commit

8357584593a7963b548eff370c08031c9b089199

parent

bd4b5d0ccd875f3f303dd9cfc6142c7fc4840630

5 files changed, 73 insertions(+), 47 deletions(-)

jump to
M core/utils.nimcore/utils.nim

@@ -44,13 +44,35 @@ proc newSym*(s: string): MinValue =

return MinValue(kind: minSymbol, symVal: s) proc isStringLike*(s: MinValue): bool = - return s.isSymbol or s.isString + return s.isSymbol or s.isString or (s.isQuotation and s.qVal.len == 1 and s.qVal[0].isSymbol) + +# Error Helpers + +proc raiseInvalid*(msg: string) = + raise MinInvalidError(msg: msg) + +proc raiseUndefined*(msg: string) = + raise MinUndefinedError(msg: msg) + +proc raiseOutOfBounds*(msg: string) = + raise MinOutOfBoundsError(msg: msg) + +proc raiseRuntime*(msg: string, qVal: var seq[MinValue]) = + raise MinRuntimeError(msg: msg, qVal: qVal) proc getString*(v: MinValue): string = if v.isSymbol: return v.symVal elif v.isString: return v.strVal + elif v.isQuotation: + if v.qVal.len == 1: + raiseInvalid("Quotation is not a quoted symbol") + let sym = v.qVal[0] + if sym.isSymbol: + return v.symVal + else: + raiseInvalid("Quotation is not a quoted symbol") proc warn*(s: string) = stderr.writeLine s

@@ -94,20 +116,6 @@ shallowCopy varname, value

proc to*(q: MinValue, T: typedesc): T = return cast[T](q.obj) - -# Error Helpers - -proc raiseInvalid*(msg: string) = - raise MinInvalidError(msg: msg) - -proc raiseUndefined*(msg: string) = - raise MinUndefinedError(msg: msg) - -proc raiseOutOfBounds*(msg: string) = - raise MinOutOfBoundsError(msg: msg) - -proc raiseRuntime*(msg: string, qVal: var seq[MinValue]) = - raise MinRuntimeError(msg: msg, qVal: qVal) # Validators

@@ -166,7 +174,7 @@ a = i.pop

if not a.isQuotation and not a.isString: raiseInvalid("A quotation or a string is required on the stack") -proc reqStringOrSymbol*(i: var MinInterpreter, a: var MinValue) = +proc reqStringLike*(i: var MinInterpreter, a: var MinValue) = a = i.pop if not a.isStringLike: raiseInvalid("A symbol or a string is required on the stack")
M lib/min_lang.nimlib/min_lang.nim

@@ -77,7 +77,7 @@ raiseUndefined("Attempting to bind undefined symbol: " & symbol)

.symbol("delete") do (i: In): var sym: MinValue - i.reqStringOrSymbol sym + i.reqStringLike sym let res = i.scope.delSymbol(sym.getString) if not res: raiseUndefined("Attempting to delete undefined symbol: " & sym.getString)

@@ -143,28 +143,42 @@ i.withScope(qscope):

i.unquote("<with-program>", qprog) .symbol("call") do (i: In): - var symbols, target: MinValue - i.reqTwoQuotations symbols, target - let vals = symbols.qVal - var q: MinValue - if vals.len == 0: - raiseInvalid("No symbol to call") + var symbol, q: Minvalue + i.reqStringLike symbol + i.reqQuotation q + let s = symbol.getString let origScope = i.scope - i.scope = target.scope - for c in 0..vals.len-1: - if not vals[c].isStringLike: - raiseInvalid("Quotation must contain only symbols or strings") - let symbol = vals[c].getString - let qProc = i.scope.getSymbol(symbol) - if qProc.isNil: - raiseUndefined("Symbol '$1' not found in scope '$2'" % [symbol, i.scope.fullname]) - qProc(i) - if vals.len > 1 and c < vals.len-1: - q = i.pop - if not q.isQuotation: - raiseInvalid("Unable to evaluate symbol '$1'" % [symbol]) - i.scope = q.scope + i.scope = q.scope + let sProc = i.scope.getSymbol(s) + if sProc.isNil: + raiseUndefined("Symbol '$1' not found in scope '$2'" % [s, i.scope.fullname]) + sProc(i) i.scope = origScope + # Restore original quotation + i.push @[q] + + #var symbols, target: MinValue + #i.reqTwoQuotations symbols, target + #let vals = symbols.qVal + #var q: MinValue + #if vals.len == 0: + # raiseInvalid("No symbol to call") + #let origScope = i.scope + #i.scope = target.scope + #for c in 0..vals.len-1: + # if not vals[c].isStringLike: + # raiseInvalid("Quotation must contain only symbols or strings") + # let symbol = vals[c].getString + # let qProc = i.scope.getSymbol(symbol) + # if qProc.isNil: + # raiseUndefined("Symbol '$1' not found in scope '$2'" % [symbol, i.scope.fullname]) + # qProc(i) + # if vals.len > 1 and c < vals.len-1: + # q = i.pop + # if not q.isQuotation: + # raiseInvalid("Unable to evaluate symbol '$1'" % [symbol]) + # i.scope = q.scope + #i.scope = origScope .symbol("inspect") do (i: In): var scope: MinValue
M lib/min_net.nimlib/min_net.nim

@@ -7,9 +7,12 @@ ../core/utils

# Network +proc close(i: In) = + discard + define("net") - .symbol("open-socket") do (i: In): + .symbol("^socket") do (i: In): var q: MinValue i.reqQuotation q # (ipv4 stream tcp)

@@ -58,8 +61,8 @@ q.to(Socket).close()

.symbol("listen") do (i: In): var port, q: MinValue - i.reqInt port i.reqObject "socket", q + i.reqInt port var socket = q.to(Socket) socket.bindAddr(Port(port.intVal)) q.qVal.add "0.0.0.0".newSym
M lib/prelude.minlib/prelude.min

@@ -18,7 +18,7 @@ (getenv) ($) sigil

(system) (!) sigil (run) (&) sigil (load) (@) sigil -(":" split call) (%) sigil +(call) (%) sigil ; Aliases 'define ::

@@ -77,11 +77,12 @@ ; Other

(print pop) :print! (put pop) :put! (:ms :q :check (check) (ms sleep q) while) :interval +(call pop) :call! ; Socket constructors -((ipv4 stream tcp) socket) :tcp-socket -((ipv6 stream tcp) socket) :tcp6-socket -((ipv4 dgram tcp) socket) :udp-socket -((ipv6 dgram tcp) socket) :udp6-socket +((ipv4 stream tcp) ^socket) :tcp-socket +((ipv6 stream tcp) ^socket) :tcp6-socket +((ipv4 dgram tcp) ^socket) :udp-socket +((ipv6 dgram tcp) ^socket) :udp6-socket
M tests/lang.mintests/lang.min

@@ -3,7 +3,7 @@ #test

"lang" describe - (symbols size 179 ==) assert + (symbols size 180 ==) assert (sigils size 10 ==) assert

@@ -34,7 +34,7 @@ ; Extend an existing scope

(defmod (#mymath (-) :myminus) => .mymath - 5 2 mymath %myminus 3 ==) assert + 5 2 mymath %myminus pop 3 ==) assert (defmod mymath inspect ("myplus") ==) assert

@@ -45,7 +45,7 @@

("2 2 +" "tests/testload.min" fwrite @testload 4 ==) assert "tests/testload.min" rm - (defmod 2 2 mymath %myplus 4 ==) assert + (defmod 2 2 mymath %myplus pop 4 ==) assert (1 2 3 4 getstack (1 2 3 4) ==) assert