all repos — min @ e662b1fe575f7c9a5f718dd62b9ba3b37a6f7154

A small but practical concatenative programming language.

minpkg/core/scope.nim

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
import
  std/[strutils,
  critbits]
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 getSymbol*(scope: ref MinScope, key: string, acc = 0): MinOperator =
  if scope.symbols.hasKey(key):
    return scope.symbols[key]
  else:
    if scope.parent.isNil:
      raiseUndefined("Symbol '$1' not found." % key)
    return scope.parent.getSymbol(key, acc + 1)

proc hasSymbol*(scope: ref MinScope, key: string): bool =
  if scope.isNil:
    return false
  elif scope.symbols.hasKey(key):
    return true
  elif not scope.parent.isNil:
    return scope.parent.hasSymbol(key)
  else:
    return false

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
  return false

proc setSymbol*(scope: ref MinScope, key: string, value: MinOperator,
    override = false): bool {.discardable.} =
  result = false
  # check if a symbol already exists in current scope
  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
    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)

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