2009-07-15 12:59:13 -06:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package eval
|
|
|
|
|
|
|
|
import (
|
|
|
|
"eval";
|
2009-07-27 14:01:23 -06:00
|
|
|
"fmt";
|
2009-07-15 12:59:13 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
func (s *Scope) Fork() *Scope {
|
2009-07-27 14:01:23 -06:00
|
|
|
return &Scope{
|
|
|
|
outer: s,
|
|
|
|
defs: make(map[string] Def),
|
|
|
|
temps: make(map[int] *Variable)
|
|
|
|
};
|
2009-07-15 12:59:13 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Scope) DefineVar(name string, t Type) *Variable {
|
|
|
|
if _, ok := s.defs[name]; ok {
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
v := &Variable{s.numVars, t};
|
|
|
|
s.defs[name] = v;
|
2009-07-27 14:01:23 -06:00
|
|
|
s.numVars++;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Scope) DefineTemp(t Type) *Variable {
|
|
|
|
v := &Variable{s.numVars, t};
|
|
|
|
s.temps[s.numVars] = v;
|
|
|
|
s.numVars++;
|
2009-07-15 12:59:13 -06:00
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2009-07-21 14:31:23 -06:00
|
|
|
func (s *Scope) DefineConst(name string, t Type, v Value) *Constant {
|
2009-07-15 12:59:13 -06:00
|
|
|
if _, ok := s.defs[name]; ok {
|
|
|
|
return nil;
|
|
|
|
}
|
2009-07-21 14:31:23 -06:00
|
|
|
c := &Constant{t, v};
|
2009-07-15 12:59:13 -06:00
|
|
|
s.defs[name] = c;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2009-07-27 14:01:23 -06:00
|
|
|
func (s *Scope) DefineType(name string, t Type) Type {
|
2009-07-15 12:59:13 -06:00
|
|
|
if _, ok := s.defs[name]; ok {
|
2009-07-27 14:01:23 -06:00
|
|
|
return nil;
|
2009-07-15 12:59:13 -06:00
|
|
|
}
|
2009-07-27 14:01:23 -06:00
|
|
|
// We take the representative type of t because multiple
|
|
|
|
// levels of naming are useless.
|
|
|
|
nt := &NamedType{s, name, t.rep()};
|
|
|
|
s.defs[name] = nt;
|
|
|
|
return nt;
|
2009-07-15 12:59:13 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Scope) Lookup(name string) (Def, *Scope) {
|
|
|
|
for s != nil {
|
|
|
|
if d, ok := s.defs[name]; ok {
|
|
|
|
return d, s;
|
|
|
|
}
|
|
|
|
s = s.outer;
|
|
|
|
}
|
|
|
|
return nil, nil;
|
|
|
|
}
|
2009-07-15 18:56:17 -06:00
|
|
|
|
2009-07-21 14:31:23 -06:00
|
|
|
func (s *Scope) NewFrame(outer *Frame) *Frame {
|
|
|
|
if s.varTypes == nil {
|
|
|
|
// First creation of a frame from this scope. Compute
|
|
|
|
// and memoize the types of all variables.
|
|
|
|
ts := make([]Type, s.numVars);
|
|
|
|
for _, d := range s.defs {
|
|
|
|
if v, ok := d.(*Variable); ok {
|
2009-07-27 14:01:23 -06:00
|
|
|
// Record the representative type to
|
|
|
|
// avoid indirecting through named
|
|
|
|
// types every time we drop a frame.
|
|
|
|
ts[v.Index] = v.Type.rep();
|
2009-07-21 14:31:23 -06:00
|
|
|
}
|
|
|
|
}
|
2009-07-27 14:01:23 -06:00
|
|
|
for _, v := range s.temps {
|
|
|
|
ts[v.Index] = v.Type.rep();
|
|
|
|
}
|
2009-07-21 14:31:23 -06:00
|
|
|
s.varTypes = ts;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create frame
|
2009-07-27 14:01:23 -06:00
|
|
|
//
|
|
|
|
// TODO(austin) This is probably rather expensive. All values
|
|
|
|
// require heap allocation and the Zero method typically
|
|
|
|
// requires some computation.
|
2009-07-21 14:31:23 -06:00
|
|
|
vars := make([]Value, s.numVars);
|
|
|
|
for i, t := range s.varTypes {
|
|
|
|
vars[i] = t.Zero();
|
|
|
|
}
|
|
|
|
return &Frame{outer, s, vars};
|
|
|
|
}
|
|
|
|
|
2009-07-15 18:56:17 -06:00
|
|
|
func (f *Frame) Get(s *Scope, index int) Value {
|
|
|
|
for f.Scope != s {
|
|
|
|
f = f.Outer;
|
|
|
|
}
|
|
|
|
return f.Vars[index];
|
|
|
|
}
|
2009-07-27 14:01:23 -06:00
|
|
|
|
|
|
|
func stringFrame(f *Frame) (string, string) {
|
|
|
|
res := "";
|
|
|
|
indent := "";
|
|
|
|
if f.Outer != nil {
|
|
|
|
res, indent = stringFrame(f.Outer);
|
|
|
|
}
|
|
|
|
|
|
|
|
names := make([]string, f.Scope.numVars);
|
|
|
|
types := make([]Type, f.Scope.numVars);
|
|
|
|
for name, def := range f.Scope.defs {
|
|
|
|
def, ok := def.(*Variable);
|
|
|
|
if !ok {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
names[def.Index] = name;
|
|
|
|
types[def.Index] = def.Type;
|
|
|
|
}
|
|
|
|
for _, def := range f.Scope.temps {
|
|
|
|
names[def.Index] = "(temp)";
|
|
|
|
types[def.Index] = def.Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, val := range f.Vars {
|
|
|
|
res += fmt.Sprintf("%s%-10s %-10s %s\n", indent, names[i], types[i], val);
|
|
|
|
}
|
|
|
|
return res, indent + " ";
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *Frame) String() string {
|
|
|
|
res, _ := stringFrame(f);
|
|
|
|
return res;
|
|
|
|
}
|