all repos — min @ fcaf01a5f2ed3fdf96fdc6a32585ec5b2ee87492

A small but practical concatenative programming language.

Typeclasses can now inly be created with the operator symbol.
h3rald h3rald@h3rald.com
Thu, 28 Jan 2021 21:21:13 +0000
commit

fcaf01a5f2ed3fdf96fdc6a32585ec5b2ee87492

parent

f6e5e809f75530270a22a533c974caf60622fe5e

3 files changed, 23 insertions(+), 21 deletions(-)

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

@@ -203,12 +203,12 @@ if split[0] == "dict":

if value.isTypedDictionary(split[1]): return true return false - elif i.scope.hasSymbol("type:$#" % t): + elif i.scope.hasSymbol("typeclass:$#" % t): # Custom type class var i2 = i.copy(i.filename) i2.withScope(): i2.push value - i2.pushSym("type:$#" % t) + i2.pushSym("typeclass:$#" % t) let res = i2.pop if not res.isBool: raiseInvalid("Type class '$#' does not evaluate to a boolean value ($# was returned instead)" % [t, $res])

@@ -233,10 +233,10 @@ proc validType*(i: In, s: string): bool =

const ts = ["bool", "null", "int", "num", "flt", "quot", "dict", "'sym", "sym", "str", "a"] if ts.contains(s): return true - if i.scope.hasSymbol("type:$#" % s): + if i.scope.hasSymbol("typeclass:$#" % s): return true for tt in s.split("|"): - if not ts.contains(tt) and not tt.startsWith("dict:") and not i.scope.hasSymbol("type:$#" % tt): + if not ts.contains(tt) and not tt.startsWith("dict:") and not i.scope.hasSymbol("typeclass:$#" % tt): return false return true
M minpkg/lib/min_lang.nimminpkg/lib/min_lang.nim

@@ -168,16 +168,19 @@ let q = vals[0]

if q.qVal.len != 4: raiseInvalid("Invalid operator definition") let tv = q.qVal[0] - if not tv.isSymbol or (tv.symVal != "symbol" and tv.symVal != "sigil"): - raiseInvalid("Incorrect operator type specified (it must be 'symbol' or 'sigil', found '$#')" % tv.symVal) let t = tv.symVal let nv = q.qVal[1] + if not tv.isSymbol or (not ["symbol", "sigil", "typeclass"].contains(t)): + raiseInvalid("Incorrect operator type specified (it must be 'symbol', 'sigil', or 'typeclass' - found '$#')" % tv.symVal) + if not nv.isSymbol: raiseInvalid("Operator name must be a symbol") - let n = nv.symVal + var n = nv.symVal when not defined(mini): if not n.match(USER_SYMBOL_REGEX): - raiseInvalid("Operator name must not contain ivalid characters") + raiseInvalid("Operator name must not contain invalid characters") + if t == "typeclass": + n = "typeclass:"&n # Validate signature let sv = q.qVal[2] if not sv.isQuotation:

@@ -225,8 +228,12 @@ elif not i.validType(v) and not generics.hasKey(v):

raiseInvalid("Invalid type specified in signature at position $#" % $(c+1)) else: if o: + if tv.symVal == "typeclass" and (outExpects.len > 0 or v != "bool"): + raiseInvalid("typeclasses can only have one boolean output value") outExpects.add v else: + if tv.symVal == "typeclass" and inExpects.len > 0: + raiseInvalid("typeclasses can only have one input value") inExpects.add v else: if v[0] != ':':

@@ -303,7 +310,7 @@ doc["name"] = %n

doc["kind"] = %t doc["signature"] = %docSig doc["description"] = %i.currSym.docComment.strip - if t == "symbol": + if ["symbol", "typeclass"].contains(t): if i.scope.symbols.hasKey(n) and i.scope.symbols[n].sealed: raiseUndefined("Attempting to redefine sealed symbol '$1'" % [n]) i.scope.symbols[n] = MinOperator(kind: minProcOp, prc: p, sealed: false, doc: doc)

@@ -499,16 +506,6 @@

def.symbol("type") do (i: In): let vals = i.expect("a") i.push vals[0].typeName.newVal - - def.symbol("typeclass") do (i: In): - let vals = i.expect("'sym", "quot") - let name = vals[0].getString - let symbol = "type:$#" % name - let code = vals[1] - info "[typeclass] $1 = $2" % [symbol, $code] - if i.scope.symbols.hasKey(symbol) and i.scope.symbols[symbol].sealed: - raiseUndefined("Attempting to redefine sealed typeclass '$1'" % [name]) - i.scope.symbols[symbol] = MinOperator(kind: minValOp, val: code, sealed: false, quotation: true) def.symbol("symbol-help") do (i: In): let vals = i.expect("'sym")
M tests/lang.mintests/lang.min

@@ -254,8 +254,13 @@ ) ::

nt"flt" ) *test/assert - (:n ((n integer?) (n 0 >)) &&) 'natural typeclass - ("type:natural" defined-symbol?) *test/assert + ; (:n ((n integer?) (n 0 >)) &&) 'natural typeclass + ( + typeclass natural + (int :n ==> bool :out) + (((n integer?) (n 0 >)) && @out) + ) :: + ("typeclass:natural" defined-symbol?) *test/assert ( symbol natural-sum (natural :n natural :m ==> natural :result)