2016-03-04 17:09:08 -08:00
|
|
|
// Copyright 2016 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 syntax
|
|
|
|
|
|
|
|
|
|
import (
|
2016-12-09 17:15:05 -08:00
|
|
|
"cmd/internal/src"
|
2016-03-04 17:09:08 -08:00
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"os"
|
|
|
|
|
)
|
|
|
|
|
|
2016-11-08 16:01:56 -08:00
|
|
|
// Mode describes the parser mode.
|
2016-03-04 17:09:08 -08:00
|
|
|
type Mode uint
|
|
|
|
|
|
2016-11-08 16:01:56 -08:00
|
|
|
// Error describes a syntax error. Error implements the error interface.
|
|
|
|
|
type Error struct {
|
2016-12-09 17:15:05 -08:00
|
|
|
Pos src.Pos
|
2016-12-02 10:44:34 -08:00
|
|
|
Msg string
|
2016-11-08 16:01:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (err Error) Error() string {
|
2016-12-02 10:44:34 -08:00
|
|
|
return fmt.Sprintf("%s: %s", err.Pos, err.Msg)
|
2016-11-08 16:01:56 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _ error = Error{} // verify that Error implements error
|
|
|
|
|
|
|
|
|
|
// An ErrorHandler is called for each error encountered reading a .go file.
|
|
|
|
|
type ErrorHandler func(err error)
|
|
|
|
|
|
cmd/compile: add go:notinheap type pragma
This adds a //go:notinheap pragma for declarations of types that must
not be heap allocated. We ensure these rules by disallowing new(T),
make([]T), append([]T), or implicit allocation of T, by disallowing
conversions to notinheap types, and by propagating notinheap to any
struct or array that contains notinheap elements.
The utility of this pragma is that we can eliminate write barriers for
writes to pointers to go:notinheap types, since the write barrier is
guaranteed to be a no-op. This will let us mark several scheduler and
memory allocator structures as go:notinheap, which will let us
disallow write barriers in the scheduler and memory allocator much
more thoroughly and also eliminate some problematic hybrid write
barriers.
This also makes go:nowritebarrierrec and go:yeswritebarrierrec much
more powerful. Currently we use go:nowritebarrier all over the place,
but it's almost never what you actually want: when write barriers are
illegal, they're typically illegal for a whole dynamic scope. Partly
this is because go:nowritebarrier has been around longer, but it's
also because go:nowritebarrierrec couldn't be used in situations that
had no-op write barriers or where some nested scope did allow write
barriers. go:notinheap eliminates many no-op write barriers and
go:yeswritebarrierrec makes it possible to opt back in to write
barriers, so these two changes will let us use go:nowritebarrierrec
far more liberally.
This updates #13386, which is about controlling pointers from non-GC'd
memory to GC'd memory. That would require some additional pragma (or
pragmas), but could build on this pragma.
Change-Id: I6314f8f4181535dd166887c9ec239977b54940bd
Reviewed-on: https://go-review.googlesource.com/30939
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2016-10-11 22:53:27 -04:00
|
|
|
// A Pragma value is a set of flags that augment a function or
|
|
|
|
|
// type declaration. Callers may assign meaning to the flags as
|
2016-08-30 16:31:53 -07:00
|
|
|
// appropriate.
|
|
|
|
|
type Pragma uint16
|
|
|
|
|
|
|
|
|
|
// A PragmaHandler is used to process //line and //go: directives as
|
|
|
|
|
// they're scanned. The returned Pragma value will be unioned into the
|
|
|
|
|
// next FuncDecl node.
|
2016-12-09 17:15:05 -08:00
|
|
|
type PragmaHandler func(pos src.Pos, text string) Pragma
|
2016-08-30 16:31:53 -07:00
|
|
|
|
2016-11-08 16:01:56 -08:00
|
|
|
// Parse parses a single Go source file from src and returns the corresponding
|
2016-12-02 10:44:34 -08:00
|
|
|
// syntax tree. If there are errors, Parse will return the first error found.
|
2016-12-09 17:15:05 -08:00
|
|
|
// The base argument is only used for position information.
|
2016-11-08 16:01:56 -08:00
|
|
|
//
|
|
|
|
|
// If errh != nil, it is called with each error encountered, and Parse will
|
|
|
|
|
// process as much source as possible. If errh is nil, Parse will terminate
|
|
|
|
|
// immediately upon encountering an error.
|
|
|
|
|
//
|
|
|
|
|
// If a PragmaHandler is provided, it is called with each pragma encountered.
|
|
|
|
|
//
|
|
|
|
|
// The Mode argument is currently ignored.
|
2016-12-09 17:15:05 -08:00
|
|
|
func Parse(base *src.PosBase, src io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) (_ *File, first error) {
|
2016-11-08 16:01:56 -08:00
|
|
|
defer func() {
|
|
|
|
|
if p := recover(); p != nil {
|
2016-12-02 10:44:34 -08:00
|
|
|
if err, ok := p.(Error); ok {
|
|
|
|
|
first = err
|
2016-11-08 16:01:56 -08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
panic(p)
|
|
|
|
|
}
|
|
|
|
|
}()
|
2016-03-04 17:09:08 -08:00
|
|
|
|
2016-11-08 16:01:56 -08:00
|
|
|
var p parser
|
2016-12-09 17:15:05 -08:00
|
|
|
p.init(base, src, errh, pragh)
|
2016-11-08 16:01:56 -08:00
|
|
|
p.next()
|
|
|
|
|
return p.file(), p.first
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ParseBytes behaves like Parse but it reads the source from the []byte slice provided.
|
2016-12-09 17:15:05 -08:00
|
|
|
func ParseBytes(base *src.PosBase, src []byte, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*File, error) {
|
|
|
|
|
return Parse(base, &bytesReader{src}, errh, pragh, mode)
|
2016-03-04 17:09:08 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type bytesReader struct {
|
|
|
|
|
data []byte
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (r *bytesReader) Read(p []byte) (int, error) {
|
|
|
|
|
if len(r.data) > 0 {
|
|
|
|
|
n := copy(p, r.data)
|
|
|
|
|
r.data = r.data[n:]
|
|
|
|
|
return n, nil
|
|
|
|
|
}
|
|
|
|
|
return 0, io.EOF
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-08 16:01:56 -08:00
|
|
|
// ParseFile behaves like Parse but it reads the source from the named file.
|
|
|
|
|
func ParseFile(filename string, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*File, error) {
|
2016-12-09 17:15:05 -08:00
|
|
|
f, err := os.Open(filename)
|
2016-11-08 16:01:56 -08:00
|
|
|
if err != nil {
|
|
|
|
|
if errh != nil {
|
|
|
|
|
errh(err)
|
2016-10-31 16:58:15 -07:00
|
|
|
}
|
2016-11-08 16:01:56 -08:00
|
|
|
return nil, err
|
2016-03-04 17:09:08 -08:00
|
|
|
}
|
2016-12-09 17:15:05 -08:00
|
|
|
defer f.Close()
|
|
|
|
|
return Parse(src.NewFileBase(filename, filename), f, errh, pragh, mode)
|
2016-03-04 17:09:08 -08:00
|
|
|
}
|