123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- package main
- import (
- "fmt"
- )
- type Any interface{}
- type Symbol string
- type Environment map[Symbol]Any
- type Scope struct {
- env Environment
- parent *Scope
- }
- func NewRootScope() *Scope {
- s := NewScope(nil)
- for k, v := range Builtins {
- s.env[k] = v
- }
- return s
- }
- func NewScope(parent *Scope) *Scope {
- return &Scope{make(Environment), parent}
- }
- func (s *Scope) evalFunctionCall(sexp []Any) Any {
- f := s.Eval(sexp[0])
- switch fn := f.(type) {
- case Macro:
- expansion := internalMacroExpand(s, sexp)
- return s.Eval(expansion)
- case Function:
- return fn.Apply(s, sexp[1:])
- case ApplyFn:
- return fn(s, sexp[1:])
- default:
- panic(fmt.Errorf("Not a function (main): %s", sexp[0]))
- }
- }
- func (s *Scope) Eval(sexp Any) Any {
- switch sexp := sexp.(type) {
- case []Any:
- if len(sexp) < 1 {
- return nil
- } else {
- return s.evalFunctionCall(sexp)
- }
- case Symbol:
- v, err := s.Lookup(sexp)
- if err != nil {
- panic(err)
- }
- return v
- default:
- return sexp
- }
- return nil
- }
- func (s *Scope) EvalAll(sexps []Any) []Any {
- res := make([]Any, len(sexps))
- for i, v := range sexps {
- res[i] = s.Eval(v)
- }
- return res
- }
- func (s *Scope) Add(sym Symbol, val Any) error {
- _, ok := s.env[sym]
- if ok {
- return fmt.Errorf("symbol: \"%s\" already defined in this scope", s)
- }
- s.env[sym] = val
- return nil
- }
- func (s *Scope) Override(sym Symbol, val Any) {
- s.env[sym] = val
- }
- func (s *Scope) getRootScope() *Scope {
- if s.parent == nil {
- return s
- } else {
- return s.parent.getRootScope()
- }
- }
- func (s *Scope) Lookup(sym Symbol) (Any, error) {
- val, ok := s.env[sym]
- if !ok && s.parent != nil {
- return s.parent.Lookup(sym)
- } else if !ok && s.parent == nil {
- return nil, fmt.Errorf("unknown variable: %s", sym)
- }
- return val, nil
- }
|