// 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 (
	"go/token";
	"log";
)

/*
 * Blocks and scopes
 */

// A definition can be a *Variable, *Constant, or Type.
type Def interface {
	Pos() token.Position;
}

type Variable struct {
	token.Position;
	// Index of this variable in the Frame structure
	Index	int;
	// Static type of this variable
	Type	Type;
	// Value of this variable.  This is only used by Scope.NewFrame;
	// therefore, it is useful for global scopes but cannot be used
	// in function scopes.
	Init	Value;
}

type Constant struct {
	token.Position;
	Type	Type;
	Value	Value;
}

// A block represents a definition block in which a name may not be
// defined more than once.
type block struct {
	// The block enclosing this one, including blocks in other
	// scopes.
	outer	*block;
	// The nested block currently being compiled, or nil.
	inner	*block;
	// The Scope containing this block.
	scope	*Scope;
	// The Variables, Constants, and Types defined in this block.
	defs	map[string]Def;
	// The index of the first variable defined in this block.
	// This must be greater than the index of any variable defined
	// in any parent of this block within the same Scope at the
	// time this block is entered.
	offset	int;
	// The number of Variables defined in this block.
	numVars	int;
	// If global, do not allocate new vars and consts in
	// the frame; assume that the refs will be compiled in
	// using defs[name].Init.
	global	bool;
}

// A Scope is the compile-time analogue of a Frame, which captures
// some subtree of blocks.
type Scope struct {
	// The root block of this scope.
	*block;
	// The maximum number of variables required at any point in
	// this Scope.  This determines the number of slots needed in
	// Frame's created from this Scope at run-time.
	maxVars	int;
}

func (b *block) enterChild() *block {
	if b.inner != nil && b.inner.scope == b.scope {
		log.Crash("Failed to exit child block before entering another child")
	}
	sub := &block{
		outer: b,
		scope: b.scope,
		defs: make(map[string]Def),
		offset: b.offset + b.numVars,
	};
	b.inner = sub;
	return sub;
}

func (b *block) exit() {
	if b.outer == nil {
		log.Crash("Cannot exit top-level block")
	}
	if b.outer.scope == b.scope {
		if b.outer.inner != b {
			log.Crash("Already exited block")
		}
		if b.inner != nil && b.inner.scope == b.scope {
			log.Crash("Exit of parent block without exit of child block")
		}
	}
	b.outer.inner = nil;
}

func (b *block) ChildScope() *Scope {
	if b.inner != nil && b.inner.scope == b.scope {
		log.Crash("Failed to exit child block before entering a child scope")
	}
	sub := b.enterChild();
	sub.offset = 0;
	sub.scope = &Scope{sub, 0};
	return sub.scope;
}

func (b *block) DefineVar(name string, pos token.Position, t Type) (*Variable, Def) {
	if prev, ok := b.defs[name]; ok {
		return nil, prev
	}
	v := b.defineSlot(t, false);
	v.Position = pos;
	b.defs[name] = v;
	return v, nil;
}

func (b *block) DefineTemp(t Type) *Variable	{ return b.defineSlot(t, true) }

func (b *block) defineSlot(t Type, temp bool) *Variable {
	if b.inner != nil && b.inner.scope == b.scope {
		log.Crash("Failed to exit child block before defining variable")
	}
	index := -1;
	if !b.global || temp {
		index = b.offset + b.numVars;
		b.numVars++;
		if index >= b.scope.maxVars {
			b.scope.maxVars = index + 1
		}
	}
	v := &Variable{token.Position{}, index, t, nil};
	return v;
}

func (b *block) DefineConst(name string, pos token.Position, t Type, v Value) (*Constant, Def) {
	if prev, ok := b.defs[name]; ok {
		return nil, prev
	}
	c := &Constant{pos, t, v};
	b.defs[name] = c;
	return c, nil;
}

func (b *block) DefineType(name string, pos token.Position, t Type) Type {
	if _, ok := b.defs[name]; ok {
		return nil
	}
	nt := &NamedType{pos, name, nil, true, make(map[string]Method)};
	if t != nil {
		nt.Complete(t)
	}
	b.defs[name] = nt;
	return nt;
}

func (b *block) Lookup(name string) (bl *block, level int, def Def) {
	for b != nil {
		if d, ok := b.defs[name]; ok {
			return b, level, d
		}
		if b.outer != nil && b.scope != b.outer.scope {
			level++
		}
		b = b.outer;
	}
	return nil, 0, nil;
}

func (s *Scope) NewFrame(outer *Frame) *Frame	{ return outer.child(s.maxVars) }

/*
 * Frames
 */

type Frame struct {
	Outer	*Frame;
	Vars	[]Value;
}

func (f *Frame) Get(level int, index int) Value {
	for ; level > 0; level-- {
		f = f.Outer
	}
	return f.Vars[index];
}

func (f *Frame) child(numVars int) *Frame {
	// TODO(austin) This is probably rather expensive.  All values
	// require heap allocation and zeroing them when we execute a
	// definition typically requires some computation.
	return &Frame{f, make([]Value, numVars)}
}
