// 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 is the beginning of an interpreter for Go.
// It can run simple Go programs but does not implement
// interface values or packages.
package eval

import (
	"go/ast"
	"go/parser"
	"go/scanner"
	"go/token"
	"os"
)

type World struct {
	scope *Scope
	frame *Frame
}

func NewWorld() *World {
	w := new(World)
	w.scope = universe.ChildScope()
	w.scope.global = true // this block's vars allocate directly
	return w
}

type Code interface {
	// The type of the value Run returns, or nil if Run returns nil.
	Type() Type

	// Run runs the code; if the code is a single expression
	// with a value, it returns the value; otherwise it returns nil.
	Run() (Value, os.Error)
}

type stmtCode struct {
	w    *World
	code code
}

func (w *World) CompileStmtList(fset *token.FileSet, stmts []ast.Stmt) (Code, os.Error) {
	if len(stmts) == 1 {
		if s, ok := stmts[0].(*ast.ExprStmt); ok {
			return w.CompileExpr(fset, s.X)
		}
	}
	errors := new(scanner.ErrorVector)
	cc := &compiler{fset, errors, 0, 0}
	cb := newCodeBuf()
	fc := &funcCompiler{
		compiler:     cc,
		fnType:       nil,
		outVarsNamed: false,
		codeBuf:      cb,
		flow:         newFlowBuf(cb),
		labels:       make(map[string]*label),
	}
	bc := &blockCompiler{
		funcCompiler: fc,
		block:        w.scope.block,
	}
	nerr := cc.numError()
	for _, stmt := range stmts {
		bc.compileStmt(stmt)
	}
	fc.checkLabels()
	if nerr != cc.numError() {
		return nil, errors.GetError(scanner.Sorted)
	}
	return &stmtCode{w, fc.get()}, nil
}

func (w *World) CompileDeclList(fset *token.FileSet, decls []ast.Decl) (Code, os.Error) {
	stmts := make([]ast.Stmt, len(decls))
	for i, d := range decls {
		stmts[i] = &ast.DeclStmt{d}
	}
	return w.CompileStmtList(fset, stmts)
}

func (s *stmtCode) Type() Type { return nil }

func (s *stmtCode) Run() (Value, os.Error) {
	t := new(Thread)
	t.f = s.w.scope.NewFrame(nil)
	return nil, t.Try(func(t *Thread) { s.code.exec(t) })
}

type exprCode struct {
	w    *World
	e    *expr
	eval func(Value, *Thread)
}

func (w *World) CompileExpr(fset *token.FileSet, e ast.Expr) (Code, os.Error) {
	errors := new(scanner.ErrorVector)
	cc := &compiler{fset, errors, 0, 0}

	ec := cc.compileExpr(w.scope.block, false, e)
	if ec == nil {
		return nil, errors.GetError(scanner.Sorted)
	}
	var eval func(Value, *Thread)
	switch t := ec.t.(type) {
	case *idealIntType:
		// nothing
	case *idealFloatType:
		// nothing
	default:
		if tm, ok := t.(*MultiType); ok && len(tm.Elems) == 0 {
			return &stmtCode{w, code{ec.exec}}, nil
		}
		eval = genAssign(ec.t, ec)
	}
	return &exprCode{w, ec, eval}, nil
}

func (e *exprCode) Type() Type { return e.e.t }

func (e *exprCode) Run() (Value, os.Error) {
	t := new(Thread)
	t.f = e.w.scope.NewFrame(nil)
	switch e.e.t.(type) {
	case *idealIntType:
		return &idealIntV{e.e.asIdealInt()()}, nil
	case *idealFloatType:
		return &idealFloatV{e.e.asIdealFloat()()}, nil
	}
	v := e.e.t.Zero()
	eval := e.eval
	err := t.Try(func(t *Thread) { eval(v, t) })
	return v, err
}

func (w *World) Compile(fset *token.FileSet, text string) (Code, os.Error) {
	stmts, err := parser.ParseStmtList(fset, "input", text)
	if err == nil {
		return w.CompileStmtList(fset, stmts)
	}

	// Otherwise try as DeclList.
	decls, err1 := parser.ParseDeclList(fset, "input", text)
	if err1 == nil {
		return w.CompileDeclList(fset, decls)
	}

	// Have to pick an error.
	// Parsing as statement list admits more forms,
	// its error is more likely to be useful.
	return nil, err
}

type RedefinitionError struct {
	Name string
	Prev Def
}

func (e *RedefinitionError) String() string {
	res := "identifier " + e.Name + " redeclared"
	pos := e.Prev.Pos()
	if pos.IsValid() {
		// TODO: fix this - currently this code is not reached by the tests
		//       need to get a file set (fset) from somewhere
		//res += "; previous declaration at " + fset.Position(pos).String()
		panic(0)
	}
	return res
}

func (w *World) DefineConst(name string, t Type, val Value) os.Error {
	_, prev := w.scope.DefineConst(name, token.NoPos, t, val)
	if prev != nil {
		return &RedefinitionError{name, prev}
	}
	return nil
}

func (w *World) DefineVar(name string, t Type, val Value) os.Error {
	v, prev := w.scope.DefineVar(name, token.NoPos, t)
	if prev != nil {
		return &RedefinitionError{name, prev}
	}
	v.Init = val
	return nil
}
