Go: store scopes and globals as maps
This commit is contained in:
parent
b210216c71
commit
563e8ba069
|
@ -48,8 +48,7 @@ func complete(L *ell.Ell, line string, pos int) (
|
||||||
head, line = line[:lastSpace+1], line[lastSpace+1:]
|
head, line = line[:lastSpace+1], line[lastSpace+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range L.Globals {
|
for name := range L.Globals {
|
||||||
name := v.List[0].String
|
|
||||||
if strings.HasPrefix(strings.ToLower(name), line) {
|
if strings.HasPrefix(strings.ToLower(name), line) {
|
||||||
completions = append(completions, name)
|
completions = append(completions, name)
|
||||||
}
|
}
|
||||||
|
|
48
ell/ell.go
48
ell/ell.go
|
@ -538,8 +538,8 @@ type Handler func(*Ell, []V, *[]V) bool
|
||||||
|
|
||||||
// Ell is an interpreter context.
|
// Ell is an interpreter context.
|
||||||
type Ell struct {
|
type Ell struct {
|
||||||
Globals []*V // list of global variables
|
Globals map[string]V // list of global variables
|
||||||
scopes [][]*V // dynamic scopes from the newest
|
scopes []map[string]V // dynamic scopes from the newest
|
||||||
Native map[string]Handler // maps strings to Go functions
|
Native map[string]Handler // maps strings to Go functions
|
||||||
|
|
||||||
Error string // error information
|
Error string // error information
|
||||||
|
@ -548,7 +548,8 @@ type Ell struct {
|
||||||
// New returns a new interpreter context ready for program execution.
|
// New returns a new interpreter context ready for program execution.
|
||||||
func New() *Ell {
|
func New() *Ell {
|
||||||
return &Ell{
|
return &Ell{
|
||||||
Native: make(map[string]Handler),
|
Globals: make(map[string]V),
|
||||||
|
Native: make(map[string]Handler),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,26 +562,15 @@ func scopeFind(scope []*V, name string) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This is O(n), let's just make them a map[string]*V.
|
|
||||||
func scopePrepend(scope []*V, name string, v *V) []*V {
|
|
||||||
key := NewString(name)
|
|
||||||
pair := NewList([]V{*key, *v})
|
|
||||||
|
|
||||||
result := make([]*V, len(scope)+1)
|
|
||||||
copy(result[1:], scope)
|
|
||||||
result[0] = pair
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get retrieves a value by name from the scope or from global variables.
|
// Get retrieves a value by name from the scope or from global variables.
|
||||||
func (ell *Ell) Get(name string) *V {
|
func (ell *Ell) Get(name string) *V {
|
||||||
for _, scope := range ell.scopes {
|
for _, scope := range ell.scopes {
|
||||||
if place := scopeFind(scope, name); place >= 0 {
|
if v, ok := scope[name]; ok {
|
||||||
return &scope[place].List[1]
|
return &v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if place := scopeFind(ell.Globals, name); place >= 0 {
|
if v, ok := ell.Globals[name]; ok {
|
||||||
return &ell.Globals[place].List[1]
|
return &v
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -588,18 +578,14 @@ func (ell *Ell) Get(name string) *V {
|
||||||
// Set sets a value by name in the scope or in global variables.
|
// Set sets a value by name in the scope or in global variables.
|
||||||
func (ell *Ell) Set(name string, v *V) {
|
func (ell *Ell) Set(name string, v *V) {
|
||||||
for _, scope := range ell.scopes {
|
for _, scope := range ell.scopes {
|
||||||
if place := scopeFind(scope, name); place >= 0 {
|
if _, ok := scope[name]; ok {
|
||||||
scope[place].List[1] = *v
|
scope[name] = *v
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variables only get deleted by "arg" or from the global scope.
|
// Variables only get deleted by "arg" or from the global scope.
|
||||||
if place := scopeFind(ell.Globals, name); place >= 0 {
|
ell.Globals[name] = *v
|
||||||
ell.Globals[place].List[1] = *v
|
|
||||||
} else {
|
|
||||||
ell.Globals = scopePrepend(ell.Globals, name, v)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -714,10 +700,10 @@ func (ell *Ell) evalStatement(statement *V, result *[]V) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func argsToScope(args []V) []*V {
|
func argsToScope(args []V) map[string]V {
|
||||||
scope := scopePrepend(nil, "args", NewList(args))
|
scope := map[string]V{"args": *NewList(args)}
|
||||||
for i, arg := range args {
|
for i, arg := range args {
|
||||||
scope = scopePrepend(scope, fmt.Sprintf("%d", i+1), arg.Clone())
|
scope[fmt.Sprintf("%d", i+1)] = *arg.Clone()
|
||||||
}
|
}
|
||||||
return scope
|
return scope
|
||||||
}
|
}
|
||||||
|
@ -726,7 +712,7 @@ func argsToScope(args []V) []*V {
|
||||||
// eats args.
|
// eats args.
|
||||||
func (ell *Ell) EvalBlock(body []V, args []V, result *[]V) bool {
|
func (ell *Ell) EvalBlock(body []V, args []V, result *[]V) bool {
|
||||||
// TODO: This is O(n), let's just rather append and traverse in reverse.
|
// TODO: This is O(n), let's just rather append and traverse in reverse.
|
||||||
newScopes := make([][]*V, len(ell.scopes)+1)
|
newScopes := make([]map[string]V, len(ell.scopes)+1)
|
||||||
newScopes[0] = argsToScope(args)
|
newScopes[0] = argsToScope(args)
|
||||||
copy(newScopes[1:], ell.scopes)
|
copy(newScopes[1:], ell.scopes)
|
||||||
ell.scopes = newScopes
|
ell.scopes = newScopes
|
||||||
|
@ -796,12 +782,12 @@ func fnLocal(ell *Ell, args []V, result *[]V) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Duplicates or non-strings don't really matter to us, user's problem.
|
// Duplicates or non-strings don't really matter to us, user's problem.
|
||||||
scope := &ell.scopes[0]
|
scope := ell.scopes[0]
|
||||||
|
|
||||||
values := args[1:]
|
values := args[1:]
|
||||||
for _, name := range args[0].List {
|
for _, name := range args[0].List {
|
||||||
*scope = scopePrepend(*scope, name.String, values[0].Clone())
|
|
||||||
if len(values) > 0 {
|
if len(values) > 0 {
|
||||||
|
scope[name.String] = *values[0].Clone()
|
||||||
values = values[1:]
|
values = values[1:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue