all repos — min @ d0572f4219fdb5803259d58d64ad1eb778f317b4

A small but practical concatenative programming language.

Implemented generics
h3rald h3rald@h3rald.com
Sat, 16 Jan 2021 23:36:06 +0000
commit

d0572f4219fdb5803259d58d64ad1eb778f317b4

parent

50b274da02e5e784c93463fec91296fac01e2195

2 files changed, 31 insertions(+), 12 deletions(-)

jump to
M minpkg/core/utils.nimminpkg/core/utils.nim

@@ -225,10 +225,10 @@ proc validate*(i: In, value: MinValue, t: string, generics: var CritBitTree[string]): bool =

if generics.hasKey(t): let ts = generics[t].split("|") for tp in ts: - if i.validate(value, tp, generics): + if i.basicValidate(value, tp): generics[t] = tp # lock type for future uses within same signature return true - return false + return false return i.basicValidate(value, t) proc validate*(i: In, value: MinValue, t: string): bool =

@@ -246,18 +246,25 @@ return false

return true proc expect*(i: var MinInterpreter, elements: varargs[string], generics: var CritBitTree[string]): seq[MinValue] = - let stack = elements.reverse.join(" ") let sym = i.currSym.getString var valid = newSeq[string](0) result = newSeq[MinValue](0) - let message = proc(invalid: string): string = - result = "Symbol: $1 - Incorrect values found on the stack:\n" % sym + let message = proc(invalid: string, elements: varargs[string], generics: CritBitTree[string]): string = + var pelements = newSeq[string](0) + for e in elements.reverse: + if generics.hasKey(e): + pelements.add(generics[e]) + else: + pelements.add e + let stack = pelements.reverse.join(" ") + result = "Incorrect values found on the stack:\n" result &= "- expected: " & stack & " $1\n" % sym var other = "" if valid.len > 0: other = valid.reverse.join(" ") & " " result &= "- got: " & invalid & " " & other & sym - for element in elements: + for el in elements: + var element = el let value = i.pop result.add value var split = element.split("|")

@@ -268,10 +275,13 @@ if i.validate(value, t, generics):

res = true break if not res: - raiseInvalid(message(value.typeName)) + raiseInvalid(message(value.typeName, elements, generics)) elif not i.validate(value, element, generics): - raiseInvalid(message(value.typeName)) - valid.add element + raiseInvalid(message(value.typeName, elements, generics)) + if generics.hasKey(el): + valid.add(generics[el]) + else: + valid.add element proc expect*(i: var MinInterpreter, elements: varargs[string]): seq[MinValue] = let stack = elements.reverse.join(" ")

@@ -279,7 +289,7 @@ let sym = i.currSym.getString

var valid = newSeq[string](0) result = newSeq[MinValue](0) let message = proc(invalid: string): string = - result = "Symbol: $1 - Incorrect values found on the stack:\n" % sym + result = "Incorrect values found on the stack:\n" result &= "- expected: " & stack & " $1\n" % sym var other = "" if valid.len > 0:
M minpkg/lib/min_lang.nimminpkg/lib/min_lang.nim

@@ -192,6 +192,7 @@ var inVars = newSeq[string](0)

var outExpects= newSeq[string](0) var outVars = newSeq[string](0) var generics: CritBitTree[string] + var origGenerics: CritBitTree[string] var o= false for vv in sv.qVal: if not vv.isSymbol and not vv.isQuotation:

@@ -234,6 +235,7 @@ inVars.add v[1..v.len-1]

c.inc() if not o: raiseInvalid("No output specified in signature") + origGenerics = deepCopy(generics) # Process body var bv = q.qVal[3] if not bv.isQuotation:

@@ -241,7 +243,12 @@ raiseInvalid("Body must be a quotation")

inExpects.reverse inVars.reverse var p: MinOperatorProc = proc (i: In) = - var inVals = i.expect(inExpects, generics) + var inVals: seq[MinValue] + try: + inVals = i.expect(inExpects, generics) + except: + generics = origGenerics + raise i.withScope(): # Inject variables for mapped inputs for k in 0..inVars.len-1:

@@ -282,7 +289,9 @@ discard i.pop

var tp = t if generics.hasKey(o): tp = generics[o] - raiseInvalid("Invalid value for output symbol '$#'. Expected $#, found $#" % [outVars[k], tp, $x]) + generics = origGenerics + raiseInvalid("Invalid value for output symbol '$#'. Expected $#, found $#" % [outVars[k], tp, $x]) + generics = origGenerics # Define symbol/sigil if t == "symbol": if i.scope.symbols.hasKey(n) and i.scope.symbols[n].sealed: