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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [exp/] [types/] [check.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2011 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
 
5
// This file implements the Check function, which typechecks a package.
6
 
7
package types
8
 
9
import (
10
        "fmt"
11
        "go/ast"
12
        "go/scanner"
13
        "go/token"
14
        "strconv"
15
)
16
 
17
const debug = false
18
 
19
type checker struct {
20
        fset *token.FileSet
21
        scanner.ErrorVector
22
        types map[ast.Expr]Type
23
}
24
 
25
func (c *checker) errorf(pos token.Pos, format string, args ...interface{}) string {
26
        msg := fmt.Sprintf(format, args...)
27
        c.Error(c.fset.Position(pos), msg)
28
        return msg
29
}
30
 
31
// collectFields collects struct fields tok = token.STRUCT), interface methods
32
// (tok = token.INTERFACE), and function arguments/results (tok = token.FUNC).
33
func (c *checker) collectFields(tok token.Token, list *ast.FieldList, cycleOk bool) (fields ObjList, tags []string, isVariadic bool) {
34
        if list != nil {
35
                for _, field := range list.List {
36
                        ftype := field.Type
37
                        if t, ok := ftype.(*ast.Ellipsis); ok {
38
                                ftype = t.Elt
39
                                isVariadic = true
40
                        }
41
                        typ := c.makeType(ftype, cycleOk)
42
                        tag := ""
43
                        if field.Tag != nil {
44
                                assert(field.Tag.Kind == token.STRING)
45
                                tag, _ = strconv.Unquote(field.Tag.Value)
46
                        }
47
                        if len(field.Names) > 0 {
48
                                // named fields
49
                                for _, name := range field.Names {
50
                                        obj := name.Obj
51
                                        obj.Type = typ
52
                                        fields = append(fields, obj)
53
                                        if tok == token.STRUCT {
54
                                                tags = append(tags, tag)
55
                                        }
56
                                }
57
                        } else {
58
                                // anonymous field
59
                                switch tok {
60
                                case token.STRUCT:
61
                                        tags = append(tags, tag)
62
                                        fallthrough
63
                                case token.FUNC:
64
                                        obj := ast.NewObj(ast.Var, "")
65
                                        obj.Type = typ
66
                                        fields = append(fields, obj)
67
                                case token.INTERFACE:
68
                                        utyp := Underlying(typ)
69
                                        if typ, ok := utyp.(*Interface); ok {
70
                                                // TODO(gri) This is not good enough. Check for double declarations!
71
                                                fields = append(fields, typ.Methods...)
72
                                        } else if _, ok := utyp.(*Bad); !ok {
73
                                                // if utyp is Bad, don't complain (the root cause was reported before)
74
                                                c.errorf(ftype.Pos(), "interface contains embedded non-interface type")
75
                                        }
76
                                default:
77
                                        panic("unreachable")
78
                                }
79
                        }
80
                }
81
        }
82
        return
83
}
84
 
85
// makeType makes a new type for an AST type specification x or returns
86
// the type referred to by a type name x. If cycleOk is set, a type may
87
// refer to itself directly or indirectly; otherwise cycles are errors.
88
//
89
func (c *checker) makeType(x ast.Expr, cycleOk bool) (typ Type) {
90
        if debug {
91
                fmt.Printf("makeType (cycleOk = %v)\n", cycleOk)
92
                ast.Print(c.fset, x)
93
                defer func() {
94
                        fmt.Printf("-> %T %v\n\n", typ, typ)
95
                }()
96
        }
97
 
98
        switch t := x.(type) {
99
        case *ast.BadExpr:
100
                return &Bad{}
101
 
102
        case *ast.Ident:
103
                // type name
104
                obj := t.Obj
105
                if obj == nil {
106
                        // unresolved identifier (error has been reported before)
107
                        return &Bad{Msg: "unresolved identifier"}
108
                }
109
                if obj.Kind != ast.Typ {
110
                        msg := c.errorf(t.Pos(), "%s is not a type", t.Name)
111
                        return &Bad{Msg: msg}
112
                }
113
                c.checkObj(obj, cycleOk)
114
                if !cycleOk && obj.Type.(*Name).Underlying == nil {
115
                        // TODO(gri) Enable this message again once its position
116
                        // is independent of the underlying map implementation.
117
                        // msg := c.errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name)
118
                        msg := "illegal cycle"
119
                        return &Bad{Msg: msg}
120
                }
121
                return obj.Type.(Type)
122
 
123
        case *ast.ParenExpr:
124
                return c.makeType(t.X, cycleOk)
125
 
126
        case *ast.SelectorExpr:
127
                // qualified identifier
128
                // TODO (gri) eventually, this code belongs to expression
129
                //            type checking - here for the time being
130
                if ident, ok := t.X.(*ast.Ident); ok {
131
                        if obj := ident.Obj; obj != nil {
132
                                if obj.Kind != ast.Pkg {
133
                                        msg := c.errorf(ident.Pos(), "%s is not a package", obj.Name)
134
                                        return &Bad{Msg: msg}
135
                                }
136
                                // TODO(gri) we have a package name but don't
137
                                // have the mapping from package name to package
138
                                // scope anymore (created in ast.NewPackage).
139
                                return &Bad{} // for now
140
                        }
141
                }
142
                // TODO(gri) can this really happen (the parser should have excluded this)?
143
                msg := c.errorf(t.Pos(), "expected qualified identifier")
144
                return &Bad{Msg: msg}
145
 
146
        case *ast.StarExpr:
147
                return &Pointer{Base: c.makeType(t.X, true)}
148
 
149
        case *ast.ArrayType:
150
                if t.Len != nil {
151
                        // TODO(gri) compute length
152
                        return &Array{Elt: c.makeType(t.Elt, cycleOk)}
153
                }
154
                return &Slice{Elt: c.makeType(t.Elt, true)}
155
 
156
        case *ast.StructType:
157
                fields, tags, _ := c.collectFields(token.STRUCT, t.Fields, cycleOk)
158
                return &Struct{Fields: fields, Tags: tags}
159
 
160
        case *ast.FuncType:
161
                params, _, _ := c.collectFields(token.FUNC, t.Params, true)
162
                results, _, isVariadic := c.collectFields(token.FUNC, t.Results, true)
163
                return &Func{Recv: nil, Params: params, Results: results, IsVariadic: isVariadic}
164
 
165
        case *ast.InterfaceType:
166
                methods, _, _ := c.collectFields(token.INTERFACE, t.Methods, cycleOk)
167
                methods.Sort()
168
                return &Interface{Methods: methods}
169
 
170
        case *ast.MapType:
171
                return &Map{Key: c.makeType(t.Key, true), Elt: c.makeType(t.Key, true)}
172
 
173
        case *ast.ChanType:
174
                return &Chan{Dir: t.Dir, Elt: c.makeType(t.Value, true)}
175
        }
176
 
177
        panic(fmt.Sprintf("unreachable (%T)", x))
178
}
179
 
180
// checkObj type checks an object.
181
func (c *checker) checkObj(obj *ast.Object, ref bool) {
182
        if obj.Type != nil {
183
                // object has already been type checked
184
                return
185
        }
186
 
187
        switch obj.Kind {
188
        case ast.Bad:
189
                // ignore
190
 
191
        case ast.Con:
192
                // TODO(gri) complete this
193
 
194
        case ast.Typ:
195
                typ := &Name{Obj: obj}
196
                obj.Type = typ // "mark" object so recursion terminates
197
                typ.Underlying = Underlying(c.makeType(obj.Decl.(*ast.TypeSpec).Type, ref))
198
 
199
        case ast.Var:
200
                // TODO(gri) complete this
201
 
202
        case ast.Fun:
203
                // TODO(gri) complete this
204
 
205
        default:
206
                panic("unreachable")
207
        }
208
}
209
 
210
// Check typechecks a package.
211
// It augments the AST by assigning types to all ast.Objects and returns a map
212
// of types for all expression nodes in statements, and a scanner.ErrorList if
213
// there are errors.
214
//
215
func Check(fset *token.FileSet, pkg *ast.Package) (types map[ast.Expr]Type, err error) {
216
        var c checker
217
        c.fset = fset
218
        c.types = make(map[ast.Expr]Type)
219
 
220
        for _, obj := range pkg.Scope.Objects {
221
                c.checkObj(obj, false)
222
        }
223
 
224
        return c.types, c.GetError(scanner.NoMultiples)
225
}

powered by: WebSVN 2.1.0

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