123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 |
- package glisp
- import (
- "errors"
- "fmt"
- )
- type Scope map[int]Sexp
- func (s Scope) IsStackElem() {}
- func (stack *Stack) PushScope() {
- stack.Push(Scope(make(map[int]Sexp)))
- }
- func (stack *Stack) PopScope() error {
- _, err := stack.Pop()
- return err
- }
- func (stack *Stack) lookupSymbol(sym SexpSymbol, minFrame int) (Sexp, error) {
- if !stack.IsEmpty() {
- for i := 0; i <= stack.tos-minFrame; i++ {
- elem, err := stack.Get(i)
- if err != nil {
- return SexpNull, err
- }
- scope := map[int]Sexp(elem.(Scope))
- expr, ok := scope[sym.number]
- if ok {
- return expr, nil
- }
- }
- }
- return SexpNull, errors.New(fmt.Sprint("symbol ", sym, " not found"))
- }
- func (stack *Stack) LookupSymbol(sym SexpSymbol) (Sexp, error) {
- return stack.lookupSymbol(sym, 0)
- }
- // LookupSymbolNonGlobal - closures use this to only find symbols below the global scope, to avoid copying globals it'll always be-able to ref
- func (stack *Stack) LookupSymbolNonGlobal(sym SexpSymbol) (Sexp, error) {
- return stack.lookupSymbol(sym, 1)
- }
- func (stack *Stack) BindSymbol(sym SexpSymbol, expr Sexp) error {
- if stack.IsEmpty() {
- return errors.New("no scope available")
- }
- stack.elements[stack.tos].(Scope)[sym.number] = expr
- return nil
- }
|