all repos — min @ cc77a4c122fb4b88255c4e8b51d4786a91da2d61

A small but practical concatenative programming language.

Implemented typealias (nodoc, notest)
h3rald h3rald@h3rald.com
Fri, 05 Feb 2021 21:42:04 +0000
commit

cc77a4c122fb4b88255c4e8b51d4786a91da2d61

parent

0c9ea7fdb038256cf4aad7e576679d2bfdc7c891

2 files changed, 63 insertions(+), 29 deletions(-)

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

@@ -171,6 +171,34 @@ return res.newVal

# Validators +proc validate*(i: In, value: MinValue, t: string, generics: var CritBitTree[string]): bool {.gcsafe.} + +proc validateValueType*(i: var MinInterpreter, element: string, value: MinValue, generics: var CritBitTree[string], vTypes: var seq[string], c: int): bool {.gcsafe.} = + vTypes.add value.typeName + let ors = element.split("|") + for to in ors: + let ands = to.split("&") + var andr = true + for ta in ands: + var t = ta + var neg = false + if t.len > 1 and t[0] == '!': + t = t[1..t.len-1] + neg = true + andr = i.validate(value, t, generics) + if neg: + andr = not andr + if not andr: + echo t + if neg: + vTypes[c] = t + else: + vTypes[c] = value.typeName + break + if andr: + result = true + break + proc basicValidate*(i: In, value: MinValue, t: string): bool = case t: of "bool":

@@ -196,6 +224,8 @@ return value.isString

of "a": return true else: + let tc = "typeclass:$#" % t + let ta = "typealias:$#" % t if t.contains(":"): var split = t.split(":") # Typed dictionaries

@@ -203,7 +233,14 @@ if split[0] == "dict":

if value.isTypedDictionary(split[1]): return true return false - elif i.scope.hasSymbol("typeclass:$#" % t): + elif i.scope.hasSymbol(ta): + # Custom type alias + let element = i.scope.getSymbol(ta).val.getString + var fakeGenerics: CritBitTree[string] + var vTypes = newSeq[string](0) + var c = 0 + return i.validateValueType(element, value, fakeGenerics, vTypes, c) + elif i.scope.hasSymbol(tc): # Custom type class var i2 = i.copy(i.filename) i2.withScope():

@@ -235,19 +272,23 @@ if ts.contains(s):

return true if i.scope.hasSymbol("typeclass:$#" % s): return true - for ta in s.split("&"): - for to in ta.split("|"): + for ta in s.split("|"): + for to in ta.split("&"): var tt = to if to.len < 2: return false if to[0] == '!': tt = to[1..to.len-1] if not ts.contains(tt) and not tt.startsWith("dict:") and not i.scope.hasSymbol("typeclass:$#" % tt): + let ta = "typealias:$#" % tt + if i.scope.hasSymbol(ta): + return i.validType(i.scope.getSymbol(ta).val.getString) return false return true + # The following is used in operator signatures -proc expect*(i: var MinInterpreter, elements: varargs[string], generics: var CritBitTree[string]): seq[MinValue] = +proc expect*(i: var MinInterpreter, elements: varargs[string], generics: var CritBitTree[string]): seq[MinValue] {.gcsafe.}= let sym = i.currSym.getString var valid = newSeq[string](0) result = newSeq[MinValue](0)

@@ -271,29 +312,7 @@ var c = 0

for el in elements: let value = i.pop result.add value - vTypes.add value.typeName - let ors = el.split("|") - for to in ors: - let ands = to.split("&") - var andr = true - for ta in ands: - var t = ta - var neg = false - if t.len > 1 and t[0] == '!': - t = t[1..t.len-1] - neg = true - andr = i.validate(value, t, generics) - if neg: - andr = not andr - if not andr: - if neg: - vTypes[c] = t - else: - vTypes[c] = value.typeName - break - if andr: - res = true - break + res = i.validateValueType(el, value, generics, vTypes, c) if res: valid.add el elif generics.hasKey(el):
M minpkg/lib/min_lang.nimminpkg/lib/min_lang.nim

@@ -34,7 +34,7 @@ let HELP = HELPFILE.parseJson

when not defined(mini): - def.symbol("from-json") do (i: In): + def.symbol("from-json") do (i: In) {.gcsafe.}: let vals = i.expect("str") let s = vals[0] i.push i.fromJson(s.getString.parseJson)

@@ -476,6 +476,21 @@ info "[define] $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, quotation: isQuot) + + def.symbol("typealias") do (i: In): + let vals = i.expect("'sym", "'sym") + let sym = vals[0].getString + var s = vals[1].getString + if not i.validType(s): + raiseInvalid("Invalid type expression: $#" % s) + let symbol = "typealias:"&sym + when not defined(mini): + if not sym.match USER_SYMBOL_REGEX: + raiseInvalid("Symbol identifier '$1' contains invalid characters." % sym) + info "[typealias] $1 = $2" % [sym, s] + 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: s.newVal, sealed: false, quotation: false) def.symbol("lambda") do (i: In): let vals = i.expect("'sym", "quot")

@@ -976,7 +991,7 @@ def.symbol("expect") do (i: In):

var q: MinValue i.reqQuotationOfSymbols q i.push(i.expect(q.qVal.mapIt(it.getString())).reversed.newVal) - + def.symbol("infix-dequote") do (i: In): let vals = i.expect("quot") let q = vals[0]