Reviewing auto-quoting mechanism (a lot of tests still fail)
@@ -209,7 +209,7 @@ op.mdl.scope.parent = origMdlParentScope
else: op.prc(i) else: - if op.val.kind == minQuotation: + if op.val.kind == minQuotation and op.lambda: var newscope = newScopeRef(i.scope) i.withScope(newscope): for e in op.val.qVal:
@@ -111,6 +111,7 @@ minValOp
MinOperator* = object sealed*: bool doc*: JsonNode + lambda*: bool # if true, stored quotation is meant to be executed mdl*: MinValue # Only set in case of modules case kind*: MinOperatorKind of minProcOp:@@ -641,7 +642,10 @@ v = $i.val.val
var k = $i.key if k.contains(" "): k = "\"$1\"" % k - d = d & v & " :" & k & " " + var keyType = " :" + if i.val.lambda: + keyType = " ^" + d = d & v & keyType & k & " " if a.objType != "": d = d & ";" & a.objType d = d.strip & "}"@@ -690,7 +694,10 @@ v = $i.val.val
var k = $i.key if k.contains(" "): k = "\"$1\"" % k - d = d & v & " :" & k & " " + var keyType = " :" + if i.val.lambda: + keyType = " ^" + d = d & v & keyType & k & " " if a.objType != "": d = d & ";" & a.objType d = d.strip & "}"@@ -763,12 +770,11 @@ if val.isNil:
val = v elif v.kind == minSymbol: let key = v.symVal - if key[0] == ':': + if key[0] == ':' or key[0] == '^': var offset = 0 if key[1] == '"': offset = 1 - scope.symbols[key[1+offset .. key.len-1-offset]] = MinOperator( - kind: minValOp, val: val, sealed: false) + scope.symbols[key[1+offset .. key.len-1-offset]] = MinOperator(kind: minValOp, val: val, sealed: false, lambda: key[0] == '^') val = nil else: raiseInvalid("Invalid dictionary key: " & key)@@ -854,9 +860,10 @@ if val.isNil:
val = v elif v.kind == minSymbol: let key = v.symVal - if key[0] == ':': + if key[0] == ':' or key[0] == '^': + let isLambda = key[0] == '^' let symkey = key[1 .. key.len-1] - result.add "i.dset($#, \"$#\", $#.newVal)" % [dictvar, symkey, $val] + result.add "i.dset($#, \"$#\", $#.newVal, lambda: $#)" % [dictvar, symkey, $val, $isLambda] val = nil else: raiseInvalid("Invalid dictionary key: " & key)@@ -972,6 +979,8 @@ let v1 = t.val
let v2 = bVal[t.key] if v1.kind != v2.kind: return false + if v1.lambda != v2.lambda: + return false if v1.kind == minValOp: return v1.val == v2.val if a.objType == "" and b.objType == "":@@ -1020,8 +1029,7 @@ debug("Unable to retrieve symbol '$1' (not found)." % key)
return MinOperator(kind: minValOp, val: MinValue(kind: minNull)) return scope.parent.getSymbol(key) -proc getSymbolFromPath(scope: ref MinScope, keys: var seq[ - string]): MinOperator = +proc getSymbolFromPath(scope: ref MinScope, keys: var seq[string]): MinOperator = let sym = keys[0] keys.delete(0) let d = scope.getSymbol(sym)@@ -1035,8 +1043,7 @@ else:
debug("Symbol '$1' is not a dictionary." % sym) return MinOperator(kind: minValOp, val: MinValue(kind: minNull)) -proc delSymbolFromPath(scope: ref MinScope, keys: var seq[ - string]): bool +proc delSymbolFromPath(scope: ref MinScope, keys: var seq[string]): bool proc delSymbol*(scope: ref MinScope, key: string): bool {.discardable.} = if scope.symbols.hasKey(key):
@@ -153,7 +153,10 @@ if val.val.kind == minProcOp:
v = "<native>".newSym else: v = val.val.val - i.pv(v); p(" :" & $val.key & " ", fgCyan) + var keyType = " :" + if val.val.lambda: + keyType = " ^" + i.pv(v); p(keyType & $val.key & " ", fgCyan) p("}", fgRed) proc printResult(i: In, res: MinValue) =@@ -176,7 +179,10 @@ if item.val.kind == minProcOp:
v = "<native>".newSym else: v = item.val.val - p(" "); i.pv(v); p(" :" & $item.key & "\n", fgCyan) + var keyType = " :" + if item.val.lambda: + keyType = " ^" + p(" "); i.pv(v); p(keyType & $item.key & "\n", fgCyan) if res.objType == "": stdout.write " ".repeat(n.len); p("}\n", fgRed) else:
@@ -16,19 +16,17 @@ var scope = newScopeRef(i.scope, minNativeScope)
scope.parent = i.scope return scope -proc symbol*(scope: ref MinScope, sym: string, - p: MinOperatorProc) {.effectsOf: p.} = - scope.symbols[sym] = MinOperator(prc: p, kind: minProcOp, sealed: true) +proc symbol*(scope: ref MinScope, sym: string, p: MinOperatorProc) {.effectsOf: p.} = + scope.symbols[sym] = MinOperator(prc: p, kind: minProcOp, sealed: true, lambda: true) proc symbol*(scope: ref MinScope, sym: string, v: MinValue) = scope.symbols[sym] = MinOperator(val: v, kind: minValOp, sealed: true) -proc sigil*(scope: ref MinScope, sym: string, - p: MinOperatorProc) {.effectsOf: p.} = - scope.sigils[sym] = MinOperator(prc: p, kind: minProcOp, sealed: true) +proc sigil*(scope: ref MinScope, sym: string, p: MinOperatorProc) {.effectsOf: p.} = + scope.sigils[sym] = MinOperator(prc: p, kind: minProcOp, sealed: true, lambda: true) proc sigil*(scope: ref MinScope, sym: string, v: MinValue) = - scope.sigils[sym] = MinOperator(val: v, kind: minValOp, sealed: true) + scope.sigils[sym] = MinOperator(val: v, kind: minValOp, sealed: true, lambda: true) proc finalize*(scope: ref MinScope, name: string = "") = var mdl = newDict(scope)@@ -46,17 +44,22 @@
proc dget*(i: In, q: MinValue, s: MinValue): MinValue = if not q.isDictionary: raiseInvalid("Value is not a dictionary") - if q.dVal[s.getString].kind == minProcOp: - raiseInvalid("Key '$1' is set to an operator and it cannot be retrieved." % - [s.getString]) - result = q.dVal[s.getString].val + let val = q.dVal[s.getString] + if val.kind == minProcOp: + raiseInvalid("Key '$1' is set to an operator and it cannot be retrieved." % [s.getString]) + if val.lambda: + return val.val + return @[val.val].newVal proc dget*(i: In, q: MinValue, s: string): MinValue = if not q.isDictionary: raiseInvalid("Value is not a dictionary") - if q.dVal[s].kind == minProcOp: + let val = q.dVal[s] + if val.kind == minProcOp: raiseInvalid("Key $1 is set to an operator and it cannot be retrieved." % [s]) - result = q.dVal[s].val + if val.lambda: + return val.val + return @[val.val].newVal proc dhas*(q: MinValue, s: MinValue): bool = if not q.isDictionary:@@ -80,20 +83,22 @@ raiseInvalid("Value is not a dictionary")
excl(p.scope.symbols, s) return p -proc dset*(i: In, p: var MinValue, s: MinValue, - m: MinValue): MinValue {.discardable.} = +proc dset*(i: In, p: var MinValue, s: MinValue, m: MinValue, lambda = false): MinValue {.discardable.} = if not p.isDictionary: raiseInvalid("Value is not a dictionary") var q = m - p.scope.symbols[s.getString] = MinOperator(kind: minValOp, val: q, sealed: false) + #if not lambda: #CLEANUP no longer autoquoting + # q = @[m].newVal + p.scope.symbols[s.getString] = MinOperator(kind: minValOp, val: q, sealed: false, lambda: lambda) return p -proc dset*(i: In, p: var MinValue, s: string, - m: MinValue): MinValue {.discardable.} = +proc dset*(i: In, p: var MinValue, s: string, m: MinValue, lambda = false): MinValue {.discardable.} = if not p.isDictionary: raiseInvalid("Value is not a dictionary") var q = m - p.scope.symbols[s] = MinOperator(kind: minValOp, val: q, sealed: false) + #if not lambda: #CLEANUP no longer autoquoting + # q = @[m].newVal + p.scope.symbols[s] = MinOperator(kind: minValOp, val: q, sealed: false, lambda: lambda) return p proc keys*(i: In, q: MinValue): MinValue =
@@ -41,6 +41,13 @@ let m = vals[1]
var d = vals[2] i.push i.dset(d, k, m) + def.symbol("lambda") do (i: In): + let vals = i.expect("'sym", "quot", "dict") + let k = vals[0] + let m = vals[1] + var d = vals[2] + i.push i.dset(d, k, m, lambda = true) + def.symbol("set-sym") do (i: In): let vals = i.expect("'sym", "'sym", "dict") let k = vals[0]
@@ -347,14 +347,12 @@ i.withScope():
# Inject variables for mapped inputs for k in 0..inVars.len-1: var iv = inVals[k] - if iv.isQuotation: - iv = @[iv].newVal - i.scope.symbols[inVars[k]] = MinOperator(kind: minValOp, - sealed: false, val: iv) + #if iv.isQuotation: #CLEANUP no longer autoquoting + # iv = @[iv].newVal + i.scope.symbols[inVars[k]] = MinOperator(kind: minValOp, sealed: false, val: iv) # Inject variables for mapped outputs for k in 0..outVars.len-1: - i.scope.symbols[outVars[k]] = MinOperator(kind: minValOp, - sealed: false, val: @[newNull()].newVal) + i.scope.symbols[outVars[k]] = MinOperator(kind: minValOp, sealed: false, val: @[newNull()].newVal) # Actually execute the body of the operator if DEV: var endSnapshot: seq[MinValue]@@ -376,8 +374,8 @@ discard
# Validate output for k in 0..outVars.len-1: var x = i.scope.symbols[outVars[k]].val - if rawOutVars[k][0] == ':': - x = x.qVal[0] + #if rawOutVars[k][0] == ':': #CLEANUP no longer auto-quoting + # x = x.qVal[0] if t == "constructor": x.objType = n if DEV:@@ -399,6 +397,7 @@ generics = origGenerics
raiseInvalid("Invalid value for output symbol '$#'. Expected $#, found $#" % [outVars[k], tp, $x]) # Push output on stack + debug "Operator - pushing: $#" % [outVars[k]] i.pushSym outVars[k] generics = origGenerics # Define symbol/sigil@@ -416,9 +415,9 @@ if i.scope.sigils.hasKey(n) and i.scope.sigils[n].sealed:
raiseUndefined("Attempting to redefine sealed sigil '$1'" % [n]) if i.scope.symbols.hasKey(n) and i.scope.symbols[n].sealed: raiseUndefined("Attempting to redefine sealed symbol '$1'" % [n]) - i.scope.sigils[n] = MinOperator(kind: minProcOp, prc: p, sealed: true, doc: doc) + i.scope.sigils[n] = MinOperator(kind: minProcOp, prc: p, sealed: true, doc: doc, lambda: true) # Define a symbol with the same name as the sigil - i.scope.symbols[n] = MinOperator(kind: minProcOp, prc: p, sealed: false, doc: doc) + i.scope.symbols[n] = MinOperator(kind: minProcOp, prc: p, sealed: false, doc: doc, lambda: true) def.symbol("expect-empty-stack") do (i: In): let l = i.stack.len@@ -542,15 +541,14 @@
def.symbol("define") do (i: In): let vals = i.expect("'sym", "a") let sym = vals[0] - var q1 = vals[1] # existing (auto-quoted) + var q1 = vals[1] var symbol: string - q1 = @[q1].newVal + #q1 = @[q1].newVal symbol = sym.getString if not symbol.contains re(USER_PATH_SYMBOL_REGEX): raiseInvalid("Symbol identifier '$1' contains invalid characters." % symbol) info "[define] $1 = $2" % [symbol, $q1] - i.scope.setSymbol(symbol, MinOperator(kind: minValOp, val: q1, - sealed: false), false, true) + i.scope.setSymbol(symbol, MinOperator(kind: minValOp, val: q1, sealed: false), false, true) def.symbol("typealias") do (i: In): let vals = i.expect("'sym", "'sym")@@ -578,8 +576,7 @@ raiseInvalid("Symbol identifier '$1' contains invalid characters." % symbol)
info "[lambda] $1 = $2" % [symbol, $q1] if i.scope.symbols.hasKey(symbol) and i.scope.symbols[symbol].sealed: raiseUndefined("Attempting to redefine sealed symbol '$1'" % [symbol]) - i.scope.symbols[symbol] = MinOperator(kind: minValOp, val: q1, - sealed: false) + i.scope.symbols[symbol] = MinOperator(kind: minValOp, val: q1, sealed: false, lambda: true) def.symbol("define-sigil") do (i: In): let vals = i.expect("'sym", "quot")@@ -594,16 +591,15 @@ if i.scope.sigils.hasKey(symbol) and i.scope.sigils[symbol].sealed:
raiseUndefined("Attempting to redefine sealed sigil '$1'" % [symbol]) if i.scope.symbols.hasKey(symbol) and i.scope.symbols[symbol].sealed: raiseUndefined("Attempting to redefine sealed symbol '$1'" % [symbol]) - i.scope.sigils[symbol] = MinOperator(kind: minValOp, val: q1, sealed: false) - i.scope.symbols[symbol] = MinOperator(kind: minValOp, val: q1, - sealed: false) + i.scope.sigils[symbol] = MinOperator(kind: minValOp, val: q1, sealed: false, lambda: true) + i.scope.symbols[symbol] = MinOperator(kind: minValOp, val: q1, sealed: false, lambda: true) def.symbol("bind") do (i: In): let vals = i.expect("'sym", "a") let sym = vals[0] - var q1 = vals[1] # existing (auto-quoted) + var q1 = vals[1] var symbol: string - q1 = @[q1].newVal + #q1 = @[q1].newVal symbol = sym.getString info "[bind] $1 = $2" % [symbol, $q1] let res = i.scope.setSymbol(symbol, MinOperator(kind: minValOp, val: q1))