Commit 4c986d86 authored by Robert Griesemer's avatar Robert Griesemer

exp/eval, exp/ogle: remove packages eval and ogle

An externally maintained version of exp/eval can
be found at: https://bitbucket.org/binet/go-eval/ .

R=golang-dev, r, rsc
CC=golang-dev
https://golang.org/cl/4695047
parent 050d839d
......@@ -79,7 +79,6 @@ DIRS=\
encoding/pem\
exec\
exp/datafmt\
exp/eval\
exp/gui\
exp/gui/x11\
exp/regexp/syntax\
......
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
include ../../../Make.inc
TARG=exp/eval
GOFILES=\
abort.go\
bridge.go\
compiler.go\
expr.go\
expr1.go\
func.go\
scope.go\
stmt.go\
type.go\
typec.go\
value.go\
world.go\
include ../../../Make.pkg
main.$O: main.go $(pkgdir)/$(TARG).a
$(GC) $<
eval: main.$O
$(LD) -o $@ $<
gen.$O: gen.go
$(GC) $<
generate: gen.$O
$(LD) -o $@ $<;\
./generate > expr1.go;\
gofmt -w expr1.go
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package eval
import (
"fmt"
"os"
"runtime"
)
// Abort aborts the thread's current computation,
// causing the innermost Try to return err.
func (t *Thread) Abort(err os.Error) {
if t.abort == nil {
panic("abort: " + err.String())
}
t.abort <- err
runtime.Goexit()
}
// Try executes a computation; if the computation
// Aborts, Try returns the error passed to abort.
func (t *Thread) Try(f func(t *Thread)) os.Error {
oc := t.abort
c := make(chan os.Error)
t.abort = c
go func() {
f(t)
c <- nil
}()
err := <-c
t.abort = oc
return err
}
type DivByZeroError struct{}
func (DivByZeroError) String() string { return "divide by zero" }
type NilPointerError struct{}
func (NilPointerError) String() string { return "nil pointer dereference" }
type IndexError struct {
Idx, Len int64
}
func (e IndexError) String() string {
if e.Idx < 0 {
return fmt.Sprintf("negative index: %d", e.Idx)
}
return fmt.Sprintf("index %d exceeds length %d", e.Idx, e.Len)
}
type SliceError struct {
Lo, Hi, Cap int64
}
func (e SliceError) String() string {
return fmt.Sprintf("slice [%d:%d]; cap %d", e.Lo, e.Hi, e.Cap)
}
type KeyError struct {
Key interface{}
}
func (e KeyError) String() string { return fmt.Sprintf("key '%v' not found in map", e.Key) }
type NegativeLengthError struct {
Len int64
}
func (e NegativeLengthError) String() string {
return fmt.Sprintf("negative length: %d", e.Len)
}
type NegativeCapacityError struct {
Len int64
}
func (e NegativeCapacityError) String() string {
return fmt.Sprintf("negative capacity: %d", e.Len)
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package eval
import (
"log"
"go/token"
"reflect"
)
/*
* Type bridging
*/
var (
evalTypes = make(map[reflect.Type]Type)
nativeTypes = make(map[Type]reflect.Type)
)
// TypeFromNative converts a regular Go type into a the corresponding
// interpreter Type.
func TypeFromNative(t reflect.Type) Type {
if et, ok := evalTypes[t]; ok {
return et
}
var nt *NamedType
if t.Name() != "" {
name := t.PkgPath() + "·" + t.Name()
nt = &NamedType{token.NoPos, name, nil, true, make(map[string]Method)}
evalTypes[t] = nt
}
var et Type
switch t.Kind() {
case reflect.Bool:
et = BoolType
case reflect.Float32:
et = Float32Type
case reflect.Float64:
et = Float64Type
case reflect.Int16:
et = Int16Type
case reflect.Int32:
et = Int32Type
case reflect.Int64:
et = Int64Type
case reflect.Int8:
et = Int8Type
case reflect.Int:
et = IntType
case reflect.Uint16:
et = Uint16Type
case reflect.Uint32:
et = Uint32Type
case reflect.Uint64:
et = Uint64Type
case reflect.Uint8:
et = Uint8Type
case reflect.Uint:
et = UintType
case reflect.Uintptr:
et = UintptrType
case reflect.String:
et = StringType
case reflect.Array:
et = NewArrayType(int64(t.Len()), TypeFromNative(t.Elem()))
case reflect.Chan:
log.Panicf("%T not implemented", t)
case reflect.Func:
nin := t.NumIn()
// Variadic functions have DotDotDotType at the end
variadic := t.IsVariadic()
if variadic {
nin--
}
in := make([]Type, nin)
for i := range in {
in[i] = TypeFromNative(t.In(i))
}
out := make([]Type, t.NumOut())
for i := range out {
out[i] = TypeFromNative(t.Out(i))
}
et = NewFuncType(in, variadic, out)
case reflect.Interface:
log.Panicf("%T not implemented", t)
case reflect.Map:
log.Panicf("%T not implemented", t)
case reflect.Ptr:
et = NewPtrType(TypeFromNative(t.Elem()))
case reflect.Slice:
et = NewSliceType(TypeFromNative(t.Elem()))
case reflect.Struct:
n := t.NumField()
fields := make([]StructField, n)
for i := 0; i < n; i++ {
sf := t.Field(i)
// TODO(austin) What to do about private fields?
fields[i].Name = sf.Name
fields[i].Type = TypeFromNative(sf.Type)
fields[i].Anonymous = sf.Anonymous
}
et = NewStructType(fields)
case reflect.UnsafePointer:
log.Panicf("%T not implemented", t)
default:
log.Panicf("unexpected reflect.Type: %T", t)
}
if nt != nil {
if _, ok := et.(*NamedType); !ok {
nt.Complete(et)
et = nt
}
}
nativeTypes[et] = t
evalTypes[t] = et
return et
}
// TypeOfNative returns the interpreter Type of a regular Go value.
func TypeOfNative(v interface{}) Type { return TypeFromNative(reflect.TypeOf(v)) }
/*
* Function bridging
*/
type nativeFunc struct {
fn func(*Thread, []Value, []Value)
in, out int
}
func (f *nativeFunc) NewFrame() *Frame {
vars := make([]Value, f.in+f.out)
return &Frame{nil, vars}
}
func (f *nativeFunc) Call(t *Thread) { f.fn(t, t.f.Vars[0:f.in], t.f.Vars[f.in:f.in+f.out]) }
// FuncFromNative creates an interpreter function from a native
// function that takes its in and out arguments as slices of
// interpreter Value's. While somewhat inconvenient, this avoids
// value marshalling.
func FuncFromNative(fn func(*Thread, []Value, []Value), t *FuncType) FuncValue {
return &funcV{&nativeFunc{fn, len(t.In), len(t.Out)}}
}
// FuncFromNativeTyped is like FuncFromNative, but constructs the
// function type from a function pointer using reflection. Typically,
// the type will be given as a nil pointer to a function with the
// desired signature.
func FuncFromNativeTyped(fn func(*Thread, []Value, []Value), t interface{}) (*FuncType, FuncValue) {
ft := TypeOfNative(t).(*FuncType)
return ft, FuncFromNative(fn, ft)
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package eval
import (
"fmt"
"go/scanner"
"go/token"
)
// A compiler captures information used throughout an entire
// compilation. Currently it includes only the error handler.
//
// TODO(austin) This might actually represent package level, in which
// case it should be package compiler.
type compiler struct {
fset *token.FileSet
errors scanner.ErrorHandler
numErrors int
silentErrors int
}
func (a *compiler) diagAt(pos token.Pos, format string, args ...interface{}) {
a.errors.Error(a.fset.Position(pos), fmt.Sprintf(format, args...))
a.numErrors++
}
func (a *compiler) numError() int { return a.numErrors + a.silentErrors }
// The universal scope
func newUniverse() *Scope {
sc := &Scope{nil, 0}
sc.block = &block{
offset: 0,
scope: sc,
global: true,
defs: make(map[string]Def),
}
return sc
}
var universe *Scope = newUniverse()
// TODO(austin) These can all go in stmt.go now
type label struct {
name string
desc string
// The PC goto statements should jump to, or nil if this label
// cannot be goto'd (such as an anonymous for loop label).
gotoPC *uint
// The PC break statements should jump to, or nil if a break
// statement is invalid.
breakPC *uint
// The PC continue statements should jump to, or nil if a
// continue statement is invalid.
continuePC *uint
// The position where this label was resolved. If it has not
// been resolved yet, an invalid position.
resolved token.Pos
// The position where this label was first jumped to.
used token.Pos
}
// A funcCompiler captures information used throughout the compilation
// of a single function body.
type funcCompiler struct {
*compiler
fnType *FuncType
// Whether the out variables are named. This affects what
// kinds of return statements are legal.
outVarsNamed bool
*codeBuf
flow *flowBuf
labels map[string]*label
}
// A blockCompiler captures information used throughout the compilation
// of a single block within a function.
type blockCompiler struct {
*funcCompiler
block *block
// The label of this block, used for finding break and
// continue labels.
label *label
// The blockCompiler for the block enclosing this one, or nil
// for a function-level block.
parent *blockCompiler
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package eval
import (
"big"
"flag"
"fmt"
"go/token"
"log"
"os"
"reflect"
"regexp"
"testing"
)
// All tests are done using the same file set.
var fset = token.NewFileSet()
// Print each statement or expression before parsing it
var noisy = false
func init() { flag.BoolVar(&noisy, "noisy", false, "chatter during eval tests") }
/*
* Generic statement/expression test framework
*/
type test []job
type job struct {
code string
cerr string
rterr string
val Value
noval bool
}
func runTests(t *testing.T, baseName string, tests []test) {
delta := 1
if testing.Short() {
delta = 16
}
for i := 0; i < len(tests); i += delta {
name := fmt.Sprintf("%s[%d]", baseName, i)
tests[i].run(t, name)
}
}
func (a test) run(t *testing.T, name string) {
w := newTestWorld()
for _, j := range a {
src := j.code + ";" // trailing semicolon to finish statement
if noisy {
println("code:", src)
}
code, err := w.Compile(fset, src)
if err != nil {
if j.cerr == "" {
t.Errorf("%s: Compile %s: %v", name, src, err)
break
}
if !match(t, err, j.cerr) {
t.Errorf("%s: Compile %s = error %s; want %v", name, src, err, j.cerr)
break
}
continue
}
if j.cerr != "" {
t.Errorf("%s: Compile %s succeeded; want %s", name, src, j.cerr)
break
}
val, err := code.Run()
if err != nil {
if j.rterr == "" {
t.Errorf("%s: Run %s: %v", name, src, err)
break
}
if !match(t, err, j.rterr) {
t.Errorf("%s: Run %s = error %s; want %v", name, src, err, j.rterr)
break
}
continue
}
if j.rterr != "" {
t.Errorf("%s: Run %s succeeded; want %s", name, src, j.rterr)
break
}
if !j.noval && !reflect.DeepEqual(val, j.val) {
t.Errorf("%s: Run %s = %T(%v) want %T(%v)", name, src, val, val, j.val, j.val)
}
}
}
func match(t *testing.T, err os.Error, pat string) bool {
ok, err1 := regexp.MatchString(pat, err.String())
if err1 != nil {
t.Fatalf("compile regexp %s: %v", pat, err1)
}
return ok
}
/*
* Test constructors
*/
// Expression compile error
func CErr(expr string, cerr string) test { return test([]job{{code: expr, cerr: cerr}}) }
// Expression runtime error
func RErr(expr string, rterr string) test { return test([]job{{code: expr, rterr: rterr}}) }
// Expression value
func Val(expr string, val interface{}) test {
return test([]job{{code: expr, val: toValue(val)}})
}
// Statement runs without error
func Run(stmts string) test { return test([]job{{code: stmts, noval: true}}) }
// Two statements without error.
// TODO(rsc): Should be possible with Run but the parser
// won't let us do both top-level and non-top-level statements.
func Run2(stmt1, stmt2 string) test {
return test([]job{{code: stmt1, noval: true}, {code: stmt2, noval: true}})
}
// Statement runs and test one expression's value
func Val1(stmts string, expr1 string, val1 interface{}) test {
return test([]job{
{code: stmts, noval: true},
{code: expr1, val: toValue(val1)},
})
}
// Statement runs and test two expressions' values
func Val2(stmts string, expr1 string, val1 interface{}, expr2 string, val2 interface{}) test {
return test([]job{
{code: stmts, noval: true},
{code: expr1, val: toValue(val1)},
{code: expr2, val: toValue(val2)},
})
}
/*
* Value constructors
*/
type vstruct []interface{}
type varray []interface{}
type vslice struct {
arr varray
len, cap int
}
func toValue(val interface{}) Value {
switch val := val.(type) {
case bool:
r := boolV(val)
return &r
case uint8:
r := uint8V(val)
return &r
case uint:
r := uintV(val)
return &r
case int:
r := intV(val)
return &r
case *big.Int:
return &idealIntV{val}
case float64:
r := float64V(val)
return &r
case *big.Rat:
return &idealFloatV{val}
case string:
r := stringV(val)
return &r
case vstruct:
elems := make([]Value, len(val))
for i, e := range val {
elems[i] = toValue(e)
}
r := structV(elems)
return &r
case varray:
elems := make([]Value, len(val))
for i, e := range val {
elems[i] = toValue(e)
}
r := arrayV(elems)
return &r
case vslice:
return &sliceV{Slice{toValue(val.arr).(ArrayValue), int64(val.len), int64(val.cap)}}
case Func:
return &funcV{val}
}
log.Panicf("toValue(%T) not implemented", val)
panic("unreachable")
}
/*
* Default test scope
*/
type testFunc struct{}
func (*testFunc) NewFrame() *Frame { return &Frame{nil, make([]Value, 2)} }
func (*testFunc) Call(t *Thread) {
n := t.f.Vars[0].(IntValue).Get(t)
res := n + 1
t.f.Vars[1].(IntValue).Set(t, res)
}
type oneTwoFunc struct{}
func (*oneTwoFunc) NewFrame() *Frame { return &Frame{nil, make([]Value, 2)} }
func (*oneTwoFunc) Call(t *Thread) {
t.f.Vars[0].(IntValue).Set(t, 1)
t.f.Vars[1].(IntValue).Set(t, 2)
}
type voidFunc struct{}
func (*voidFunc) NewFrame() *Frame { return &Frame{nil, []Value{}} }
func (*voidFunc) Call(t *Thread) {}
func newTestWorld() *World {
w := NewWorld()
def := func(name string, t Type, val interface{}) { w.DefineVar(name, t, toValue(val)) }
w.DefineConst("c", IdealIntType, toValue(big.NewInt(1)))
def("i", IntType, 1)
def("i2", IntType, 2)
def("u", UintType, uint(1))
def("f", Float64Type, 1.0)
def("s", StringType, "abc")
def("t", NewStructType([]StructField{{"a", IntType, false}}), vstruct{1})
def("ai", NewArrayType(2, IntType), varray{1, 2})
def("aai", NewArrayType(2, NewArrayType(2, IntType)), varray{varray{1, 2}, varray{3, 4}})
def("aai2", NewArrayType(2, NewArrayType(2, IntType)), varray{varray{5, 6}, varray{7, 8}})
def("fn", NewFuncType([]Type{IntType}, false, []Type{IntType}), &testFunc{})
def("oneTwo", NewFuncType([]Type{}, false, []Type{IntType, IntType}), &oneTwoFunc{})
def("void", NewFuncType([]Type{}, false, []Type{}), &voidFunc{})
def("sli", NewSliceType(IntType), vslice{varray{1, 2, 3}, 2, 3})
return w
}
This diff is collapsed.
This diff is collapsed.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package eval
import (
"big"
"testing"
)
var undefined = "undefined"
var typeAsExpr = "type .* used as expression"
var badCharLit = "character literal"
var unknownEscape = "unknown escape sequence"
var opTypes = "illegal (operand|argument) type|cannot index into"
var badAddrOf = "cannot take the address"
var constantTruncated = "constant [^ ]* truncated"
var constantUnderflows = "constant [^ ]* underflows"
var constantOverflows = "constant [^ ]* overflows"
var implLimit = "implementation limit"
var mustBeUnsigned = "must be unsigned"
var divByZero = "divide by zero"
var hugeInteger = new(big.Int).Lsh(idealOne, 64)
var exprTests = []test{
Val("i", 1),
CErr("zzz", undefined),
// TODO(austin) Test variable in constant context
//CErr("t", typeAsExpr),
Val("'a'", big.NewInt('a')),
Val("'\\uffff'", big.NewInt('\uffff')),
Val("'\\n'", big.NewInt('\n')),
CErr("''+x", badCharLit),
// Produces two parse errors
//CErr("'''", ""),
CErr("'\n'", badCharLit),
CErr("'\\z'", unknownEscape),
CErr("'ab'", badCharLit),
Val("1.0", big.NewRat(1, 1)),
Val("1.", big.NewRat(1, 1)),
Val(".1", big.NewRat(1, 10)),
Val("1e2", big.NewRat(100, 1)),
Val("\"abc\"", "abc"),
Val("\"\"", ""),
Val("\"\\n\\\"\"", "\n\""),
CErr("\"\\z\"", unknownEscape),
CErr("\"abc", "string not terminated"),
Val("(i)", 1),
Val("ai[0]", 1),
Val("(&ai)[0]", 1),
Val("ai[1]", 2),
Val("ai[i]", 2),
Val("ai[u]", 2),
CErr("ai[f]", opTypes),
CErr("ai[0][0]", opTypes),
CErr("ai[2]", "index 2 exceeds"),
CErr("ai[1+1]", "index 2 exceeds"),
CErr("ai[-1]", "negative index"),
RErr("ai[i+i]", "index 2 exceeds"),
RErr("ai[-i]", "negative index"),
CErr("i[0]", opTypes),
CErr("f[0]", opTypes),
Val("aai[0][0]", 1),
Val("aai[1][1]", 4),
CErr("aai[2][0]", "index 2 exceeds"),
CErr("aai[0][2]", "index 2 exceeds"),
Val("sli[0]", 1),
Val("sli[1]", 2),
CErr("sli[-1]", "negative index"),
RErr("sli[-i]", "negative index"),
RErr("sli[2]", "index 2 exceeds"),
Val("s[0]", uint8('a')),
Val("s[1]", uint8('b')),
CErr("s[-1]", "negative index"),
RErr("s[-i]", "negative index"),
RErr("s[3]", "index 3 exceeds"),
Val("ai[0:2]", vslice{varray{1, 2}, 2, 2}),
Val("ai[0:1]", vslice{varray{1, 2}, 1, 2}),
Val("ai[0:]", vslice{varray{1, 2}, 2, 2}),
Val("ai[i:]", vslice{varray{2}, 1, 1}),
Val("sli[0:2]", vslice{varray{1, 2, 3}, 2, 3}),
Val("sli[0:i]", vslice{varray{1, 2, 3}, 1, 3}),
Val("sli[1:]", vslice{varray{2, 3}, 1, 2}),
CErr("1(2)", "cannot call"),
CErr("fn(1,2)", "too many"),
CErr("fn()", "not enough"),
CErr("fn(true)", opTypes),
CErr("fn(true)", "function call"),
// Single argument functions don't say which argument.
//CErr("fn(true)", "argument 1"),
Val("fn(1)", 2),
Val("fn(1.0)", 2),
CErr("fn(1.5)", constantTruncated),
Val("fn(i)", 2),
CErr("fn(u)", opTypes),
CErr("void()+2", opTypes),
CErr("oneTwo()+2", opTypes),
Val("cap(ai)", 2),
Val("cap(&ai)", 2),
Val("cap(aai)", 2),
Val("cap(sli)", 3),
CErr("cap(0)", opTypes),
CErr("cap(i)", opTypes),
CErr("cap(s)", opTypes),
Val("len(s)", 3),
Val("len(ai)", 2),
Val("len(&ai)", 2),
Val("len(ai[0:])", 2),
Val("len(ai[1:])", 1),
Val("len(ai[2:])", 0),
Val("len(aai)", 2),
Val("len(sli)", 2),
Val("len(sli[0:])", 2),
Val("len(sli[1:])", 1),
Val("len(sli[2:])", 0),
// TODO(austin) Test len of map
CErr("len(0)", opTypes),
CErr("len(i)", opTypes),
CErr("*i", opTypes),
Val("*&i", 1),
Val("*&(i)", 1),
CErr("&1", badAddrOf),
CErr("&c", badAddrOf),
Val("*(&ai[0])", 1),
Val("+1", big.NewInt(+1)),
Val("+1.0", big.NewRat(1, 1)),
Val("01.5", big.NewRat(15, 10)),
CErr("+\"x\"", opTypes),
Val("-42", big.NewInt(-42)),
Val("-i", -1),
Val("-f", -1.0),
// 6g bug?
//Val("-(f-1)", -0.0),
CErr("-\"x\"", opTypes),
// TODO(austin) Test unary !
Val("^2", big.NewInt(^2)),
Val("^(-2)", big.NewInt(^(-2))),
CErr("^2.0", opTypes),
CErr("^2.5", opTypes),
Val("^i", ^1),
Val("^u", ^uint(1)),
CErr("^f", opTypes),
Val("1+i", 2),
Val("1+u", uint(2)),
Val("3.0+i", 4),
Val("1+1", big.NewInt(2)),
Val("f+f", 2.0),
Val("1+f", 2.0),
Val("1.0+1", big.NewRat(2, 1)),
Val("\"abc\" + \"def\"", "abcdef"),
CErr("i+u", opTypes),
CErr("-1+u", constantUnderflows),
// TODO(austin) Test named types
Val("2-1", big.NewInt(1)),
Val("2.0-1", big.NewRat(1, 1)),
Val("f-2", -1.0),
Val("-0.0", big.NewRat(0, 1)),
Val("2*2", big.NewInt(4)),
Val("2*i", 2),
Val("3/2", big.NewInt(1)),
Val("3/i", 3),
CErr("1/0", divByZero),
CErr("1.0/0", divByZero),
RErr("i/0", divByZero),
Val("3%2", big.NewInt(1)),
Val("i%2", 1),
CErr("3%0", divByZero),
CErr("3.0%0", opTypes),
RErr("i%0", divByZero),
// Examples from "Arithmetic operators"
Val("5/3", big.NewInt(1)),
Val("(i+4)/(i+2)", 1),
Val("5%3", big.NewInt(2)),
Val("(i+4)%(i+2)", 2),
Val("-5/3", big.NewInt(-1)),
Val("(i-6)/(i+2)", -1),
Val("-5%3", big.NewInt(-2)),
Val("(i-6)%(i+2)", -2),
Val("5/-3", big.NewInt(-1)),
Val("(i+4)/(i-4)", -1),
Val("5%-3", big.NewInt(2)),
Val("(i+4)%(i-4)", 2),
Val("-5/-3", big.NewInt(1)),
Val("(i-6)/(i-4)", 1),
Val("-5%-3", big.NewInt(-2)),
Val("(i-6)%(i-4)", -2),
// Examples from "Arithmetic operators"
Val("11/4", big.NewInt(2)),
Val("(i+10)/4", 2),
Val("11%4", big.NewInt(3)),
Val("(i+10)%4", 3),
Val("11>>2", big.NewInt(2)),
Val("(i+10)>>2", 2),
Val("11&3", big.NewInt(3)),
Val("(i+10)&3", 3),
Val("-11/4", big.NewInt(-2)),
Val("(i-12)/4", -2),
Val("-11%4", big.NewInt(-3)),
Val("(i-12)%4", -3),
Val("-11>>2", big.NewInt(-3)),
Val("(i-12)>>2", -3),
Val("-11&3", big.NewInt(1)),
Val("(i-12)&3", 1),
// TODO(austin) Test bit ops
// For shift, we try nearly every combination of positive
// ideal int, negative ideal int, big ideal int, ideal
// fractional float, ideal non-fractional float, int, uint,
// and float.
Val("2<<2", big.NewInt(2<<2)),
CErr("2<<(-1)", constantUnderflows),
CErr("2<<0x10000000000000000", constantOverflows),
CErr("2<<2.5", constantTruncated),
Val("2<<2.0", big.NewInt(2<<2.0)),
CErr("2<<i", mustBeUnsigned),
Val("2<<u", 2<<1),
CErr("2<<f", opTypes),
Val("-2<<2", big.NewInt(-2<<2)),
CErr("-2<<(-1)", constantUnderflows),
CErr("-2<<0x10000000000000000", constantOverflows),
CErr("-2<<2.5", constantTruncated),
Val("-2<<2.0", big.NewInt(-2<<2.0)),
CErr("-2<<i", mustBeUnsigned),
Val("-2<<u", -2<<1),
CErr("-2<<f", opTypes),
Val("0x10000000000000000<<2", new(big.Int).Lsh(hugeInteger, 2)),
CErr("0x10000000000000000<<(-1)", constantUnderflows),
CErr("0x10000000000000000<<0x10000000000000000", constantOverflows),
CErr("0x10000000000000000<<2.5", constantTruncated),
Val("0x10000000000000000<<2.0", new(big.Int).Lsh(hugeInteger, 2)),
CErr("0x10000000000000000<<i", mustBeUnsigned),
CErr("0x10000000000000000<<u", constantOverflows),
CErr("0x10000000000000000<<f", opTypes),
CErr("2.5<<2", opTypes),
CErr("2.0<<2", opTypes),
Val("i<<2", 1<<2),
CErr("i<<(-1)", constantUnderflows),
CErr("i<<0x10000000000000000", constantOverflows),
CErr("i<<2.5", constantTruncated),
Val("i<<2.0", 1<<2),
CErr("i<<i", mustBeUnsigned),
Val("i<<u", 1<<1),
CErr("i<<f", opTypes),
Val("i<<u", 1<<1),
Val("u<<2", uint(1<<2)),
CErr("u<<(-1)", constantUnderflows),
CErr("u<<0x10000000000000000", constantOverflows),
CErr("u<<2.5", constantTruncated),
Val("u<<2.0", uint(1<<2)),
CErr("u<<i", mustBeUnsigned),
Val("u<<u", uint(1<<1)),
CErr("u<<f", opTypes),
Val("u<<u", uint(1<<1)),
CErr("f<<2", opTypes),
// <, <=, >, >=
Val("1<2", 1 < 2),
Val("1<=2", 1 <= 2),
Val("2<=2", 2 <= 2),
Val("1>2", 1 > 2),
Val("1>=2", 1 >= 2),
Val("2>=2", 2 >= 2),
Val("i<2", 1 < 2),
Val("i<=2", 1 <= 2),
Val("i+1<=2", 2 <= 2),
Val("i>2", 1 > 2),
Val("i>=2", 1 >= 2),
Val("i+1>=2", 2 >= 2),
Val("u<2", 1 < 2),
Val("f<2", 1 < 2),
Val("s<\"b\"", true),
Val("s<\"a\"", false),
Val("s<=\"abc\"", true),
Val("s>\"aa\"", true),
Val("s>\"ac\"", false),
Val("s>=\"abc\"", true),
CErr("i<u", opTypes),
CErr("i<f", opTypes),
CErr("i<s", opTypes),
CErr("&i<&i", opTypes),
CErr("ai<ai", opTypes),
// ==, !=
Val("1==1", true),
Val("1!=1", false),
Val("1==2", false),
Val("1!=2", true),
Val("1.0==1", true),
Val("1.5==1", false),
Val("i==1", true),
Val("i!=1", false),
Val("i==2", false),
Val("i!=2", true),
Val("u==1", true),
Val("f==1", true),
Val("s==\"abc\"", true),
Val("s!=\"abc\"", false),
Val("s==\"abcd\"", false),
Val("s!=\"abcd\"", true),
Val("&i==&i", true),
Val("&i==&i2", false),
Val("fn==fn", true),
Val("fn==func(int)int{return 0}", false),
CErr("i==u", opTypes),
CErr("i==f", opTypes),
CErr("&i==&f", opTypes),
CErr("ai==ai", opTypes),
CErr("t==t", opTypes),
CErr("fn==oneTwo", opTypes),
}
func TestExpr(t *testing.T) { runTests(t, "exprTests", exprTests) }
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package eval
import "os"
/*
* Virtual machine
*/
type Thread struct {
abort chan os.Error
pc uint
// The execution frame of this function. This remains the
// same throughout a function invocation.
f *Frame
}
type code []func(*Thread)
func (i code) exec(t *Thread) {
opc := t.pc
t.pc = 0
l := uint(len(i))
for t.pc < l {
pc := t.pc
t.pc++
i[pc](t)
}
t.pc = opc
}
/*
* Code buffer
*/
type codeBuf struct {
instrs code
}
func newCodeBuf() *codeBuf { return &codeBuf{make(code, 0, 16)} }
func (b *codeBuf) push(instr func(*Thread)) {
b.instrs = append(b.instrs, instr)
}
func (b *codeBuf) nextPC() uint { return uint(len(b.instrs)) }
func (b *codeBuf) get() code {
// Freeze this buffer into an array of exactly the right size
a := make(code, len(b.instrs))
copy(a, b.instrs)
return code(a)
}
/*
* User-defined functions
*/
type evalFunc struct {
outer *Frame
frameSize int
code code
}
func (f *evalFunc) NewFrame() *Frame { return f.outer.child(f.frameSize) }
func (f *evalFunc) Call(t *Thread) { f.code.exec(t) }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#!/usr/bin/env bash
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Run the interpreter against all the Go test programs
# that begin with the magic
# // $G $D/$F.go && $L $F.$A && ./$A.out
# line and do not contain imports.
set -e
gomake
6g main.go && 6l main.6
(
for i in $(egrep -l '// \$G (\$D/)?\$F\.go \&\& \$L \$F\.\$A && \./\$A\.out' "$GOROOT"/test/*.go "$GOROOT"/test/*/*.go)
do
if grep '^import' $i >/dev/null 2>&1
then
true
else
if "$GOROOT"/usr/austin/eval/6.out -f $i >/tmp/out 2>&1 && ! test -s /tmp/out
then
echo PASS $i
else
echo FAIL $i
(
echo '>>> ' $i
cat /tmp/out
echo
) 1>&3
fi
fi
done | (tee /dev/fd/2 | awk '{print $1}' | sort | uniq -c) 2>&1
) 3>test.log
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment