2024-10-05 23:27:00 +03:00
|
|
|
package main
|
|
|
|
|
2024-10-11 17:01:12 +03:00
|
|
|
import "fmt"
|
|
|
|
|
2024-10-05 23:27:00 +03:00
|
|
|
type Environment struct {
|
2024-10-11 17:01:12 +03:00
|
|
|
values map[string]any
|
|
|
|
enclosing *Environment
|
2024-10-05 23:27:00 +03:00
|
|
|
}
|
|
|
|
|
2024-10-11 17:01:12 +03:00
|
|
|
func newEnvironment(enclosing *Environment) *Environment {
|
|
|
|
return &Environment{map[string]any{}, enclosing}
|
2024-10-05 23:27:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (env *Environment) get(key string) any {
|
|
|
|
if found, ok := env.values[key]; ok {
|
|
|
|
return found
|
|
|
|
}
|
|
|
|
|
2024-10-11 17:01:12 +03:00
|
|
|
if env.enclosing != nil {
|
|
|
|
return env.enclosing.get(key)
|
2024-10-05 23:27:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (env *Environment) exists(key string) bool {
|
|
|
|
_, ok := env.values[key]
|
|
|
|
return ok
|
2024-10-11 17:01:12 +03:00
|
|
|
}
|
2024-10-05 23:27:00 +03:00
|
|
|
|
2024-10-11 17:01:12 +03:00
|
|
|
func (env *Environment) define(key string, val any) {
|
|
|
|
env.values[key] = val
|
2024-10-05 23:27:00 +03:00
|
|
|
}
|
|
|
|
|
2024-10-11 17:01:12 +03:00
|
|
|
func (env *Environment) assign(key Token, val any) *RuntimeError {
|
|
|
|
if env.exists(key.lexeme) {
|
|
|
|
env.values[key.lexeme] = val
|
|
|
|
return nil
|
|
|
|
}
|
2024-10-07 21:06:23 +03:00
|
|
|
|
2024-10-11 17:01:12 +03:00
|
|
|
if env.enclosing == nil {
|
|
|
|
return &RuntimeError{key, fmt.Sprintf("Can't assign: undefined variable '%s'.", key.lexeme)}
|
2024-10-07 21:06:23 +03:00
|
|
|
}
|
|
|
|
|
2024-10-11 17:01:12 +03:00
|
|
|
return env.enclosing.assign(key, val)
|
2024-10-05 23:27:00 +03:00
|
|
|
}
|
2024-10-14 22:53:26 +03:00
|
|
|
|
|
|
|
func (env *Environment) getAt(distance int, key string) any {
|
|
|
|
return env.ancestor(distance).get(key)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (env *Environment) assignAt(distance int, key Token, val any) {
|
|
|
|
env.ancestor(distance).values[key.lexeme] = val
|
|
|
|
}
|
|
|
|
|
|
|
|
func (env *Environment) ancestor(distance int) *Environment {
|
|
|
|
parent := env
|
|
|
|
for i := 0; i < distance; i++ {
|
|
|
|
parent = parent.enclosing
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent
|
|
|
|
}
|