all repos — min @ b697fc22b09e22f2ddb54bcbd920a76fdd598c9d

A small but practical concatenative programming language.

Started re-implementing socket symbols as object methods.
h3rald h3rald@h3rald.com
Fri, 24 Jun 2016 13:26:12 +0200
commit

b697fc22b09e22f2ddb54bcbd920a76fdd598c9d

parent

8357584593a7963b548eff370c08031c9b089199

6 files changed, 73 insertions(+), 36 deletions(-)

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

@@ -81,6 +81,7 @@ debugging*: bool

evaluating*: bool unsafe*: bool In* = var MinInterpreter + Val* = var MinValue MinOperator* = proc (i: In) MinSigil* = proc (i: In, sym: string) MinParsingError* = ref object of ValueError
M core/utils.nimcore/utils.nim

@@ -22,6 +22,12 @@

proc isBool*(s: MinValue): bool = return s.kind == minBool +proc isStringLike*(s: MinValue): bool = + return s.isSymbol or s.isString or (s.isQuotation and s.qVal.len == 1 and s.qVal[0].isSymbol) + +proc isObject*(a: MinValue, t: string): bool = + return a.isQuotation and not a.objType.isNil and a.objType == t + proc newVal*(s: string): MinValue = return MinValue(kind: minString, strVal: s)

@@ -43,9 +49,6 @@

proc newSym*(s: string): MinValue = return MinValue(kind: minSymbol, symVal: s) -proc isStringLike*(s: MinValue): bool = - 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) =

@@ -66,11 +69,11 @@ return v.symVal

elif v.isString: return v.strVal elif v.isQuotation: - if v.qVal.len == 1: + if v.qVal.len != 1: raiseInvalid("Quotation is not a quoted symbol") let sym = v.qVal[0] if sym.isSymbol: - return v.symVal + return sym.symVal else: raiseInvalid("Quotation is not a quoted symbol")

@@ -94,6 +97,13 @@ scope.symbols[sym] = p

#if not scope.parent.isNil: # scope.parent.symbols[scope.name & ":" & sym] = p return scope + +proc localSymbol*(i: In, obj: MinValue, objType: string, body: MinOperator): MinOperator = + if not obj.isObject(objType): + raiseInvalid("Object is not a socket") + return proc(i: In) = + i.push @[obj] + i.body() proc sigil*(scope: ref MinScope, sym: string, p: MinOperator): ref MinScope = scope.previous.sigils[sym] = p

@@ -227,5 +237,5 @@ raiseInvalid("Two non-symbol values of similar type are required on the stack")

proc reqObject*(i: var MinInterpreter, t: string, a: var MinValue) = a = i.pop - if not a.isQuotation or a.objType.isNil or a.objType != t: + if not a.isObject(t): raiseInvalid("A $1 object is required" % [t])
M lib/min_lang.nimlib/min_lang.nim

@@ -152,9 +152,9 @@ 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]) + # Restore original quotation sProc(i) i.scope = origScope - # Restore original quotation i.push @[q] #var symbols, target: MinValue
M lib/min_net.nimlib/min_net.nim

@@ -7,8 +7,39 @@ ../core/utils

# Network -proc close(i: In) = - discard +var symbols*: CritBitTree[proc(obj: Val, i: In): MinOperator] + +proc socketSymbol(name: string, body: proc(q: Val, i: In))= + symbols[name] = proc(obj: Val, i: In): MinOperator = + i.localSymbol(obj, "socket") do (i: In): + var q: MinValue + i.reqObject "socket", q + q.body(i) + +socketSymbol("domain") do (q: Val, i: In): + i.push q.qVal[0].symVal.newVal + +socketSymbol("type") do (q: Val, i: In): + i.push q.qVal[1].symVal.newVal + +socketSymbol("protocol") do (q: Val, i: In): + i.push q.qVal[2].symVal.newVal + +socketSymbol("close") do (q: Val, i: In): + q.to(Socket).close() + +socketSymbol("listen") do (q: Val, i: In): + var port: MinValue + i.reqInt port + var socket = q.to(Socket) + socket.bindAddr(Port(port.intVal)) + q.qVal.add "0.0.0.0".newSym + q.qVal.add port + q.scope.symbols["address"] = proc (i:In) = + i.push "0.0.0.0".newVal + q.scope.symbols["port"] = proc (i:In) = + i.push port + socket.listen() define("net")

@@ -46,39 +77,32 @@ var socket = newSocket(domain, sockettype, protocol)

q.objType = "socket" q.obj = socket[].addr i.newScope("<socket>", q) - q.scope.symbols["protocol"] = proc (i:In) = - i.push vals[2].symVal.newVal - q.scope.symbols["type"] = proc (i:In) = - i.push vals[1].symVal.newVal - q.scope.symbols["domain"] = proc (i:In) = - i.push vals[0].symVal.newVal + q.scope.symbols["domain"] = symbols["domain"](q, i) + q.scope.symbols["type"] = symbols["type"](q, i) + q.scope.symbols["protocol"] = symbols["protocol"](q, i) + q.scope.symbols["close"] = symbols["close"](q, i) + q.scope.symbols["listen"] = symbols["listen"](q, i) i.push @[q] - .symbol("close-socket") do (i: In): - var q: MinValue - i.reqObject "socket", q - q.to(Socket).close() - - .symbol("listen") do (i: In): - var port, q: MinValue - 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 - q.qVal.add port - q.scope.symbols["address"] = proc (i:In) = - i.push "0.0.0.0".newVal - q.scope.symbols["port"] = proc (i:In) = - i.push port - socket.listen() - i.push @[q] + #.symbol("listen") do (i: In): + # var port, q: MinValue + # 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 + # q.qVal.add port + # q.scope.symbols["address"] = proc (i:In) = + # i.push "0.0.0.0".newVal + # q.scope.symbols["port"] = proc (i:In) = + # i.push port + # socket.listen() + # i.push @[q] .symbol("accept") do (i: In): var server: MinValue i.reqObject "socket", server # Open same socket type as server - echo $server i.eval "$1 net %open-socket" % [$server.qVal[0..2].newVal] var clientVal: MinValue i.reqObject "socket", clientVal
M lib/prelude.minlib/prelude.min

@@ -48,6 +48,7 @@ 'filter :select

'clear :empty 'cons :prepend 'size :length +'swap :<> ; Mathematical Operators (1 +) :succ

@@ -78,6 +79,7 @@ (print pop) :print!

(put pop) :put! (:ms :q :check (check) (ms sleep q) while) :interval (call pop) :call! +(swap pop) :<!> ; Socket constructors ((ipv4 stream tcp) ^socket) :tcp-socket
M tests/lang.mintests/lang.min

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

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