monna/object/environment.go

66 lines
2.0 KiB
Go
Raw Normal View History

/*
Environment
An environment in this interpreter is what is used to keep track of values by associating them with a name.
Under the hood, the environment is basically an hash map that associates strings with objects.
*/
package object
type Environment struct {
store map[string]Object
outer *Environment
}
func NewEnvironment() *Environment {
s := make(map[string]Object)
return &Environment{store: s, outer: nil}
}
/*
Enclosing Environments
2024-08-28 19:31:35 -05:00
Here is a problem case, lets say in monna I would want to type this:
```
let i = 5;
let print_num = fn(i) {
puts(i);
}
print_num(10);
puts(i);
```
2024-08-28 19:31:35 -05:00
The ideal result of the above code in the monna programming language is for 10 and 5 to be the outputs respectively.
In a situation where enclosed environment does not exists, both outputs will be 10 because the current value of i
would be overwritten. The ideal situation would be to preserve the previous binding to 'i' while also making a a new
one.
This works be creating a new instance of object.Environment with a pointer to the environment it should extend, doing this
encloses a fresh and empty environment with an existing one. When the Get method is called and it itself doesn't have the value
associated with the given name, it calls the Get of the enclosing environment. That's the environment it's extending. If that
enclosing environment can't find the value, it calls its own enclosing environment and so on until there is no enclosing environment
anymore and it will error out to an unknown identifier.
*/
func NewEnclosedEnvironment(outer *Environment) *Environment {
env := NewEnvironment()
env.outer = outer
return env
}
func (l_environment *Environment) Get(name string) (Object, bool) {
obj, ok := l_environment.store[name]
if !ok && l_environment.outer != nil {
obj, ok = l_environment.outer.Get(name)
}
return obj, ok
}
func (l_environment *Environment) Set(name string, value Object) Object {
l_environment.store[name] = value
return value
}