// 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.

// Parse input AST and prepare Prog structure.

package main

import (
	"fmt"
	"go/ast"
	"go/doc"
	"go/parser"
	"go/scanner"
	"os"
)

// A Cref refers to an expression of the form C.xxx in the AST.
type Cref struct {
	Name     string
	Expr     *ast.Expr
	Context  string // "type", "expr", or "call"
	TypeName bool   // whether xxx is a C type name
	Type     *Type  // the type of xxx
	FuncType *FuncType
}

// A Prog collects information about a cgo program.
type Prog struct {
	AST         *ast.File // parsed AST
	Preamble    string    // C preamble (doc comment on import "C")
	PackagePath string
	Package     string
	Crefs       []*Cref
	Typedef     map[string]ast.Expr
	Vardef      map[string]*Type
	Funcdef     map[string]*FuncType
	Enumdef     map[string]int64
	PtrSize     int64
	GccOptions  []string
	OutDefs     map[string]bool
}

// A Type collects information about a type in both the C and Go worlds.
type Type struct {
	Size       int64
	Align      int64
	C          string
	Go         ast.Expr
	EnumValues map[string]int64
}

// A FuncType collects information about a function type in both the C and Go worlds.
type FuncType struct {
	Params []*Type
	Result *Type
	Go     *ast.FuncType
}

func openProg(name string, p *Prog) {
	var err os.Error
	p.AST, err = parser.ParsePkgFile("", name, parser.ParseComments)
	if err != nil {
		if list, ok := err.(scanner.ErrorList); ok {
			// If err is a scanner.ErrorList, its String will print just
			// the first error and then (+n more errors).
			// Instead, turn it into a new Error that will return
			// details for all the errors.
			for _, e := range list {
				fmt.Fprintln(os.Stderr, e)
			}
			os.Exit(2)
		}
		fatal("parsing %s: %s", name, err)
	}
	p.Package = p.AST.Name.Value

	// Find the import "C" line and get any extra C preamble.
	// Delete the import "C" line along the way.
	sawC := false
	w := 0
	for _, decl := range p.AST.Decls {
		d, ok := decl.(*ast.GenDecl)
		if !ok {
			p.AST.Decls[w] = decl
			w++
			continue
		}
		ws := 0
		for _, spec := range d.Specs {
			s, ok := spec.(*ast.ImportSpec)
			if !ok || len(s.Path) != 1 || string(s.Path[0].Value) != `"C"` {
				d.Specs[ws] = spec
				ws++
				continue
			}
			sawC = true
			if s.Name != nil {
				error(s.Path[0].Pos(), `cannot rename import "C"`)
			}
			if s.Doc != nil {
				p.Preamble += doc.CommentText(s.Doc) + "\n"
			} else if len(d.Specs) == 1 && d.Doc != nil {
				p.Preamble += doc.CommentText(d.Doc) + "\n"
			}
		}
		if ws == 0 {
			continue
		}
		d.Specs = d.Specs[0:ws]
		p.AST.Decls[w] = d
		w++
	}
	p.AST.Decls = p.AST.Decls[0:w]

	if !sawC {
		error(noPos, `cannot find import "C"`)
	}

	// Accumulate pointers to uses of C.x.
	p.Crefs = make([]*Cref, 0, 8)
	walk(p.AST, p, "prog")
}

func walk(x interface{}, p *Prog, context string) {
	switch n := x.(type) {
	case *ast.Expr:
		if sel, ok := (*n).(*ast.SelectorExpr); ok {
			// For now, assume that the only instance of capital C is
			// when used as the imported package identifier.
			// The parser should take care of scoping in the future,
			// so that we will be able to distinguish a "top-level C"
			// from a local C.
			if l, ok := sel.X.(*ast.Ident); ok && l.Value == "C" {
				i := len(p.Crefs)
				if i >= cap(p.Crefs) {
					new := make([]*Cref, 2*i)
					for j, v := range p.Crefs {
						new[j] = v
					}
					p.Crefs = new
				}
				p.Crefs = p.Crefs[0 : i+1]
				p.Crefs[i] = &Cref{
					Name: sel.Sel.Value,
					Expr: n,
					Context: context,
				}
				break
			}
		}
		walk(*n, p, context)

	// everything else just recurs
	default:
		error(noPos, "unexpected type %T in walk", x)
		panic()

	case nil:

	// These are ordered and grouped to match ../../pkg/go/ast/ast.go
	case *ast.Field:
		walk(&n.Type, p, "type")
	case *ast.BadExpr:
	case *ast.Ident:
	case *ast.Ellipsis:
	case *ast.BasicLit:
	case *ast.StringList:
	case *ast.FuncLit:
		walk(n.Type, p, "type")
		walk(n.Body, p, "stmt")
	case *ast.CompositeLit:
		walk(&n.Type, p, "type")
		walk(n.Elts, p, "expr")
	case *ast.ParenExpr:
		walk(&n.X, p, context)
	case *ast.SelectorExpr:
		walk(&n.X, p, "selector")
	case *ast.IndexExpr:
		walk(&n.X, p, "expr")
		walk(&n.Index, p, "expr")
	case *ast.SliceExpr:
		walk(&n.X, p, "expr")
		walk(&n.Index, p, "expr")
		if n.End != nil {
			walk(&n.End, p, "expr")
		}
	case *ast.TypeAssertExpr:
		walk(&n.X, p, "expr")
		walk(&n.Type, p, "type")
	case *ast.CallExpr:
		walk(&n.Fun, p, "call")
		walk(n.Args, p, "expr")
	case *ast.StarExpr:
		walk(&n.X, p, context)
	case *ast.UnaryExpr:
		walk(&n.X, p, "expr")
	case *ast.BinaryExpr:
		walk(&n.X, p, "expr")
		walk(&n.Y, p, "expr")
	case *ast.KeyValueExpr:
		walk(&n.Key, p, "expr")
		walk(&n.Value, p, "expr")

	case *ast.ArrayType:
		walk(&n.Len, p, "expr")
		walk(&n.Elt, p, "type")
	case *ast.StructType:
		walk(n.Fields, p, "field")
	case *ast.FuncType:
		walk(n.Params, p, "field")
		walk(n.Results, p, "field")
	case *ast.InterfaceType:
		walk(n.Methods, p, "field")
	case *ast.MapType:
		walk(&n.Key, p, "type")
		walk(&n.Value, p, "type")
	case *ast.ChanType:
		walk(&n.Value, p, "type")

	case *ast.BadStmt:
	case *ast.DeclStmt:
		walk(n.Decl, p, "decl")
	case *ast.EmptyStmt:
	case *ast.LabeledStmt:
		walk(n.Stmt, p, "stmt")
	case *ast.ExprStmt:
		walk(&n.X, p, "expr")
	case *ast.IncDecStmt:
		walk(&n.X, p, "expr")
	case *ast.AssignStmt:
		walk(n.Lhs, p, "expr")
		walk(n.Rhs, p, "expr")
	case *ast.GoStmt:
		walk(n.Call, p, "expr")
	case *ast.DeferStmt:
		walk(n.Call, p, "expr")
	case *ast.ReturnStmt:
		walk(n.Results, p, "expr")
	case *ast.BranchStmt:
	case *ast.BlockStmt:
		walk(n.List, p, "stmt")
	case *ast.IfStmt:
		walk(n.Init, p, "stmt")
		walk(&n.Cond, p, "expr")
		walk(n.Body, p, "stmt")
		walk(n.Else, p, "stmt")
	case *ast.CaseClause:
		walk(n.Values, p, "expr")
		walk(n.Body, p, "stmt")
	case *ast.SwitchStmt:
		walk(n.Init, p, "stmt")
		walk(&n.Tag, p, "expr")
		walk(n.Body, p, "stmt")
	case *ast.TypeCaseClause:
		walk(n.Types, p, "type")
		walk(n.Body, p, "stmt")
	case *ast.TypeSwitchStmt:
		walk(n.Init, p, "stmt")
		walk(n.Assign, p, "stmt")
		walk(n.Body, p, "stmt")
	case *ast.CommClause:
		walk(n.Lhs, p, "expr")
		walk(n.Rhs, p, "expr")
		walk(n.Body, p, "stmt")
	case *ast.SelectStmt:
		walk(n.Body, p, "stmt")
	case *ast.ForStmt:
		walk(n.Init, p, "stmt")
		walk(&n.Cond, p, "expr")
		walk(n.Post, p, "stmt")
		walk(n.Body, p, "stmt")
	case *ast.RangeStmt:
		walk(&n.Key, p, "expr")
		walk(&n.Value, p, "expr")
		walk(&n.X, p, "expr")
		walk(n.Body, p, "stmt")

	case *ast.ImportSpec:
	case *ast.ValueSpec:
		walk(&n.Type, p, "type")
		walk(n.Values, p, "expr")
	case *ast.TypeSpec:
		walk(&n.Type, p, "type")

	case *ast.BadDecl:
	case *ast.GenDecl:
		walk(n.Specs, p, "spec")
	case *ast.FuncDecl:
		if n.Recv != nil {
			walk(n.Recv, p, "field")
		}
		walk(n.Type, p, "type")
		if n.Body != nil {
			walk(n.Body, p, "stmt")
		}

	case *ast.File:
		walk(n.Decls, p, "decl")

	case *ast.Package:
		for _, f := range n.Files {
			walk(f, p, "file")
		}

	case []ast.Decl:
		for _, d := range n {
			walk(d, p, context)
		}
	case []ast.Expr:
		for i := range n {
			walk(&n[i], p, context)
		}
	case []*ast.Field:
		for _, f := range n {
			walk(f, p, context)
		}
	case []ast.Stmt:
		for _, s := range n {
			walk(s, p, context)
		}
	case []ast.Spec:
		for _, s := range n {
			walk(s, p, context)
		}
	}
}
