all repos — min @ 50a2b9ebd8bd90d3cc977896b44f653c6fbbfcc9

A small but practical concatenative programming language.

More refactoring on symbol definitions.
h3rald h3rald@h3rald.com
Tue, 18 Jun 2024 13:07:00 +0200
commit

50a2b9ebd8bd90d3cc977896b44f653c6fbbfcc9

parent

e3170f6ceb89e049f37709fecda01dee526a8990

5 files changed, 188 insertions(+), 189 deletions(-)

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

@@ -13,7 +13,6 @@ logging]

import baseutils, value, - scope, parser type

@@ -467,6 +466,7 @@ for key, value in i2.scope.symbols.pairs:

var v = value if v.kind == minProcOp: v.mdl = result + #result.scope.setSymbol(key, v) result.scope.symbols[key] = v CACHEDMODULES[s] = result
M minpkg/core/parser.nimminpkg/core/parser.nim

@@ -5,6 +5,7 @@ strutils,

sequtils, streams, critbits, + logging, json] import

@@ -697,6 +698,9 @@ d = d & ";" & a.objType

d = d.strip & "}" return d +proc setSymbol*(scope: ref MinScope, key: string, value: MinOperator, + override = false, define = false): bool {.discardable.} + proc parseMinValue*(p: var MinParser, i: In): MinValue = case p.token of tkNull:

@@ -861,8 +865,8 @@ result.add indent&valvar&" = "&vs

elif v.kind == minSymbol: let key = v.symVal if key[0] == ':': - result.add indent&scopevar&".symbols["&key[1 .. - key.len-1]&"] = MinOperator(kind: minValOp, val: "&valvar&", sealed: false)" + result.add indent&scopevar&".setSymbol("&key[1 .. + key.len-1]&"), MinOperator(kind: minValOp, val: "&valvar&", sealed: false))" val = nil else: raiseInvalid("Invalid dictionary key: " & key)

@@ -990,3 +994,182 @@ else:

return false else: return false + +## Scope-related methods + +proc copy*(s: ref MinScope): ref MinScope = + var scope = newScope(s.parent) + scope.symbols = s.symbols + scope.sigils = s.sigils + new(result) + result[] = scope + +proc getDictionary(d: MinOperator): MinValue = + if d.kind == minProcOp: + return d.mdl + elif d.kind == minValOp and d.val.kind == minQuotation and d.val.qVal.len == + 1 and d.val.qVal[0].kind == minDictionary: + return d.val.qVal[0] + elif d.kind == minValOp and d.val.kind == minDictionary: + return d.val + +proc getSymbolFromPath(scope: ref MinScope, keys: var seq[ + string]): MinOperator + +proc isNull*(op: MinOperator): bool = + return op.kind == minValOp and op.val.kind == minNull + +proc getSymbol*(scope: ref MinScope, key: string): MinOperator = + debug "getSymbol: $#" % [key] + if scope.symbols.hasKey(key): + return scope.symbols[key] + elif key.contains ".": + var keys = key.split(".") + return getSymbolFromPath(scope, keys) + else: + if scope.parent.isNil: + 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 = + let sym = keys[0] + keys.delete(0) + let d = scope.getSymbol(sym) + let dict = d.getDictionary + if not dict.isNil: + if keys.len > 1: + return dict.scope.getSymbolFromPath(keys) + else: + return dict.scope.getSymbol(keys[0]) + 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 delSymbol*(scope: ref MinScope, key: string): bool {.discardable.} = + if scope.symbols.hasKey(key): + if scope.symbols[key].sealed: + raiseInvalid("Symbol '$1' is sealed." % key) + scope.symbols.excl(key) + return true + elif key.contains ".": + var keys = key.split(".") + return delSymbolFromPath(scope, keys) + return false + +proc delSymbolFromPath(scope: ref MinScope, keys: var seq[ + string]): bool = + let sym = keys[0] + keys.delete(0) + let d = scope.getSymbol(sym) + let dict = d.getDictionary + if not dict.isNil: + if keys.len > 1: + return dict.scope.delSymbolFromPath(keys) + else: + return dict.scope.delSymbol(keys[0]) + else: + raiseInvalid("Symbol '$1' is not a dictionary." % sym) + +proc setSymbolFromPath(scope: ref MinScope, keys: var seq[ + string], value: MinOperator, override = false, + define = false): bool {.discardable.} + +proc setSymbol*(scope: ref MinScope, key: string, value: MinOperator, + override = false, define = false): bool {.discardable.} = + result = false + # check if a symbol already exists in current scope + debug "setSymbol: $#" % [key] + if not scope.isNil and scope.symbols.hasKey(key): + if not override and scope.symbols[key].sealed: + raiseInvalid("Symbol '$1' is sealed ." % key) + scope.symbols[key] = value + debug "setSymbol (existing): $# = $#" % [key, $value] + result = true + elif key.contains ".": + var keys = key.split(".") + return setSymbolFromPath(scope, keys, value, override, define) + # define new symbol + elif not scope.isNil and define: + debug "setSymbol (new): $# = $#" % [key, $value] + scope.symbols[key] = value + result = true + else: + # Go up the scope chain and attempt to find the symbol + if not scope.parent.isNil: + result = scope.parent.setSymbol(key, value, override, define) + else: + debug "setSymbol: failure to set: $# = $#" % [key, $value] + +proc setSymbolFromPath(scope: ref MinScope, keys: var seq[ + string], value: MinOperator, override = false, + define = false): bool {.discardable.} = + let sym = keys[0] + keys.delete(0) + let d = scope.getSymbol(sym) + let dict = d.getDictionary + debug "setSymbolFromPath: Found dictionary $# - keys: $#" % [sym, keys.join(".")] + if not dict.isNil: + if keys.len > 1: + return dict.scope.setSymbolFromPath(keys, value, override, define) + else: + return dict.scope.setSymbol(keys[0], value, override, define) + else: + raiseInvalid("Symbol '$1' is not a dictionary." % sym) + +proc getSigil*(scope: ref MinScope, key: string): MinOperator = + if scope.sigils.hasKey(key): + return scope.sigils[key] + elif not scope.parent.isNil: + return scope.parent.getSigil(key) + else: + raiseUndefined("Sigil '$1' not found." % key) + +proc hasSigil*(scope: ref MinScope, key: string): bool = + if scope.isNil: + return false + elif scope.sigils.hasKey(key): + return true + elif not scope.parent.isNil: + return scope.parent.hasSigil(key) + else: + return false + +proc delSigil*(scope: ref MinScope, key: string): bool {.discardable.} = + if scope.sigils.hasKey(key): + if scope.sigils[key].sealed: + raiseInvalid("Sigil '$1' is sealed." % key) + scope.sigils.excl(key) + return true + return false + +proc setSigil*(scope: ref MinScope, key: string, value: MinOperator, + override = false): bool {.discardable.} = + result = false + # check if a sigil already exists in current scope + if not scope.isNil and scope.sigils.hasKey(key): + if not override and scope.sigils[key].sealed: + raiseInvalid("Sigil '$1' is sealed." % key) + scope.sigils[key] = value + result = true + else: + # Go up the scope chain and attempt to find the sigil + if not scope.parent.isNil: + result = scope.parent.setSymbol(key, value) + +proc previous*(scope: ref MinScope): ref MinScope = + if scope.parent.isNil: + return scope + else: + return scope.parent + +proc hasParent*(scope: ref MinScope, parent: ref MinScope): bool = + if scope.parent.isNil: + return false + if scope.parent == parent: + return true + return scope.parent.hasParent parent
D minpkg/core/scope.nim

@@ -1,182 +0,0 @@

-import - std/[strutils, critbits, logging] -import - parser - -proc copy*(s: ref MinScope): ref MinScope = - var scope = newScope(s.parent) - scope.symbols = s.symbols - scope.sigils = s.sigils - new(result) - result[] = scope - -proc getDictionary(d: MinOperator): MinValue = - if d.kind == minProcOp: - return d.mdl - elif d.kind == minValOp and d.val.kind == minQuotation and d.val.qVal.len == - 1 and d.val.qVal[0].kind == minDictionary: - return d.val.qVal[0] - elif d.kind == minValOp and d.val.kind == minDictionary: - return d.val - -proc getSymbolFromPath(scope: ref MinScope, keys: var seq[ - string]): MinOperator - -proc isNull*(op: MinOperator): bool = - return op.kind == minValOp and op.val.kind == minNull - -proc getSymbol*(scope: ref MinScope, key: string): MinOperator = - debug "getSymbol: $#" % [key] - if scope.symbols.hasKey(key): - return scope.symbols[key] - elif key.contains ".": - var keys = key.split(".") - return getSymbolFromPath(scope, keys) - else: - if scope.parent.isNil: - 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 = - let sym = keys[0] - keys.delete(0) - let d = scope.getSymbol(sym) - let dict = d.getDictionary - if not dict.isNil: - if keys.len > 1: - return dict.scope.getSymbolFromPath(keys) - else: - return dict.scope.getSymbol(keys[0]) - 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 delSymbol*(scope: ref MinScope, key: string): bool {.discardable.} = - if scope.symbols.hasKey(key): - if scope.symbols[key].sealed: - raiseInvalid("Symbol '$1' is sealed." % key) - scope.symbols.excl(key) - return true - elif key.contains ".": - var keys = key.split(".") - return delSymbolFromPath(scope, keys) - return false - -proc delSymbolFromPath(scope: ref MinScope, keys: var seq[ - string]): bool = - let sym = keys[0] - keys.delete(0) - let d = scope.getSymbol(sym) - let dict = d.getDictionary - if not dict.isNil: - if keys.len > 1: - return dict.scope.delSymbolFromPath(keys) - else: - return dict.scope.delSymbol(keys[0]) - else: - raiseInvalid("Symbol '$1' is not a dictionary." % sym) - -proc setSymbolFromPath(scope: ref MinScope, keys: var seq[ - string], value: MinOperator, override = false, - define = false): bool {.discardable.} - -proc setSymbol*(scope: ref MinScope, key: string, value: MinOperator, - override = false, define = false): bool {.discardable.} = - result = false - # check if a symbol already exists in current scope - debug "setSymbol: $#" % [key] - #debug "setSymbol: scope symbols: $#" % [$scope.symbols.keys.toSeq] - if not scope.isNil and scope.symbols.hasKey(key): - if not override and scope.symbols[key].sealed: - raiseInvalid("Symbol '$1' is sealed ." % key) - scope.symbols[key] = value - debug "setSymbol (existing): $# = $#" % [key, $value] - result = true - elif key.contains ".": - var keys = key.split(".") - return setSymbolFromPath(scope, keys, value, override, define) - # define new symbol - elif not scope.isNil and define: - debug "setSymbol (new): $# = $#" % [key, $value] - scope.symbols[key] = value - result = true - else: - # Go up the scope chain and attempt to find the symbol - if not scope.parent.isNil: - result = scope.parent.setSymbol(key, value, override, define) - else: - debug "setSymbol: failure to set: $# = $#" % [key, $value] - -proc setSymbolFromPath(scope: ref MinScope, keys: var seq[ - string], value: MinOperator, override = false, - define = false): bool {.discardable.} = - let sym = keys[0] - keys.delete(0) - let d = scope.getSymbol(sym) - let dict = d.getDictionary - debug "setSymbolFromPath: Found dictionary $# - keys: $#" % [sym, keys.join(".")] - if not dict.isNil: - if keys.len > 1: - return dict.scope.setSymbolFromPath(keys, value, override, define) - else: - return dict.scope.setSymbol(keys[0], value, override, define) - else: - raiseInvalid("Symbol '$1' is not a dictionary." % sym) - -proc getSigil*(scope: ref MinScope, key: string): MinOperator = - if scope.sigils.hasKey(key): - return scope.sigils[key] - elif not scope.parent.isNil: - return scope.parent.getSigil(key) - else: - raiseUndefined("Sigil '$1' not found." % key) - -proc hasSigil*(scope: ref MinScope, key: string): bool = - if scope.isNil: - return false - elif scope.sigils.hasKey(key): - return true - elif not scope.parent.isNil: - return scope.parent.hasSigil(key) - else: - return false - -proc delSigil*(scope: ref MinScope, key: string): bool {.discardable.} = - if scope.sigils.hasKey(key): - if scope.sigils[key].sealed: - raiseInvalid("Sigil '$1' is sealed." % key) - scope.sigils.excl(key) - return true - return false - -proc setSigil*(scope: ref MinScope, key: string, value: MinOperator, - override = false): bool {.discardable.} = - result = false - # check if a sigil already exists in current scope - if not scope.isNil and scope.sigils.hasKey(key): - if not override and scope.sigils[key].sealed: - raiseInvalid("Sigil '$1' is sealed." % key) - scope.sigils[key] = value - result = true - else: - # Go up the scope chain and attempt to find the sigil - if not scope.parent.isNil: - result = scope.parent.setSymbol(key, value) - -proc previous*(scope: ref MinScope): ref MinScope = - if scope.parent.isNil: - return scope - else: - return scope.parent - -proc hasParent*(scope: ref MinScope, parent: ref MinScope): bool = - if scope.parent.isNil: - return false - if scope.parent == parent: - return true - return scope.parent.hasParent parent
M minpkg/core/utils.nimminpkg/core/utils.nim

@@ -6,7 +6,6 @@ baseutils,

parser, value, json, - scope, env, interpreter
M minpkg/lib/min_global.nimminpkg/lib/min_global.nim

@@ -19,8 +19,7 @@ ../core/meta,

../core/parser, ../core/value, ../core/interpreter, - ../core/utils, - ../core/scope + ../core/utils proc processTokenValue(v: string, t: MinTokenKind): string = case t:

@@ -163,7 +162,7 @@ CACHEDMODULES[f] = newDict(i2.scope)

CACHEDMODULES[f].objType = "module" mdl = CACHEDMODULES[f] for key, value in i2.scope.symbols.pairs: - mdl.scope.symbols[key] = value + mdl.scope.setSymbol(key, value, false, false) i.push(mdl) else: if not f.fileExists: