OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [exp/] [types/] [types.go] - Rev 833

Go to most recent revision | Compare with Previous | Blame | View Log

// Copyright 2011 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 UNDER CONSTRUCTION. ANY AND ALL PARTS MAY CHANGE.
// Package types declares the types used to represent Go types.
//
package types

import (
        "go/ast"
        "sort"
)

// All types implement the Type interface.
type Type interface {
        isType()
}

// All concrete types embed ImplementsType which
// ensures that all types implement the Type interface.
type ImplementsType struct{}

func (t *ImplementsType) isType() {}

// A Bad type is a non-nil placeholder type when we don't know a type.
type Bad struct {
        ImplementsType
        Msg string // for better error reporting/debugging
}

// A Basic represents a (unnamed) basic type.
type Basic struct {
        ImplementsType
        // TODO(gri) need a field specifying the exact basic type
}

// An Array represents an array type [Len]Elt.
type Array struct {
        ImplementsType
        Len uint64
        Elt Type
}

// A Slice represents a slice type []Elt.
type Slice struct {
        ImplementsType
        Elt Type
}

// A Struct represents a struct type struct{...}.
// Anonymous fields are represented by objects with empty names.
type Struct struct {
        ImplementsType
        Fields ObjList  // struct fields; or nil
        Tags   []string // corresponding tags; or nil
        // TODO(gri) This type needs some rethinking:
        // - at the moment anonymous fields are marked with "" object names,
        //   and their names have to be reconstructed
        // - there is no scope for fast lookup (but the parser creates one)
}

// A Pointer represents a pointer type *Base.
type Pointer struct {
        ImplementsType
        Base Type
}

// A Func represents a function type func(...) (...).
// Unnamed parameters are represented by objects with empty names.
type Func struct {
        ImplementsType
        Recv       *ast.Object // nil if not a method
        Params     ObjList     // (incoming) parameters from left to right; or nil
        Results    ObjList     // (outgoing) results from left to right; or nil
        IsVariadic bool        // true if the last parameter's type is of the form ...T
}

// An Interface represents an interface type interface{...}.
type Interface struct {
        ImplementsType
        Methods ObjList // interface methods sorted by name; or nil
}

// A Map represents a map type map[Key]Elt.
type Map struct {
        ImplementsType
        Key, Elt Type
}

// A Chan represents a channel type chan Elt, <-chan Elt, or chan<-Elt.
type Chan struct {
        ImplementsType
        Dir ast.ChanDir
        Elt Type
}

// A Name represents a named type as declared in a type declaration.
type Name struct {
        ImplementsType
        Underlying Type        // nil if not fully declared
        Obj        *ast.Object // corresponding declared object
        // TODO(gri) need to remember fields and methods.
}

// If typ is a pointer type, Deref returns the pointer's base type;
// otherwise it returns typ.
func Deref(typ Type) Type {
        if typ, ok := typ.(*Pointer); ok {
                return typ.Base
        }
        return typ
}

// Underlying returns the underlying type of a type.
func Underlying(typ Type) Type {
        if typ, ok := typ.(*Name); ok {
                utyp := typ.Underlying
                if _, ok := utyp.(*Basic); !ok {
                        return utyp
                }
                // the underlying type of a type name referring
                // to an (untyped) basic type is the basic type
                // name
        }
        return typ
}

// An ObjList represents an ordered (in some fashion) list of objects.
type ObjList []*ast.Object

// ObjList implements sort.Interface.
func (list ObjList) Len() int           { return len(list) }
func (list ObjList) Less(i, j int) bool { return list[i].Name < list[j].Name }
func (list ObjList) Swap(i, j int)      { list[i], list[j] = list[j], list[i] }

// Sort sorts an object list by object name.
func (list ObjList) Sort() { sort.Sort(list) }

// identicalTypes returns true if both lists a and b have the
// same length and corresponding objects have identical types.
func identicalTypes(a, b ObjList) bool {
        if len(a) == len(b) {
                for i, x := range a {
                        y := b[i]
                        if !Identical(x.Type.(Type), y.Type.(Type)) {
                                return false
                        }
                }
                return true
        }
        return false
}

// Identical returns true if two types are identical.
func Identical(x, y Type) bool {
        if x == y {
                return true
        }

        switch x := x.(type) {
        case *Bad:
                // A Bad type is always identical to any other type
                // (to avoid spurious follow-up errors).
                return true

        case *Basic:
                if y, ok := y.(*Basic); ok {
                        panic("unimplemented")
                        _ = y
                }

        case *Array:
                // Two array types are identical if they have identical element types
                // and the same array length.
                if y, ok := y.(*Array); ok {
                        return x.Len == y.Len && Identical(x.Elt, y.Elt)
                }

        case *Slice:
                // Two slice types are identical if they have identical element types.
                if y, ok := y.(*Slice); ok {
                        return Identical(x.Elt, y.Elt)
                }

        case *Struct:
                // Two struct types are identical if they have the same sequence of fields,
                // and if corresponding fields have the same names, and identical types,
                // and identical tags. Two anonymous fields are considered to have the same
                // name. Lower-case field names from different packages are always different.
                if y, ok := y.(*Struct); ok {
                        // TODO(gri) handle structs from different packages
                        if identicalTypes(x.Fields, y.Fields) {
                                for i, f := range x.Fields {
                                        g := y.Fields[i]
                                        if f.Name != g.Name || x.Tags[i] != y.Tags[i] {
                                                return false
                                        }
                                }
                                return true
                        }
                }

        case *Pointer:
                // Two pointer types are identical if they have identical base types.
                if y, ok := y.(*Pointer); ok {
                        return Identical(x.Base, y.Base)
                }

        case *Func:
                // Two function types are identical if they have the same number of parameters
                // and result values, corresponding parameter and result types are identical,
                // and either both functions are variadic or neither is. Parameter and result
                // names are not required to match.
                if y, ok := y.(*Func); ok {
                        return identicalTypes(x.Params, y.Params) &&
                                identicalTypes(x.Results, y.Results) &&
                                x.IsVariadic == y.IsVariadic
                }

        case *Interface:
                // Two interface types are identical if they have the same set of methods with
                // the same names and identical function types. Lower-case method names from
                // different packages are always different. The order of the methods is irrelevant.
                if y, ok := y.(*Interface); ok {
                        return identicalTypes(x.Methods, y.Methods) // methods are sorted
                }

        case *Map:
                // Two map types are identical if they have identical key and value types.
                if y, ok := y.(*Map); ok {
                        return Identical(x.Key, y.Key) && Identical(x.Elt, y.Elt)
                }

        case *Chan:
                // Two channel types are identical if they have identical value types
                // and the same direction.
                if y, ok := y.(*Chan); ok {
                        return x.Dir == y.Dir && Identical(x.Elt, y.Elt)
                }

        case *Name:
                // Two named types are identical if their type names originate
                // in the same type declaration.
                if y, ok := y.(*Name); ok {
                        return x.Obj == y.Obj ||
                                // permit bad objects to be equal to avoid
                                // follow up errors
                                x.Obj != nil && x.Obj.Kind == ast.Bad ||
                                y.Obj != nil && y.Obj.Kind == ast.Bad
                }
        }

        return false
}

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.