├── cmd ├── gen │ ├── generate.sh │ └── gen.go └── go-eval │ └── eval.go ├── .travis.yml ├── README.md ├── .hgtags ├── func.go ├── LICENSE ├── abort.go ├── compiler.go ├── bridge.go ├── scope.go ├── eval_test.go ├── world.go ├── typec.go ├── expr_test.go ├── value.go ├── stmt_test.go ├── type.go └── stmt.go /cmd/gen/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | go build gen.go 4 | ./gen > expr1.go 5 | gofmt -w expr1.go 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.6.2 4 | - tip 5 | 6 | sudo: false 7 | 8 | notifications: 9 | email: 10 | recipients: 11 | - binet@cern.ch 12 | on_success: change 13 | on_failure: always 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | go-eval 2 | ======= 3 | 4 | [![Build Status](https://secure.travis-ci.org/sbinet/go-eval.png)](http://travis-ci.org/sbinet/go-eval) [![GoDoc](https://godoc.org/github.com/sbinet/go-eval?status.svg)](https://godoc.org/github.com/sbinet/go-eval) 5 | 6 | This is the new home for the ``exp/eval`` package: the beginning of an interpreter for Go. 7 | 8 | ## Installation 9 | 10 | ```sh 11 | $ go get github.com/sbinet/go-eval/... 12 | ``` 13 | 14 | ## Usage 15 | 16 | ```sh 17 | $ go-eval 18 | :: welcome to go-eval... 19 | (hit ^D to exit) 20 | > hello := "world" 21 | > println(hello) 22 | world 23 | > 24 | ``` 25 | 26 | ## Documentation 27 | 28 | http://godoc.org/github.com/sbinet/go-eval 29 | 30 | 31 | ## Limitations (*aka* TODO) 32 | 33 | - channels are not implemented 34 | - imports are not implemented 35 | - goroutines are not implemented 36 | - consts are not implemented 37 | - select is not implemented 38 | 39 | ## Interpreter 40 | 41 | The ``go-eval`` command is rather barebone. 42 | But there is [igo](http://github.com/sbinet/igo) which is built on top of the ``eval`` package and provides some additional refinements. 43 | 44 | See: 45 | 46 | ```sh 47 | $ go get github.com/sbinet/igo 48 | ``` 49 | -------------------------------------------------------------------------------- /.hgtags: -------------------------------------------------------------------------------- 1 | af50ae6589379d1c7272893de34976f128ee2dc4 go.weekly.2011-09-21 2 | 88e94d7c3cd1a2bfb7ad7958603a49d242005e03 go.r60 3 | 12167b82a76c560d9a5bdeb1c34922863e13a963 go.weekly.2011-10-18 4 | feba094df0730c58e30ca35044798c3c50d3b4ec go.weekly.2011-11-02 5 | ba5a44797dd9c1309d4ef6e45453de73eda95c0b go.weekly.2011-11-09 6 | ae73d3729731a2f5b45603524b9baa5cb8083cde go.weekly.2012-01-15 7 | ae73d3729731a2f5b45603524b9baa5cb8083cde go.weekly.2012-01-15 8 | 0000000000000000000000000000000000000000 go.weekly.2012-01-15 9 | 0000000000000000000000000000000000000000 go.weekly.2012-01-15 10 | 7cc7192a8b6c85ab154f641f9485dc1971122c92 go.weekly.2012-01-15 11 | 63e152a3b6f53d2997ae032a621bd2c9b78077e7 go.weekly-2012-02-14 12 | 63e152a3b6f53d2997ae032a621bd2c9b78077e7 go.weekly-2012-02-14 13 | 0000000000000000000000000000000000000000 go.weekly-2012-02-14 14 | a6a8415df52462d0e1949d936263495e27853e77 go.weekly.2012-02-14 15 | 7996d78d6ac3c8b99b134e6914563f07451f3c1e go.weekly.2012-02-22 16 | 3693b3cbb2be3fc56ca5c37ef80960264d80b357 go.weekly.2012-03-04 17 | 8886906165cec1f60f91d4b3c7b7fbc942187668 go.go1 18 | cd0cd45afaab9d92b8dbb1b7494f56acbfae96b3 go.go1 19 | 874c243520aaf5019d7a3ce8120decf0bb30a4f5 go.go1 20 | 874c243520aaf5019d7a3ce8120decf0bb30a4f5 go.go1 21 | f8e43b962b50779f16dba5b0b4f06ca335705724 go.go1 22 | f8e43b962b50779f16dba5b0b4f06ca335705724 go.go1 23 | 4e665d9b74d94387e772bbefeb6b4767172f15cf go.go1 24 | -------------------------------------------------------------------------------- /func.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package eval 6 | 7 | /* 8 | * Virtual machine 9 | */ 10 | 11 | type Thread struct { 12 | abort chan error 13 | pc uint 14 | // The execution frame of this function. This remains the 15 | // same throughout a function invocation. 16 | f *Frame 17 | } 18 | 19 | type code []func(*Thread) 20 | 21 | func (i code) exec(t *Thread) { 22 | opc := t.pc 23 | t.pc = 0 24 | l := uint(len(i)) 25 | for t.pc < l { 26 | pc := t.pc 27 | t.pc++ 28 | i[pc](t) 29 | } 30 | t.pc = opc 31 | } 32 | 33 | /* 34 | * Code buffer 35 | */ 36 | 37 | type codeBuf struct { 38 | instrs code 39 | } 40 | 41 | func newCodeBuf() *codeBuf { return &codeBuf{make(code, 0, 16)} } 42 | 43 | func (b *codeBuf) push(instr func(*Thread)) { 44 | b.instrs = append(b.instrs, instr) 45 | } 46 | 47 | func (b *codeBuf) nextPC() uint { return uint(len(b.instrs)) } 48 | 49 | func (b *codeBuf) get() code { 50 | // Freeze this buffer into an array of exactly the right size 51 | a := make(code, len(b.instrs)) 52 | copy(a, b.instrs) 53 | return code(a) 54 | } 55 | 56 | /* 57 | * User-defined functions 58 | */ 59 | 60 | type evalFunc struct { 61 | outer *Frame 62 | frameSize int 63 | code code 64 | } 65 | 66 | func (f *evalFunc) NewFrame() *Frame { return f.outer.child(f.frameSize) } 67 | 68 | func (f *evalFunc) Call(t *Thread) { f.code.exec(t) } 69 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /abort.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package eval 6 | 7 | import ( 8 | "fmt" 9 | "runtime" 10 | ) 11 | 12 | // Abort aborts the thread's current computation, 13 | // causing the innermost Try to return err. 14 | func (t *Thread) Abort(err error) { 15 | if t.abort == nil { 16 | panic("abort: " + err.Error()) 17 | } 18 | t.abort <- err 19 | runtime.Goexit() 20 | } 21 | 22 | // Try executes a computation; if the computation 23 | // Aborts, Try returns the error passed to abort. 24 | func (t *Thread) Try(f func(t *Thread)) error { 25 | oc := t.abort 26 | c := make(chan error) 27 | t.abort = c 28 | go func() { 29 | f(t) 30 | c <- nil 31 | }() 32 | err := <-c 33 | t.abort = oc 34 | return err 35 | } 36 | 37 | type DivByZeroError struct{} 38 | 39 | func (DivByZeroError) Error() string { return "divide by zero" } 40 | 41 | type NilPointerError struct{} 42 | 43 | func (NilPointerError) Error() string { return "nil pointer dereference" } 44 | 45 | type IndexError struct { 46 | Idx, Len int64 47 | } 48 | 49 | func (e IndexError) Error() string { 50 | if e.Idx < 0 { 51 | return fmt.Sprintf("negative index: %d", e.Idx) 52 | } 53 | return fmt.Sprintf("index %d exceeds length %d", e.Idx, e.Len) 54 | } 55 | 56 | type SliceError struct { 57 | Lo, Hi, Cap int64 58 | } 59 | 60 | func (e SliceError) Error() string { 61 | return fmt.Sprintf("slice [%d:%d]; cap %d", e.Lo, e.Hi, e.Cap) 62 | } 63 | 64 | type KeyError struct { 65 | Key interface{} 66 | } 67 | 68 | func (e KeyError) Error() string { return fmt.Sprintf("key '%v' not found in map", e.Key) } 69 | 70 | type NegativeLengthError struct { 71 | Len int64 72 | } 73 | 74 | func (e NegativeLengthError) Error() string { 75 | return fmt.Sprintf("negative length: %d", e.Len) 76 | } 77 | 78 | type NegativeCapacityError struct { 79 | Len int64 80 | } 81 | 82 | func (e NegativeCapacityError) Error() string { 83 | return fmt.Sprintf("negative capacity: %d", e.Len) 84 | } 85 | -------------------------------------------------------------------------------- /cmd/go-eval/eval.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package main 6 | 7 | import ( 8 | "errors" 9 | "flag" 10 | "fmt" 11 | "go/ast" 12 | "go/parser" 13 | "go/scanner" 14 | "go/token" 15 | "io" 16 | "io/ioutil" 17 | "os" 18 | 19 | eval "github.com/sbinet/go-eval" 20 | "golang.org/x/crypto/ssh/terminal" 21 | ) 22 | 23 | var fset = token.NewFileSet() 24 | var filename = flag.String("f", "", "file to run") 25 | 26 | type shell struct { 27 | r io.Reader 28 | w io.Writer 29 | } 30 | 31 | func (sh *shell) Read(data []byte) (n int, err error) { 32 | return sh.r.Read(data) 33 | } 34 | func (sh *shell) Write(data []byte) (n int, err error) { 35 | return sh.w.Write(data) 36 | } 37 | 38 | func main() { 39 | flag.Parse() 40 | w := eval.NewWorld() 41 | if *filename != "" { 42 | data, err := ioutil.ReadFile(*filename) 43 | if err != nil { 44 | fmt.Println(err.Error()) 45 | os.Exit(1) 46 | } 47 | file, err := parser.ParseFile(fset, *filename, data, 0) 48 | if err != nil { 49 | fmt.Println(err.Error()) 50 | os.Exit(1) 51 | } 52 | files := []*ast.File{file} 53 | code, err := w.CompilePackage(fset, files, "main") 54 | if err != nil { 55 | if list, ok := err.(scanner.ErrorList); ok { 56 | for _, e := range list { 57 | fmt.Println(e.Error()) 58 | } 59 | } else { 60 | fmt.Println(err.Error()) 61 | } 62 | os.Exit(1) 63 | } 64 | code, err = w.Compile(fset, "main()") 65 | if err != nil { 66 | fmt.Println(err.Error()) 67 | os.Exit(1) 68 | } 69 | _, err = code.Run() 70 | if err != nil { 71 | fmt.Println(err.Error()) 72 | os.Exit(1) 73 | } 74 | os.Exit(0) 75 | } 76 | 77 | fmt.Println(":: welcome to go-eval...\n(hit ^D to exit)") 78 | 79 | fd := int(os.Stdin.Fd()) 80 | oldState, err := terminal.MakeRaw(fd) 81 | if err != nil { 82 | panic(err) 83 | } 84 | defer terminal.Restore(fd, oldState) 85 | term := terminal.NewTerminal(&shell{r: os.Stdin, w: os.Stdout}, "> ") 86 | if term == nil { 87 | panic(errors.New("could not create terminal")) 88 | } 89 | 90 | for { 91 | line, err := term.ReadLine() 92 | if err != nil { 93 | break 94 | } 95 | code, err := w.Compile(fset, line) 96 | if err != nil { 97 | term.Write([]byte(err.Error() + "\n")) 98 | continue 99 | } 100 | if code == nil { 101 | term.Write([]byte("failed to compile codelet\n")) 102 | continue 103 | } 104 | v, err := code.Run() 105 | if err != nil { 106 | term.Write([]byte(err.Error() + "\n")) 107 | continue 108 | } 109 | if v != nil { 110 | term.Write([]byte(v.String() + "\n")) 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /compiler.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package eval 6 | 7 | import ( 8 | "fmt" 9 | "go/scanner" 10 | "go/token" 11 | ) 12 | 13 | // A compiler captures information used throughout an entire 14 | // compilation. Currently it includes only the error handler. 15 | // 16 | // TODO(austin) This might actually represent package level, in which 17 | // case it should be package compiler. 18 | type compiler struct { 19 | fset *token.FileSet 20 | errors *scanner.ErrorList 21 | numErrors int 22 | silentErrors int 23 | } 24 | 25 | func (a *compiler) diagAt(pos token.Pos, format string, args ...interface{}) { 26 | a.errors.Add(a.fset.Position(pos), fmt.Sprintf(format, args...)) 27 | a.numErrors++ 28 | } 29 | 30 | func (a *compiler) numError() int { return a.numErrors + a.silentErrors } 31 | 32 | // The universal scope 33 | func newUniverse() *universeScope { 34 | sc := &universeScope{&Scope{nil, 0}, make(map[string]*Scope)} 35 | sc.block = &block{ 36 | offset: 0, 37 | scope: sc.Scope, 38 | global: true, 39 | defs: make(map[string]Def), 40 | } 41 | return sc 42 | } 43 | 44 | var universe *universeScope = newUniverse() 45 | 46 | // TODO(austin) These can all go in stmt.go now 47 | type label struct { 48 | name string 49 | desc string 50 | // The PC goto statements should jump to, or nil if this label 51 | // cannot be goto'd (such as an anonymous for loop label). 52 | gotoPC *uint 53 | // The PC break statements should jump to, or nil if a break 54 | // statement is invalid. 55 | breakPC *uint 56 | // The PC continue statements should jump to, or nil if a 57 | // continue statement is invalid. 58 | continuePC *uint 59 | // The position where this label was resolved. If it has not 60 | // been resolved yet, an invalid position. 61 | resolved token.Pos 62 | // The position where this label was first jumped to. 63 | used token.Pos 64 | } 65 | 66 | // A funcCompiler captures information used throughout the compilation 67 | // of a single function body. 68 | type funcCompiler struct { 69 | *compiler 70 | fnType *FuncType 71 | // Whether the out variables are named. This affects what 72 | // kinds of return statements are legal. 73 | outVarsNamed bool 74 | *codeBuf 75 | flow *flowBuf 76 | labels map[string]*label 77 | } 78 | 79 | // A blockCompiler captures information used throughout the compilation 80 | // of a single block within a function. 81 | type blockCompiler struct { 82 | *funcCompiler 83 | block *block 84 | // The label of this block, used for finding break and 85 | // continue labels. 86 | label *label 87 | // The blockCompiler for the block enclosing this one, or nil 88 | // for a function-level block. 89 | parent *blockCompiler 90 | } 91 | -------------------------------------------------------------------------------- /bridge.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package eval 6 | 7 | import ( 8 | "go/token" 9 | "log" 10 | "reflect" 11 | ) 12 | 13 | /* 14 | * Type bridging 15 | */ 16 | 17 | var ( 18 | evalTypes = make(map[reflect.Type]Type) 19 | nativeTypes = make(map[Type]reflect.Type) 20 | ) 21 | 22 | // TypeFromNative converts a regular Go type into a the corresponding 23 | // interpreter Type. 24 | func TypeFromNative(t reflect.Type) Type { 25 | if et, ok := evalTypes[t]; ok { 26 | return et 27 | } 28 | 29 | var nt *NamedType 30 | if t.Name() != "" { 31 | name := t.PkgPath() + "·" + t.Name() 32 | nt = &NamedType{token.NoPos, name, nil, true, make(map[string]Method)} 33 | evalTypes[t] = nt 34 | } 35 | 36 | var et Type 37 | switch t.Kind() { 38 | case reflect.Bool: 39 | et = BoolType 40 | 41 | case reflect.Float32: 42 | et = Float32Type 43 | case reflect.Float64: 44 | et = Float64Type 45 | 46 | case reflect.Int16: 47 | et = Int16Type 48 | case reflect.Int32: 49 | et = Int32Type 50 | case reflect.Int64: 51 | et = Int64Type 52 | case reflect.Int8: 53 | et = Int8Type 54 | case reflect.Int: 55 | et = IntType 56 | 57 | case reflect.Uint16: 58 | et = Uint16Type 59 | case reflect.Uint32: 60 | et = Uint32Type 61 | case reflect.Uint64: 62 | et = Uint64Type 63 | case reflect.Uint8: 64 | et = Uint8Type 65 | case reflect.Uint: 66 | et = UintType 67 | case reflect.Uintptr: 68 | et = UintptrType 69 | 70 | case reflect.String: 71 | et = StringType 72 | case reflect.Array: 73 | et = NewArrayType(int64(t.Len()), TypeFromNative(t.Elem())) 74 | case reflect.Chan: 75 | log.Panicf("%T not implemented", t) 76 | case reflect.Func: 77 | nin := t.NumIn() 78 | // Variadic functions have DotDotDotType at the end 79 | variadic := t.IsVariadic() 80 | if variadic { 81 | nin-- 82 | } 83 | in := make([]Type, nin) 84 | for i := range in { 85 | in[i] = TypeFromNative(t.In(i)) 86 | } 87 | out := make([]Type, t.NumOut()) 88 | for i := range out { 89 | out[i] = TypeFromNative(t.Out(i)) 90 | } 91 | et = NewFuncType(in, variadic, out) 92 | case reflect.Interface: 93 | log.Panicf("%T not implemented", t) 94 | case reflect.Map: 95 | et = NewMapType(TypeFromNative(t.Key()), TypeFromNative(t.Elem())) 96 | case reflect.Ptr: 97 | et = NewPtrType(TypeFromNative(t.Elem())) 98 | case reflect.Slice: 99 | et = NewSliceType(TypeFromNative(t.Elem())) 100 | case reflect.Struct: 101 | n := t.NumField() 102 | fields := make([]StructField, n) 103 | for i := 0; i < n; i++ { 104 | sf := t.Field(i) 105 | // TODO(austin) What to do about private fields? 106 | fields[i].Name = sf.Name 107 | fields[i].Type = TypeFromNative(sf.Type) 108 | fields[i].Anonymous = sf.Anonymous 109 | } 110 | et = NewStructType(fields) 111 | case reflect.UnsafePointer: 112 | log.Panicf("%T not implemented", t) 113 | default: 114 | log.Panicf("unexpected reflect.Type: %T", t) 115 | } 116 | 117 | if nt != nil { 118 | if _, ok := et.(*NamedType); !ok { 119 | nt.Complete(et) 120 | et = nt 121 | } 122 | } 123 | 124 | nativeTypes[et] = t 125 | evalTypes[t] = et 126 | 127 | return et 128 | } 129 | 130 | // TypeOfNative returns the interpreter Type of a regular Go value. 131 | func TypeOfNative(v interface{}) Type { 132 | return TypeFromNative(reflect.TypeOf(v)) 133 | } 134 | 135 | /* 136 | * Function bridging 137 | */ 138 | 139 | type nativeFunc struct { 140 | fn func(*Thread, []Value, []Value) 141 | in, out int 142 | } 143 | 144 | func (f *nativeFunc) NewFrame() *Frame { 145 | vars := make([]Value, f.in+f.out) 146 | return &Frame{nil, vars} 147 | } 148 | 149 | func (f *nativeFunc) Call(t *Thread) { f.fn(t, t.f.Vars[0:f.in], t.f.Vars[f.in:f.in+f.out]) } 150 | 151 | // FuncFromNative creates an interpreter function from a native 152 | // function that takes its in and out arguments as slices of 153 | // interpreter Value's. While somewhat inconvenient, this avoids 154 | // value marshalling. 155 | func FuncFromNative(fn func(*Thread, []Value, []Value), t *FuncType) FuncValue { 156 | return &funcV{&nativeFunc{fn, len(t.In), len(t.Out)}} 157 | } 158 | 159 | // FuncFromNativeTyped is like FuncFromNative, but constructs the 160 | // function type from a function pointer using reflection. Typically, 161 | // the type will be given as a nil pointer to a function with the 162 | // desired signature. 163 | func FuncFromNativeTyped(fn func(*Thread, []Value, []Value), t interface{}) (*FuncType, FuncValue) { 164 | ft := TypeOfNative(t).(*FuncType) 165 | return ft, FuncFromNative(fn, ft) 166 | } 167 | -------------------------------------------------------------------------------- /scope.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package eval 6 | 7 | import ( 8 | "go/token" 9 | "log" 10 | ) 11 | 12 | /* 13 | * Blocks and scopes 14 | */ 15 | 16 | // A definition can be a *Variable, *Constant, or Type. 17 | type Def interface { 18 | Pos() token.Pos 19 | } 20 | 21 | type Variable struct { 22 | VarPos token.Pos 23 | // Index of this variable in the Frame structure 24 | Index int 25 | // Static type of this variable 26 | Type Type 27 | // Value of this variable. This is only used by Scope.NewFrame; 28 | // therefore, it is useful for global scopes but cannot be used 29 | // in function scopes. 30 | Init Value 31 | } 32 | 33 | func (v *Variable) Pos() token.Pos { 34 | return v.VarPos 35 | } 36 | 37 | type Constant struct { 38 | ConstPos token.Pos 39 | Type Type 40 | Value Value 41 | } 42 | 43 | func (c *Constant) Pos() token.Pos { 44 | return c.ConstPos 45 | } 46 | 47 | type PkgIdent struct { 48 | PkgPos token.Pos 49 | path string // the unique path to that package 50 | scope *Scope // the scope holding the package definition(s) 51 | } 52 | 53 | func (p *PkgIdent) Pos() token.Pos { 54 | return p.PkgPos 55 | } 56 | 57 | // A block represents a definition block in which a name may not be 58 | // defined more than once. 59 | type block struct { 60 | // The block enclosing this one, including blocks in other 61 | // scopes. 62 | outer *block 63 | // The nested block currently being compiled, or nil. 64 | inner *block 65 | // The Scope containing this block. 66 | scope *Scope 67 | // The Variables, Constants, and Types defined in this block. 68 | defs map[string]Def 69 | // The index of the first variable defined in this block. 70 | // This must be greater than the index of any variable defined 71 | // in any parent of this block within the same Scope at the 72 | // time this block is entered. 73 | offset int 74 | // The number of Variables defined in this block. 75 | numVars int 76 | // If global, do not allocate new vars and consts in 77 | // the frame; assume that the refs will be compiled in 78 | // using defs[name].Init. 79 | global bool 80 | } 81 | 82 | // A Scope is the compile-time analogue of a Frame, which captures 83 | // some subtree of blocks. 84 | type Scope struct { 85 | // The root block of this scope. 86 | *block 87 | // The maximum number of variables required at any point in 88 | // this Scope. This determines the number of slots needed in 89 | // Frame's created from this Scope at run-time. 90 | maxVars int 91 | } 92 | 93 | // A special scope for the universe, to be able to stash 'packages' 94 | type universeScope struct { 95 | *Scope 96 | // a lookup-table for easy retrieval of packages by their 'path' 97 | pkgs map[string]*Scope 98 | } 99 | 100 | func (b *block) enterChild() *block { 101 | if b.inner != nil && b.inner.scope == b.scope { 102 | log.Panic("Failed to exit child block before entering another child") 103 | } 104 | sub := &block{ 105 | outer: b, 106 | scope: b.scope, 107 | defs: make(map[string]Def), 108 | offset: b.offset + b.numVars, 109 | } 110 | b.inner = sub 111 | return sub 112 | } 113 | 114 | func (b *block) exit() { 115 | if b.outer == nil { 116 | log.Panic("Cannot exit top-level block") 117 | } 118 | if b.outer.scope == b.scope { 119 | if b.outer.inner != b { 120 | log.Panic("Already exited block") 121 | } 122 | if b.inner != nil && b.inner.scope == b.scope { 123 | log.Panic("Exit of parent block without exit of child block") 124 | } 125 | } 126 | b.outer.inner = nil 127 | } 128 | 129 | func (b *block) ChildScope() *Scope { 130 | if b.inner != nil && b.inner.scope == b.scope { 131 | log.Panic("Failed to exit child block before entering a child scope") 132 | } 133 | sub := b.enterChild() 134 | sub.offset = 0 135 | sub.scope = &Scope{sub, 0} 136 | return sub.scope 137 | } 138 | 139 | func (b *block) undefine(name string) { 140 | delete(b.defs, name) 141 | } 142 | 143 | func (b *block) DefineVar(name string, pos token.Pos, t Type) (*Variable, Def) { 144 | if prev, ok := b.defs[name]; ok { 145 | return nil, prev 146 | } 147 | v := b.defineSlot(t, false) 148 | v.VarPos = pos 149 | b.defs[name] = v 150 | return v, nil 151 | } 152 | 153 | func (b *block) DefineTemp(t Type) *Variable { return b.defineSlot(t, true) } 154 | 155 | func (b *block) defineSlot(t Type, temp bool) *Variable { 156 | if b.inner != nil && b.inner.scope == b.scope { 157 | log.Panic("Failed to exit child block before defining variable") 158 | } 159 | index := -1 160 | if !b.global || temp { 161 | index = b.offset + b.numVars 162 | b.numVars++ 163 | if index >= b.scope.maxVars { 164 | b.scope.maxVars = index + 1 165 | } 166 | } 167 | v := &Variable{token.NoPos, index, t, nil} 168 | return v 169 | } 170 | 171 | func (b *block) DefineConst(name string, pos token.Pos, t Type, v Value) (*Constant, Def) { 172 | if prev, ok := b.defs[name]; ok { 173 | return nil, prev 174 | } 175 | c := &Constant{pos, t, v} 176 | b.defs[name] = c 177 | return c, nil 178 | } 179 | 180 | func (b *block) DefineType(name string, pos token.Pos, t Type) Type { 181 | if _, ok := b.defs[name]; ok { 182 | return nil 183 | } 184 | nt := &NamedType{pos, name, nil, true, make(map[string]Method)} 185 | if t != nil { 186 | nt.Complete(t) 187 | } 188 | b.defs[name] = nt 189 | return nt 190 | } 191 | 192 | func (b *block) DefinePackage(id, path string, pos token.Pos) (*PkgIdent, Def) { 193 | if prev, ok := b.defs[id]; ok { 194 | return nil, prev 195 | } 196 | p := &PkgIdent{pos, path, universe.pkgs[path]} 197 | b.defs[id] = p 198 | return p, nil 199 | } 200 | 201 | func (b *block) Lookup(name string) (bl *block, level int, def Def) { 202 | for b != nil { 203 | if d, ok := b.defs[name]; ok { 204 | return b, level, d 205 | } 206 | if b.outer != nil && b.scope != b.outer.scope { 207 | level++ 208 | } 209 | b = b.outer 210 | } 211 | return nil, 0, nil 212 | } 213 | 214 | func (s *Scope) NewFrame(outer *Frame) *Frame { return outer.child(s.maxVars) } 215 | 216 | /* 217 | * Frames 218 | */ 219 | 220 | type Frame struct { 221 | Outer *Frame 222 | Vars []Value 223 | } 224 | 225 | func (f *Frame) Get(level int, index int) Value { 226 | for ; level > 0; level-- { 227 | f = f.Outer 228 | } 229 | return f.Vars[index] 230 | } 231 | 232 | func (f *Frame) child(numVars int) *Frame { 233 | // TODO(austin) This is probably rather expensive. All values 234 | // require heap allocation and zeroing them when we execute a 235 | // definition typically requires some computation. 236 | return &Frame{f, make([]Value, numVars)} 237 | } 238 | -------------------------------------------------------------------------------- /eval_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package eval 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | "go/token" 11 | "log" 12 | "math/big" 13 | "reflect" 14 | "regexp" 15 | "testing" 16 | ) 17 | 18 | // All tests are done using the same file set. 19 | var fset = token.NewFileSet() 20 | 21 | // Print each statement or expression before parsing it 22 | var noisy = false 23 | 24 | func init() { flag.BoolVar(&noisy, "noisy", false, "chatter during eval tests") } 25 | 26 | /* 27 | * Generic statement/expression test framework 28 | */ 29 | 30 | type test []job 31 | 32 | type job struct { 33 | code string 34 | cerr string 35 | rterr string 36 | val Value 37 | noval bool 38 | } 39 | 40 | func runTests(t *testing.T, baseName string, tests []test) { 41 | delta := 1 42 | if testing.Short() { 43 | delta = 16 44 | } 45 | for i := 0; i < len(tests); i += delta { 46 | name := fmt.Sprintf("%s[%d]", baseName, i) 47 | tests[i].run(t, name) 48 | } 49 | } 50 | 51 | func (a test) run(t *testing.T, name string) { 52 | w := newTestWorld() 53 | for _, j := range a { 54 | src := j.code + ";" // trailing semicolon to finish statement 55 | if noisy { 56 | println("code:", src) 57 | } 58 | 59 | code, err := w.Compile(fset, src) 60 | if err != nil { 61 | if j.cerr == "" { 62 | t.Errorf("%s: Compile %s: %v", name, src, err) 63 | break 64 | } 65 | if !match(t, err, j.cerr) { 66 | t.Errorf("%s: Compile %s = error %s; want %v", name, src, err, j.cerr) 67 | break 68 | } 69 | continue 70 | } 71 | if j.cerr != "" { 72 | t.Errorf("%s: Compile %s succeeded; want %s", name, src, j.cerr) 73 | break 74 | } 75 | 76 | val, err := code.Run() 77 | if err != nil { 78 | if j.rterr == "" { 79 | t.Errorf("%s: Run %s: %v", name, src, err) 80 | break 81 | } 82 | if !match(t, err, j.rterr) { 83 | t.Errorf("%s: Run %s = error %s; want %v", name, src, err, j.rterr) 84 | break 85 | } 86 | continue 87 | } 88 | if j.rterr != "" { 89 | t.Errorf("%s: Run %s succeeded; want %s", name, src, j.rterr) 90 | break 91 | } 92 | 93 | if !j.noval && !reflect.DeepEqual(val, j.val) { 94 | t.Errorf("%s: Run %s = %T(%v) want %T(%v) [deep-equal=%v]", name, src, val, val, j.val, j.val, reflect.DeepEqual(val, j.val)) 95 | } 96 | } 97 | } 98 | 99 | func match(t *testing.T, err error, pat string) bool { 100 | ok, err1 := regexp.MatchString(pat, err.Error()) 101 | if err1 != nil { 102 | t.Fatalf("compile regexp %s: %v", pat, err1) 103 | } 104 | return ok 105 | } 106 | 107 | /* 108 | * Test constructors 109 | */ 110 | 111 | // Expression compile error 112 | func CErr(expr string, cerr string) test { return test([]job{{code: expr, cerr: cerr}}) } 113 | 114 | // Expression runtime error 115 | func RErr(expr string, rterr string) test { return test([]job{{code: expr, rterr: rterr}}) } 116 | 117 | // Expression value 118 | func Val(expr string, val interface{}) test { 119 | return test([]job{{code: expr, val: toValue(val)}}) 120 | } 121 | 122 | // Statement runs without error 123 | func Run(stmts string) test { return test([]job{{code: stmts, noval: true}}) } 124 | 125 | // Two statements without error. 126 | // TODO(rsc): Should be possible with Run but the parser 127 | // won't let us do both top-level and non-top-level statements. 128 | func Run2(stmt1, stmt2 string) test { 129 | return test([]job{{code: stmt1, noval: true}, {code: stmt2, noval: true}}) 130 | } 131 | 132 | // Statement runs and test one expression's value 133 | func Val1(stmts string, expr1 string, val1 interface{}) test { 134 | return test([]job{ 135 | {code: stmts, noval: true}, 136 | {code: expr1, val: toValue(val1)}, 137 | }) 138 | } 139 | 140 | // Statement runs and test two expressions' values 141 | func Val2(stmts string, expr1 string, val1 interface{}, expr2 string, val2 interface{}) test { 142 | return test([]job{ 143 | {code: stmts, noval: true}, 144 | {code: expr1, val: toValue(val1)}, 145 | {code: expr2, val: toValue(val2)}, 146 | }) 147 | } 148 | 149 | /* 150 | * Value constructors 151 | */ 152 | 153 | type vstruct []interface{} 154 | 155 | type varray []interface{} 156 | 157 | type vslice struct { 158 | arr varray 159 | len, cap int 160 | } 161 | 162 | type vmap map[interface{}]interface{} 163 | 164 | func toValue(val interface{}) Value { 165 | switch val := val.(type) { 166 | case bool: 167 | r := boolV(val) 168 | return &r 169 | case uint8: 170 | r := uint8V(val) 171 | return &r 172 | case uint: 173 | r := uintV(val) 174 | return &r 175 | case int: 176 | r := intV(val) 177 | return &r 178 | case *big.Int: 179 | return &idealIntV{val} 180 | case float64: 181 | r := float64V(val) 182 | return &r 183 | case *big.Rat: 184 | return &idealFloatV{val} 185 | case string: 186 | r := stringV(val) 187 | return &r 188 | case vstruct: 189 | elems := make([]Value, len(val)) 190 | for i, e := range val { 191 | elems[i] = toValue(e) 192 | } 193 | r := structV(elems) 194 | return &r 195 | case varray: 196 | elems := make([]Value, len(val)) 197 | for i, e := range val { 198 | elems[i] = toValue(e) 199 | } 200 | r := arrayV(elems) 201 | return &r 202 | case vslice: 203 | return &sliceV{Slice{toValue(val.arr).(ArrayValue), int64(val.len), int64(val.cap)}} 204 | case vmap: 205 | target := evalMap{} 206 | for k, v := range val { 207 | target[k] = toValue(v) 208 | } 209 | r := mapV{target} 210 | return &r 211 | case Func: 212 | return &funcV{val} 213 | } 214 | log.Panicf("toValue(%T) not implemented", val) 215 | panic("unreachable") 216 | } 217 | 218 | /* 219 | * Default test scope 220 | */ 221 | 222 | type testFunc struct{} 223 | 224 | func (*testFunc) NewFrame() *Frame { return &Frame{nil, make([]Value, 2)} } 225 | 226 | func (*testFunc) Call(t *Thread) { 227 | n := t.f.Vars[0].(IntValue).Get(t) 228 | 229 | res := n + 1 230 | 231 | t.f.Vars[1].(IntValue).Set(t, res) 232 | } 233 | 234 | type oneTwoFunc struct{} 235 | 236 | func (*oneTwoFunc) NewFrame() *Frame { return &Frame{nil, make([]Value, 2)} } 237 | 238 | func (*oneTwoFunc) Call(t *Thread) { 239 | t.f.Vars[0].(IntValue).Set(t, 1) 240 | t.f.Vars[1].(IntValue).Set(t, 2) 241 | } 242 | 243 | type voidFunc struct{} 244 | 245 | func (*voidFunc) NewFrame() *Frame { return &Frame{nil, []Value{}} } 246 | 247 | func (*voidFunc) Call(t *Thread) {} 248 | 249 | func newTestWorld() *World { 250 | w := NewWorld() 251 | 252 | def := func(name string, t Type, val interface{}) { w.DefineVar(name, t, toValue(val)) } 253 | 254 | w.DefineConst("c", IdealIntType, toValue(big.NewInt(1))) 255 | def("i", IntType, 1) 256 | def("i2", IntType, 2) 257 | def("u", UintType, uint(1)) 258 | def("f", Float64Type, 1.0) 259 | def("s", StringType, "abc") 260 | def("t", NewStructType([]StructField{{"a", IntType, false}}), vstruct{1}) 261 | def("ai", NewArrayType(2, IntType), varray{1, 2}) 262 | def("aai", NewArrayType(2, NewArrayType(2, IntType)), varray{varray{1, 2}, varray{3, 4}}) 263 | def("aai2", NewArrayType(2, NewArrayType(2, IntType)), varray{varray{5, 6}, varray{7, 8}}) 264 | def("fn", NewFuncType([]Type{IntType}, false, []Type{IntType}), &testFunc{}) 265 | def("oneTwo", NewFuncType([]Type{}, false, []Type{IntType, IntType}), &oneTwoFunc{}) 266 | def("void", NewFuncType([]Type{}, false, []Type{}), &voidFunc{}) 267 | def("sli", NewSliceType(IntType), vslice{varray{1, 2, 3}, 2, 3}) 268 | 269 | def("ami", NewMapType(IntType, IntType), vmap{1: 10, 2: 20}) 270 | return w 271 | } 272 | -------------------------------------------------------------------------------- /world.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | // Package eval is the beginning of an interpreter for Go. 6 | // It can run simple Go programs but does not implement 7 | // interface values or packages. 8 | 9 | // go/importer is only available in go1.6 and later 10 | // +build go1.6 11 | 12 | package eval 13 | 14 | import ( 15 | "errors" 16 | "fmt" 17 | "go/ast" 18 | "go/importer" 19 | "go/parser" 20 | "go/scanner" 21 | "go/token" 22 | "go/types" 23 | "regexp" 24 | "strconv" 25 | ) 26 | 27 | // track the status of each package we visit (unvisited/visiting/done) 28 | var g_visiting = make(map[string]status) 29 | 30 | // config used for type checking 31 | var g_typesConfig = types.Config{Importer: importer.Default()} 32 | 33 | 34 | type status int // status for visiting map 35 | const ( 36 | unvisited status = iota 37 | visiting 38 | done 39 | ) 40 | 41 | type World struct { 42 | scope *Scope 43 | frame *Frame 44 | inits []Code 45 | } 46 | 47 | func NewWorld() *World { 48 | w := &World{ 49 | scope: universe.ChildScope(), 50 | } 51 | w.scope.global = true // this block's vars allocate directly 52 | return w 53 | } 54 | 55 | type Code interface { 56 | // The type of the value Run returns, or nil if Run returns nil. 57 | Type() Type 58 | 59 | // Run runs the code; if the code is a single expression 60 | // with a value, it returns the value; otherwise it returns nil. 61 | Run() (Value, error) 62 | } 63 | 64 | type pkgCode struct { 65 | w *World 66 | code code 67 | } 68 | 69 | func (p *pkgCode) Type() Type { return nil } 70 | 71 | func (p *pkgCode) Run() (Value, error) { 72 | t := new(Thread) 73 | t.f = p.w.scope.NewFrame(nil) 74 | return nil, t.Try(func(t *Thread) { p.code.exec(t) }) 75 | } 76 | 77 | func (w *World) CompilePackage(fset *token.FileSet, files []*ast.File, pkgpath string) (Code, error) { 78 | pkgFiles := make(map[string]*ast.File) 79 | for _, f := range files { 80 | pkgFiles[f.Name.Name] = f 81 | } 82 | 83 | //pkg, err := ast.NewPackage(fset, pkgFiles, srcImporter, types.Universe) 84 | pkg, err := g_typesConfig.Check(files[0].Name.String(), fset, files, nil) 85 | if err != nil { 86 | return nil, err 87 | } 88 | if pkg == nil { 89 | return nil, errors.New("could not create an AST package out of ast.Files") 90 | } 91 | 92 | switch g_visiting[pkgpath] { 93 | case done: 94 | return &pkgCode{w, make(code, 0)}, nil 95 | case visiting: 96 | //fmt.Printf("** package dependency cycle **\n") 97 | return nil, errors.New("package dependency cycle") 98 | } 99 | g_visiting[pkgpath] = visiting 100 | // create a new scope in which to process this new package 101 | imports := []*ast.ImportSpec{} 102 | for _, f := range files { 103 | imports = append(imports, f.Imports...) 104 | } 105 | 106 | for _, imp := range imports { 107 | path, _ := strconv.Unquote(imp.Path.Value) 108 | if _, ok := universe.pkgs[path]; ok { 109 | // already compiled 110 | continue 111 | } 112 | imp_files, err := findPkgFiles(path) 113 | if err != nil { 114 | return nil, errors.New(fmt.Sprintf("could not find files for package [%s]", path)) 115 | } 116 | code, err := w.CompilePackage(fset, imp_files, path) 117 | if err != nil { 118 | return nil, err 119 | } 120 | _, err = code.Run() 121 | if err != nil { 122 | return nil, err 123 | } 124 | } 125 | 126 | prev_scope := w.scope 127 | w.scope = w.scope.ChildScope() 128 | w.scope.global = true 129 | defer func() { 130 | g_visiting[pkgpath] = done 131 | // add this scope (the package's scope) to the lookup-table of packages 132 | universe.pkgs[pkgpath] = w.scope 133 | // restore the previous scope 134 | w.scope.exit() 135 | if pkgpath != "main" { 136 | w.scope = prev_scope 137 | } 138 | }() 139 | 140 | decls := make([]ast.Decl, 0) 141 | for _, f := range files { 142 | decls = append(decls, f.Decls...) 143 | } 144 | code, err := w.CompileDeclList(fset, decls) 145 | if err != nil { 146 | return nil, err 147 | } 148 | _, err = code.Run() 149 | if err != nil { 150 | return nil, err 151 | } 152 | 153 | //FIXME: make sure all the imports are used at this point. 154 | 155 | { 156 | // store the init function (if any) for later use 157 | init_code, init_err := w.Compile(fset, "init()") 158 | if init_code != nil { 159 | if init_err == nil || init_err != nil { 160 | w.inits = append(w.inits, init_code) 161 | } 162 | } 163 | } 164 | return code, err 165 | } 166 | 167 | type stmtCode struct { 168 | w *World 169 | code code 170 | } 171 | 172 | func (w *World) CompileStmtList(fset *token.FileSet, stmts []ast.Stmt) (Code, error) { 173 | if len(stmts) == 1 { 174 | if s, ok := stmts[0].(*ast.ExprStmt); ok { 175 | return w.CompileExpr(fset, s.X) 176 | } 177 | } 178 | errors := new(scanner.ErrorList) 179 | cc := &compiler{fset, errors, 0, 0} 180 | cb := newCodeBuf() 181 | fc := &funcCompiler{ 182 | compiler: cc, 183 | fnType: nil, 184 | outVarsNamed: false, 185 | codeBuf: cb, 186 | flow: newFlowBuf(cb), 187 | labels: make(map[string]*label), 188 | } 189 | bc := &blockCompiler{ 190 | funcCompiler: fc, 191 | block: w.scope.block, 192 | } 193 | nerr := cc.numError() 194 | for _, stmt := range stmts { 195 | bc.compileStmt(stmt) 196 | } 197 | fc.checkLabels() 198 | if nerr != cc.numError() { 199 | errors.Sort() 200 | return nil, errors.Err() 201 | } 202 | return &stmtCode{w, fc.get()}, nil 203 | } 204 | 205 | func (w *World) CompileDeclList(fset *token.FileSet, decls []ast.Decl) (Code, error) { 206 | stmts := make([]ast.Stmt, len(decls)) 207 | for i, d := range decls { 208 | stmts[i] = &ast.DeclStmt{d} 209 | } 210 | return w.CompileStmtList(fset, stmts) 211 | } 212 | 213 | func (s *stmtCode) Type() Type { return nil } 214 | 215 | func (s *stmtCode) Run() (Value, error) { 216 | t := new(Thread) 217 | t.f = s.w.scope.NewFrame(nil) 218 | return nil, t.Try(func(t *Thread) { s.code.exec(t) }) 219 | } 220 | 221 | type exprCode struct { 222 | w *World 223 | e *expr 224 | eval func(Value, *Thread) 225 | } 226 | 227 | func (w *World) CompileExpr(fset *token.FileSet, e ast.Expr) (Code, error) { 228 | errors := new(scanner.ErrorList) 229 | cc := &compiler{fset, errors, 0, 0} 230 | 231 | ec := cc.compileExpr(w.scope.block, false, e) 232 | if ec == nil { 233 | errors.Sort() 234 | return nil, errors.Err() 235 | } 236 | var eval func(Value, *Thread) 237 | switch t := ec.t.(type) { 238 | case *idealIntType: 239 | // nothing 240 | case *idealFloatType: 241 | // nothing 242 | default: 243 | if tm, ok := t.(*MultiType); ok && len(tm.Elems) == 0 { 244 | return &stmtCode{w, code{ec.exec}}, nil 245 | } 246 | eval = genAssign(ec.t, ec) 247 | } 248 | return &exprCode{w, ec, eval}, nil 249 | } 250 | 251 | func (e *exprCode) Type() Type { return e.e.t } 252 | 253 | func (e *exprCode) Run() (Value, error) { 254 | t := new(Thread) 255 | t.f = e.w.scope.NewFrame(nil) 256 | switch e.e.t.(type) { 257 | case *idealIntType: 258 | return &idealIntV{e.e.asIdealInt()()}, nil 259 | case *idealFloatType: 260 | return &idealFloatV{e.e.asIdealFloat()()}, nil 261 | } 262 | v := e.e.t.Zero() 263 | eval := e.eval 264 | err := t.Try(func(t *Thread) { eval(v, t) }) 265 | return v, err 266 | } 267 | 268 | func (w *World) run_init() error { 269 | // run the 'init()' function of all dependent packages 270 | for _, init_code := range w.inits { 271 | _, err := init_code.Run() 272 | if err != nil { 273 | return err 274 | } 275 | } 276 | // reset 277 | w.inits = make([]Code, 0) 278 | return nil 279 | } 280 | 281 | // Regexp to match the import keyword 282 | var import_regexp = regexp.MustCompile("[ \t\n]*import[ \t(]") 283 | 284 | func (w *World) Compile(fset *token.FileSet, text string) (Code, error) { 285 | if text == "main()" { 286 | err := w.run_init() 287 | if err != nil { 288 | return nil, err 289 | } 290 | } 291 | if i := import_regexp.FindStringIndex(text); i != nil && i[0] == 0 { 292 | // special case for import-ing on the command line... 293 | //return w.compileImport(fset, text) 294 | return nil, fmt.Errorf("sorry. import \"foo\" not (yet?) implemented") 295 | } 296 | 297 | stmts, err := parseStmtList(fset, text) 298 | if err == nil { 299 | return w.CompileStmtList(fset, stmts) 300 | } 301 | 302 | // Otherwise try as DeclList 303 | decls, err1 := parseDeclList(fset, text) 304 | if err1 == nil { 305 | return w.CompileDeclList(fset, decls) 306 | } 307 | 308 | // Have to pick an error. 309 | // Parsing as statement list admits more forms, 310 | // its error is more likely to be useful. 311 | return nil, err 312 | } 313 | 314 | func (w *World) compileImport(fset *token.FileSet, text string) (Code, error) { 315 | f, err := parser.ParseFile(fset, "input", "package main;"+text, 0) 316 | if err != nil { 317 | return nil, err 318 | } 319 | 320 | imp := f.Imports[0] 321 | path, _ := strconv.Unquote(imp.Path.Value) 322 | imp_files, err := findPkgFiles(path) 323 | if err != nil { 324 | return nil, errors.New(fmt.Sprintf("could not find files for package [%s]", path)) 325 | } 326 | { 327 | code, err := w.CompilePackage(fset, imp_files, path) 328 | if err != nil { 329 | return nil, err 330 | } 331 | _, err = code.Run() 332 | if err != nil { 333 | return nil, err 334 | } 335 | err = w.run_init() 336 | if err != nil { 337 | return nil, err 338 | } 339 | } 340 | return w.CompileDeclList(fset, f.Decls) 341 | } 342 | 343 | func parseStmtList(fset *token.FileSet, src string) ([]ast.Stmt, error) { 344 | f, err := parser.ParseFile(fset, "input", "package p;func _(){"+src+"\n}", 0) 345 | if err != nil { 346 | return nil, err 347 | } 348 | return f.Decls[0].(*ast.FuncDecl).Body.List, nil 349 | } 350 | 351 | func parseDeclList(fset *token.FileSet, src string) ([]ast.Decl, error) { 352 | f, err := parser.ParseFile(fset, "input", "package p;"+src, 0) 353 | if err != nil { 354 | return nil, err 355 | } 356 | return f.Decls, nil 357 | } 358 | 359 | type RedefinitionError struct { 360 | Name string 361 | Prev Def 362 | } 363 | 364 | func (e *RedefinitionError) Error() string { 365 | res := "identifier " + e.Name + " redeclared" 366 | pos := e.Prev.Pos() 367 | if pos.IsValid() { 368 | // TODO: fix this - currently this code is not reached by the tests 369 | // need to get a file set (fset) from somewhere 370 | //res += "; previous declaration at " + fset.Position(pos).String() 371 | panic(0) 372 | } 373 | return res 374 | } 375 | 376 | func (w *World) DefineConst(name string, t Type, val Value) error { 377 | _, prev := w.scope.DefineConst(name, token.NoPos, t, val) 378 | if prev != nil { 379 | return &RedefinitionError{name, prev} 380 | } 381 | return nil 382 | } 383 | 384 | func (w *World) DefineVar(name string, t Type, val Value) error { 385 | v, prev := w.scope.DefineVar(name, token.NoPos, t) 386 | if prev != nil { 387 | return &RedefinitionError{name, prev} 388 | } 389 | v.Init = val 390 | return nil 391 | } 392 | -------------------------------------------------------------------------------- /cmd/gen/gen.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package main 6 | 7 | // generate operator implementations 8 | 9 | import ( 10 | "log" 11 | "os" 12 | "text/template" 13 | ) 14 | 15 | type Op struct { 16 | Name string 17 | Expr string 18 | Body string // overrides Expr 19 | ConstExpr string 20 | AsRightName string 21 | ReturnType string 22 | Types []*Type 23 | } 24 | 25 | type Size struct { 26 | Bits int 27 | Sized string 28 | } 29 | 30 | type Type struct { 31 | Repr string 32 | Value string 33 | Native string 34 | As string 35 | IsIdeal bool 36 | HasAssign bool 37 | Sizes []Size 38 | } 39 | 40 | var ( 41 | boolType = &Type{Repr: "*boolType", Value: "BoolValue", Native: "bool", As: "asBool"} 42 | uintType = &Type{Repr: "*uintType", Value: "UintValue", Native: "uint64", As: "asUint", 43 | Sizes: []Size{{8, "uint8"}, {16, "uint16"}, {32, "uint32"}, {64, "uint64"}, {0, "uint"}}, 44 | } 45 | intType = &Type{Repr: "*intType", Value: "IntValue", Native: "int64", As: "asInt", 46 | Sizes: []Size{{8, "int8"}, {16, "int16"}, {32, "int32"}, {64, "int64"}, {0, "int"}}, 47 | } 48 | idealIntType = &Type{Repr: "*idealIntType", Value: "IdealIntValue", Native: "*big.Int", As: "asIdealInt", IsIdeal: true} 49 | floatType = &Type{Repr: "*floatType", Value: "FloatValue", Native: "float64", As: "asFloat", 50 | Sizes: []Size{{32, "float32"}, {64, "float64"}}, 51 | } 52 | idealFloatType = &Type{Repr: "*idealFloatType", Value: "IdealFloatValue", Native: "*big.Rat", As: "asIdealFloat", IsIdeal: true} 53 | stringType = &Type{Repr: "*stringType", Value: "StringValue", Native: "string", As: "asString"} 54 | arrayType = &Type{Repr: "*ArrayType", Value: "ArrayValue", Native: "ArrayValue", As: "asArray", HasAssign: true} 55 | structType = &Type{Repr: "*StructType", Value: "StructValue", Native: "StructValue", As: "asStruct", HasAssign: true} 56 | ptrType = &Type{Repr: "*PtrType", Value: "PtrValue", Native: "Value", As: "asPtr"} 57 | funcType = &Type{Repr: "*FuncType", Value: "FuncValue", Native: "Func", As: "asFunc"} 58 | sliceType = &Type{Repr: "*SliceType", Value: "SliceValue", Native: "Slice", As: "asSlice"} 59 | mapType = &Type{Repr: "*MapType", Value: "MapValue", Native: "Map", As: "asMap"} 60 | 61 | all = []*Type{ 62 | boolType, 63 | uintType, 64 | intType, 65 | idealIntType, 66 | floatType, 67 | idealFloatType, 68 | stringType, 69 | arrayType, 70 | structType, 71 | ptrType, 72 | funcType, 73 | sliceType, 74 | mapType, 75 | } 76 | bools = all[0:1] 77 | integers = all[1:4] 78 | shiftable = all[1:3] 79 | numbers = all[1:6] 80 | addable = all[1:7] 81 | cmpable = []*Type{ 82 | boolType, 83 | uintType, 84 | intType, 85 | idealIntType, 86 | floatType, 87 | idealFloatType, 88 | stringType, 89 | ptrType, 90 | funcType, 91 | mapType, 92 | } 93 | ) 94 | 95 | var unOps = []Op{ 96 | {Name: "Neg", Expr: "-v", ConstExpr: "val.Neg(val)", Types: numbers}, 97 | {Name: "Not", Expr: "!v", Types: bools}, 98 | {Name: "Xor", Expr: "^v", ConstExpr: "val.Not(val)", Types: integers}, 99 | } 100 | 101 | var binOps = []Op{ 102 | {Name: "Add", Expr: "l + r", ConstExpr: "l.Add(l, r)", Types: addable}, 103 | {Name: "Sub", Expr: "l - r", ConstExpr: "l.Sub(l, r)", Types: numbers}, 104 | {Name: "Mul", Expr: "l * r", ConstExpr: "l.Mul(l, r)", Types: numbers}, 105 | {Name: "Quo", 106 | Body: "if r == 0 { t.Abort(DivByZeroError{}) }; ret = l / r", 107 | ConstExpr: "l.Quo(l, r)", 108 | Types: numbers, 109 | }, 110 | {Name: "Rem", 111 | Body: "if r == 0 { t.Abort(DivByZeroError{}) }; ret = l % r", 112 | ConstExpr: "l.Rem(l, r)", 113 | Types: integers, 114 | }, 115 | {Name: "And", Expr: "l & r", ConstExpr: "l.And(l, r)", Types: integers}, 116 | {Name: "Or", Expr: "l | r", ConstExpr: "l.Or(l, r)", Types: integers}, 117 | {Name: "Xor", Expr: "l ^ r", ConstExpr: "l.Xor(l, r)", Types: integers}, 118 | {Name: "AndNot", Expr: "l &^ r", ConstExpr: "l.AndNot(l, r)", Types: integers}, 119 | {Name: "Shl", Expr: "l << r", ConstExpr: "l.Lsh(l, uint(r.Value()))", 120 | AsRightName: "asUint", Types: shiftable, 121 | }, 122 | {Name: "Shr", Expr: "l >> r", ConstExpr: "new(big.Int).Rsh(l, uint(r.Value()))", 123 | AsRightName: "asUint", Types: shiftable, 124 | }, 125 | {Name: "Lss", Expr: "l < r", ConstExpr: "l.Cmp(r) < 0", ReturnType: "bool", Types: addable}, 126 | {Name: "Gtr", Expr: "l > r", ConstExpr: "l.Cmp(r) > 0", ReturnType: "bool", Types: addable}, 127 | {Name: "Leq", Expr: "l <= r", ConstExpr: "l.Cmp(r) <= 0", ReturnType: "bool", Types: addable}, 128 | {Name: "Geq", Expr: "l >= r", ConstExpr: "l.Cmp(r) >= 0", ReturnType: "bool", Types: addable}, 129 | {Name: "Eql", Expr: "l == r", ConstExpr: "l.Cmp(r) == 0", ReturnType: "bool", Types: cmpable}, 130 | {Name: "Neq", Expr: "l != r", ConstExpr: "l.Cmp(r) != 0", ReturnType: "bool", Types: cmpable}, 131 | } 132 | 133 | type Data struct { 134 | UnaryOps []Op 135 | BinaryOps []Op 136 | Types []*Type 137 | } 138 | 139 | var data = Data{ 140 | unOps, 141 | binOps, 142 | all, 143 | } 144 | 145 | const templateStr = ` 146 | // This file is machine generated by gen.go. 147 | // cd cmd/gen; go build . && ./gen >expr1.go 148 | 149 | package eval 150 | 151 | import ( 152 | "log" 153 | "math/big" 154 | ) 155 | 156 | /* 157 | * "As" functions. These retrieve evaluator functions from an 158 | * expr, panicking if the requested evaluator has the wrong type. 159 | */ 160 | «range .Types» 161 | «if .IsIdeal» 162 | func (a *expr) «.As»() (func() «.Native») { 163 | return a.eval.(func()(«.Native»)) 164 | } 165 | «else» 166 | func (a *expr) «.As»() (func(*Thread) «.Native») { 167 | return a.eval.(func(*Thread)(«.Native»)) 168 | } 169 | «end» 170 | «end» 171 | func (a *expr) asMulti() (func(*Thread) []Value) { 172 | return a.eval.(func(*Thread)[]Value) 173 | } 174 | 175 | func (a *expr) asInterface() (func(*Thread) interface{}) { 176 | switch sf := a.eval.(type) { 177 | «range .Types» 178 | «if .IsIdeal» 179 | case func()«.Native»: 180 | return func(*Thread) interface{} { return sf() } 181 | «else» 182 | case func(t *Thread)«.Native»: 183 | return func(t *Thread) interface{} { return sf(t) } 184 | «end» 185 | «end» 186 | default: 187 | log.Panicf("unexpected expression node type %T at %v", a.eval, a.pos) 188 | } 189 | panic("fail") 190 | } 191 | 192 | /* 193 | * Operator generators. 194 | */ 195 | 196 | func (a *expr) genConstant(v Value) { 197 | switch a.t.lit().(type) { 198 | «range .Types» 199 | case «.Repr»: 200 | «if .IsIdeal» 201 | val := v.(«.Value»).Get() 202 | a.eval = func() «.Native» { return val } 203 | «else» 204 | a.eval = func(t *Thread) «.Native» { return v.(«.Value»).Get(t) } 205 | «end» 206 | «end» 207 | default: 208 | log.Panicf("unexpected constant type %v at %v", a.t, a.pos) 209 | } 210 | } 211 | 212 | func (a *expr) genIdentOp(level, index int) { 213 | a.evalAddr = func(t *Thread) Value { return t.f.Get(level, index) } 214 | switch a.t.lit().(type) { 215 | «range .Types» 216 | «if .IsIdeal» 217 | «else» 218 | case «.Repr»: 219 | a.eval = func(t *Thread) «.Native» { return t.f.Get(level, index).(«.Value»).Get(t) } 220 | «end» 221 | «end» 222 | default: 223 | log.Panicf("unexpected identifier type %v at %v", a.t, a.pos) 224 | } 225 | } 226 | 227 | func (a *expr) genFuncCall(call func(t *Thread) []Value) { 228 | a.exec = func(t *Thread) { call(t)} 229 | switch a.t.lit().(type) { 230 | «range .Types» 231 | «if .IsIdeal» 232 | «else» 233 | case «.Repr»: 234 | a.eval = func(t *Thread) «.Native» { return call(t)[0].(«.Value»).Get(t) } 235 | «end» 236 | «end» 237 | case *MultiType: 238 | a.eval = func(t *Thread) []Value { return call(t) } 239 | default: 240 | log.Panicf("unexpected result type %v at %v", a.t, a.pos) 241 | } 242 | } 243 | 244 | func (a *expr) genValue(vf func(*Thread) Value) { 245 | a.evalAddr = vf 246 | switch a.t.lit().(type) { 247 | «range .Types» 248 | «if .IsIdeal» 249 | «else» 250 | case «.Repr»: 251 | a.eval = func(t *Thread) «.Native» { return vf(t).(«.Value»).Get(t) } 252 | «end» 253 | «end» 254 | default: 255 | log.Panicf("unexpected result type %v at %v", a.t, a.pos) 256 | } 257 | } 258 | 259 | «range $op := .UnaryOps» 260 | func (a *expr) genUnaryOp«.Name»(v *expr) { 261 | switch a.t.lit().(type) { 262 | «range .Types» 263 | case «.Repr»: 264 | «if .IsIdeal» 265 | val := v.«.As»()() 266 | «$op.ConstExpr» 267 | a.eval = func() «.Native» { return val } 268 | «else» 269 | vf := v.«.As»() 270 | a.eval = func(t *Thread) «.Native» { v := vf(t); return «$op.Expr» } 271 | «end» 272 | «end» 273 | default: 274 | log.Panicf("unexpected type %v at %v", a.t, a.pos) 275 | } 276 | } 277 | 278 | «end» 279 | func (a *expr) genBinOpLogAnd(l, r *expr) { 280 | lf := l.asBool() 281 | rf := r.asBool() 282 | a.eval = func(t *Thread) bool { return lf(t) && rf(t) } 283 | } 284 | 285 | func (a *expr) genBinOpLogOr(l, r *expr) { 286 | lf := l.asBool() 287 | rf := r.asBool() 288 | a.eval = func(t *Thread) bool { return lf(t) || rf(t) } 289 | } 290 | 291 | «range $op := .BinaryOps» 292 | func (a *expr) genBinOp«$op.Name»(l, r *expr) { 293 | switch t := l.t.lit().(type) { 294 | «range $type := .Types» 295 | case «$type.Repr»: 296 | «if $type.IsIdeal» 297 | l := l.«$type.As»()() 298 | r := r.«$type.As»()() 299 | val := «$op.ConstExpr» 300 | «if $op.ReturnType» 301 | a.eval = func(t *Thread) «$op.ReturnType» { return val } 302 | «else» 303 | a.eval = func() «$type.Native» { return val } 304 | «end» 305 | «else» 306 | lf := l.«$type.As»() 307 | rf := r.«if $op.AsRightName»«$op.AsRightName»«else»«$type.As»«end»() 308 | «if $op.ReturnType» 309 | a.eval = func(t *Thread) «$op.ReturnType» { 310 | l, r := lf(t), rf(t) 311 | return «$op.Expr» 312 | } 313 | «else» 314 | «if .Sizes» 315 | switch t.Bits { 316 | «range .Sizes» 317 | case «.Bits»: 318 | a.eval = func(t *Thread) «$type.Native» { 319 | l, r := lf(t), rf(t) 320 | var ret «$type.Native» 321 | «if $op.Body» 322 | «$op.Body» 323 | «else» 324 | ret = «$op.Expr» 325 | «end» 326 | return «$type.Native»(«.Sized»(ret)) 327 | } 328 | «end» 329 | default: 330 | log.Panicf("unexpected size %d in type %v at %v", t.Bits, t, a.pos) 331 | } 332 | «else» 333 | a.eval = func(t *Thread) «$type.Native» { 334 | l, r := lf(t), rf(t) 335 | return «$op.Expr» 336 | } 337 | «end» 338 | «end» 339 | «end» 340 | «end» 341 | default: 342 | log.Panicf("unexpected type %v at %v", l.t, a.pos) 343 | } 344 | } 345 | 346 | «end» 347 | func genAssign(lt Type, r *expr) (func(lv Value, t *Thread)) { 348 | switch lt.lit().(type) { 349 | «range .Types» 350 | «if .IsIdeal» 351 | «else» 352 | case «.Repr»: 353 | rf := r.«.As»() 354 | return func(lv Value, t *Thread) { «if .HasAssign»lv.Assign(t, rf(t))«else»lv.(«.Value»).Set(t, rf(t))«end» } 355 | «end» 356 | «end» 357 | default: 358 | log.Panicf("unexpected left operand type %v at %v", lt, r.pos) 359 | } 360 | panic("fail") 361 | } 362 | ` 363 | 364 | func main() { 365 | t := template.New("") 366 | t.Delims("«", "»") 367 | t, err := t.Parse(templateStr) 368 | if err != nil { 369 | log.Fatal(err) 370 | } 371 | err = t.Execute(os.Stdout, data) 372 | if err != nil { 373 | log.Fatal(err) 374 | } 375 | } 376 | -------------------------------------------------------------------------------- /typec.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package eval 6 | 7 | import ( 8 | "go/ast" 9 | "go/token" 10 | "log" 11 | ) 12 | 13 | /* 14 | * Type compiler 15 | */ 16 | 17 | type typeCompiler struct { 18 | *compiler 19 | block *block 20 | // Check to be performed after a type declaration is compiled. 21 | // 22 | // TODO(austin) This will probably have to change after we 23 | // eliminate forward declarations. 24 | lateCheck func() bool 25 | } 26 | 27 | func (a *typeCompiler) compileIdent(x *ast.Ident, allowRec bool) Type { 28 | _, _, def := a.block.Lookup(x.Name) 29 | if def == nil { 30 | a.diagAt(x.Pos(), "%s: undefined", x.Name) 31 | return nil 32 | } 33 | switch def := def.(type) { 34 | case *Constant: 35 | a.diagAt(x.Pos(), "constant %v used as type", x.Name) 36 | return nil 37 | case *Variable: 38 | a.diagAt(x.Pos(), "variable %v used as type", x.Name) 39 | return nil 40 | case *NamedType: 41 | if !allowRec && def.incomplete { 42 | a.diagAt(x.Pos(), "illegal recursive type") 43 | return nil 44 | } 45 | if !def.incomplete && def.Def == nil { 46 | // Placeholder type from an earlier error 47 | return nil 48 | } 49 | return def 50 | case Type: 51 | return def 52 | } 53 | log.Panicf("name %s has unknown type %T", x.Name, def) 54 | return nil 55 | } 56 | 57 | func (a *typeCompiler) compileArrayType(x *ast.ArrayType, allowRec bool) Type { 58 | // Compile element type 59 | elem := a.compileType(x.Elt, allowRec) 60 | 61 | // Compile length expression 62 | if x.Len == nil { 63 | if elem == nil { 64 | return nil 65 | } 66 | return NewSliceType(elem) 67 | } 68 | 69 | if _, ok := x.Len.(*ast.Ellipsis); ok { 70 | a.diagAt(x.Len.Pos(), "... array initializers not implemented") 71 | return nil 72 | } 73 | l, ok := a.compileArrayLen(a.block, x.Len) 74 | if !ok { 75 | return nil 76 | } 77 | if l < 0 { 78 | a.diagAt(x.Len.Pos(), "array length must be non-negative") 79 | return nil 80 | } 81 | if elem == nil { 82 | return nil 83 | } 84 | 85 | return NewArrayType(l, elem) 86 | } 87 | 88 | func (a *typeCompiler) compileFields(fields *ast.FieldList, allowRec bool) ([]Type, []*ast.Ident, []token.Pos, bool) { 89 | n := fields.NumFields() 90 | ts := make([]Type, n) 91 | ns := make([]*ast.Ident, n) 92 | ps := make([]token.Pos, n) 93 | bad := false 94 | 95 | if fields != nil { 96 | i := 0 97 | for _, f := range fields.List { 98 | t := a.compileType(f.Type, allowRec) 99 | if t == nil { 100 | bad = true 101 | } 102 | if f.Names == nil { 103 | ns[i] = nil 104 | ts[i] = t 105 | ps[i] = f.Type.Pos() 106 | i++ 107 | continue 108 | } 109 | for _, n := range f.Names { 110 | ns[i] = n 111 | ts[i] = t 112 | ps[i] = n.Pos() 113 | i++ 114 | } 115 | } 116 | } 117 | 118 | return ts, ns, ps, bad 119 | } 120 | 121 | func (a *typeCompiler) compileStructType(x *ast.StructType, allowRec bool) Type { 122 | ts, names, poss, bad := a.compileFields(x.Fields, allowRec) 123 | 124 | // XXX(Spec) The spec claims that field identifiers must be 125 | // unique, but 6g only checks this when they are accessed. I 126 | // think the spec is better in this regard: if I write two 127 | // fields with the same name in the same struct type, clearly 128 | // that's a mistake. This definition does *not* descend into 129 | // anonymous fields, so it doesn't matter if those change. 130 | // There's separate language in the spec about checking 131 | // uniqueness of field names inherited from anonymous fields 132 | // at use time. 133 | fields := make([]StructField, len(ts)) 134 | nameSet := make(map[string]token.Pos, len(ts)) 135 | for i := range fields { 136 | // Compute field name and check anonymous fields 137 | var name string 138 | if names[i] != nil { 139 | name = names[i].Name 140 | } else { 141 | if ts[i] == nil { 142 | continue 143 | } 144 | 145 | var nt *NamedType 146 | // [For anonymous fields,] the unqualified 147 | // type name acts as the field identifier. 148 | switch t := ts[i].(type) { 149 | case *NamedType: 150 | name = t.Name 151 | nt = t 152 | case *PtrType: 153 | switch t := t.Elem.(type) { 154 | case *NamedType: 155 | name = t.Name 156 | nt = t 157 | } 158 | } 159 | // [An anonymous field] must be specified as a 160 | // type name T or as a pointer to a type name 161 | // *T, and T itself, may not be a pointer or 162 | // interface type. 163 | if nt == nil { 164 | a.diagAt(poss[i], "embedded type must T or *T, where T is a named type") 165 | bad = true 166 | continue 167 | } 168 | // The check for embedded pointer types must 169 | // be deferred because of things like 170 | // type T *struct { T } 171 | lateCheck := a.lateCheck 172 | a.lateCheck = func() bool { 173 | if _, ok := nt.lit().(*PtrType); ok { 174 | a.diagAt(poss[i], "embedded type %v is a pointer type", nt) 175 | return false 176 | } 177 | return lateCheck() 178 | } 179 | } 180 | 181 | // Check name uniqueness 182 | if prev, ok := nameSet[name]; ok { 183 | a.diagAt(poss[i], "field %s redeclared\n\tprevious declaration at %s", name, a.fset.Position(prev)) 184 | bad = true 185 | continue 186 | } 187 | nameSet[name] = poss[i] 188 | 189 | // Create field 190 | fields[i].Name = name 191 | fields[i].Type = ts[i] 192 | fields[i].Anonymous = (names[i] == nil) 193 | } 194 | 195 | if bad { 196 | return nil 197 | } 198 | 199 | return NewStructType(fields) 200 | } 201 | 202 | func (a *typeCompiler) compilePtrType(x *ast.StarExpr) Type { 203 | elem := a.compileType(x.X, true) 204 | if elem == nil { 205 | return nil 206 | } 207 | return NewPtrType(elem) 208 | } 209 | 210 | func (a *typeCompiler) compileFuncType(x *ast.FuncType, allowRec bool) *FuncDecl { 211 | // TODO(austin) Variadic function types 212 | 213 | // The types of parameters and results must be complete. 214 | // 215 | // TODO(austin) It's not clear they actually have to be complete. 216 | in, inNames, _, inBad := a.compileFields(x.Params, allowRec) 217 | out, outNames, _, outBad := a.compileFields(x.Results, allowRec) 218 | 219 | if inBad || outBad { 220 | return nil 221 | } 222 | return &FuncDecl{NewFuncType(in, false, out), nil, inNames, outNames} 223 | } 224 | 225 | func (a *typeCompiler) compileInterfaceType(x *ast.InterfaceType, allowRec bool) *InterfaceType { 226 | ts, names, poss, bad := a.compileFields(x.Methods, allowRec) 227 | 228 | methods := make([]IMethod, len(ts)) 229 | nameSet := make(map[string]token.Pos, len(ts)) 230 | embeds := make([]*InterfaceType, len(ts)) 231 | 232 | var nm, ne int 233 | for i := range ts { 234 | if ts[i] == nil { 235 | continue 236 | } 237 | 238 | if names[i] != nil { 239 | name := names[i].Name 240 | methods[nm].Name = name 241 | methods[nm].Type = ts[i].(*FuncType) 242 | nm++ 243 | if prev, ok := nameSet[name]; ok { 244 | a.diagAt(poss[i], "method %s redeclared\n\tprevious declaration at %s", name, a.fset.Position(prev)) 245 | bad = true 246 | continue 247 | } 248 | nameSet[name] = poss[i] 249 | } else { 250 | // Embedded interface 251 | it, ok := ts[i].lit().(*InterfaceType) 252 | if !ok { 253 | a.diagAt(poss[i], "embedded type must be an interface") 254 | bad = true 255 | continue 256 | } 257 | embeds[ne] = it 258 | ne++ 259 | for _, m := range it.methods { 260 | if prev, ok := nameSet[m.Name]; ok { 261 | a.diagAt(poss[i], "method %s redeclared\n\tprevious declaration at %s", m.Name, a.fset.Position(prev)) 262 | bad = true 263 | continue 264 | } 265 | nameSet[m.Name] = poss[i] 266 | } 267 | } 268 | } 269 | 270 | if bad { 271 | return nil 272 | } 273 | 274 | methods = methods[0:nm] 275 | embeds = embeds[0:ne] 276 | 277 | return NewInterfaceType(methods, embeds) 278 | } 279 | 280 | func (a *typeCompiler) compileMapType(x *ast.MapType) Type { 281 | key := a.compileType(x.Key, true) 282 | val := a.compileType(x.Value, true) 283 | if key == nil || val == nil { 284 | return nil 285 | } 286 | // XXX(Spec) The Map types section explicitly lists all types 287 | // that can be map keys except for function types. 288 | switch key.lit().(type) { 289 | case *StructType: 290 | a.diagAt(x.Pos(), "map key cannot be a struct type") 291 | return nil 292 | case *ArrayType: 293 | a.diagAt(x.Pos(), "map key cannot be an array type") 294 | return nil 295 | case *SliceType: 296 | a.diagAt(x.Pos(), "map key cannot be a slice type") 297 | return nil 298 | } 299 | return NewMapType(key, val) 300 | } 301 | 302 | func (a *typeCompiler) compileType(x ast.Expr, allowRec bool) Type { 303 | switch x := x.(type) { 304 | case *ast.BadExpr: 305 | // Error already reported by parser 306 | a.silentErrors++ 307 | return nil 308 | 309 | case *ast.Ident: 310 | return a.compileIdent(x, allowRec) 311 | 312 | case *ast.ArrayType: 313 | return a.compileArrayType(x, allowRec) 314 | 315 | case *ast.StructType: 316 | return a.compileStructType(x, allowRec) 317 | 318 | case *ast.StarExpr: 319 | return a.compilePtrType(x) 320 | 321 | case *ast.FuncType: 322 | fd := a.compileFuncType(x, allowRec) 323 | if fd == nil { 324 | return nil 325 | } 326 | return fd.Type 327 | 328 | case *ast.InterfaceType: 329 | return a.compileInterfaceType(x, allowRec) 330 | 331 | case *ast.MapType: 332 | return a.compileMapType(x) 333 | 334 | case *ast.ChanType: 335 | goto notimpl 336 | 337 | case *ast.ParenExpr: 338 | return a.compileType(x.X, allowRec) 339 | 340 | case *ast.Ellipsis: 341 | a.diagAt(x.Pos(), "illegal use of ellipsis") 342 | return nil 343 | } 344 | a.diagAt(x.Pos(), "expression used as type") 345 | return nil 346 | 347 | notimpl: 348 | a.diagAt(x.Pos(), "compileType: %T not implemented", x) 349 | return nil 350 | } 351 | 352 | /* 353 | * Type compiler interface 354 | */ 355 | 356 | func noLateCheck() bool { return true } 357 | 358 | func (a *compiler) compileType(b *block, typ ast.Expr) Type { 359 | tc := &typeCompiler{a, b, noLateCheck} 360 | t := tc.compileType(typ, false) 361 | if !tc.lateCheck() { 362 | t = nil 363 | } 364 | return t 365 | } 366 | 367 | func (a *compiler) compileTypeDecl(b *block, decl *ast.GenDecl) bool { 368 | ok := true 369 | for _, spec := range decl.Specs { 370 | spec := spec.(*ast.TypeSpec) 371 | // Create incomplete type for this type 372 | nt := b.DefineType(spec.Name.Name, spec.Name.Pos(), nil) 373 | if nt != nil { 374 | nt.(*NamedType).incomplete = true 375 | } 376 | // Compile type 377 | tc := &typeCompiler{a, b, noLateCheck} 378 | t := tc.compileType(spec.Type, false) 379 | if t == nil { 380 | // Create a placeholder type 381 | ok = false 382 | } 383 | // Fill incomplete type 384 | if nt != nil { 385 | nt.(*NamedType).Complete(t) 386 | } 387 | // Perform late type checking with complete type 388 | if !tc.lateCheck() { 389 | ok = false 390 | if nt != nil { 391 | // Make the type a placeholder 392 | nt.(*NamedType).Def = nil 393 | } 394 | } 395 | } 396 | return ok 397 | } 398 | 399 | func (a *compiler) compileFuncType(b *block, typ *ast.FuncType) *FuncDecl { 400 | tc := &typeCompiler{a, b, noLateCheck} 401 | res := tc.compileFuncType(typ, false) 402 | if res != nil { 403 | if !tc.lateCheck() { 404 | res = nil 405 | } 406 | } 407 | return res 408 | } 409 | -------------------------------------------------------------------------------- /expr_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package eval 6 | 7 | import ( 8 | "math/big" 9 | "testing" 10 | ) 11 | 12 | var undefined = "undefined" 13 | var typeAsExpr = "type .* used as expression" 14 | var badRuneLit = "rune literal" 15 | var unknownEscape = "unknown escape sequence" 16 | var opTypes = "illegal (operand|argument) type|cannot index into" 17 | var badAddrOf = "cannot take the address" 18 | var constantTruncated = "constant [^ ]* truncated" 19 | var constantUnderflows = "constant [^ ]* underflows" 20 | var constantOverflows = "constant [^ ]* overflows" 21 | var implLimit = "implementation limit" 22 | var mustBeUnsigned = "must be unsigned" 23 | var divByZero = "divide by zero" 24 | 25 | var hugeInteger = new(big.Int).Lsh(idealOne, 64) 26 | 27 | var exprTests = []test{ 28 | Val("i", 1), 29 | CErr("zzz", undefined), 30 | // TODO(austin) Test variable in constant context 31 | //CErr("t", typeAsExpr), 32 | 33 | Val("'a'", big.NewInt('a')), 34 | Val("'\\uffff'", big.NewInt('\uffff')), 35 | Val("'\\n'", big.NewInt('\n')), 36 | CErr("''+x", badRuneLit), 37 | // Produces two parse errors 38 | //CErr("'''", ""), 39 | CErr("'\n'", badRuneLit), 40 | CErr("'\\z'", unknownEscape), 41 | CErr("'ab'", badRuneLit), 42 | 43 | Val("1.0", big.NewRat(1, 1)), 44 | //Val("1.", big.NewRat(1, 1)), //FIXME 45 | Val(".1", big.NewRat(1, 10)), 46 | //Val("1e2", big.NewRat(100, 1)), 47 | //Val("1E2", big.NewRat(100, 1)), //FIXME 48 | Val("100.0", big.NewRat(100, 1)), 49 | 50 | Val("\"abc\"", "abc"), 51 | Val("\"\"", ""), 52 | Val("\"\\n\\\"\"", "\n\""), 53 | CErr("\"\\z\"", unknownEscape), 54 | CErr("\"abc", "string literal not terminated"), 55 | 56 | Val("(i)", 1), 57 | 58 | Val("ai[0]", 1), 59 | Val("(&ai)[0]", 1), 60 | Val("ai[1]", 2), 61 | Val("ai[i]", 2), 62 | Val("ai[u]", 2), 63 | CErr("ai[f]", opTypes), 64 | CErr("ai[0][0]", opTypes), 65 | CErr("ai[2]", "index 2 exceeds"), 66 | CErr("ai[1+1]", "index 2 exceeds"), 67 | CErr("ai[-1]", "negative index"), 68 | RErr("ai[i+i]", "index 2 exceeds"), 69 | RErr("ai[-i]", "negative index"), 70 | CErr("i[0]", opTypes), 71 | CErr("f[0]", opTypes), 72 | 73 | Val("aai[0][0]", 1), 74 | Val("aai[1][1]", 4), 75 | CErr("aai[2][0]", "index 2 exceeds"), 76 | CErr("aai[0][2]", "index 2 exceeds"), 77 | 78 | Val("sli[0]", 1), 79 | Val("sli[1]", 2), 80 | CErr("sli[-1]", "negative index"), 81 | RErr("sli[-i]", "negative index"), 82 | RErr("sli[2]", "index 2 exceeds"), 83 | 84 | Val("s[0]", uint8('a')), 85 | Val("s[1]", uint8('b')), 86 | CErr("s[-1]", "negative index"), 87 | RErr("s[-i]", "negative index"), 88 | RErr("s[3]", "index 3 exceeds"), 89 | 90 | Val("ai[0:2]", vslice{varray{1, 2}, 2, 2}), 91 | Val("ai[0:1]", vslice{varray{1, 2}, 1, 2}), 92 | Val("ai[0:]", vslice{varray{1, 2}, 2, 2}), 93 | Val("ai[i:]", vslice{varray{2}, 1, 1}), 94 | Val("ai[:2]", vslice{varray{1, 2}, 2, 2}), 95 | Val("ai[:]", vslice{varray{1, 2}, 2, 2}), 96 | 97 | Val("sli[0:2]", vslice{varray{1, 2, 3}, 2, 3}), 98 | Val("sli[0:i]", vslice{varray{1, 2, 3}, 1, 3}), 99 | Val("sli[1:]", vslice{varray{2, 3}, 1, 2}), 100 | Val("sli[:2]", vslice{varray{1, 2, 3}, 2, 3}), 101 | Val("sli[:]", vslice{varray{1, 2, 3}, 2, 3}), 102 | 103 | CErr("1(2)", "cannot call"), 104 | CErr("fn(1,2)", "too many"), 105 | CErr("fn()", "not enough"), 106 | CErr("fn(true)", opTypes), 107 | CErr("fn(true)", "function call"), 108 | // Single argument functions don't say which argument. 109 | //CErr("fn(true)", "argument 1"), 110 | Val("fn(1)", 2), 111 | Val("fn(1.0)", 2), 112 | CErr("fn(1.5)", constantTruncated), 113 | Val("fn(i)", 2), 114 | CErr("fn(u)", opTypes), 115 | 116 | CErr("void()+2", opTypes), 117 | CErr("oneTwo()+2", opTypes), 118 | 119 | Val("append(sli, 3)", vslice{varray{1, 2, 3}, 3, 3}), 120 | Val("append(sli, 3, 4)", vslice{varray{1, 2, 3, 4}, 4, 4}), 121 | //FIXME: implement ellipsis unpacking 122 | //Val("append(sli, []int{3,4}...)", vslice{varray{1, 2, 3, 4}, 4, 4}), 123 | Val("append(sli, 3.0)", vslice{varray{1, 2, 3}, 3, 3}), 124 | CErr("append(sli, 3.1)", "cannot convert argument 1 [(]type ideal float[)] to type int in 'append'"), 125 | CErr("append(sli, \"2\")", "cannot use string literal [(]type [)] as type int in 'append'"), 126 | 127 | Val("cap(ai)", 2), 128 | Val("cap(&ai)", 2), 129 | Val("cap(aai)", 2), 130 | Val("cap(sli)", 3), 131 | CErr("cap(0)", opTypes), 132 | CErr("cap(i)", opTypes), 133 | CErr("cap(s)", opTypes), 134 | 135 | Val("copy([]int{}, sli)", 0), 136 | Val("copy([]int{0,0,0}, sli)", 2), 137 | Val2("x := []int{0,0,0}; _ := copy(x, sli)", 138 | "x[0] == sli[0]", true, "x[1]==sli[1]", true), 139 | Val2("x := []int{0,0,99}; _ := copy(x, sli)", 140 | "x[0] == sli[0]", true, "x[2]==99", true), 141 | Val2("x := []int{90,91,92}; _ := copy(x[1:], sli)", 142 | "x[0] == 90", true, "x[1]==sli[0]", true), 143 | Val2("x := []int{90,91,92}; _ := copy(x[1:], sli)", 144 | "x[2] == sli[1]", true, "x[1]==sli[0]", true), 145 | 146 | Val("len(s)", 3), 147 | Val("len(ai)", 2), 148 | Val("len(&ai)", 2), 149 | Val("len(ai[0:])", 2), 150 | Val("len(ai[1:])", 1), 151 | Val("len(ai[2:])", 0), 152 | Val("len(aai)", 2), 153 | Val("len(sli)", 2), 154 | Val("len(sli[0:])", 2), 155 | Val("len(sli[1:])", 1), 156 | Val("len(sli[2:])", 0), 157 | Val("len(map[int]int{})", 0), 158 | Val("len(map[int]int{1:1,2:2})", 2), 159 | Val("len(ami)", 2), 160 | CErr("len(0)", opTypes), 161 | CErr("len(i)", opTypes), 162 | 163 | CErr("*i", opTypes), 164 | Val("*&i", 1), 165 | Val("*&(i)", 1), 166 | CErr("&1", badAddrOf), 167 | CErr("&c", badAddrOf), 168 | Val("*(&ai[0])", 1), 169 | 170 | Val("+1", big.NewInt(+1)), 171 | Val("+1.0", big.NewRat(1, 1)), 172 | Val("01.5", big.NewRat(15, 10)), 173 | CErr("+\"x\"", opTypes), 174 | 175 | Val("-42", big.NewInt(-42)), 176 | Val("-i", -1), 177 | Val("-f", -1.0), 178 | // 6g bug? 179 | //Val("-(f-1)", -0.0), 180 | CErr("-\"x\"", opTypes), 181 | 182 | // TODO(austin) Test unary ! 183 | 184 | Val("^2", big.NewInt(^2)), 185 | Val("^(-2)", big.NewInt(^(-2))), 186 | CErr("^2.0", opTypes), 187 | CErr("^2.5", opTypes), 188 | Val("^i", ^1), 189 | Val("^u", ^uint(1)), 190 | CErr("^f", opTypes), 191 | 192 | Val("1+i", 2), 193 | Val("1+u", uint(2)), 194 | Val("3.0+i", 4), 195 | Val("1+1", big.NewInt(2)), 196 | Val("f+f", 2.0), 197 | Val("1+f", 2.0), 198 | Val("1.0+1", big.NewRat(2, 1)), 199 | Val("\"abc\" + \"def\"", "abcdef"), 200 | CErr("i+u", opTypes), 201 | CErr("-1+u", constantUnderflows), 202 | // TODO(austin) Test named types 203 | 204 | Val("2-1", big.NewInt(1)), 205 | Val("2.0-1", big.NewRat(1, 1)), 206 | Val("f-2", -1.0), 207 | Val("-0.0", big.NewRat(0, 1)), 208 | Val("2*2", big.NewInt(4)), 209 | Val("2*i", 2), 210 | Val("3/2", big.NewInt(1)), 211 | Val("3/i", 3), 212 | CErr("1/0", divByZero), 213 | CErr("1.0/0", divByZero), 214 | RErr("i/0", divByZero), 215 | Val("3%2", big.NewInt(1)), 216 | Val("i%2", 1), 217 | CErr("3%0", divByZero), 218 | CErr("3.0%0", opTypes), 219 | RErr("i%0", divByZero), 220 | 221 | // Examples from "Arithmetic operators" 222 | Val("5/3", big.NewInt(1)), 223 | Val("(i+4)/(i+2)", 1), 224 | Val("5%3", big.NewInt(2)), 225 | Val("(i+4)%(i+2)", 2), 226 | Val("-5/3", big.NewInt(-1)), 227 | Val("(i-6)/(i+2)", -1), 228 | Val("-5%3", big.NewInt(-2)), 229 | Val("(i-6)%(i+2)", -2), 230 | Val("5/-3", big.NewInt(-1)), 231 | Val("(i+4)/(i-4)", -1), 232 | Val("5%-3", big.NewInt(2)), 233 | Val("(i+4)%(i-4)", 2), 234 | Val("-5/-3", big.NewInt(1)), 235 | Val("(i-6)/(i-4)", 1), 236 | Val("-5%-3", big.NewInt(-2)), 237 | Val("(i-6)%(i-4)", -2), 238 | 239 | // Examples from "Arithmetic operators" 240 | Val("11/4", big.NewInt(2)), 241 | Val("(i+10)/4", 2), 242 | Val("11%4", big.NewInt(3)), 243 | Val("(i+10)%4", 3), 244 | Val("11>>2", big.NewInt(2)), 245 | Val("(i+10)>>2", 2), 246 | Val("11&3", big.NewInt(3)), 247 | Val("(i+10)&3", 3), 248 | Val("-11/4", big.NewInt(-2)), 249 | Val("(i-12)/4", -2), 250 | Val("-11%4", big.NewInt(-3)), 251 | Val("(i-12)%4", -3), 252 | Val("-11>>2", big.NewInt(-3)), 253 | Val("(i-12)>>2", -3), 254 | Val("-11&3", big.NewInt(1)), 255 | Val("(i-12)&3", 1), 256 | 257 | // TODO(austin) Test bit ops 258 | 259 | // For shift, we try nearly every combination of positive 260 | // ideal int, negative ideal int, big ideal int, ideal 261 | // fractional float, ideal non-fractional float, int, uint, 262 | // and float. 263 | Val("2<<2", big.NewInt(2<<2)), 264 | CErr("2<<(-1)", constantUnderflows), 265 | CErr("2<<0x10000000000000000", constantOverflows), 266 | CErr("2<<2.5", constantTruncated), 267 | Val("2<<2.0", big.NewInt(2<<2.0)), 268 | CErr("2<, >= 316 | Val("1<2", 1 < 2), 317 | Val("1<=2", 1 <= 2), 318 | Val("2<=2", 2 <= 2), 319 | Val("1>2", 1 > 2), 320 | Val("1>=2", 1 >= 2), 321 | Val("2>=2", 2 >= 2), 322 | 323 | Val("i<2", 1 < 2), 324 | Val("i<=2", 1 <= 2), 325 | Val("i+1<=2", 2 <= 2), 326 | Val("i>2", 1 > 2), 327 | Val("i>=2", 1 >= 2), 328 | Val("i+1>=2", 2 >= 2), 329 | 330 | Val("u<2", 1 < 2), 331 | Val("f<2", 1 < 2), 332 | 333 | Val("s<\"b\"", true), 334 | Val("s<\"a\"", false), 335 | Val("s<=\"abc\"", true), 336 | Val("s>\"aa\"", true), 337 | Val("s>\"ac\"", false), 338 | Val("s>=\"abc\"", true), 339 | 340 | CErr("i 0 { 357 | res += ", " 358 | } 359 | res += e.String() 360 | } 361 | return res + "}" 362 | } 363 | 364 | func (v *arrayV) Assign(t *Thread, o Value) { 365 | oa := o.(ArrayValue) 366 | l := int64(len(*v)) 367 | for i := int64(0); i < l; i++ { 368 | (*v)[i].Assign(t, oa.Elem(t, i)) 369 | } 370 | } 371 | 372 | func (v *arrayV) Get(*Thread) ArrayValue { return v } 373 | 374 | func (v *arrayV) Elem(t *Thread, i int64) Value { 375 | return (*v)[i] 376 | } 377 | 378 | func (v *arrayV) Sub(i int64, len int64) ArrayValue { 379 | res := (*v)[i : i+len] 380 | return &res 381 | } 382 | 383 | /* 384 | * Struct 385 | */ 386 | 387 | type structV []Value 388 | 389 | // TODO(austin) Should these methods (and arrayV's) be on structV 390 | // instead of *structV? 391 | func (v *structV) String() string { 392 | res := "{" 393 | for i, v := range *v { 394 | if i > 0 { 395 | res += ", " 396 | } 397 | res += v.String() 398 | } 399 | return res + "}" 400 | } 401 | 402 | func (v *structV) Assign(t *Thread, o Value) { 403 | oa := o.(StructValue) 404 | l := len(*v) 405 | for i := 0; i < l; i++ { 406 | (*v)[i].Assign(t, oa.Field(t, i)) 407 | } 408 | } 409 | 410 | func (v *structV) Get(*Thread) StructValue { return v } 411 | 412 | func (v *structV) Field(t *Thread, i int) Value { 413 | return (*v)[i] 414 | } 415 | 416 | /* 417 | * Pointer 418 | */ 419 | 420 | type ptrV struct { 421 | // nil if the pointer is nil 422 | target Value 423 | } 424 | 425 | func (v *ptrV) String() string { 426 | if v.target == nil { 427 | return "" 428 | } 429 | return "&" + v.target.String() 430 | } 431 | 432 | func (v *ptrV) Assign(t *Thread, o Value) { v.target = o.(PtrValue).Get(t) } 433 | 434 | func (v *ptrV) Get(*Thread) Value { return v.target } 435 | 436 | func (v *ptrV) Set(t *Thread, x Value) { v.target = x } 437 | 438 | /* 439 | * Functions 440 | */ 441 | 442 | type funcV struct { 443 | target Func 444 | } 445 | 446 | func (v *funcV) String() string { 447 | // TODO(austin) Rob wants to see the definition 448 | return "func {...}" 449 | } 450 | 451 | func (v *funcV) Assign(t *Thread, o Value) { v.target = o.(FuncValue).Get(t) } 452 | 453 | func (v *funcV) Get(*Thread) Func { return v.target } 454 | 455 | func (v *funcV) Set(t *Thread, x Func) { v.target = x } 456 | 457 | /* 458 | * Interfaces 459 | */ 460 | 461 | type interfaceV struct { 462 | Interface 463 | } 464 | 465 | func (v *interfaceV) String() string { 466 | if v.Type == nil || v.Value == nil { 467 | return "" 468 | } 469 | return v.Value.String() 470 | } 471 | 472 | func (v *interfaceV) Assign(t *Thread, o Value) { 473 | v.Interface = o.(InterfaceValue).Get(t) 474 | } 475 | 476 | func (v *interfaceV) Get(*Thread) Interface { return v.Interface } 477 | 478 | func (v *interfaceV) Set(t *Thread, x Interface) { 479 | v.Interface = x 480 | } 481 | 482 | /* 483 | * Slices 484 | */ 485 | 486 | type sliceV struct { 487 | Slice 488 | } 489 | 490 | func (v *sliceV) String() string { 491 | if v.Base == nil { 492 | return "" 493 | } 494 | return v.Base.Sub(0, v.Len).String() 495 | } 496 | 497 | func (v *sliceV) Assign(t *Thread, o Value) { v.Slice = o.(SliceValue).Get(t) } 498 | 499 | func (v *sliceV) Get(*Thread) Slice { return v.Slice } 500 | 501 | func (v *sliceV) Set(t *Thread, x Slice) { v.Slice = x } 502 | 503 | /* 504 | * Maps 505 | */ 506 | 507 | type mapV struct { 508 | target Map 509 | } 510 | 511 | func (v *mapV) String() string { 512 | if v.target == nil { 513 | return "" 514 | } 515 | res := "map[" 516 | i := 0 517 | v.target.Iter(func(key interface{}, val Value) bool { 518 | if i > 0 { 519 | res += ", " 520 | } 521 | i++ 522 | res += fmt.Sprint(key) + ":" + val.String() 523 | return true 524 | }) 525 | return res + "]" 526 | } 527 | 528 | func (v *mapV) Assign(t *Thread, o Value) { v.target = o.(MapValue).Get(t) } 529 | 530 | func (v *mapV) Get(*Thread) Map { return v.target } 531 | 532 | func (v *mapV) Set(t *Thread, x Map) { v.target = x } 533 | 534 | type evalMap map[interface{}]Value 535 | 536 | func (m evalMap) Len(t *Thread) int64 { return int64(len(m)) } 537 | 538 | func (m evalMap) Elem(t *Thread, key interface{}) Value { 539 | return m[key] 540 | } 541 | 542 | func (m evalMap) SetElem(t *Thread, key interface{}, val Value) { 543 | if val == nil { 544 | delete(m, key) 545 | } else { 546 | m[key] = val 547 | } 548 | } 549 | 550 | func (m evalMap) Iter(cb func(key interface{}, val Value) bool) { 551 | for k, v := range m { 552 | if !cb(k, v) { 553 | break 554 | } 555 | } 556 | } 557 | 558 | /* 559 | * package value 560 | */ 561 | 562 | type packageV struct { 563 | name string 564 | idents []Value 565 | } 566 | 567 | func (p *packageV) String() string { return p.name } 568 | 569 | func (p *packageV) Assign(t *Thread, o Value) { 570 | t.Abort(errors.New("cant assign to a package")) 571 | } 572 | 573 | func (p *packageV) Get(*Thread) PackageValue { 574 | return p 575 | } 576 | 577 | func (p *packageV) Ident(t *Thread, n int) Value { 578 | return p.idents[n] 579 | } 580 | 581 | /* 582 | * Multi-values 583 | */ 584 | 585 | type multiV []Value 586 | 587 | func (v multiV) String() string { 588 | res := "(" 589 | for i, v := range v { 590 | if i > 0 { 591 | res += ", " 592 | } 593 | res += v.String() 594 | } 595 | return res + ")" 596 | } 597 | 598 | func (v multiV) Assign(t *Thread, o Value) { 599 | omv := o.(multiV) 600 | for i := range v { 601 | v[i].Assign(t, omv[i]) 602 | } 603 | } 604 | 605 | /* 606 | * Universal constants 607 | */ 608 | 609 | func init() { 610 | s := universe 611 | 612 | true := boolV(true) 613 | s.DefineConst("true", universePos, BoolType, &true) 614 | false := boolV(false) 615 | s.DefineConst("false", universePos, BoolType, &false) 616 | } 617 | -------------------------------------------------------------------------------- /stmt_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package eval 6 | 7 | import "testing" 8 | 9 | var atLeastOneDecl = "at least one new variable must be declared" 10 | 11 | var stmtTests = []test{ 12 | // Short declarations 13 | Val1("x := i", "x", 1), 14 | Val1("x := f", "x", 1.0), 15 | // Type defaulting 16 | Val1("a := 42", "a", 42), 17 | Val1("a := 1.0", "a", 1.0), 18 | // Parallel assignment 19 | Val2("a, b := 1, 2", "a", 1, "b", 2), 20 | Val2("a, i := 1, 2", "a", 1, "i", 2), 21 | CErr("a, i := 1, f", opTypes), 22 | CErr("a, b := 1, 2, 3", "too many"), 23 | CErr("a := 1, 2", "too many"), 24 | CErr("a, b := 1", "not enough"), 25 | // Mixed declarations 26 | CErr("i := 1", atLeastOneDecl), 27 | CErr("i, u := 1, 2", atLeastOneDecl), 28 | Val2("i, x := 2, f", "i", 2, "x", 1.0), 29 | // Various errors 30 | CErr("1 := 2", "expected identifier"), 31 | CErr("c, a := 1, 1", "cannot assign"), 32 | // Unpacking 33 | Val2("x, y := oneTwo()", "x", 1, "y", 2), 34 | CErr("x := oneTwo()", "too many"), 35 | CErr("x, y, z := oneTwo()", "not enough"), 36 | CErr("x, y := oneTwo(), 2", "multi-valued"), 37 | CErr("x := oneTwo()+2", opTypes), 38 | // TOOD(austin) This error message is weird 39 | CErr("x := void()", "not enough"), 40 | // Placeholders 41 | CErr("x := 1+\"x\"; i=x+1", opTypes), 42 | 43 | // Assignment 44 | Val1("i = 2", "i", 2), 45 | Val1("(i) = 2", "i", 2), 46 | CErr("1 = 2", "cannot assign"), 47 | CErr("1-1 = 2", "- expression"), 48 | Val1("i = 2.0", "i", 2), 49 | CErr("i = 2.2", constantTruncated), 50 | CErr("u = -2", constantUnderflows), 51 | CErr("i = f", opTypes), 52 | CErr("i, u = 0, f", opTypes), 53 | CErr("i, u = 0, f", "value 2"), 54 | Val2("i, i2 = i2, i", "i", 2, "i2", 1), 55 | CErr("c = 1", "cannot assign"), 56 | 57 | Val1("x := &i; *x = 2", "i", 2), 58 | 59 | Val1("ai[0] = 42", "ai", varray{42, 2}), 60 | Val1("aai[1] = ai; ai[0] = 42", "aai", varray{varray{1, 2}, varray{1, 2}}), 61 | Val1("aai = aai2", "aai", varray{varray{5, 6}, varray{7, 8}}), 62 | 63 | // Assignment conversions 64 | Run("var sl []int; sl = &ai"), 65 | CErr("type ST []int; type AT *[2]int; var x AT = &ai; var y ST = x", opTypes), 66 | Run("type ST []int; var y ST = &ai"), 67 | Run("type AT *[2]int; var x AT = &ai; var y []int = x"), 68 | 69 | // Op-assignment 70 | Val1("i += 2", "i", 3), 71 | Val("i", 1), 72 | Val1("f += 2", "f", 3.0), 73 | CErr("2 += 2", "cannot assign"), 74 | CErr("i, j += 2", "cannot be combined"), 75 | CErr("i += 2, 3", "cannot be combined"), 76 | Val2("s2 := s; s += \"def\"", "s2", "abc", "s", "abcdef"), 77 | CErr("s += 1", opTypes), 78 | // Single evaluation 79 | Val2("ai[func()int{i+=1;return 0}()] *= 3; i2 = ai[0]", "i", 2, "i2", 3), 80 | 81 | // Type declarations 82 | // Identifiers 83 | Run("type T int"), 84 | CErr("type T x", "undefined"), 85 | CErr("type T c", "constant"), 86 | CErr("type T i", "variable"), 87 | CErr("type T T", "recursive"), 88 | CErr("type T x; type U T; var v U; v = 1", "undefined"), 89 | CErr("type A int; type A uint", "A redeclared in this block"), 90 | Run("type A int; func F() {type A uint}"), 91 | 92 | // Pointer types 93 | Run("type T *int"), 94 | Run("type T *T"), 95 | // Array types 96 | Run("type T [5]int"), 97 | Run("type T [c+42/2]int"), 98 | Run("type T [2.0]int"), 99 | CErr("type T [i]int", "constant expression"), 100 | CErr("type T [2.5]int", constantTruncated), 101 | CErr("type T [-1]int", "negative"), 102 | CErr("type T [2]T", "recursive"), 103 | // Struct types 104 | Run("type T struct { a int; b int }"), 105 | Run("type T struct { a int; int }"), 106 | Run("type T struct { x *T }"), 107 | Run("type T int; type U struct { T }"), 108 | CErr("type T *int; type U struct { T }", "embedded.*pointer"), 109 | CErr("type T *struct { T }", "embedded.*pointer"), 110 | CErr("type T struct { a int; a int }", " a .*redeclared"), 111 | CErr("type T struct { int; int }", "int .*redeclared"), 112 | CErr("type T struct { int int; int }", "int .*redeclared"), 113 | Run("type T struct { x *struct { T } }"), 114 | CErr("type T struct { x struct { T } }", "recursive"), 115 | CErr("type T struct { x }; type U struct { T }", "undefined"), 116 | // Function types 117 | Run("type T func()"), 118 | Run("type T func(a, b int) int"), 119 | Run("type T func(a, b int) (x int, y int)"), 120 | Run("type T func(a, a int) (a int, a int)"), 121 | Run("type T func(a, b int) (x, y int)"), 122 | Run("type T func(int, int) (int, int)"), 123 | CErr("type T func(x); type U T", "undefined"), 124 | CErr("type T func(a T)", "recursive"), 125 | // Interface types 126 | Run("type T interface {x(a, b int) int}"), 127 | Run("type T interface {x(a, b int) int}; type U interface {T; y(c int)}"), 128 | CErr("type T interface {x(a int); x()}", "method x redeclared"), 129 | CErr("type T interface {x()}; type U interface {T; x()}", "method x redeclared"), 130 | CErr("type T int; type U interface {T}", "embedded type"), 131 | // Parens 132 | Run("type T (int)"), 133 | 134 | // Variable declarations 135 | Val2("var x int", "i", 1, "x", 0), 136 | Val1("var x = 1", "x", 1), 137 | Val1("var x = 1.0", "x", 1.0), 138 | Val1("var x int = 1.0", "x", 1), 139 | // Placeholders 140 | CErr("var x foo; x = 1", "undefined"), 141 | CErr("var x foo = 1; x = 1", "undefined"), 142 | // Redeclaration 143 | CErr("var i, x int", " i .*redeclared"), 144 | CErr("var x int; var x int", " x .*redeclared"), 145 | 146 | // Expression statements 147 | CErr("x := func(){ 1-1 }", "expression statement"), 148 | CErr("x := func(){ 1-1 }", "- expression"), 149 | Val1("fn(2)", "i", 1), 150 | 151 | // IncDec statements 152 | Val1("i++", "i", 2), 153 | Val1("i--", "i", 0), 154 | Val1("u++", "u", uint(2)), 155 | Val1("u--", "u", uint(0)), 156 | Val1("f++", "f", 2.0), 157 | Val1("f--", "f", 0.0), 158 | // Single evaluation 159 | Val2("ai[func()int{i+=1;return 0}()]++; i2 = ai[0]", "i", 2, "i2", 2), 160 | // Operand types 161 | CErr("s++", opTypes), 162 | CErr("s++", "'\\+\\+'"), 163 | CErr("2++", "cannot assign"), 164 | CErr("c++", "cannot assign"), 165 | 166 | // Function scoping 167 | Val1("fn1 := func() { i=2 }; fn1()", "i", 2), 168 | Val1("fn1 := func() { i:=2 }; fn1()", "i", 1), 169 | Val2("fn1 := func() int { i=2; i:=3; i=4; return i }; x := fn1()", "i", 2, "x", 4), 170 | 171 | // Basic returns 172 | CErr("fn1 := func() int {}", "return"), 173 | Run("fn1 := func() {}"), 174 | CErr("fn1 := func() (r int) {}", "return"), 175 | Val1("fn1 := func() (r int) {return}; i = fn1()", "i", 0), 176 | Val1("fn1 := func() (r int) {r = 2; return}; i = fn1()", "i", 2), 177 | Val1("fn1 := func() (r int) {return 2}; i = fn1()", "i", 2), 178 | Val1("fn1 := func(int) int {return 2}; i = fn1(1)", "i", 2), 179 | 180 | // Multi-valued returns 181 | Val2("fn1 := func() (bool, int) {return true, 2}; x, y := fn1()", "x", true, "y", 2), 182 | CErr("fn1 := func() int {return}", "not enough values"), 183 | CErr("fn1 := func() int {return 1,2}", "too many values"), 184 | CErr("fn1 := func() {return 1}", "too many values"), 185 | CErr("fn1 := func() (int,int,int) {return 1,2}", "not enough values"), 186 | Val2("fn1 := func() (int, int) {return oneTwo()}; x, y := fn1()", "x", 1, "y", 2), 187 | CErr("fn1 := func() int {return oneTwo()}", "too many values"), 188 | CErr("fn1 := func() (int,int,int) {return oneTwo()}", "not enough values"), 189 | Val1("fn1 := func(x,y int) int {return x+y}; x := fn1(oneTwo())", "x", 3), 190 | 191 | // Return control flow 192 | Val2("fn1 := func(x *int) bool { *x = 2; return true; *x = 3; }; x := fn1(&i)", "i", 2, "x", true), 193 | 194 | // Break/continue/goto/fallthrough 195 | CErr("break", "outside"), 196 | CErr("break foo", "break.*foo.*not defined"), 197 | CErr("continue", "outside"), 198 | CErr("continue foo", "continue.*foo.*not defined"), 199 | CErr("fallthrough", "outside"), 200 | CErr("goto foo", "foo.*not defined"), 201 | CErr(" foo: foo:;", "foo.*redeclared"), 202 | Val1("i+=2; goto L; i+=4; L: i+=8", "i", 1+2+8), 203 | // Return checking 204 | CErr("fn1 := func() int { goto L; return 1; L: }", "return"), 205 | Run("fn1 := func() int { L: goto L; i = 2 }"), 206 | Run("fn1 := func() int { return 1; L: goto L }"), 207 | // Scope checking 208 | Run("fn1 := func() { { L: x:=1 }; goto L }"), 209 | CErr("fn1 := func() { { x:=1; L: }; goto L }", "into scope"), 210 | CErr("fn1 := func() { goto L; x:=1; L: }", "into scope"), 211 | Run("fn1 := func() { goto L; { L: x:=1 } }"), 212 | CErr("fn1 := func() { goto L; { x:=1; L: } }", "into scope"), 213 | 214 | // Blocks 215 | CErr("fn1 := func() int {{}}", "return"), 216 | Val1("fn1 := func() bool { { return true } }; b := fn1()", "b", true), 217 | 218 | // If 219 | Val2("if true { i = 2 } else { i = 3 }; i2 = 4", "i", 2, "i2", 4), 220 | Val2("if false { i = 2 } else { i = 3 }; i2 = 4", "i", 3, "i2", 4), 221 | Val2("if i == i2 { i = 2 } else { i = 3 }; i2 = 4", "i", 3, "i2", 4), 222 | // Omit optional parts 223 | Val2("if true { i = 2 } else { i = 3 }; i2 = 4", "i", 2, "i2", 4), 224 | Val2("if true { i = 2 }; i2 = 4", "i", 2, "i2", 4), 225 | Val2("if false { i = 2 }; i2 = 4", "i", 1, "i2", 4), 226 | // Init 227 | Val2("if x := true; x { i = 2 } else { i = 3 }; i2 = 4", "i", 2, "i2", 4), 228 | Val2("if x := false; x { i = 2 } else { i = 3 }; i2 = 4", "i", 3, "i2", 4), 229 | // Statement else 230 | Val2("if true { i = 2 } else { i = 3 }; i2 = 4", "i", 2, "i2", 4), 231 | Val2("if false { i = 2 } else { i = 3 }; i2 = 4", "i", 3, "i2", 4), 232 | // Scoping 233 | Val2("if true { i := 2 } else { i := 3 }; i2 = i", "i", 1, "i2", 1), 234 | Val2("if false { i := 2 } else { i := 3 }; i2 = i", "i", 1, "i2", 1), 235 | Val2("if false { i := 2 } else { i := 3 }; i2 = i", "i", 1, "i2", 1), 236 | CErr("if true { x := 2 }; x = 4", undefined), 237 | Val2("if i := 2; true { i2 = i; i := 3 }", "i", 1, "i2", 2), 238 | Val2("if i := 2; false {} else { i2 = i; i := 3 }", "i", 1, "i2", 2), 239 | // Return checking 240 | Run("fn1 := func() int { if true { return 1 } else { return 2 } }"), 241 | CErr("fn1 := func() int { if true { return 1 } else { } }", "return"), 242 | CErr("fn1 := func() int { if true { } else { return 1 } }", "return"), 243 | CErr("fn1 := func() int { if true { } else { } }", "return"), 244 | CErr("fn1 := func() int { if true { return 1 } }", "return"), 245 | CErr("fn1 := func() int { if true { } }", "return"), 246 | Run("fn1 := func() int { if true { }; return 1 }"), 247 | CErr("fn1 := func() int { if true { } }", "return"), 248 | CErr("fn1 := func() int { if true { } else { return 2 } }", "return"), 249 | Run("fn1 := func() int { if true { return 1 }; return 0 }"), 250 | Run("fn1 := func() int { if true { return 1 } else { }; return 0 }"), 251 | 252 | // Switch 253 | Val1("switch { case false: i += 2; case true: i += 4; default: i += 8 }", "i", 1+4), 254 | Val1("switch { default: i += 2; case false: i += 4; case true: i += 8 }", "i", 1+8), 255 | CErr("switch { default: i += 2; default: i += 4 }", "more than one"), 256 | Val1("switch false { case false: i += 2; case true: i += 4; default: i += 8 }", "i", 1+2), 257 | CErr("switch s { case 1: }", opTypes), 258 | CErr("switch ai { case ai: i += 2 }", opTypes), 259 | Val1("switch 1.0 { case 1: i += 2; case 2: i += 4 }", "i", 1+2), 260 | Val1("switch 1.5 { case 1: i += 2; case 2: i += 4 }", "i", 1), 261 | CErr("switch oneTwo() {}", "multi-valued expression"), 262 | Val1("switch 2 { case 1: i += 2; fallthrough; case 2: i += 4; fallthrough; case 3: i += 8; fallthrough }", "i", 1+4+8), 263 | Val1("switch 5 { case 1: i += 2; fallthrough; default: i += 4; fallthrough; case 2: i += 8; fallthrough; case 3: i += 16; fallthrough }", "i", 1+4+8+16), 264 | CErr("switch { case true: fallthrough; i += 2 }", "final statement"), 265 | Val1("switch { case true: i += 2; fallthrough; ; ; case false: i += 4 }", "i", 1+2+4), 266 | Val1("switch 2 { case 0, 1: i += 2; case 2, 3: i += 4 }", "i", 1+4), 267 | Val2("switch func()int{i2++;return 5}() { case 1, 2: i += 2; case 4, 5: i += 4 }", "i", 1+4, "i2", 3), 268 | Run("switch i { case i: }"), 269 | // TODO(austin) Why doesn't this fail? 270 | //CErr("case 1:", "XXX"), 271 | 272 | // For 273 | Val2("for x := 1; x < 5; x++ { i+=x }; i2 = 4", "i", 11, "i2", 4), 274 | Val2("for x := 1; x < 5; x++ { i+=x; break; i++ }; i2 = 4", "i", 2, "i2", 4), 275 | Val2("for x := 1; x < 5; x++ { i+=x; continue; i++ }; i2 = 4", "i", 11, "i2", 4), 276 | Val2("for i = 2; false; i = 3 { i = 4 }; i2 = 4", "i", 2, "i2", 4), 277 | Val2("for i < 5 { i++ }; i2 = 4", "i", 5, "i2", 4), 278 | Val2("for i < 0 { i++ }; i2 = 4", "i", 1, "i2", 4), 279 | // Scoping 280 | Val2("for i := 2; true; { i2 = i; i := 3; break }", "i", 1, "i2", 2), 281 | // Labeled break/continue 282 | Val1("L1: for { L2: for { i+=2; break L1; i+=4 }; i+=8 }", "i", 1+2), 283 | Val1("L1: for { L2: for { i+=2; break L2; i+=4 }; i+=8; break; i+=16 }", "i", 1+2+8), 284 | CErr("L1: { for { break L1 } }", "break.*not defined"), 285 | CErr("L1: for {}; for { break L1 }", "break.*not defined"), 286 | CErr("L1:; for { break L1 }", "break.*not defined"), 287 | Val2("L1: for i = 0; i < 2; i++ { L2: for { i2++; continue L1; i2++ } }", "i", 2, "i2", 4), 288 | CErr("L1: { for { continue L1 } }", "continue.*not defined"), 289 | CErr("L1:; for { continue L1 }", "continue.*not defined"), 290 | // Return checking 291 | Run("fn1 := func() int{ for {} }"), 292 | CErr("fn1 := func() int{ for true {} }", "return"), 293 | CErr("fn1 := func() int{ for true {return 1} }", "return"), 294 | CErr("fn1 := func() int{ for {break} }", "return"), 295 | Run("fn1 := func() int{ for { for {break} } }"), 296 | CErr("fn1 := func() int{ L1: for { for {break L1} } }", "return"), 297 | Run("fn1 := func() int{ for true {}; return 1 }"), 298 | 299 | // Selectors 300 | Val1("var x struct { a int; b int }; x.a = 42; i = x.a", "i", 42), 301 | Val1("type T struct { x int }; var y struct { T }; y.x = 42; i = y.x", "i", 42), 302 | Val2("type T struct { x int }; var y struct { T; x int }; y.x = 42; i = y.x; i2 = y.T.x", "i", 42, "i2", 0), 303 | Run("type T struct { x int }; var y struct { *T }; a := func(){i=y.x}"), 304 | CErr("type T struct { x int }; var x T; x.y = 42", "no field"), 305 | CErr("type T struct { x int }; type U struct { x int }; var y struct { T; U }; y.x = 42", "ambiguous.*[\n].*T\\.x.*[\n].*U\\.x"), 306 | CErr("type T struct { *T }; var x T; x.foo", "no field"), 307 | 308 | Val1("fib := func(int) int{return 0;}; fib = func(v int) int { if v < 2 { return 1 }; return fib(v-1)+fib(v-2) }; i = fib(20)", "i", 10946), 309 | 310 | // Make slice 311 | Val2("x := make([]int, 2); x[0] = 42; i, i2 = x[0], x[1]", "i", 42, "i2", 0), 312 | Val2("x := make([]int, 2); x[1] = 42; i, i2 = x[0], x[1]", "i", 0, "i2", 42), 313 | RErr("x := make([]int, 2); x[-i] = 42", "negative index"), 314 | RErr("x := make([]int, 2); x[2] = 42", "index 2 exceeds"), 315 | Val2("x := make([]int, 2, 3); i, i2 = len(x), cap(x)", "i", 2, "i2", 3), 316 | Val2("x := make([]int, 3, 2); i, i2 = len(x), cap(x)", "i", 3, "i2", 3), 317 | RErr("x := make([]int, -i)", "negative length"), 318 | RErr("x := make([]int, 2, -i)", "negative capacity"), 319 | RErr("x := make([]int, 2, 3); x[2] = 42", "index 2 exceeds"), 320 | CErr("x := make([]int, 2, 3, 4)", "too many"), 321 | CErr("x := make([]int)", "not enough"), 322 | 323 | // TODO(austin) Test make map 324 | 325 | // Maps 326 | Val1("x := make(map[int] int); x[1] = 42; i = x[1]", "i", 42), 327 | Val2("x := make(map[int] int); x[1] = 42; i, y := x[1]", "i", 42, "y", true), 328 | Val2("x := make(map[int] int); x[1] = 42; i, y := x[2]", "i", 0, "y", false), 329 | // Not implemented 330 | //Val1("x := make(map[int] int); x[1] = 42, true; i = x[1]", "i", 42), 331 | //Val2("x := make(map[int] int); x[1] = 42; x[1] = 42, false; i, y := x[1]", "i", 0, "y", false), 332 | Run("var x int; a := make(map[int] int); a[0], x = 1, 2"), 333 | CErr("x := make(map[int] int); (func(a,b int){})(x[0])", "not enough"), 334 | CErr("x := make(map[int] int); x[1] = oneTwo()", "too many"), 335 | RErr("x := make(map[int] int); i = x[1]", "key '1' not found"), 336 | 337 | // Functions 338 | Val2("func fib(n int) int { if n <= 2 { return n }; return fib(n-1) + fib(n-2) }", "fib(4)", 5, "fib(10)", 89), 339 | Run("func f1(){}"), 340 | Run2("func f1(){}", "f1()"), 341 | 342 | // Imports 343 | CErr(`import "__a"`, `import "foo" not .*? implemented`), 344 | } 345 | 346 | func TestStmt(t *testing.T) { runTests(t, "stmtTests", stmtTests) } 347 | -------------------------------------------------------------------------------- /type.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | package eval 6 | 7 | import ( 8 | "go/ast" 9 | "go/token" 10 | "log" 11 | "math/big" 12 | "reflect" 13 | "sort" 14 | "unsafe" // For Sizeof 15 | ) 16 | 17 | // XXX(Spec) The type compatibility section is very confusing because 18 | // it makes it seem like there are three distinct types of 19 | // compatibility: plain compatibility, assignment compatibility, and 20 | // comparison compatibility. As I understand it, there's really only 21 | // assignment compatibility and comparison and conversion have some 22 | // restrictions and have special meaning in some cases where the types 23 | // are not otherwise assignment compatible. The comparison 24 | // compatibility section is almost all about the semantics of 25 | // comparison, not the type checking of it, so it would make much more 26 | // sense in the comparison operators section. The compatibility and 27 | // assignment compatibility sections should be rolled into one. 28 | 29 | type Type interface { 30 | // compat returns whether this type is compatible with another 31 | // type. If conv is false, this is normal compatibility, 32 | // where two named types are compatible only if they are the 33 | // same named type. If conv if true, this is conversion 34 | // compatibility, where two named types are conversion 35 | // compatible if their definitions are conversion compatible. 36 | // 37 | // TODO(austin) Deal with recursive types 38 | compat(o Type, conv bool) bool 39 | // lit returns this type's literal. If this is a named type, 40 | // this is the unnamed underlying type. Otherwise, this is an 41 | // identity operation. 42 | lit() Type 43 | // isBoolean returns true if this is a boolean type. 44 | isBoolean() bool 45 | // isInteger returns true if this is an integer type. 46 | isInteger() bool 47 | // isFloat returns true if this is a floating type. 48 | isFloat() bool 49 | // isIdeal returns true if this is an ideal int or float. 50 | isIdeal() bool 51 | // Zero returns a new zero value of this type. 52 | Zero() Value 53 | // String returns the string representation of this type. 54 | String() string 55 | // The position where this type was defined, if any. 56 | //Pos() token.Pos 57 | } 58 | 59 | type BoundedType interface { 60 | Type 61 | // minVal returns the smallest value of this type. 62 | minVal() *big.Rat 63 | // maxVal returns the largest value of this type. 64 | maxVal() *big.Rat 65 | } 66 | 67 | var universePos = token.NoPos 68 | 69 | /* 70 | * Type array maps. These are used to memoize composite types. 71 | */ 72 | 73 | type typeArrayMapEntry struct { 74 | key []Type 75 | v interface{} 76 | next *typeArrayMapEntry 77 | } 78 | 79 | type typeArrayMap map[uintptr]*typeArrayMapEntry 80 | 81 | func hashTypeArray(key []Type) uintptr { 82 | hash := uintptr(0) 83 | for _, t := range key { 84 | hash = hash * 33 85 | if t == nil { 86 | continue 87 | } 88 | addr := reflect.ValueOf(t).Pointer() 89 | hash ^= addr 90 | } 91 | return hash 92 | } 93 | 94 | func newTypeArrayMap() typeArrayMap { return make(map[uintptr]*typeArrayMapEntry) } 95 | 96 | func (m typeArrayMap) Get(key []Type) interface{} { 97 | ent, ok := m[hashTypeArray(key)] 98 | if !ok { 99 | return nil 100 | } 101 | 102 | nextEnt: 103 | for ; ent != nil; ent = ent.next { 104 | if len(key) != len(ent.key) { 105 | continue 106 | } 107 | for i := 0; i < len(key); i++ { 108 | if key[i] != ent.key[i] { 109 | continue nextEnt 110 | } 111 | } 112 | // Found it 113 | return ent.v 114 | } 115 | 116 | return nil 117 | } 118 | 119 | func (m typeArrayMap) Put(key []Type, v interface{}) interface{} { 120 | hash := hashTypeArray(key) 121 | ent := m[hash] 122 | 123 | new := &typeArrayMapEntry{key, v, ent} 124 | m[hash] = new 125 | return v 126 | } 127 | 128 | /* 129 | * Common type 130 | */ 131 | 132 | type commonType struct{} 133 | 134 | func (commonType) isBoolean() bool { return false } 135 | 136 | func (commonType) isInteger() bool { return false } 137 | 138 | func (commonType) isFloat() bool { return false } 139 | 140 | func (commonType) isIdeal() bool { return false } 141 | 142 | /* 143 | * Package 144 | */ 145 | 146 | type packageField struct { 147 | Name string 148 | Type Type 149 | } 150 | 151 | type packageType struct { 152 | commonType 153 | Elems []packageField 154 | } 155 | 156 | var packageTypes = make(map[string]*packageType) 157 | 158 | func newPackageType(path string, fields []packageField) *packageType { 159 | t, ok := packageTypes[path] 160 | if !ok { 161 | t = &packageType{commonType{}, fields} 162 | packageTypes[path] = t 163 | } 164 | return t 165 | } 166 | 167 | func (p *packageType) compat(o Type, conv bool) bool { return false } 168 | func (p *packageType) lit() Type { return p } 169 | func (p *packageType) String() string { 170 | // Use angle brackets as a convention for printing the 171 | // underlying, unnamed type. This should only show up in 172 | // debug output. 173 | return "" 174 | } 175 | 176 | func (p *packageType) Zero() Value { 177 | pkg := packageV{} 178 | pkg.name = "" 179 | pkg.idents = make([]Value, 0) 180 | return &pkg 181 | } 182 | 183 | /* 184 | * Bool 185 | */ 186 | 187 | type boolType struct { 188 | commonType 189 | } 190 | 191 | var BoolType = universe.DefineType("bool", universePos, &boolType{}) 192 | 193 | func (t *boolType) compat(o Type, conv bool) bool { 194 | _, ok := o.lit().(*boolType) 195 | return ok 196 | } 197 | 198 | func (t *boolType) lit() Type { return t } 199 | 200 | func (t *boolType) isBoolean() bool { return true } 201 | 202 | func (boolType) String() string { 203 | // Use angle brackets as a convention for printing the 204 | // underlying, unnamed type. This should only show up in 205 | // debug output. 206 | return "" 207 | } 208 | 209 | func (t *boolType) Zero() Value { 210 | res := boolV(false) 211 | return &res 212 | } 213 | 214 | /* 215 | * Uint 216 | */ 217 | 218 | type uintType struct { 219 | commonType 220 | 221 | // 0 for architecture-dependent types 222 | Bits uint 223 | // true for uintptr, false for all others 224 | Ptr bool 225 | name string 226 | } 227 | 228 | var ( 229 | Uint8Type = universe.DefineType("uint8", universePos, &uintType{commonType{}, 8, false, "uint8"}) 230 | Uint16Type = universe.DefineType("uint16", universePos, &uintType{commonType{}, 16, false, "uint16"}) 231 | Uint32Type = universe.DefineType("uint32", universePos, &uintType{commonType{}, 32, false, "uint32"}) 232 | Uint64Type = universe.DefineType("uint64", universePos, &uintType{commonType{}, 64, false, "uint64"}) 233 | 234 | UintType = universe.DefineType("uint", universePos, &uintType{commonType{}, 0, false, "uint"}) 235 | UintptrType = universe.DefineType("uintptr", universePos, &uintType{commonType{}, 0, true, "uintptr"}) 236 | ) 237 | 238 | func (t *uintType) compat(o Type, conv bool) bool { 239 | t2, ok := o.lit().(*uintType) 240 | return ok && t == t2 241 | } 242 | 243 | func (t *uintType) lit() Type { return t } 244 | 245 | func (t *uintType) isInteger() bool { return true } 246 | 247 | func (t *uintType) String() string { return "<" + t.name + ">" } 248 | 249 | func (t *uintType) Zero() Value { 250 | switch t.Bits { 251 | case 0: 252 | if t.Ptr { 253 | res := uintptrV(0) 254 | return &res 255 | } else { 256 | res := uintV(0) 257 | return &res 258 | } 259 | case 8: 260 | res := uint8V(0) 261 | return &res 262 | case 16: 263 | res := uint16V(0) 264 | return &res 265 | case 32: 266 | res := uint32V(0) 267 | return &res 268 | case 64: 269 | res := uint64V(0) 270 | return &res 271 | } 272 | panic("unexpected uint bit count") 273 | } 274 | 275 | func (t *uintType) minVal() *big.Rat { return big.NewRat(0, 1) } 276 | 277 | func (t *uintType) maxVal() *big.Rat { 278 | bits := t.Bits 279 | if bits == 0 { 280 | if t.Ptr { 281 | bits = uint(8 * unsafe.Sizeof(uintptr(0))) 282 | } else { 283 | bits = uint(8 * unsafe.Sizeof(uint(0))) 284 | } 285 | } 286 | numer := big.NewInt(1) 287 | numer.Lsh(numer, bits) 288 | numer.Sub(numer, idealOne) 289 | return new(big.Rat).SetInt(numer) 290 | } 291 | 292 | /* 293 | * Int 294 | */ 295 | 296 | type intType struct { 297 | commonType 298 | 299 | // XXX(Spec) Numeric types: "There is also a set of 300 | // architecture-independent basic numeric types whose size 301 | // depends on the architecture." Should that be 302 | // architecture-dependent? 303 | 304 | // 0 for architecture-dependent types 305 | Bits uint 306 | name string 307 | } 308 | 309 | var ( 310 | Int8Type = universe.DefineType("int8", universePos, &intType{commonType{}, 8, "int8"}) 311 | Int16Type = universe.DefineType("int16", universePos, &intType{commonType{}, 16, "int16"}) 312 | Int32Type = universe.DefineType("int32", universePos, &intType{commonType{}, 32, "int32"}) 313 | Int64Type = universe.DefineType("int64", universePos, &intType{commonType{}, 64, "int64"}) 314 | 315 | IntType = universe.DefineType("int", universePos, &intType{commonType{}, 0, "int"}) 316 | ) 317 | 318 | func (t *intType) compat(o Type, conv bool) bool { 319 | t2, ok := o.lit().(*intType) 320 | return ok && t == t2 321 | } 322 | 323 | func (t *intType) lit() Type { return t } 324 | 325 | func (t *intType) isInteger() bool { return true } 326 | 327 | func (t *intType) String() string { return "<" + t.name + ">" } 328 | 329 | func (t *intType) Zero() Value { 330 | switch t.Bits { 331 | case 8: 332 | res := int8V(0) 333 | return &res 334 | case 16: 335 | res := int16V(0) 336 | return &res 337 | case 32: 338 | res := int32V(0) 339 | return &res 340 | case 64: 341 | res := int64V(0) 342 | return &res 343 | 344 | case 0: 345 | res := intV(0) 346 | return &res 347 | } 348 | panic("unexpected int bit count") 349 | } 350 | 351 | func (t *intType) minVal() *big.Rat { 352 | bits := t.Bits 353 | if bits == 0 { 354 | bits = uint(8 * unsafe.Sizeof(int(0))) 355 | } 356 | numer := big.NewInt(-1) 357 | numer.Lsh(numer, bits-1) 358 | return new(big.Rat).SetInt(numer) 359 | } 360 | 361 | func (t *intType) maxVal() *big.Rat { 362 | bits := t.Bits 363 | if bits == 0 { 364 | bits = uint(8 * unsafe.Sizeof(int(0))) 365 | } 366 | numer := big.NewInt(1) 367 | numer.Lsh(numer, bits-1) 368 | numer.Sub(numer, idealOne) 369 | return new(big.Rat).SetInt(numer) 370 | } 371 | 372 | /* 373 | * Ideal int 374 | */ 375 | 376 | type idealIntType struct { 377 | commonType 378 | } 379 | 380 | var IdealIntType Type = &idealIntType{} 381 | 382 | func (t *idealIntType) compat(o Type, conv bool) bool { 383 | _, ok := o.lit().(*idealIntType) 384 | return ok 385 | } 386 | 387 | func (t *idealIntType) lit() Type { return t } 388 | 389 | func (t *idealIntType) isInteger() bool { return true } 390 | 391 | func (t *idealIntType) isIdeal() bool { return true } 392 | 393 | func (t *idealIntType) String() string { return "ideal integer" } 394 | 395 | func (t *idealIntType) Zero() Value { return &idealIntV{idealZero} } 396 | 397 | /* 398 | * Float 399 | */ 400 | 401 | type floatType struct { 402 | commonType 403 | 404 | // 0 for architecture-dependent type 405 | Bits uint 406 | 407 | name string 408 | } 409 | 410 | var ( 411 | Float32Type = universe.DefineType("float32", universePos, &floatType{commonType{}, 32, "float32"}) 412 | Float64Type = universe.DefineType("float64", universePos, &floatType{commonType{}, 64, "float64"}) 413 | ) 414 | 415 | func (t *floatType) compat(o Type, conv bool) bool { 416 | t2, ok := o.lit().(*floatType) 417 | return ok && t == t2 418 | } 419 | 420 | func (t *floatType) lit() Type { return t } 421 | 422 | func (t *floatType) isFloat() bool { return true } 423 | 424 | func (t *floatType) String() string { return "<" + t.name + ">" } 425 | 426 | func (t *floatType) Zero() Value { 427 | switch t.Bits { 428 | case 32: 429 | res := float32V(0) 430 | return &res 431 | case 64: 432 | res := float64V(0) 433 | return &res 434 | } 435 | panic("unexpected float bit count") 436 | } 437 | 438 | var maxFloat32Val *big.Rat 439 | var maxFloat64Val *big.Rat 440 | var minFloat32Val *big.Rat 441 | var minFloat64Val *big.Rat 442 | 443 | func (t *floatType) minVal() *big.Rat { 444 | bits := t.Bits 445 | switch bits { 446 | case 32: 447 | return minFloat32Val 448 | case 64: 449 | return minFloat64Val 450 | } 451 | log.Panicf("unexpected floating point bit count: %d", bits) 452 | panic("unreachable") 453 | } 454 | 455 | func (t *floatType) maxVal() *big.Rat { 456 | bits := t.Bits 457 | switch bits { 458 | case 32: 459 | return maxFloat32Val 460 | case 64: 461 | return maxFloat64Val 462 | } 463 | log.Panicf("unexpected floating point bit count: %d", bits) 464 | panic("unreachable") 465 | } 466 | 467 | /* 468 | * Ideal float 469 | */ 470 | 471 | type idealFloatType struct { 472 | commonType 473 | } 474 | 475 | var IdealFloatType Type = &idealFloatType{} 476 | 477 | func (t *idealFloatType) compat(o Type, conv bool) bool { 478 | _, ok := o.lit().(*idealFloatType) 479 | return ok 480 | } 481 | 482 | func (t *idealFloatType) lit() Type { return t } 483 | 484 | func (t *idealFloatType) isFloat() bool { return true } 485 | 486 | func (t *idealFloatType) isIdeal() bool { return true } 487 | 488 | func (t *idealFloatType) String() string { return "ideal float" } 489 | 490 | func (t *idealFloatType) Zero() Value { return &idealFloatV{big.NewRat(0, 1)} } 491 | 492 | /* 493 | * String 494 | */ 495 | 496 | type stringType struct { 497 | commonType 498 | } 499 | 500 | var StringType = universe.DefineType("string", universePos, &stringType{}) 501 | 502 | func (t *stringType) compat(o Type, conv bool) bool { 503 | _, ok := o.lit().(*stringType) 504 | return ok 505 | } 506 | 507 | func (t *stringType) lit() Type { return t } 508 | 509 | func (t *stringType) String() string { return "" } 510 | 511 | func (t *stringType) Zero() Value { 512 | res := stringV("") 513 | return &res 514 | } 515 | 516 | /* 517 | * Array 518 | */ 519 | 520 | type ArrayType struct { 521 | commonType 522 | Len int64 523 | Elem Type 524 | } 525 | 526 | var arrayTypes = make(map[int64]map[Type]*ArrayType) 527 | 528 | // Two array types are identical if they have identical element types 529 | // and the same array length. 530 | 531 | func NewArrayType(len int64, elem Type) *ArrayType { 532 | ts, ok := arrayTypes[len] 533 | if !ok { 534 | ts = make(map[Type]*ArrayType) 535 | arrayTypes[len] = ts 536 | } 537 | t, ok := ts[elem] 538 | if !ok { 539 | t = &ArrayType{commonType{}, len, elem} 540 | ts[elem] = t 541 | } 542 | return t 543 | } 544 | 545 | func (t *ArrayType) compat(o Type, conv bool) bool { 546 | t2, ok := o.lit().(*ArrayType) 547 | if !ok { 548 | return false 549 | } 550 | return t.Len == t2.Len && t.Elem.compat(t2.Elem, conv) 551 | } 552 | 553 | func (t *ArrayType) lit() Type { return t } 554 | 555 | func (t *ArrayType) String() string { return "[]" + t.Elem.String() } 556 | 557 | func (t *ArrayType) Zero() Value { 558 | res := arrayV(make([]Value, t.Len)) 559 | // TODO(austin) It's unfortunate that each element is 560 | // separately heap allocated. We could add ZeroArray to 561 | // everything, though that doesn't help with multidimensional 562 | // arrays. Or we could do something unsafe. We'll have this 563 | // same problem with structs. 564 | for i := int64(0); i < t.Len; i++ { 565 | res[i] = t.Elem.Zero() 566 | } 567 | return &res 568 | } 569 | 570 | /* 571 | * Struct 572 | */ 573 | 574 | type StructField struct { 575 | Name string 576 | Type Type 577 | Anonymous bool 578 | } 579 | 580 | type StructType struct { 581 | commonType 582 | Elems []StructField 583 | } 584 | 585 | var structTypes = newTypeArrayMap() 586 | 587 | // Two struct types are identical if they have the same sequence of 588 | // fields, and if corresponding fields have the same names and 589 | // identical types. Two anonymous fields are considered to have the 590 | // same name. 591 | 592 | func NewStructType(fields []StructField) *StructType { 593 | // Start by looking up just the types 594 | fts := make([]Type, len(fields)) 595 | for i, f := range fields { 596 | fts[i] = f.Type 597 | } 598 | tMapI := structTypes.Get(fts) 599 | if tMapI == nil { 600 | tMapI = structTypes.Put(fts, make(map[string]*StructType)) 601 | } 602 | tMap := tMapI.(map[string]*StructType) 603 | 604 | // Construct key for field names 605 | key := "" 606 | for _, f := range fields { 607 | // XXX(Spec) It's not clear if struct { T } and struct 608 | // { T T } are either identical or compatible. The 609 | // "Struct Types" section says that the name of that 610 | // field is "T", which suggests that they are 611 | // identical, but it really means that it's the name 612 | // for the purpose of selector expressions and nothing 613 | // else. We decided that they should be neither 614 | // identical or compatible. 615 | if f.Anonymous { 616 | key += "!" 617 | } 618 | key += f.Name + " " 619 | } 620 | 621 | // XXX(Spec) Do the tags also have to be identical for the 622 | // types to be identical? I certainly hope so, because 623 | // otherwise, this is the only case where two distinct type 624 | // objects can represent identical types. 625 | 626 | t, ok := tMap[key] 627 | if !ok { 628 | // Create new struct type 629 | t = &StructType{commonType{}, fields} 630 | tMap[key] = t 631 | } 632 | return t 633 | } 634 | 635 | func (t *StructType) compat(o Type, conv bool) bool { 636 | t2, ok := o.lit().(*StructType) 637 | if !ok { 638 | return false 639 | } 640 | if len(t.Elems) != len(t2.Elems) { 641 | return false 642 | } 643 | for i, e := range t.Elems { 644 | e2 := t2.Elems[i] 645 | // XXX(Spec) An anonymous and a non-anonymous field 646 | // are neither identical nor compatible. 647 | if e.Anonymous != e2.Anonymous || 648 | (!e.Anonymous && e.Name != e2.Name) || 649 | !e.Type.compat(e2.Type, conv) { 650 | return false 651 | } 652 | } 653 | return true 654 | } 655 | 656 | func (t *StructType) lit() Type { return t } 657 | 658 | func (t *StructType) String() string { 659 | s := "struct {" 660 | for i, f := range t.Elems { 661 | if i > 0 { 662 | s += "; " 663 | } 664 | if !f.Anonymous { 665 | s += f.Name + " " 666 | } 667 | s += f.Type.String() 668 | } 669 | return s + "}" 670 | } 671 | 672 | func (t *StructType) Zero() Value { 673 | res := structV(make([]Value, len(t.Elems))) 674 | for i, f := range t.Elems { 675 | res[i] = f.Type.Zero() 676 | } 677 | return &res 678 | } 679 | 680 | /* 681 | * Pointer 682 | */ 683 | 684 | type PtrType struct { 685 | commonType 686 | Elem Type 687 | } 688 | 689 | var ptrTypes = make(map[Type]*PtrType) 690 | 691 | // Two pointer types are identical if they have identical base types. 692 | 693 | func NewPtrType(elem Type) *PtrType { 694 | t, ok := ptrTypes[elem] 695 | if !ok { 696 | t = &PtrType{commonType{}, elem} 697 | ptrTypes[elem] = t 698 | } 699 | return t 700 | } 701 | 702 | func (t *PtrType) compat(o Type, conv bool) bool { 703 | t2, ok := o.lit().(*PtrType) 704 | if !ok { 705 | return false 706 | } 707 | return t.Elem.compat(t2.Elem, conv) 708 | } 709 | 710 | func (t *PtrType) lit() Type { return t } 711 | 712 | func (t *PtrType) String() string { return "*" + t.Elem.String() } 713 | 714 | func (t *PtrType) Zero() Value { return &ptrV{nil} } 715 | 716 | /* 717 | * Function 718 | */ 719 | 720 | type FuncType struct { 721 | commonType 722 | // TODO(austin) Separate receiver Type for methods? 723 | In []Type 724 | Variadic bool 725 | Out []Type 726 | builtin string 727 | } 728 | 729 | var funcTypes = newTypeArrayMap() 730 | var variadicFuncTypes = newTypeArrayMap() 731 | 732 | // Create singleton function types for magic built-in functions 733 | var ( 734 | appendType = &FuncType{builtin: "append"} 735 | capType = &FuncType{builtin: "cap"} 736 | closeType = &FuncType{builtin: "close"} 737 | closedType = &FuncType{builtin: "closed"} 738 | lenType = &FuncType{builtin: "len"} 739 | makeType = &FuncType{builtin: "make"} 740 | newType = &FuncType{builtin: "new"} 741 | panicType = &FuncType{builtin: "panic"} 742 | printType = &FuncType{builtin: "print"} 743 | printlnType = &FuncType{builtin: "println"} 744 | copyType = &FuncType{builtin: "copy"} 745 | ) 746 | 747 | // Two function types are identical if they have the same number of 748 | // parameters and result values and if corresponding parameter and 749 | // result types are identical. All "..." parameters have identical 750 | // type. Parameter and result names are not required to match. 751 | 752 | func NewFuncType(in []Type, variadic bool, out []Type) *FuncType { 753 | inMap := funcTypes 754 | if variadic { 755 | inMap = variadicFuncTypes 756 | } 757 | 758 | outMapI := inMap.Get(in) 759 | if outMapI == nil { 760 | outMapI = inMap.Put(in, newTypeArrayMap()) 761 | } 762 | outMap := outMapI.(typeArrayMap) 763 | 764 | tI := outMap.Get(out) 765 | if tI != nil { 766 | return tI.(*FuncType) 767 | } 768 | 769 | t := &FuncType{commonType{}, in, variadic, out, ""} 770 | outMap.Put(out, t) 771 | return t 772 | } 773 | 774 | func (t *FuncType) compat(o Type, conv bool) bool { 775 | t2, ok := o.lit().(*FuncType) 776 | if !ok { 777 | return false 778 | } 779 | if len(t.In) != len(t2.In) || t.Variadic != t2.Variadic || len(t.Out) != len(t2.Out) { 780 | return false 781 | } 782 | for i := range t.In { 783 | if !t.In[i].compat(t2.In[i], conv) { 784 | return false 785 | } 786 | } 787 | for i := range t.Out { 788 | if !t.Out[i].compat(t2.Out[i], conv) { 789 | return false 790 | } 791 | } 792 | return true 793 | } 794 | 795 | func (t *FuncType) lit() Type { return t } 796 | 797 | func typeListString(ts []Type, ns []*ast.Ident) string { 798 | s := "" 799 | for i, t := range ts { 800 | if i > 0 { 801 | s += ", " 802 | } 803 | if ns != nil && ns[i] != nil { 804 | s += ns[i].Name + " " 805 | } 806 | if t == nil { 807 | // Some places use nil types to represent errors 808 | s += "" 809 | } else { 810 | s += t.String() 811 | } 812 | } 813 | return s 814 | } 815 | 816 | func (t *FuncType) String() string { 817 | if t.builtin != "" { 818 | return "built-in function " + t.builtin 819 | } 820 | args := typeListString(t.In, nil) 821 | if t.Variadic { 822 | if len(args) > 0 { 823 | args += ", " 824 | } 825 | args += "..." 826 | } 827 | s := "func(" + args + ")" 828 | if len(t.Out) > 0 { 829 | s += " (" + typeListString(t.Out, nil) + ")" 830 | } 831 | return s 832 | } 833 | 834 | func (t *FuncType) Zero() Value { return &funcV{nil} } 835 | 836 | type FuncDecl struct { 837 | Type *FuncType 838 | Name *ast.Ident // nil for function literals 839 | // InNames will be one longer than Type.In if this function is 840 | // variadic. 841 | InNames []*ast.Ident 842 | OutNames []*ast.Ident 843 | } 844 | 845 | func (t *FuncDecl) String() string { 846 | s := "func" 847 | if t.Name != nil { 848 | s += " " + t.Name.Name 849 | } 850 | s += funcTypeString(t.Type, t.InNames, t.OutNames) 851 | return s 852 | } 853 | 854 | func funcTypeString(ft *FuncType, ins []*ast.Ident, outs []*ast.Ident) string { 855 | s := "(" 856 | s += typeListString(ft.In, ins) 857 | if ft.Variadic { 858 | if len(ft.In) > 0 { 859 | s += ", " 860 | } 861 | s += "..." 862 | } 863 | s += ")" 864 | if len(ft.Out) > 0 { 865 | s += " (" + typeListString(ft.Out, outs) + ")" 866 | } 867 | return s 868 | } 869 | 870 | /* 871 | * Interface 872 | */ 873 | 874 | // TODO(austin) Interface values, types, and type compilation are 875 | // implemented, but none of the type checking or semantics of 876 | // interfaces are. 877 | 878 | type InterfaceType struct { 879 | commonType 880 | // TODO(austin) This should be a map from names to 881 | // *FuncType's. We only need the sorted list for generating 882 | // the type map key. It's detrimental for everything else. 883 | methods []IMethod 884 | } 885 | 886 | type IMethod struct { 887 | Name string 888 | Type *FuncType 889 | } 890 | 891 | var interfaceTypes = newTypeArrayMap() 892 | 893 | func NewInterfaceType(methods []IMethod, embeds []*InterfaceType) *InterfaceType { 894 | // Count methods of embedded interfaces 895 | nMethods := len(methods) 896 | for _, e := range embeds { 897 | nMethods += len(e.methods) 898 | } 899 | 900 | // Combine methods 901 | allMethods := make([]IMethod, nMethods) 902 | copy(allMethods, methods) 903 | n := len(methods) 904 | for _, e := range embeds { 905 | for _, m := range e.methods { 906 | allMethods[n] = m 907 | n++ 908 | } 909 | } 910 | 911 | // Sort methods 912 | sort.Sort(iMethodSorter(allMethods)) 913 | 914 | mts := make([]Type, len(allMethods)) 915 | for i, m := range methods { 916 | mts[i] = m.Type 917 | } 918 | tMapI := interfaceTypes.Get(mts) 919 | if tMapI == nil { 920 | tMapI = interfaceTypes.Put(mts, make(map[string]*InterfaceType)) 921 | } 922 | tMap := tMapI.(map[string]*InterfaceType) 923 | 924 | key := "" 925 | for _, m := range allMethods { 926 | key += m.Name + " " 927 | } 928 | 929 | t, ok := tMap[key] 930 | if !ok { 931 | t = &InterfaceType{commonType{}, allMethods} 932 | tMap[key] = t 933 | } 934 | return t 935 | } 936 | 937 | type iMethodSorter []IMethod 938 | 939 | func (s iMethodSorter) Less(a, b int) bool { return s[a].Name < s[b].Name } 940 | 941 | func (s iMethodSorter) Swap(a, b int) { s[a], s[b] = s[b], s[a] } 942 | 943 | func (s iMethodSorter) Len() int { return len(s) } 944 | 945 | func (t *InterfaceType) compat(o Type, conv bool) bool { 946 | t2, ok := o.lit().(*InterfaceType) 947 | if !ok { 948 | return false 949 | } 950 | if len(t.methods) != len(t2.methods) { 951 | return false 952 | } 953 | for i, e := range t.methods { 954 | e2 := t2.methods[i] 955 | if e.Name != e2.Name || !e.Type.compat(e2.Type, conv) { 956 | return false 957 | } 958 | } 959 | return true 960 | } 961 | 962 | func (t *InterfaceType) lit() Type { return t } 963 | 964 | func (t *InterfaceType) String() string { 965 | // TODO(austin) Instead of showing embedded interfaces, this 966 | // shows their methods. 967 | s := "interface {" 968 | for i, m := range t.methods { 969 | if i > 0 { 970 | s += "; " 971 | } 972 | s += m.Name + funcTypeString(m.Type, nil, nil) 973 | } 974 | return s + "}" 975 | } 976 | 977 | // implementedBy tests if o implements t, returning nil, true if it does. 978 | // Otherwise, it returns a method of t that o is missing and false. 979 | func (t *InterfaceType) implementedBy(o Type) (*IMethod, bool) { 980 | if len(t.methods) == 0 { 981 | return nil, true 982 | } 983 | 984 | // The methods of a named interface types are those of the 985 | // underlying type. 986 | if it, ok := o.lit().(*InterfaceType); ok { 987 | o = it 988 | } 989 | 990 | // XXX(Spec) Interface types: "A type implements any interface 991 | // comprising any subset of its methods" It's unclear if 992 | // methods must have identical or compatible types. 6g 993 | // requires identical types. 994 | 995 | switch o := o.(type) { 996 | case *NamedType: 997 | for _, tm := range t.methods { 998 | sm, ok := o.methods[tm.Name] 999 | if !ok || sm.decl.Type != tm.Type { 1000 | return &tm, false 1001 | } 1002 | } 1003 | return nil, true 1004 | 1005 | case *InterfaceType: 1006 | var ti, oi int 1007 | for ti < len(t.methods) && oi < len(o.methods) { 1008 | tm, om := &t.methods[ti], &o.methods[oi] 1009 | switch { 1010 | case tm.Name == om.Name: 1011 | if tm.Type != om.Type { 1012 | return tm, false 1013 | } 1014 | ti++ 1015 | oi++ 1016 | case tm.Name > om.Name: 1017 | oi++ 1018 | default: 1019 | return tm, false 1020 | } 1021 | } 1022 | if ti < len(t.methods) { 1023 | return &t.methods[ti], false 1024 | } 1025 | return nil, true 1026 | } 1027 | 1028 | return &t.methods[0], false 1029 | } 1030 | 1031 | func (t *InterfaceType) Zero() Value { return &interfaceV{} } 1032 | 1033 | /* 1034 | * Slice 1035 | */ 1036 | 1037 | type SliceType struct { 1038 | commonType 1039 | Elem Type 1040 | } 1041 | 1042 | var sliceTypes = make(map[Type]*SliceType) 1043 | 1044 | // Two slice types are identical if they have identical element types. 1045 | 1046 | func NewSliceType(elem Type) *SliceType { 1047 | t, ok := sliceTypes[elem] 1048 | if !ok { 1049 | t = &SliceType{commonType{}, elem} 1050 | sliceTypes[elem] = t 1051 | } 1052 | return t 1053 | } 1054 | 1055 | func (t *SliceType) compat(o Type, conv bool) bool { 1056 | t2, ok := o.lit().(*SliceType) 1057 | if !ok { 1058 | return false 1059 | } 1060 | return t.Elem.compat(t2.Elem, conv) 1061 | } 1062 | 1063 | func (t *SliceType) lit() Type { return t } 1064 | 1065 | func (t *SliceType) String() string { return "[]" + t.Elem.String() } 1066 | 1067 | func (t *SliceType) Zero() Value { 1068 | // The value of an uninitialized slice is nil. The length and 1069 | // capacity of a nil slice are 0. 1070 | return &sliceV{Slice{nil, 0, 0}} 1071 | } 1072 | 1073 | /* 1074 | * Map type 1075 | */ 1076 | 1077 | type MapType struct { 1078 | commonType 1079 | Key Type 1080 | Elem Type 1081 | } 1082 | 1083 | var mapTypes = make(map[Type]map[Type]*MapType) 1084 | 1085 | func NewMapType(key Type, elem Type) *MapType { 1086 | ts, ok := mapTypes[key] 1087 | if !ok { 1088 | ts = make(map[Type]*MapType) 1089 | mapTypes[key] = ts 1090 | } 1091 | t, ok := ts[elem] 1092 | if !ok { 1093 | t = &MapType{commonType{}, key, elem} 1094 | ts[elem] = t 1095 | } 1096 | return t 1097 | } 1098 | 1099 | func (t *MapType) compat(o Type, conv bool) bool { 1100 | t2, ok := o.lit().(*MapType) 1101 | if !ok { 1102 | return false 1103 | } 1104 | return t.Elem.compat(t2.Elem, conv) && t.Key.compat(t2.Key, conv) 1105 | } 1106 | 1107 | func (t *MapType) lit() Type { return t } 1108 | 1109 | func (t *MapType) String() string { return "map[" + t.Key.String() + "] " + t.Elem.String() } 1110 | 1111 | func (t *MapType) Zero() Value { 1112 | // The value of an uninitialized map is nil. 1113 | return &mapV{nil} 1114 | } 1115 | 1116 | /* 1117 | type ChanType struct { 1118 | // TODO(austin) 1119 | } 1120 | */ 1121 | 1122 | /* 1123 | * Named types 1124 | */ 1125 | 1126 | type Method struct { 1127 | decl *FuncDecl 1128 | fn Func 1129 | } 1130 | 1131 | type NamedType struct { 1132 | NamePos token.Pos 1133 | Name string 1134 | // Underlying type. If incomplete is true, this will be nil. 1135 | // If incomplete is false and this is still nil, then this is 1136 | // a placeholder type representing an error. 1137 | Def Type 1138 | // True while this type is being defined. 1139 | incomplete bool 1140 | methods map[string]Method 1141 | } 1142 | 1143 | // TODO(austin) This is temporarily needed by the debugger's remote 1144 | // type parser. This should only be possible with block.DefineType. 1145 | func NewNamedType(name string) *NamedType { 1146 | return &NamedType{token.NoPos, name, nil, true, make(map[string]Method)} 1147 | } 1148 | 1149 | func (t *NamedType) Pos() token.Pos { 1150 | return t.NamePos 1151 | } 1152 | 1153 | func (t *NamedType) Complete(def Type) { 1154 | if !t.incomplete { 1155 | log.Panicf("cannot complete already completed NamedType %+v", *t) 1156 | } 1157 | // We strip the name from def because multiple levels of 1158 | // naming are useless. 1159 | if ndef, ok := def.(*NamedType); ok { 1160 | def = ndef.Def 1161 | } 1162 | t.Def = def 1163 | t.incomplete = false 1164 | } 1165 | 1166 | func (t *NamedType) compat(o Type, conv bool) bool { 1167 | t2, ok := o.(*NamedType) 1168 | if ok { 1169 | if conv { 1170 | // Two named types are conversion compatible 1171 | // if their literals are conversion 1172 | // compatible. 1173 | return t.Def.compat(t2.Def, conv) 1174 | } else { 1175 | // Two named types are compatible if their 1176 | // type names originate in the same type 1177 | // declaration. 1178 | return t == t2 1179 | } 1180 | } 1181 | // A named and an unnamed type are compatible if the 1182 | // respective type literals are compatible. 1183 | return o.compat(t.Def, conv) 1184 | } 1185 | 1186 | func (t *NamedType) lit() Type { return t.Def.lit() } 1187 | 1188 | func (t *NamedType) isBoolean() bool { return t.Def.isBoolean() } 1189 | 1190 | func (t *NamedType) isInteger() bool { return t.Def.isInteger() } 1191 | 1192 | func (t *NamedType) isFloat() bool { return t.Def.isFloat() } 1193 | 1194 | func (t *NamedType) isIdeal() bool { return false } 1195 | 1196 | func (t *NamedType) String() string { return t.Name } 1197 | 1198 | func (t *NamedType) Zero() Value { return t.Def.Zero() } 1199 | 1200 | /* 1201 | * Multi-valued type 1202 | */ 1203 | 1204 | // MultiType is a special type used for multi-valued expressions, akin 1205 | // to a tuple type. It's not generally accessible within the 1206 | // language. 1207 | type MultiType struct { 1208 | commonType 1209 | Elems []Type 1210 | } 1211 | 1212 | var multiTypes = newTypeArrayMap() 1213 | 1214 | func NewMultiType(elems []Type) *MultiType { 1215 | if t := multiTypes.Get(elems); t != nil { 1216 | return t.(*MultiType) 1217 | } 1218 | 1219 | t := &MultiType{commonType{}, elems} 1220 | multiTypes.Put(elems, t) 1221 | return t 1222 | } 1223 | 1224 | func (t *MultiType) compat(o Type, conv bool) bool { 1225 | t2, ok := o.lit().(*MultiType) 1226 | if !ok { 1227 | return false 1228 | } 1229 | if len(t.Elems) != len(t2.Elems) { 1230 | return false 1231 | } 1232 | for i := range t.Elems { 1233 | if !t.Elems[i].compat(t2.Elems[i], conv) { 1234 | return false 1235 | } 1236 | } 1237 | return true 1238 | } 1239 | 1240 | var EmptyType Type = NewMultiType([]Type{}) 1241 | 1242 | func (t *MultiType) lit() Type { return t } 1243 | 1244 | func (t *MultiType) String() string { 1245 | if len(t.Elems) == 0 { 1246 | return "" 1247 | } 1248 | return typeListString(t.Elems, nil) 1249 | } 1250 | 1251 | func (t *MultiType) Zero() Value { 1252 | res := make([]Value, len(t.Elems)) 1253 | for i, t := range t.Elems { 1254 | res[i] = t.Zero() 1255 | } 1256 | return multiV(res) 1257 | } 1258 | 1259 | /* 1260 | * Initialize the universe 1261 | */ 1262 | 1263 | func init() { 1264 | numer := big.NewInt(0xffffff) 1265 | numer.Lsh(numer, 127-23) 1266 | maxFloat32Val = new(big.Rat).SetInt(numer) 1267 | numer.SetInt64(0x1fffffffffffff) 1268 | numer.Lsh(numer, 1023-52) 1269 | maxFloat64Val = new(big.Rat).SetInt(numer) 1270 | minFloat32Val = new(big.Rat).Neg(maxFloat32Val) 1271 | minFloat64Val = new(big.Rat).Neg(maxFloat64Val) 1272 | 1273 | // To avoid portability issues all numeric types are distinct 1274 | // except byte, which is an alias for uint8. 1275 | 1276 | // Make byte an alias for the named type uint8. Type aliases 1277 | // are otherwise impossible in Go, so just hack it here. 1278 | universe.defs["byte"] = universe.defs["uint8"] 1279 | 1280 | // Built-in functions 1281 | universe.DefineConst("append", universePos, appendType, nil) 1282 | universe.DefineConst("cap", universePos, capType, nil) 1283 | universe.DefineConst("close", universePos, closeType, nil) 1284 | universe.DefineConst("closed", universePos, closedType, nil) 1285 | universe.DefineConst("copy", universePos, copyType, nil) 1286 | universe.DefineConst("len", universePos, lenType, nil) 1287 | universe.DefineConst("make", universePos, makeType, nil) 1288 | universe.DefineConst("new", universePos, newType, nil) 1289 | universe.DefineConst("panic", universePos, panicType, nil) 1290 | universe.DefineConst("print", universePos, printType, nil) 1291 | universe.DefineConst("println", universePos, printlnType, nil) 1292 | } 1293 | -------------------------------------------------------------------------------- /stmt.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 | // go/importer is only available in go1.6 and later 6 | // +build go1.6 7 | 8 | package eval 9 | 10 | import ( 11 | "go/ast" 12 | "go/build" 13 | "go/importer" 14 | "go/parser" 15 | "go/token" 16 | "go/types" 17 | "log" 18 | "math/big" 19 | "path/filepath" 20 | "strconv" 21 | ) 22 | 23 | const ( 24 | returnPC = ^uint(0) 25 | badPC = ^uint(1) 26 | ) 27 | 28 | // default importer of packages 29 | var g_importer types.Importer = importer.Default() 30 | 31 | 32 | /* 33 | * Statement compiler 34 | */ 35 | 36 | type stmtCompiler struct { 37 | *blockCompiler 38 | pos token.Pos 39 | // This statement's label, or nil if it is not labeled. 40 | stmtLabel *label 41 | } 42 | 43 | func (a *stmtCompiler) diag(format string, args ...interface{}) { 44 | a.diagAt(a.pos, format, args...) 45 | } 46 | 47 | /* 48 | * Flow checker 49 | */ 50 | 51 | type flowEnt struct { 52 | // Whether this flow entry is conditional. If true, flow can 53 | // continue to the next PC. 54 | cond bool 55 | // True if this will terminate flow (e.g., a return statement). 56 | // cond must be false and jumps must be nil if this is true. 57 | term bool 58 | // PC's that can be reached from this flow entry. 59 | jumps []*uint 60 | // Whether this flow entry has been visited by reachesEnd. 61 | visited bool 62 | } 63 | 64 | type flowBlock struct { 65 | // If this is a goto, the target label. 66 | target string 67 | // The inner-most block containing definitions. 68 | block *block 69 | // The numVars from each block leading to the root of the 70 | // scope, starting at block. 71 | numVars []int 72 | } 73 | 74 | type flowBuf struct { 75 | cb *codeBuf 76 | // ents is a map from PC's to flow entries. Any PC missing 77 | // from this map is assumed to reach only PC+1. 78 | ents map[uint]*flowEnt 79 | // gotos is a map from goto positions to information on the 80 | // block at the point of the goto. 81 | gotos map[token.Pos]*flowBlock 82 | // labels is a map from label name to information on the block 83 | // at the point of the label. labels are tracked by name, 84 | // since multiple labels at the same PC can have different 85 | // blocks. 86 | labels map[string]*flowBlock 87 | } 88 | 89 | func newFlowBuf(cb *codeBuf) *flowBuf { 90 | return &flowBuf{cb, make(map[uint]*flowEnt), make(map[token.Pos]*flowBlock), make(map[string]*flowBlock)} 91 | } 92 | 93 | // put creates a flow control point for the next PC in the code buffer. 94 | // This should be done before pushing the instruction into the code buffer. 95 | func (f *flowBuf) put(cond bool, term bool, jumps []*uint) { 96 | pc := f.cb.nextPC() 97 | if ent, ok := f.ents[pc]; ok { 98 | log.Panicf("Flow entry already exists at PC %d: %+v", pc, ent) 99 | } 100 | f.ents[pc] = &flowEnt{cond, term, jumps, false} 101 | } 102 | 103 | // putTerm creates a flow control point at the next PC that 104 | // unconditionally terminates execution. 105 | func (f *flowBuf) putTerm() { f.put(false, true, nil) } 106 | 107 | // put1 creates a flow control point at the next PC that jumps to one 108 | // PC and, if cond is true, can also continue to the PC following the 109 | // next PC. 110 | func (f *flowBuf) put1(cond bool, jumpPC *uint) { 111 | f.put(cond, false, []*uint{jumpPC}) 112 | } 113 | 114 | func newFlowBlock(target string, b *block) *flowBlock { 115 | // Find the inner-most block containing definitions 116 | for b.numVars == 0 && b.outer != nil && b.outer.scope == b.scope { 117 | b = b.outer 118 | } 119 | 120 | // Count parents leading to the root of the scope 121 | n := 0 122 | for bp := b; bp.scope == b.scope; bp = bp.outer { 123 | n++ 124 | } 125 | 126 | // Capture numVars from each block to the root of the scope 127 | numVars := make([]int, n) 128 | i := 0 129 | for bp := b; i < n; bp = bp.outer { 130 | numVars[i] = bp.numVars 131 | i++ 132 | } 133 | 134 | return &flowBlock{target, b, numVars} 135 | } 136 | 137 | // putGoto captures the block at a goto statement. This should be 138 | // called in addition to putting a flow control point. 139 | func (f *flowBuf) putGoto(pos token.Pos, target string, b *block) { 140 | f.gotos[pos] = newFlowBlock(target, b) 141 | } 142 | 143 | // putLabel captures the block at a label. 144 | func (f *flowBuf) putLabel(name string, b *block) { 145 | f.labels[name] = newFlowBlock("", b) 146 | } 147 | 148 | // reachesEnd returns true if the end of f's code buffer can be 149 | // reached from the given program counter. Error reporting is the 150 | // caller's responsibility. 151 | func (f *flowBuf) reachesEnd(pc uint) bool { 152 | endPC := f.cb.nextPC() 153 | if pc > endPC { 154 | log.Panicf("Reached bad PC %d past end PC %d", pc, endPC) 155 | } 156 | 157 | for ; pc < endPC; pc++ { 158 | ent, ok := f.ents[pc] 159 | if !ok { 160 | continue 161 | } 162 | 163 | if ent.visited { 164 | return false 165 | } 166 | ent.visited = true 167 | 168 | if ent.term { 169 | return false 170 | } 171 | 172 | // If anything can reach the end, we can reach the end 173 | // from pc. 174 | for _, j := range ent.jumps { 175 | if f.reachesEnd(*j) { 176 | return true 177 | } 178 | } 179 | // If the jump was conditional, we can reach the next 180 | // PC, so try reaching the end from it. 181 | if ent.cond { 182 | continue 183 | } 184 | return false 185 | } 186 | return true 187 | } 188 | 189 | // gotosObeyScopes returns true if no goto statement causes any 190 | // variables to come into scope that were not in scope at the point of 191 | // the goto. Reports any errors using the given compiler. 192 | func (f *flowBuf) gotosObeyScopes(a *compiler) { 193 | for pos, src := range f.gotos { 194 | tgt := f.labels[src.target] 195 | 196 | // The target block must be a parent of this block 197 | numVars := src.numVars 198 | b := src.block 199 | for len(numVars) > 0 && b != tgt.block { 200 | b = b.outer 201 | numVars = numVars[1:] 202 | } 203 | if b != tgt.block { 204 | // We jumped into a deeper block 205 | a.diagAt(pos, "goto causes variables to come into scope") 206 | return 207 | } 208 | 209 | // There must be no variables in the target block that 210 | // did not exist at the jump 211 | tgtNumVars := tgt.numVars 212 | for i := range numVars { 213 | if tgtNumVars[i] > numVars[i] { 214 | a.diagAt(pos, "goto causes variables to come into scope") 215 | return 216 | } 217 | } 218 | } 219 | } 220 | 221 | /* 222 | * Statement generation helpers 223 | */ 224 | 225 | func (a *stmtCompiler) defineVar(ident *ast.Ident, t Type) *Variable { 226 | v, prev := a.block.DefineVar(ident.Name, ident.Pos(), t) 227 | if prev != nil { 228 | if prev.Pos().IsValid() { 229 | a.diagAt(ident.Pos(), "variable %s redeclared in this block\n\tprevious declaration at %s", ident.Name, a.fset.Position(prev.Pos())) 230 | } else { 231 | a.diagAt(ident.Pos(), "variable %s redeclared in this block", ident.Name) 232 | } 233 | return nil 234 | } 235 | 236 | // Initialize the variable 237 | index := v.Index 238 | if v.Index >= 0 { 239 | a.push(func(v *Thread) { v.f.Vars[index] = t.Zero() }) 240 | } 241 | return v 242 | } 243 | 244 | func (a *stmtCompiler) definePkg(ident ast.Node, id, path string) *PkgIdent { 245 | v, prev := a.block.DefinePackage(id, path, ident.Pos()) 246 | if prev != nil { 247 | a.diagAt(ident.Pos(), "%s redeclared as imported package name\n\tprevious declaration at %s", id, a.fset.Position(prev.Pos())) 248 | return nil 249 | } 250 | return v 251 | } 252 | 253 | // TODO(austin) Move doAssign to here 254 | 255 | /* 256 | * Statement compiler 257 | */ 258 | 259 | func (a *stmtCompiler) compile(s ast.Stmt) { 260 | if a.block.inner != nil { 261 | log.Panic("Child scope still entered") 262 | } 263 | 264 | notimpl := false 265 | switch s := s.(type) { 266 | case *ast.BadStmt: 267 | // Error already reported by parser. 268 | a.silentErrors++ 269 | 270 | case *ast.DeclStmt: 271 | a.compileDeclStmt(s) 272 | 273 | case *ast.EmptyStmt: 274 | // Do nothing. 275 | 276 | case *ast.LabeledStmt: 277 | a.compileLabeledStmt(s) 278 | 279 | case *ast.ExprStmt: 280 | a.compileExprStmt(s) 281 | 282 | case *ast.IncDecStmt: 283 | a.compileIncDecStmt(s) 284 | 285 | case *ast.AssignStmt: 286 | a.compileAssignStmt(s) 287 | 288 | case *ast.GoStmt: 289 | notimpl = true 290 | 291 | case *ast.DeferStmt: 292 | notimpl = true 293 | 294 | case *ast.ReturnStmt: 295 | a.compileReturnStmt(s) 296 | 297 | case *ast.BranchStmt: 298 | a.compileBranchStmt(s) 299 | 300 | case *ast.BlockStmt: 301 | a.compileBlockStmt(s) 302 | 303 | case *ast.IfStmt: 304 | a.compileIfStmt(s) 305 | 306 | case *ast.CaseClause: 307 | a.diag("case clause outside switch") 308 | 309 | case *ast.SwitchStmt: 310 | a.compileSwitchStmt(s) 311 | 312 | case *ast.TypeSwitchStmt: 313 | notimpl = true 314 | 315 | case *ast.CommClause: 316 | notimpl = true 317 | 318 | case *ast.SelectStmt: 319 | notimpl = true 320 | 321 | case *ast.ForStmt: 322 | a.compileForStmt(s) 323 | 324 | case *ast.RangeStmt: 325 | notimpl = true 326 | 327 | default: 328 | log.Panicf("unexpected ast node type %T", s) 329 | } 330 | 331 | if notimpl { 332 | a.diag("%T statement node not implemented", s) 333 | } 334 | 335 | if a.block.inner != nil { 336 | log.Panic("Forgot to exit child scope") 337 | } 338 | } 339 | 340 | func (a *stmtCompiler) compileDeclStmt(s *ast.DeclStmt) { 341 | switch decl := s.Decl.(type) { 342 | case *ast.BadDecl: 343 | // Do nothing. Already reported by parser. 344 | a.silentErrors++ 345 | 346 | case *ast.FuncDecl: 347 | if !a.block.global { 348 | log.Panic("FuncDecl at statement level") 349 | } 350 | 351 | case *ast.GenDecl: 352 | if decl.Tok == token.IMPORT && !a.block.global { 353 | log.Panic("import at statement level") 354 | } 355 | 356 | default: 357 | log.Panicf("Unexpected Decl type %T", s.Decl) 358 | } 359 | a.compileDecl(s.Decl) 360 | } 361 | 362 | func (a *stmtCompiler) compileVarDecl(decl *ast.GenDecl) { 363 | for _, spec := range decl.Specs { 364 | spec := spec.(*ast.ValueSpec) 365 | if spec.Values == nil { 366 | // Declaration without assignment 367 | if spec.Type == nil { 368 | // Parser should have caught 369 | log.Panic("Type and Values nil") 370 | } 371 | t := a.compileType(a.block, spec.Type) 372 | // Define placeholders only if type compile succeeded 373 | if t != nil { 374 | for _, n := range spec.Names { 375 | a.defineVar(n, t) 376 | } 377 | } 378 | } else { 379 | // Declaration with assignment 380 | lhs := make([]ast.Expr, len(spec.Names)) 381 | for i, n := range spec.Names { 382 | lhs[i] = n 383 | } 384 | a.doAssign(lhs, spec.Values, decl.Tok, spec.Type) 385 | } 386 | } 387 | } 388 | 389 | func (a *stmtCompiler) compileImportDecl(decl *ast.GenDecl) { 390 | for _, spec := range decl.Specs { 391 | spec := spec.(*ast.ImportSpec) 392 | path, _ := strconv.Unquote(spec.Path.Value) 393 | n := path 394 | if spec.Name != nil { 395 | n = spec.Name.Name 396 | } 397 | 398 | pkg, err := srcImporter(g_importer, path) 399 | if err != nil { 400 | a.diagAt(spec.Pos(), "could not import package [%s]: %v", 401 | path, err) 402 | continue 403 | } 404 | if spec.Name != nil { 405 | a.definePkg(spec.Name, n, path) 406 | } else { 407 | n = pkg.Name() 408 | a.definePkg(spec.Path, n, path) 409 | } 410 | } 411 | } 412 | 413 | func (a *stmtCompiler) compileConstDecl(decl *ast.GenDecl) { 414 | log.Panicf("%v not implemented", decl.Tok) 415 | } 416 | 417 | func (a *stmtCompiler) compileDecl(decl ast.Decl) { 418 | switch d := decl.(type) { 419 | case *ast.BadDecl: 420 | // Do nothing. Already reported by parser. 421 | a.silentErrors++ 422 | 423 | case *ast.FuncDecl: 424 | //fmt.Printf("...compileDecl(%s)...\n", d.Name.Name) 425 | decl := a.compileFuncType(a.block, d.Type) 426 | if decl == nil { 427 | return 428 | } 429 | // Declare and initialize v before compiling func 430 | // so that body can refer to itself. 431 | c, prev := a.block.DefineConst(d.Name.Name, a.pos, decl.Type, decl.Type.Zero()) 432 | if prev != nil { 433 | pos := prev.Pos() 434 | if pos.IsValid() { 435 | a.diagAt(d.Name.Pos(), "identifier %s redeclared in this block\n\tprevious declaration at %s", d.Name.Name, a.fset.Position(pos)) 436 | } else { 437 | a.diagAt(d.Name.Pos(), "identifier %s redeclared in this block", d.Name.Name) 438 | } 439 | } 440 | fn := a.compileFunc(a.block, decl, d.Body) 441 | if c == nil || fn == nil { 442 | //when compile error, remove func identifier from the table 443 | a.block.undefine(d.Name.Name) 444 | return 445 | } 446 | var zeroThread Thread 447 | c.Value.(FuncValue).Set(nil, fn(&zeroThread)) 448 | 449 | case *ast.GenDecl: 450 | switch d.Tok { 451 | case token.IMPORT: 452 | a.compileImportDecl(d) 453 | case token.CONST: 454 | a.compileConstDecl(d) 455 | case token.TYPE: 456 | name := d.Specs[0].(*ast.TypeSpec).Name.Name 457 | _, level, dup := a.block.Lookup(name) 458 | if dup != nil && level == 0 { 459 | a.diag( 460 | "%s redeclared in this block\n\tprevious declaration at %s", 461 | name, 462 | a.fset.Position(dup.Pos()), 463 | ) 464 | return 465 | } 466 | ok := a.compileTypeDecl(a.block, d) 467 | if !ok { 468 | a.block.undefine(name) 469 | } 470 | case token.VAR: 471 | a.compileVarDecl(d) 472 | default: 473 | log.Panicf("unknown ast.GenDecl token: %v\n", d.Tok) 474 | } 475 | 476 | default: 477 | log.Panicf("Unexpected Decl type %T", decl) 478 | } 479 | 480 | } 481 | 482 | func (a *stmtCompiler) compileLabeledStmt(s *ast.LabeledStmt) { 483 | // Define label 484 | l, ok := a.labels[s.Label.Name] 485 | if ok { 486 | if l.resolved.IsValid() { 487 | a.diag("label %s redeclared in this block\n\tprevious declaration at %s", s.Label.Name, a.fset.Position(l.resolved)) 488 | } 489 | } else { 490 | pc := badPC 491 | l = &label{name: s.Label.Name, gotoPC: &pc} 492 | a.labels[l.name] = l 493 | } 494 | l.desc = "regular label" 495 | l.resolved = s.Pos() 496 | 497 | // Set goto PC 498 | *l.gotoPC = a.nextPC() 499 | 500 | // Define flow entry so we can check for jumps over declarations. 501 | a.flow.putLabel(l.name, a.block) 502 | 503 | // Compile the statement. Reuse our stmtCompiler for simplicity. 504 | sc := &stmtCompiler{a.blockCompiler, s.Stmt.Pos(), l} 505 | sc.compile(s.Stmt) 506 | } 507 | 508 | func (a *stmtCompiler) compileExprStmt(s *ast.ExprStmt) { 509 | bc := a.enterChild() 510 | defer bc.exit() 511 | 512 | e := a.compileExpr(bc.block, false, s.X) 513 | if e == nil { 514 | return 515 | } 516 | 517 | if e.exec == nil { 518 | a.diag("%s cannot be used as expression statement", e.desc) 519 | return 520 | } 521 | 522 | a.push(e.exec) 523 | } 524 | 525 | func (a *stmtCompiler) compileIncDecStmt(s *ast.IncDecStmt) { 526 | // Create temporary block for extractEffect 527 | bc := a.enterChild() 528 | defer bc.exit() 529 | 530 | l := a.compileExpr(bc.block, false, s.X) 531 | if l == nil { 532 | return 533 | } 534 | 535 | if l.evalAddr == nil { 536 | l.diag("cannot assign to %s", l.desc) 537 | return 538 | } 539 | if !(l.t.isInteger() || l.t.isFloat()) { 540 | l.diagOpType(s.Tok, l.t) 541 | return 542 | } 543 | 544 | var op token.Token 545 | var desc string 546 | switch s.Tok { 547 | case token.INC: 548 | op = token.ADD 549 | desc = "increment statement" 550 | case token.DEC: 551 | op = token.SUB 552 | desc = "decrement statement" 553 | default: 554 | log.Panicf("Unexpected IncDec token %v", s.Tok) 555 | } 556 | 557 | effect, l := l.extractEffect(bc.block, desc) 558 | 559 | one := l.newExpr(IdealIntType, "constant") 560 | one.pos = s.Pos() 561 | one.eval = func() *big.Int { return big.NewInt(1) } 562 | 563 | binop := l.compileBinaryExpr(op, l, one) 564 | if binop == nil { 565 | return 566 | } 567 | 568 | assign := a.compileAssign(s.Pos(), bc.block, l.t, []*expr{binop}, "", "") 569 | if assign == nil { 570 | log.Panicf("compileAssign type check failed") 571 | } 572 | 573 | lf := l.evalAddr 574 | a.push(func(v *Thread) { 575 | effect(v) 576 | assign(lf(v), v) 577 | }) 578 | } 579 | 580 | func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token, declTypeExpr ast.Expr) { 581 | nerr := a.numError() 582 | 583 | // Compile right side first so we have the types when 584 | // compiling the left side and so we don't see definitions 585 | // made on the left side. 586 | rs := make([]*expr, len(rhs)) 587 | for i, re := range rhs { 588 | rs[i] = a.compileExpr(a.block, false, re) 589 | } 590 | 591 | // Check if compileExpr failed on any expr 592 | for _, r := range rs { 593 | if r == nil { 594 | return 595 | } 596 | } 597 | 598 | errOp := "assignment" 599 | if tok == token.DEFINE || tok == token.VAR { 600 | errOp = "declaration" 601 | } 602 | ac, ok := a.checkAssign(a.pos, rs, errOp, "value") 603 | ac.allowMapForms(len(lhs)) 604 | 605 | // If this is a definition and the LHS is too big, we won't be 606 | // able to produce the usual error message because we can't 607 | // begin to infer the types of the LHS. 608 | if (tok == token.DEFINE || tok == token.VAR) && len(lhs) > len(ac.rmt.Elems) { 609 | a.diag("not enough values for definition") 610 | } 611 | 612 | // Compile left type if there is one 613 | var declType Type 614 | if declTypeExpr != nil { 615 | declType = a.compileType(a.block, declTypeExpr) 616 | } 617 | 618 | // Compile left side 619 | ls := make([]*expr, len(lhs)) 620 | nDefs := 0 621 | for i, le := range lhs { 622 | // If this is a definition, get the identifier and its type 623 | var ident *ast.Ident 624 | var lt Type 625 | switch tok { 626 | case token.DEFINE: 627 | // Check that it's an identifier 628 | ident, ok = le.(*ast.Ident) 629 | if !ok { 630 | a.diagAt(le.Pos(), "left side of := must be a name") 631 | // Suppress new definitions errors 632 | nDefs++ 633 | continue 634 | } 635 | 636 | // Is this simply an assignment? 637 | if _, ok := a.block.defs[ident.Name]; ok { 638 | ident = nil 639 | break 640 | } 641 | nDefs++ 642 | 643 | case token.VAR: 644 | ident = le.(*ast.Ident) 645 | } 646 | 647 | // If it's a definition, get or infer its type. 648 | if ident != nil { 649 | // Compute the identifier's type from the RHS 650 | // type. We use the computed MultiType so we 651 | // don't have to worry about unpacking. 652 | switch { 653 | case declTypeExpr != nil: 654 | // We have a declaration type, use it. 655 | // If declType is nil, we gave an 656 | // error when we compiled it. 657 | lt = declType 658 | 659 | case i >= len(ac.rmt.Elems): 660 | // Define a placeholder. We already 661 | // gave the "not enough" error above. 662 | lt = nil 663 | 664 | case ac.rmt.Elems[i] == nil: 665 | // We gave the error when we compiled 666 | // the RHS. 667 | lt = nil 668 | 669 | case ac.rmt.Elems[i].isIdeal(): 670 | // If the type is absent and the 671 | // corresponding expression is a 672 | // constant expression of ideal 673 | // integer or ideal float type, the 674 | // type of the declared variable is 675 | // int or float respectively. 676 | switch { 677 | case ac.rmt.Elems[i].isInteger(): 678 | lt = IntType 679 | case ac.rmt.Elems[i].isFloat(): 680 | lt = Float64Type 681 | default: 682 | log.Panicf("unexpected ideal type %v", rs[i].t) 683 | } 684 | 685 | default: 686 | lt = ac.rmt.Elems[i] 687 | } 688 | } 689 | 690 | // If it's a definition, define the identifier 691 | if ident != nil { 692 | if a.defineVar(ident, lt) == nil { 693 | continue 694 | } 695 | } 696 | 697 | // Compile LHS 698 | ls[i] = a.compileExpr(a.block, false, le) 699 | if ls[i] == nil { 700 | continue 701 | } 702 | 703 | if ls[i].evalMapValue != nil { 704 | // Map indexes are not generally addressable, 705 | // but they are assignable. 706 | // 707 | // TODO(austin) Now that the expression 708 | // compiler uses semantic values, this might 709 | // be easier to implement as a function call. 710 | sub := ls[i] 711 | ls[i] = ls[i].newExpr(sub.t, sub.desc) 712 | ls[i].evalMapValue = sub.evalMapValue 713 | mvf := sub.evalMapValue 714 | et := sub.t 715 | ls[i].evalAddr = func(t *Thread) Value { 716 | m, k := mvf(t) 717 | e := m.Elem(t, k) 718 | if e == nil { 719 | e = et.Zero() 720 | m.SetElem(t, k, e) 721 | } 722 | return e 723 | } 724 | } else if ls[i].evalAddr == nil { 725 | ls[i].diag("cannot assign to %s", ls[i].desc) 726 | continue 727 | } 728 | } 729 | 730 | // A short variable declaration may redeclare variables 731 | // provided they were originally declared in the same block 732 | // with the same type, and at least one of the variables is 733 | // new. 734 | if tok == token.DEFINE && nDefs == 0 { 735 | a.diag("at least one new variable must be declared") 736 | return 737 | } 738 | 739 | // If there have been errors, our arrays are full of nil's so 740 | // get out of here now. 741 | if nerr != a.numError() { 742 | return 743 | } 744 | 745 | // Check for 'a[x] = r, ok' 746 | if len(ls) == 1 && len(rs) == 2 && ls[0].evalMapValue != nil { 747 | a.diag("a[x] = r, ok form not implemented") 748 | return 749 | } 750 | 751 | // Create assigner 752 | var lt Type 753 | n := len(lhs) 754 | if n == 1 { 755 | lt = ls[0].t 756 | } else { 757 | lts := make([]Type, len(ls)) 758 | for i, l := range ls { 759 | if l != nil { 760 | lts[i] = l.t 761 | } 762 | } 763 | lt = NewMultiType(lts) 764 | } 765 | bc := a.enterChild() 766 | defer bc.exit() 767 | assign := ac.compile(bc.block, lt) 768 | if assign == nil { 769 | return 770 | } 771 | 772 | // Compile 773 | if n == 1 { 774 | // Don't need temporaries and can avoid []Value. 775 | lf := ls[0].evalAddr 776 | a.push(func(t *Thread) { assign(lf(t), t) }) 777 | } else if tok == token.VAR || (tok == token.DEFINE && nDefs == n) { 778 | // Don't need temporaries 779 | lfs := make([]func(*Thread) Value, n) 780 | for i, l := range ls { 781 | lfs[i] = l.evalAddr 782 | } 783 | a.push(func(t *Thread) { 784 | dest := make([]Value, n) 785 | for i, lf := range lfs { 786 | dest[i] = lf(t) 787 | } 788 | assign(multiV(dest), t) 789 | }) 790 | } else { 791 | // Need temporaries 792 | lmt := lt.(*MultiType) 793 | lfs := make([]func(*Thread) Value, n) 794 | for i, l := range ls { 795 | lfs[i] = l.evalAddr 796 | } 797 | a.push(func(t *Thread) { 798 | temp := lmt.Zero().(multiV) 799 | assign(temp, t) 800 | // Copy to destination 801 | for i := 0; i < n; i++ { 802 | // TODO(austin) Need to evaluate LHS 803 | // before RHS 804 | lfs[i](t).Assign(t, temp[i]) 805 | } 806 | }) 807 | } 808 | } 809 | 810 | var assignOpToOp = map[token.Token]token.Token{ 811 | token.ADD_ASSIGN: token.ADD, 812 | token.SUB_ASSIGN: token.SUB, 813 | token.MUL_ASSIGN: token.MUL, 814 | token.QUO_ASSIGN: token.QUO, 815 | token.REM_ASSIGN: token.REM, 816 | 817 | token.AND_ASSIGN: token.AND, 818 | token.OR_ASSIGN: token.OR, 819 | token.XOR_ASSIGN: token.XOR, 820 | token.SHL_ASSIGN: token.SHL, 821 | token.SHR_ASSIGN: token.SHR, 822 | token.AND_NOT_ASSIGN: token.AND_NOT, 823 | } 824 | 825 | func (a *stmtCompiler) doAssignOp(s *ast.AssignStmt) { 826 | if len(s.Lhs) != 1 || len(s.Rhs) != 1 { 827 | a.diag("tuple assignment cannot be combined with an arithmetic operation") 828 | return 829 | } 830 | 831 | // Create temporary block for extractEffect 832 | bc := a.enterChild() 833 | defer bc.exit() 834 | 835 | l := a.compileExpr(bc.block, false, s.Lhs[0]) 836 | r := a.compileExpr(bc.block, false, s.Rhs[0]) 837 | if l == nil || r == nil { 838 | return 839 | } 840 | 841 | if l.evalAddr == nil { 842 | l.diag("cannot assign to %s", l.desc) 843 | return 844 | } 845 | 846 | effect, l := l.extractEffect(bc.block, "operator-assignment") 847 | 848 | binop := r.compileBinaryExpr(assignOpToOp[s.Tok], l, r) 849 | if binop == nil { 850 | return 851 | } 852 | 853 | assign := a.compileAssign(s.Pos(), bc.block, l.t, []*expr{binop}, "assignment", "value") 854 | if assign == nil { 855 | log.Panicf("compileAssign type check failed") 856 | } 857 | 858 | lf := l.evalAddr 859 | a.push(func(t *Thread) { 860 | effect(t) 861 | assign(lf(t), t) 862 | }) 863 | } 864 | 865 | func (a *stmtCompiler) compileAssignStmt(s *ast.AssignStmt) { 866 | switch s.Tok { 867 | case token.ASSIGN, token.DEFINE: 868 | a.doAssign(s.Lhs, s.Rhs, s.Tok, nil) 869 | 870 | default: 871 | a.doAssignOp(s) 872 | } 873 | } 874 | 875 | func (a *stmtCompiler) compileReturnStmt(s *ast.ReturnStmt) { 876 | if a.fnType == nil { 877 | a.diag("cannot return at the top level") 878 | return 879 | } 880 | 881 | if len(s.Results) == 0 && (len(a.fnType.Out) == 0 || a.outVarsNamed) { 882 | // Simple case. Simply exit from the function. 883 | a.flow.putTerm() 884 | a.push(func(v *Thread) { v.pc = returnPC }) 885 | return 886 | } 887 | 888 | bc := a.enterChild() 889 | defer bc.exit() 890 | 891 | // Compile expressions 892 | bad := false 893 | rs := make([]*expr, len(s.Results)) 894 | for i, re := range s.Results { 895 | rs[i] = a.compileExpr(bc.block, false, re) 896 | if rs[i] == nil { 897 | bad = true 898 | } 899 | } 900 | if bad { 901 | return 902 | } 903 | 904 | // Create assigner 905 | 906 | // However, if the expression list in the "return" statement 907 | // is a single call to a multi-valued function, the values 908 | // returned from the called function will be returned from 909 | // this one. 910 | assign := a.compileAssign(s.Pos(), bc.block, NewMultiType(a.fnType.Out), rs, "return", "value") 911 | 912 | // XXX(Spec) "The result types of the current function and the 913 | // called function must match." Match is fuzzy. It should 914 | // say that they must be assignment compatible. 915 | 916 | // Compile 917 | start := len(a.fnType.In) 918 | nout := len(a.fnType.Out) 919 | a.flow.putTerm() 920 | a.push(func(t *Thread) { 921 | assign(multiV(t.f.Vars[start:start+nout]), t) 922 | t.pc = returnPC 923 | }) 924 | } 925 | 926 | func (a *stmtCompiler) findLexicalLabel(name *ast.Ident, pred func(*label) bool, errOp, errCtx string) *label { 927 | bc := a.blockCompiler 928 | for ; bc != nil; bc = bc.parent { 929 | if bc.label == nil { 930 | continue 931 | } 932 | l := bc.label 933 | if name == nil && pred(l) { 934 | return l 935 | } 936 | if name != nil && l.name == name.Name { 937 | if !pred(l) { 938 | a.diag("cannot %s to %s %s", errOp, l.desc, l.name) 939 | return nil 940 | } 941 | return l 942 | } 943 | } 944 | if name == nil { 945 | a.diag("%s outside %s", errOp, errCtx) 946 | } else { 947 | a.diag("%s label %s not defined", errOp, name.Name) 948 | } 949 | return nil 950 | } 951 | 952 | func (a *stmtCompiler) compileBranchStmt(s *ast.BranchStmt) { 953 | var pc *uint 954 | 955 | switch s.Tok { 956 | case token.BREAK: 957 | l := a.findLexicalLabel(s.Label, func(l *label) bool { return l.breakPC != nil }, "break", "for loop, switch, or select") 958 | if l == nil { 959 | return 960 | } 961 | pc = l.breakPC 962 | 963 | case token.CONTINUE: 964 | l := a.findLexicalLabel(s.Label, func(l *label) bool { return l.continuePC != nil }, "continue", "for loop") 965 | if l == nil { 966 | return 967 | } 968 | pc = l.continuePC 969 | 970 | case token.GOTO: 971 | l, ok := a.labels[s.Label.Name] 972 | if !ok { 973 | pc := badPC 974 | l = &label{name: s.Label.Name, desc: "unresolved label", gotoPC: &pc, used: s.Pos()} 975 | a.labels[l.name] = l 976 | } 977 | 978 | pc = l.gotoPC 979 | a.flow.putGoto(s.Pos(), l.name, a.block) 980 | 981 | case token.FALLTHROUGH: 982 | a.diag("fallthrough outside switch") 983 | return 984 | 985 | default: 986 | log.Panicf("Unexpected branch token %v", s.Tok) 987 | } 988 | 989 | a.flow.put1(false, pc) 990 | a.push(func(v *Thread) { v.pc = *pc }) 991 | } 992 | 993 | func (a *stmtCompiler) compileBlockStmt(s *ast.BlockStmt) { 994 | bc := a.enterChild() 995 | bc.compileStmts(s) 996 | bc.exit() 997 | } 998 | 999 | func (a *stmtCompiler) compileIfStmt(s *ast.IfStmt) { 1000 | // The scope of any variables declared by [the init] statement 1001 | // extends to the end of the "if" statement and the variables 1002 | // are initialized once before the statement is entered. 1003 | // 1004 | // XXX(Spec) What this really wants to say is that there's an 1005 | // implicit scope wrapping every if, for, and switch 1006 | // statement. This is subtly different from what it actually 1007 | // says when there's a non-block else clause, because that 1008 | // else claus has to execute in a scope that is *not* the 1009 | // surrounding scope. 1010 | bc := a.enterChild() 1011 | defer bc.exit() 1012 | 1013 | // Compile init statement, if any 1014 | if s.Init != nil { 1015 | bc.compileStmt(s.Init) 1016 | } 1017 | 1018 | elsePC := badPC 1019 | endPC := badPC 1020 | 1021 | // Compile condition, if any. If there is no condition, we 1022 | // fall through to the body. 1023 | if s.Cond != nil { 1024 | e := bc.compileExpr(bc.block, false, s.Cond) 1025 | switch { 1026 | case e == nil: 1027 | // Error reported by compileExpr 1028 | case !e.t.isBoolean(): 1029 | e.diag("'if' condition must be boolean\n\t%v", e.t) 1030 | default: 1031 | eval := e.asBool() 1032 | a.flow.put1(true, &elsePC) 1033 | a.push(func(t *Thread) { 1034 | if !eval(t) { 1035 | t.pc = elsePC 1036 | } 1037 | }) 1038 | } 1039 | } 1040 | 1041 | // Compile body 1042 | body := bc.enterChild() 1043 | body.compileStmts(s.Body) 1044 | body.exit() 1045 | 1046 | // Compile else 1047 | if s.Else != nil { 1048 | // Skip over else if we executed the body 1049 | a.flow.put1(false, &endPC) 1050 | a.push(func(v *Thread) { v.pc = endPC }) 1051 | elsePC = a.nextPC() 1052 | bc.compileStmt(s.Else) 1053 | } else { 1054 | elsePC = a.nextPC() 1055 | } 1056 | endPC = a.nextPC() 1057 | } 1058 | 1059 | func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) { 1060 | // Create implicit scope around switch 1061 | bc := a.enterChild() 1062 | defer bc.exit() 1063 | 1064 | // Compile init statement, if any 1065 | if s.Init != nil { 1066 | bc.compileStmt(s.Init) 1067 | } 1068 | 1069 | // Compile condition, if any, and extract its effects 1070 | var cond *expr 1071 | condbc := bc.enterChild() 1072 | if s.Tag != nil { 1073 | e := condbc.compileExpr(condbc.block, false, s.Tag) 1074 | if e != nil { 1075 | var effect func(*Thread) 1076 | effect, cond = e.extractEffect(condbc.block, "switch") 1077 | a.push(effect) 1078 | } 1079 | } 1080 | 1081 | // Count cases 1082 | ncases := 0 1083 | hasDefault := false 1084 | for _, c := range s.Body.List { 1085 | clause, ok := c.(*ast.CaseClause) 1086 | if !ok { 1087 | a.diagAt(clause.Pos(), "switch statement must contain case clauses") 1088 | continue 1089 | } 1090 | if clause.List == nil { 1091 | if hasDefault { 1092 | a.diagAt(clause.Pos(), "switch statement contains more than one default case") 1093 | } 1094 | hasDefault = true 1095 | } else { 1096 | ncases += len(clause.List) 1097 | } 1098 | } 1099 | 1100 | // Compile case expressions 1101 | cases := make([]func(*Thread) bool, ncases) 1102 | i := 0 1103 | for _, c := range s.Body.List { 1104 | clause, ok := c.(*ast.CaseClause) 1105 | if !ok { 1106 | continue 1107 | } 1108 | for _, v := range clause.List { 1109 | e := condbc.compileExpr(condbc.block, false, v) 1110 | switch { 1111 | case e == nil: 1112 | // Error reported by compileExpr 1113 | case cond == nil && !e.t.isBoolean(): 1114 | a.diagAt(v.Pos(), "'case' condition must be boolean") 1115 | case cond == nil: 1116 | cases[i] = e.asBool() 1117 | case cond != nil: 1118 | // Create comparison 1119 | // TOOD(austin) This produces bad error messages 1120 | compare := e.compileBinaryExpr(token.EQL, cond, e) 1121 | if compare != nil { 1122 | cases[i] = compare.asBool() 1123 | } 1124 | } 1125 | i++ 1126 | } 1127 | } 1128 | 1129 | // Emit condition 1130 | casePCs := make([]*uint, ncases+1) 1131 | endPC := badPC 1132 | 1133 | a.flow.put(false, false, casePCs) 1134 | a.push(func(t *Thread) { 1135 | for i, c := range cases { 1136 | if c(t) { 1137 | t.pc = *casePCs[i] 1138 | return 1139 | } 1140 | } 1141 | t.pc = *casePCs[ncases] 1142 | }) 1143 | condbc.exit() 1144 | 1145 | // Compile cases 1146 | i = 0 1147 | for _, c := range s.Body.List { 1148 | clause, ok := c.(*ast.CaseClause) 1149 | if !ok { 1150 | continue 1151 | } 1152 | 1153 | // Save jump PC's 1154 | pc := a.nextPC() 1155 | if clause.List != nil { 1156 | for _ = range clause.List { 1157 | casePCs[i] = &pc 1158 | i++ 1159 | } 1160 | } else { 1161 | // Default clause 1162 | casePCs[ncases] = &pc 1163 | } 1164 | 1165 | // Compile body 1166 | fall := false 1167 | for j, s := range clause.Body { 1168 | if br, ok := s.(*ast.BranchStmt); ok && br.Tok == token.FALLTHROUGH { 1169 | // println("Found fallthrough"); 1170 | // It may be used only as the final 1171 | // non-empty statement in a case or 1172 | // default clause in an expression 1173 | // "switch" statement. 1174 | for _, s2 := range clause.Body[j+1:] { 1175 | // XXX(Spec) 6g also considers 1176 | // empty blocks to be empty 1177 | // statements. 1178 | if _, ok := s2.(*ast.EmptyStmt); !ok { 1179 | a.diagAt(s.Pos(), "fallthrough statement must be final statement in case") 1180 | break 1181 | } 1182 | } 1183 | fall = true 1184 | } else { 1185 | bc.compileStmt(s) 1186 | } 1187 | } 1188 | // Jump out of switch, unless there was a fallthrough 1189 | if !fall { 1190 | a.flow.put1(false, &endPC) 1191 | a.push(func(v *Thread) { v.pc = endPC }) 1192 | } 1193 | } 1194 | 1195 | // Get end PC 1196 | endPC = a.nextPC() 1197 | if !hasDefault { 1198 | casePCs[ncases] = &endPC 1199 | } 1200 | } 1201 | 1202 | func (a *stmtCompiler) compileForStmt(s *ast.ForStmt) { 1203 | // Wrap the entire for in a block. 1204 | bc := a.enterChild() 1205 | defer bc.exit() 1206 | 1207 | // Compile init statement, if any 1208 | if s.Init != nil { 1209 | bc.compileStmt(s.Init) 1210 | } 1211 | 1212 | bodyPC := badPC 1213 | postPC := badPC 1214 | checkPC := badPC 1215 | endPC := badPC 1216 | 1217 | // Jump to condition check. We generate slightly less code by 1218 | // placing the condition check after the body. 1219 | a.flow.put1(false, &checkPC) 1220 | a.push(func(v *Thread) { v.pc = checkPC }) 1221 | 1222 | // Compile body 1223 | bodyPC = a.nextPC() 1224 | body := bc.enterChild() 1225 | if a.stmtLabel != nil { 1226 | body.label = a.stmtLabel 1227 | } else { 1228 | body.label = &label{resolved: s.Pos()} 1229 | } 1230 | body.label.desc = "for loop" 1231 | body.label.breakPC = &endPC 1232 | body.label.continuePC = &postPC 1233 | body.compileStmts(s.Body) 1234 | body.exit() 1235 | 1236 | // Compile post, if any 1237 | postPC = a.nextPC() 1238 | if s.Post != nil { 1239 | // TODO(austin) Does the parser disallow short 1240 | // declarations in s.Post? 1241 | bc.compileStmt(s.Post) 1242 | } 1243 | 1244 | // Compile condition check, if any 1245 | checkPC = a.nextPC() 1246 | if s.Cond == nil { 1247 | // If the condition is absent, it is equivalent to true. 1248 | a.flow.put1(false, &bodyPC) 1249 | a.push(func(v *Thread) { v.pc = bodyPC }) 1250 | } else { 1251 | e := bc.compileExpr(bc.block, false, s.Cond) 1252 | switch { 1253 | case e == nil: 1254 | // Error reported by compileExpr 1255 | case !e.t.isBoolean(): 1256 | a.diag("'for' condition must be boolean\n\t%v", e.t) 1257 | default: 1258 | eval := e.asBool() 1259 | a.flow.put1(true, &bodyPC) 1260 | a.push(func(t *Thread) { 1261 | if eval(t) { 1262 | t.pc = bodyPC 1263 | } 1264 | }) 1265 | } 1266 | } 1267 | 1268 | endPC = a.nextPC() 1269 | } 1270 | 1271 | /* 1272 | * Block compiler 1273 | */ 1274 | 1275 | func (a *blockCompiler) compileStmt(s ast.Stmt) { 1276 | sc := &stmtCompiler{a, s.Pos(), nil} 1277 | sc.compile(s) 1278 | } 1279 | 1280 | func (a *blockCompiler) compileStmts(block *ast.BlockStmt) { 1281 | if block == nil || block.List == nil { 1282 | return 1283 | } 1284 | 1285 | for _, sub := range block.List { 1286 | a.compileStmt(sub) 1287 | } 1288 | } 1289 | 1290 | func (a *blockCompiler) enterChild() *blockCompiler { 1291 | block := a.block.enterChild() 1292 | return &blockCompiler{ 1293 | funcCompiler: a.funcCompiler, 1294 | block: block, 1295 | parent: a, 1296 | } 1297 | } 1298 | 1299 | func (a *blockCompiler) exit() { a.block.exit() } 1300 | 1301 | /* 1302 | * Function compiler 1303 | */ 1304 | 1305 | func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) func(*Thread) Func { 1306 | // Create body scope 1307 | // 1308 | // The scope of a parameter or result is the body of the 1309 | // corresponding function. 1310 | bodyScope := b.ChildScope() 1311 | defer bodyScope.exit() 1312 | for i, t := range decl.Type.In { 1313 | if decl.InNames[i] != nil { 1314 | bodyScope.DefineVar(decl.InNames[i].Name, decl.InNames[i].Pos(), t) 1315 | } else { 1316 | bodyScope.DefineTemp(t) 1317 | } 1318 | } 1319 | for i, t := range decl.Type.Out { 1320 | if decl.OutNames[i] != nil { 1321 | bodyScope.DefineVar(decl.OutNames[i].Name, decl.OutNames[i].Pos(), t) 1322 | } else { 1323 | bodyScope.DefineTemp(t) 1324 | } 1325 | } 1326 | 1327 | // Create block context 1328 | cb := newCodeBuf() 1329 | fc := &funcCompiler{ 1330 | compiler: a, 1331 | fnType: decl.Type, 1332 | outVarsNamed: len(decl.OutNames) > 0 && decl.OutNames[0] != nil, 1333 | codeBuf: cb, 1334 | flow: newFlowBuf(cb), 1335 | labels: make(map[string]*label), 1336 | } 1337 | bc := &blockCompiler{ 1338 | funcCompiler: fc, 1339 | block: bodyScope.block, 1340 | } 1341 | 1342 | // Compile body 1343 | nerr := a.numError() 1344 | bc.compileStmts(body) 1345 | fc.checkLabels() 1346 | if nerr != a.numError() { 1347 | return nil 1348 | } 1349 | 1350 | // Check that the body returned if necessary. We only check 1351 | // this if there were no errors compiling the body. 1352 | if len(decl.Type.Out) > 0 && fc.flow.reachesEnd(0) { 1353 | // XXX(Spec) Not specified. 1354 | a.diagAt(body.Rbrace, "function ends without a return statement") 1355 | return nil 1356 | } 1357 | 1358 | code := fc.get() 1359 | maxVars := bodyScope.maxVars 1360 | return func(t *Thread) Func { return &evalFunc{t.f, maxVars, code} } 1361 | } 1362 | 1363 | // Checks that labels were resolved and that all jumps obey scoping 1364 | // rules. Reports an error and set fc.err if any check fails. 1365 | func (a *funcCompiler) checkLabels() { 1366 | nerr := a.numError() 1367 | for _, l := range a.labels { 1368 | if !l.resolved.IsValid() { 1369 | a.diagAt(l.used, "label %s not defined", l.name) 1370 | } 1371 | } 1372 | if nerr != a.numError() { 1373 | // Don't check scopes if we have unresolved labels 1374 | return 1375 | } 1376 | 1377 | // Executing the "goto" statement must not cause any variables 1378 | // to come into scope that were not already in scope at the 1379 | // point of the goto. 1380 | a.flow.gotosObeyScopes(a.compiler) 1381 | } 1382 | 1383 | func findPkgFiles(path string) ([]*ast.File, error) { 1384 | pkg, err := build.Import(path, "", 0) 1385 | if err != nil { 1386 | return nil, err 1387 | } 1388 | //FIXME: CGoFiles and the 'C' package ? 1389 | 1390 | fset := token.NewFileSet() 1391 | var files []*ast.File 1392 | for i := range pkg.GoFiles { 1393 | pkgfile := filepath.Join(pkg.Dir, pkg.GoFiles[i]) 1394 | f, err := parser.ParseFile(fset, pkgfile, nil, 0) 1395 | if err != nil { 1396 | return nil, err 1397 | } 1398 | files = append(files, f) 1399 | } 1400 | 1401 | return files, nil 1402 | } 1403 | 1404 | // srcImporter implements the ast.Importer signature. 1405 | func srcImporter(typesImporter types.Importer, path string) (pkg *types.Package, err error) { 1406 | return typesImporter.Import(path) 1407 | } 1408 | --------------------------------------------------------------------------------