Files
gotext/vendor/github.com/mattn/anko/vm/vm.go
2016-07-19 14:18:24 -03:00

1505 lines
36 KiB
Go

package vm
import (
"errors"
"fmt"
"math"
"os"
"reflect"
"strconv"
"strings"
"github.com/mattn/anko/ast"
"github.com/mattn/anko/parser"
)
var (
NilValue = reflect.ValueOf((*interface{})(nil))
NilType = reflect.TypeOf((*interface{})(nil))
TrueValue = reflect.ValueOf(true)
FalseValue = reflect.ValueOf(false)
)
// Error provides a convenient interface for handling runtime error.
// It can be Error interface with type cast which can call Pos().
type Error struct {
Message string
Pos ast.Position
}
var (
BreakError = errors.New("Unexpected break statement")
ContinueError = errors.New("Unexpected continue statement")
ReturnError = errors.New("Unexpected return statement")
InterruptError = errors.New("Execution interrupted")
)
// NewStringError makes error interface with message.
func NewStringError(pos ast.Pos, err string) error {
if pos == nil {
return &Error{Message: err, Pos: ast.Position{1, 1}}
}
return &Error{Message: err, Pos: pos.Position()}
}
// NewErrorf makes error interface with message.
func NewErrorf(pos ast.Pos, format string, args ...interface{}) error {
return &Error{Message: fmt.Sprintf(format, args...), Pos: pos.Position()}
}
// NewError makes error interface with message.
// This doesn't overwrite last error.
func NewError(pos ast.Pos, err error) error {
if err == nil {
return nil
}
if err == BreakError || err == ContinueError || err == ReturnError {
return err
}
if pe, ok := err.(*parser.Error); ok {
return pe
}
if ee, ok := err.(*Error); ok {
return ee
}
return &Error{Message: err.Error(), Pos: pos.Position()}
}
// Error returns the error message.
func (e *Error) Error() string {
return e.Message
}
// Func is function interface to reflect functions internaly.
type Func func(args ...reflect.Value) (reflect.Value, error)
func (f Func) String() string {
return fmt.Sprintf("[Func: %p]", f)
}
func ToFunc(f Func) reflect.Value {
return reflect.ValueOf(f)
}
// Run executes statements in the specified environment.
func Run(stmts []ast.Stmt, env *Env) (reflect.Value, error) {
rv := NilValue
var err error
for _, stmt := range stmts {
if _, ok := stmt.(*ast.BreakStmt); ok {
return NilValue, BreakError
}
if _, ok := stmt.(*ast.ContinueStmt); ok {
return NilValue, ContinueError
}
rv, err = RunSingleStmt(stmt, env)
if err != nil {
return rv, err
}
if _, ok := stmt.(*ast.ReturnStmt); ok {
return reflect.ValueOf(rv), ReturnError
}
}
return rv, nil
}
// Interrupts the execution of any running statements in the specified environment.
//
// Note that the execution is not instantly aborted: after a call to Interrupt,
// the current running statement will finish, but the next statement will not run,
// and instead will return a NilValue and an InterruptError.
func Interrupt(env *Env) {
env.Lock()
*(env.interrupt) = true
env.Unlock()
}
// RunSingleStmt executes one statement in the specified environment.
func RunSingleStmt(stmt ast.Stmt, env *Env) (reflect.Value, error) {
env.Lock()
if *(env.interrupt) {
*(env.interrupt) = false
env.Unlock()
return NilValue, InterruptError
}
env.Unlock()
switch stmt := stmt.(type) {
case *ast.ExprStmt:
rv, err := invokeExpr(stmt.Expr, env)
if err != nil {
return rv, NewError(stmt, err)
}
return rv, nil
case *ast.VarStmt:
rv := NilValue
var err error
rvs := []reflect.Value{}
for _, expr := range stmt.Exprs {
rv, err = invokeExpr(expr, env)
if err != nil {
return rv, NewError(expr, err)
}
rvs = append(rvs, rv)
}
result := []interface{}{}
for i, name := range stmt.Names {
if i < len(rvs) {
env.Define(name, rvs[i])
result = append(result, rvs[i].Interface())
}
}
return reflect.ValueOf(result), nil
case *ast.LetsStmt:
rv := NilValue
var err error
vs := []interface{}{}
for _, rhs := range stmt.Rhss {
rv, err = invokeExpr(rhs, env)
if err != nil {
return rv, NewError(rhs, err)
}
if rv == NilValue {
vs = append(vs, nil)
} else if rv.IsValid() && rv.CanInterface() {
vs = append(vs, rv.Interface())
} else {
vs = append(vs, nil)
}
}
rvs := reflect.ValueOf(vs)
if len(stmt.Lhss) > 1 && rvs.Len() == 1 {
item := rvs.Index(0)
if item.Kind() == reflect.Interface {
item = item.Elem()
}
if item.Kind() == reflect.Slice {
rvs = item
}
}
for i, lhs := range stmt.Lhss {
if i >= rvs.Len() {
break
}
v := rvs.Index(i)
if v.Kind() == reflect.Interface {
v = v.Elem()
}
_, err = invokeLetExpr(lhs, v, env)
if err != nil {
return rvs, NewError(lhs, err)
}
}
if rvs.Len() == 1 {
return rvs.Index(0), nil
}
return rvs, nil
case *ast.IfStmt:
// If
rv, err := invokeExpr(stmt.If, env)
if err != nil {
return rv, NewError(stmt, err)
}
if toBool(rv) {
// Then
newenv := env.NewEnv()
defer newenv.Destroy()
rv, err = Run(stmt.Then, newenv)
if err != nil {
return rv, NewError(stmt, err)
}
return rv, nil
}
done := false
if len(stmt.ElseIf) > 0 {
for _, stmt := range stmt.ElseIf {
stmt_if := stmt.(*ast.IfStmt)
// ElseIf
rv, err = invokeExpr(stmt_if.If, env)
if err != nil {
return rv, NewError(stmt, err)
}
if !toBool(rv) {
continue
}
// ElseIf Then
done = true
rv, err = Run(stmt_if.Then, env)
if err != nil {
return rv, NewError(stmt, err)
}
break
}
}
if !done && len(stmt.Else) > 0 {
// Else
newenv := env.NewEnv()
defer newenv.Destroy()
rv, err = Run(stmt.Else, newenv)
if err != nil {
return rv, NewError(stmt, err)
}
}
return rv, nil
case *ast.TryStmt:
newenv := env.NewEnv()
defer newenv.Destroy()
_, err := Run(stmt.Try, newenv)
if err != nil {
// Catch
cenv := env.NewEnv()
defer cenv.Destroy()
if stmt.Var != "" {
cenv.Define(stmt.Var, reflect.ValueOf(err))
}
_, e1 := Run(stmt.Catch, cenv)
if e1 != nil {
err = NewError(stmt.Catch[0], e1)
} else {
err = nil
}
}
if len(stmt.Finally) > 0 {
// Finally
fenv := env.NewEnv()
defer fenv.Destroy()
_, e2 := Run(stmt.Finally, newenv)
if e2 != nil {
err = NewError(stmt.Finally[0], e2)
}
}
return NilValue, NewError(stmt, err)
case *ast.LoopStmt:
newenv := env.NewEnv()
defer newenv.Destroy()
for {
if stmt.Expr != nil {
ev, ee := invokeExpr(stmt.Expr, newenv)
if ee != nil {
return ev, ee
}
if !toBool(ev) {
break
}
}
rv, err := Run(stmt.Stmts, newenv)
if err != nil {
if err == BreakError {
err = nil
break
}
if err == ContinueError {
err = nil
continue
}
if err == ReturnError {
return rv, err
}
return rv, NewError(stmt, err)
}
}
return NilValue, nil
case *ast.ForStmt:
val, ee := invokeExpr(stmt.Value, env)
if ee != nil {
return val, ee
}
if val.Kind() == reflect.Interface {
val = val.Elem()
}
if val.Kind() != reflect.Array && val.Kind() != reflect.Slice {
return NilValue, NewStringError(stmt, "Invalid operation for non-array value")
}
newenv := env.NewEnv()
defer newenv.Destroy()
for i := 0; i < val.Len(); i++ {
iv := val.Index(i)
if val.Index(i).Kind() == reflect.Interface || val.Index(i).Kind() == reflect.Ptr {
iv = iv.Elem()
}
newenv.Define(stmt.Var, iv)
rv, err := Run(stmt.Stmts, newenv)
if err != nil {
if err == BreakError {
err = nil
break
}
if err == ContinueError {
err = nil
continue
}
if err == ReturnError {
return rv, err
}
return rv, NewError(stmt, err)
}
}
return NilValue, nil
case *ast.CForStmt:
newenv := env.NewEnv()
defer newenv.Destroy()
_, err := invokeExpr(stmt.Expr1, newenv)
if err != nil {
return NilValue, err
}
for {
fb, err := invokeExpr(stmt.Expr2, newenv)
if err != nil {
return NilValue, err
}
if !toBool(fb) {
break
}
rv, err := Run(stmt.Stmts, newenv)
if err != nil {
if err == BreakError {
err = nil
break
}
if err == ContinueError {
err = nil
continue
}
if err == ReturnError {
return rv, err
}
return rv, NewError(stmt, err)
}
_, err = invokeExpr(stmt.Expr3, newenv)
if err != nil {
return NilValue, err
}
}
return NilValue, nil
case *ast.ReturnStmt:
rvs := []interface{}{}
switch len(stmt.Exprs) {
case 0:
return NilValue, nil
case 1:
rv, err := invokeExpr(stmt.Exprs[0], env)
if err != nil {
return rv, NewError(stmt, err)
}
return rv, nil
}
for _, expr := range stmt.Exprs {
rv, err := invokeExpr(expr, env)
if err != nil {
return rv, NewError(stmt, err)
}
if isNil(rv) {
rvs = append(rvs, nil)
} else if rv.IsValid() {
rvs = append(rvs, rv.Interface())
} else {
rvs = append(rvs, nil)
}
}
return reflect.ValueOf(rvs), nil
case *ast.ThrowStmt:
rv, err := invokeExpr(stmt.Expr, env)
if err != nil {
return rv, NewError(stmt, err)
}
if !rv.IsValid() {
return NilValue, NewError(stmt, err)
}
return rv, NewStringError(stmt, fmt.Sprint(rv.Interface()))
case *ast.ModuleStmt:
newenv := env.NewEnv()
newenv.SetName(stmt.Name)
rv, err := Run(stmt.Stmts, newenv)
if err != nil {
return rv, NewError(stmt, err)
}
env.DefineGlobal(stmt.Name, reflect.ValueOf(newenv))
return rv, nil
case *ast.SwitchStmt:
rv, err := invokeExpr(stmt.Expr, env)
if err != nil {
return rv, NewError(stmt, err)
}
done := false
var default_stmt *ast.DefaultStmt
for _, ss := range stmt.Cases {
if ssd, ok := ss.(*ast.DefaultStmt); ok {
default_stmt = ssd
continue
}
case_stmt := ss.(*ast.CaseStmt)
cv, err := invokeExpr(case_stmt.Expr, env)
if err != nil {
return rv, NewError(stmt, err)
}
if !equal(rv, cv) {
continue
}
rv, err = Run(case_stmt.Stmts, env)
if err != nil {
return rv, NewError(stmt, err)
}
done = true
break
}
if !done && default_stmt != nil {
rv, err = Run(default_stmt.Stmts, env)
if err != nil {
return rv, NewError(stmt, err)
}
}
return rv, nil
default:
return NilValue, NewStringError(stmt, "unknown statement")
}
}
// toString converts all reflect.Value-s into string.
func toString(v reflect.Value) string {
if v.Kind() == reflect.Interface {
v = v.Elem()
}
if v.Kind() == reflect.String {
return v.String()
}
if !v.IsValid() {
return "nil"
}
return fmt.Sprint(v.Interface())
}
// toBool converts all reflect.Value-s into bool.
func toBool(v reflect.Value) bool {
if v.Kind() == reflect.Interface {
v = v.Elem()
}
switch v.Kind() {
case reflect.Float32, reflect.Float64:
return v.Float() != 0.0
case reflect.Int, reflect.Int32, reflect.Int64:
return v.Int() != 0
case reflect.Bool:
return v.Bool()
case reflect.String:
if v.String() == "true" {
return true
}
if toInt64(v) != 0 {
return true
}
}
return false
}
// toFloat64 converts all reflect.Value-s into float64.
func toFloat64(v reflect.Value) float64 {
if v.Kind() == reflect.Interface {
v = v.Elem()
}
switch v.Kind() {
case reflect.Float32, reflect.Float64:
return v.Float()
case reflect.Int, reflect.Int32, reflect.Int64:
return float64(v.Int())
}
return 0.0
}
func isNil(v reflect.Value) bool {
if !v.IsValid() || v.Kind().String() == "unsafe.Pointer" {
return true
}
if (v.Kind() == reflect.Interface || v.Kind() == reflect.Ptr) && v.IsNil() {
return true
}
return false
}
func isNum(v reflect.Value) bool {
switch v.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64:
return true
}
return false
}
// equal returns true when lhsV and rhsV is same value.
func equal(lhsV, rhsV reflect.Value) bool {
lhsIsNil, rhsIsNil := isNil(lhsV), isNil(rhsV)
if lhsIsNil && rhsIsNil {
return true
}
if (!lhsIsNil && rhsIsNil) || (lhsIsNil && !rhsIsNil) {
return false
}
if lhsV.Kind() == reflect.Interface || lhsV.Kind() == reflect.Ptr {
lhsV = lhsV.Elem()
}
if rhsV.Kind() == reflect.Interface || rhsV.Kind() == reflect.Ptr {
rhsV = rhsV.Elem()
}
if !lhsV.IsValid() || !rhsV.IsValid() {
return true
}
if isNum(lhsV) && isNum(rhsV) {
if rhsV.Type().ConvertibleTo(lhsV.Type()) {
rhsV = rhsV.Convert(lhsV.Type())
}
}
if lhsV.CanInterface() && rhsV.CanInterface() {
return reflect.DeepEqual(lhsV.Interface(), rhsV.Interface())
}
return reflect.DeepEqual(lhsV, rhsV)
}
// toInt64 converts all reflect.Value-s into int64.
func toInt64(v reflect.Value) int64 {
if v.Kind() == reflect.Interface {
v = v.Elem()
}
switch v.Kind() {
case reflect.Float32, reflect.Float64:
return int64(v.Float())
case reflect.Int, reflect.Int32, reflect.Int64:
return v.Int()
case reflect.String:
s := v.String()
var i int64
var err error
if strings.HasPrefix(s, "0x") {
i, err = strconv.ParseInt(s, 16, 64)
} else {
i, err = strconv.ParseInt(s, 10, 64)
}
if err == nil {
return int64(i)
}
}
return 0
}
func invokeLetExpr(expr ast.Expr, rv reflect.Value, env *Env) (reflect.Value, error) {
switch lhs := expr.(type) {
case *ast.IdentExpr:
if env.Set(lhs.Lit, rv) != nil {
if strings.Contains(lhs.Lit, ".") {
return NilValue, NewErrorf(expr, "Undefined symbol '%s'", lhs.Lit)
}
env.Define(lhs.Lit, rv)
}
return rv, nil
case *ast.MemberExpr:
v, err := invokeExpr(lhs.Expr, env)
if err != nil {
return v, NewError(expr, err)
}
if v.Kind() == reflect.Interface {
v = v.Elem()
}
if v.Kind() == reflect.Slice {
v = v.Index(0)
}
if !v.IsValid() {
return NilValue, NewStringError(expr, "Cannot assignable")
}
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() == reflect.Struct {
v = v.FieldByName(lhs.Name)
if !v.CanSet() {
return NilValue, NewStringError(expr, "Cannot assignable")
}
v.Set(rv)
} else if v.Kind() == reflect.Map {
v.SetMapIndex(reflect.ValueOf(lhs.Name), rv)
} else {
if !v.CanSet() {
return NilValue, NewStringError(expr, "Cannot assignable")
}
v.Set(rv)
}
return v, nil
case *ast.ItemExpr:
v, err := invokeExpr(lhs.Value, env)
if err != nil {
return v, NewError(expr, err)
}
i, err := invokeExpr(lhs.Index, env)
if err != nil {
return i, NewError(expr, err)
}
if v.Kind() == reflect.Interface {
v = v.Elem()
}
if v.Kind() == reflect.Array || v.Kind() == reflect.Slice {
if i.Kind() != reflect.Int && i.Kind() != reflect.Int64 {
return NilValue, NewStringError(expr, "Array index should be int")
}
ii := int(i.Int())
if ii < 0 || ii >= v.Len() {
return NilValue, NewStringError(expr, "Cannot assignable")
}
vv := v.Index(ii)
if !vv.CanSet() {
return NilValue, NewStringError(expr, "Cannot assignable")
}
vv.Set(rv)
return rv, nil
}
if v.Kind() == reflect.Map {
if i.Kind() != reflect.String {
return NilValue, NewStringError(expr, "Map key should be string")
}
v.SetMapIndex(i, rv)
return rv, nil
}
return v, NewStringError(expr, "Invalid operation")
case *ast.SliceExpr:
v, err := invokeExpr(lhs.Value, env)
if err != nil {
return v, NewError(expr, err)
}
rb, err := invokeExpr(lhs.Begin, env)
if err != nil {
return rb, NewError(expr, err)
}
re, err := invokeExpr(lhs.End, env)
if err != nil {
return re, NewError(expr, err)
}
if v.Kind() == reflect.Interface {
v = v.Elem()
}
if v.Kind() == reflect.Array || v.Kind() == reflect.Slice {
if rb.Kind() != reflect.Int && rb.Kind() != reflect.Int64 {
return NilValue, NewStringError(expr, "Array index should be int")
}
if re.Kind() != reflect.Int && re.Kind() != reflect.Int64 {
return NilValue, NewStringError(expr, "Array index should be int")
}
ii := int(rb.Int())
if ii < 0 || ii >= v.Len() {
return NilValue, NewStringError(expr, "Cannot assignable")
}
ij := int(re.Int())
if ij < 0 || ij >= v.Len() {
return NilValue, NewStringError(expr, "Cannot assignable")
}
vv := v.Slice(ii, ij)
if !vv.CanSet() {
return NilValue, NewStringError(expr, "Cannot assignable")
}
vv.Set(rv)
return rv, nil
}
return v, NewStringError(expr, "Invalid operation")
}
return NilValue, NewStringError(expr, "Invalid operation")
}
// invokeExpr evaluates one expression.
func invokeExpr(expr ast.Expr, env *Env) (reflect.Value, error) {
switch e := expr.(type) {
case *ast.NumberExpr:
if strings.Contains(e.Lit, ".") || strings.Contains(e.Lit, "e") {
v, err := strconv.ParseFloat(e.Lit, 64)
if err != nil {
return NilValue, NewError(expr, err)
}
return reflect.ValueOf(float64(v)), nil
}
var i int64
var err error
if strings.HasPrefix(e.Lit, "0x") {
i, err = strconv.ParseInt(e.Lit[2:], 16, 64)
} else {
i, err = strconv.ParseInt(e.Lit, 10, 64)
}
if err != nil {
return NilValue, NewError(expr, err)
}
return reflect.ValueOf(i), nil
case *ast.IdentExpr:
return env.Get(e.Lit)
case *ast.StringExpr:
return reflect.ValueOf(e.Lit), nil
case *ast.ArrayExpr:
a := make([]interface{}, len(e.Exprs))
for i, expr := range e.Exprs {
arg, err := invokeExpr(expr, env)
if err != nil {
return arg, NewError(expr, err)
}
a[i] = arg.Interface()
}
return reflect.ValueOf(a), nil
case *ast.MapExpr:
m := make(map[string]interface{})
for k, expr := range e.MapExpr {
v, err := invokeExpr(expr, env)
if err != nil {
return v, NewError(expr, err)
}
m[k] = v.Interface()
}
return reflect.ValueOf(m), nil
case *ast.DerefExpr:
v := NilValue
var err error
switch ee := e.Expr.(type) {
case *ast.IdentExpr:
v, err = env.Get(ee.Lit)
if err != nil {
return v, err
}
case *ast.MemberExpr:
v, err := invokeExpr(ee.Expr, env)
if err != nil {
return v, NewError(expr, err)
}
if v.Kind() == reflect.Interface {
v = v.Elem()
}
if v.Kind() == reflect.Slice {
v = v.Index(0)
}
if v.IsValid() && v.CanInterface() {
if vme, ok := v.Interface().(*Env); ok {
m, err := vme.Get(ee.Name)
if !m.IsValid() || err != nil {
return NilValue, NewStringError(expr, fmt.Sprintf("Invalid operation '%s'", ee.Name))
}
return m, nil
}
}
m := v.MethodByName(ee.Name)
if !m.IsValid() {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() == reflect.Struct {
m = v.FieldByName(ee.Name)
if !m.IsValid() {
return NilValue, NewStringError(expr, fmt.Sprintf("Invalid operation '%s'", ee.Name))
}
} else if v.Kind() == reflect.Map {
m = v.MapIndex(reflect.ValueOf(ee.Name))
if !m.IsValid() {
return NilValue, NewStringError(expr, fmt.Sprintf("Invalid operation '%s'", ee.Name))
}
} else {
return NilValue, NewStringError(expr, fmt.Sprintf("Invalid operation '%s'", ee.Name))
}
v = m
} else {
v = m
}
default:
return NilValue, NewStringError(expr, "Invalid operation for the value")
}
if v.Kind() != reflect.Ptr {
return NilValue, NewStringError(expr, "Cannot deference for the value")
}
return v.Addr(), nil
case *ast.AddrExpr:
v := NilValue
var err error
switch ee := e.Expr.(type) {
case *ast.IdentExpr:
v, err = env.Get(ee.Lit)
if err != nil {
return v, err
}
case *ast.MemberExpr:
v, err := invokeExpr(ee.Expr, env)
if err != nil {
return v, NewError(expr, err)
}
if v.Kind() == reflect.Interface {
v = v.Elem()
}
if v.Kind() == reflect.Slice {
v = v.Index(0)
}
if v.IsValid() && v.CanInterface() {
if vme, ok := v.Interface().(*Env); ok {
m, err := vme.Get(ee.Name)
if !m.IsValid() || err != nil {
return NilValue, NewStringError(expr, fmt.Sprintf("Invalid operation '%s'", ee.Name))
}
return m, nil
}
}
m := v.MethodByName(ee.Name)
if !m.IsValid() {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() == reflect.Struct {
m = v.FieldByName(ee.Name)
if !m.IsValid() {
return NilValue, NewStringError(expr, fmt.Sprintf("Invalid operation '%s'", ee.Name))
}
} else if v.Kind() == reflect.Map {
m = v.MapIndex(reflect.ValueOf(ee.Name))
if !m.IsValid() {
return NilValue, NewStringError(expr, fmt.Sprintf("Invalid operation '%s'", ee.Name))
}
} else {
return NilValue, NewStringError(expr, fmt.Sprintf("Invalid operation '%s'", ee.Name))
}
v = m
} else {
v = m
}
default:
return NilValue, NewStringError(expr, "Invalid operation for the value")
}
if !v.CanAddr() {
i := v.Interface()
return reflect.ValueOf(&i), nil
}
return v.Addr(), nil
case *ast.UnaryExpr:
v, err := invokeExpr(e.Expr, env)
if err != nil {
return v, NewError(expr, err)
}
switch e.Operator {
case "-":
if v.Kind() == reflect.Float64 {
return reflect.ValueOf(-v.Float()), nil
}
return reflect.ValueOf(-v.Int()), nil
case "^":
return reflect.ValueOf(^toInt64(v)), nil
case "!":
return reflect.ValueOf(!toBool(v)), nil
default:
return NilValue, NewStringError(e, "Unknown operator ''")
}
case *ast.ParenExpr:
v, err := invokeExpr(e.SubExpr, env)
if err != nil {
return v, NewError(expr, err)
}
return v, nil
case *ast.FuncExpr:
f := reflect.ValueOf(func(expr *ast.FuncExpr, env *Env) Func {
return func(args ...reflect.Value) (reflect.Value, error) {
if !expr.VarArg {
if len(args) != len(expr.Args) {
return NilValue, NewStringError(expr, "Arguments Number of mismatch")
}
}
newenv := env.NewEnv()
if expr.VarArg {
newenv.Define(expr.Args[0], reflect.ValueOf(args))
} else {
for i, arg := range expr.Args {
newenv.Define(arg, args[i])
}
}
rr, err := Run(expr.Stmts, newenv)
if err == ReturnError {
err = nil
rr = rr.Interface().(reflect.Value)
}
return rr, err
}
}(e, env))
env.Define(e.Name, f)
return f, nil
case *ast.MemberExpr:
v, err := invokeExpr(e.Expr, env)
if err != nil {
return v, NewError(expr, err)
}
if v.Kind() == reflect.Interface {
v = v.Elem()
}
if v.Kind() == reflect.Slice {
v = v.Index(0)
}
if v.IsValid() && v.CanInterface() {
if vme, ok := v.Interface().(*Env); ok {
m, err := vme.Get(e.Name)
if !m.IsValid() || err != nil {
return NilValue, NewStringError(expr, fmt.Sprintf("Invalid operation '%s'", e.Name))
}
return m, nil
}
}
m := v.MethodByName(e.Name)
if !m.IsValid() {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() == reflect.Struct {
m = v.FieldByName(e.Name)
if !m.IsValid() {
return NilValue, NewStringError(expr, fmt.Sprintf("Invalid operation '%s'", e.Name))
}
} else if v.Kind() == reflect.Map {
m = v.MapIndex(reflect.ValueOf(e.Name))
if !m.IsValid() {
return NilValue, NewStringError(expr, fmt.Sprintf("Invalid operation '%s'", e.Name))
}
} else {
return NilValue, NewStringError(expr, fmt.Sprintf("Invalid operation '%s'", e.Name))
}
}
return m, nil
case *ast.ItemExpr:
v, err := invokeExpr(e.Value, env)
if err != nil {
return v, NewError(expr, err)
}
i, err := invokeExpr(e.Index, env)
if err != nil {
return i, NewError(expr, err)
}
if v.Kind() == reflect.Interface {
v = v.Elem()
}
if v.Kind() == reflect.Array || v.Kind() == reflect.Slice {
if i.Kind() != reflect.Int && i.Kind() != reflect.Int64 {
return NilValue, NewStringError(expr, "Array index should be int")
}
ii := int(i.Int())
if ii < 0 || ii >= v.Len() {
return NilValue, nil
}
return v.Index(ii), nil
}
if v.Kind() == reflect.Map {
if i.Kind() != reflect.String {
return NilValue, NewStringError(expr, "Map key should be string")
}
return v.MapIndex(i), nil
}
if v.Kind() == reflect.String {
rs := []rune(v.Interface().(string))
ii := int(i.Int())
if ii < 0 || ii >= len(rs) {
return NilValue, nil
}
return reflect.ValueOf(rs[ii]), nil
}
return v, NewStringError(expr, "Invalid operation")
case *ast.SliceExpr:
v, err := invokeExpr(e.Value, env)
if err != nil {
return v, NewError(expr, err)
}
rb, err := invokeExpr(e.Begin, env)
if err != nil {
return rb, NewError(expr, err)
}
re, err := invokeExpr(e.End, env)
if err != nil {
return re, NewError(expr, err)
}
if v.Kind() == reflect.Interface {
v = v.Elem()
}
if v.Kind() == reflect.Array || v.Kind() == reflect.Slice {
if rb.Kind() != reflect.Int && rb.Kind() != reflect.Int64 {
return NilValue, NewStringError(expr, "Array index should be int")
}
if re.Kind() != reflect.Int && re.Kind() != reflect.Int64 {
return NilValue, NewStringError(expr, "Array index should be int")
}
ii := int(rb.Int())
if ii < 0 || ii > v.Len() {
return NilValue, nil
}
ij := int(re.Int())
if ij < 0 || ij > v.Len() {
return v, nil
}
return v.Slice(ii, ij), nil
}
if v.Kind() == reflect.String {
if rb.Kind() != reflect.Int && rb.Kind() != reflect.Int64 {
return NilValue, NewStringError(expr, "Array index should be int")
}
if re.Kind() != reflect.Int && re.Kind() != reflect.Int64 {
return NilValue, NewStringError(expr, "Array index should be int")
}
r := []rune(v.String())
ii := int(rb.Int())
if ii < 0 || ii >= len(r) {
return NilValue, nil
}
ij := int(re.Int())
if ij < 0 || ij >= len(r) {
return NilValue, nil
}
return reflect.ValueOf(string(r[ii:ij])), nil
}
return v, NewStringError(expr, "Invalid operation")
case *ast.AssocExpr:
switch e.Operator {
case "++":
if alhs, ok := e.Lhs.(*ast.IdentExpr); ok {
v, err := env.Get(alhs.Lit)
if err != nil {
return v, err
}
if v.Kind() == reflect.Float64 {
v = reflect.ValueOf(toFloat64(v) + 1.0)
} else {
v = reflect.ValueOf(toInt64(v) + 1)
}
if env.Set(alhs.Lit, v) != nil {
env.Define(alhs.Lit, v)
}
return v, nil
}
case "--":
if alhs, ok := e.Lhs.(*ast.IdentExpr); ok {
v, err := env.Get(alhs.Lit)
if err != nil {
return v, err
}
if v.Kind() == reflect.Float64 {
v = reflect.ValueOf(toFloat64(v) - 1.0)
} else {
v = reflect.ValueOf(toInt64(v) - 1)
}
if env.Set(alhs.Lit, v) != nil {
env.Define(alhs.Lit, v)
}
return v, nil
}
}
v, err := invokeExpr(&ast.BinOpExpr{Lhs: e.Lhs, Operator: e.Operator[0:1], Rhs: e.Rhs}, env)
if err != nil {
return v, err
}
if v.Kind() == reflect.Interface {
v = v.Elem()
}
return invokeLetExpr(e.Lhs, v, env)
case *ast.LetExpr:
rv, err := invokeExpr(e.Rhs, env)
if err != nil {
return rv, NewError(e, err)
}
if rv.Kind() == reflect.Interface {
rv = rv.Elem()
}
return invokeLetExpr(e.Lhs, rv, env)
case *ast.LetsExpr:
rv := NilValue
var err error
vs := []interface{}{}
for _, rhs := range e.Rhss {
rv, err = invokeExpr(rhs, env)
if err != nil {
return rv, NewError(rhs, err)
}
if rv == NilValue {
vs = append(vs, nil)
} else if rv.IsValid() && rv.CanInterface() {
vs = append(vs, rv.Interface())
} else {
vs = append(vs, nil)
}
}
rvs := reflect.ValueOf(vs)
if len(e.Lhss) > 1 && rvs.Len() == 1 {
item := rvs.Index(0)
if item.Kind() == reflect.Interface {
item = item.Elem()
}
if item.Kind() == reflect.Slice {
rvs = item
}
}
for i, lhs := range e.Lhss {
if i >= rvs.Len() {
break
}
v := rvs.Index(i)
if v.Kind() == reflect.Interface {
v = v.Elem()
}
_, err = invokeLetExpr(lhs, v, env)
if err != nil {
return rvs, NewError(lhs, err)
}
}
if rvs.Len() == 1 {
return rvs.Index(0), nil
}
return rvs, nil
//case *ast.NewExpr:
// println("NEW")
// return NilValue, nil
case *ast.BinOpExpr:
lhsV := NilValue
rhsV := NilValue
var err error
lhsV, err = invokeExpr(e.Lhs, env)
if err != nil {
return lhsV, NewError(expr, err)
}
if lhsV.Kind() == reflect.Interface {
lhsV = lhsV.Elem()
}
if e.Rhs != nil {
rhsV, err = invokeExpr(e.Rhs, env)
if err != nil {
return rhsV, NewError(expr, err)
}
if rhsV.Kind() == reflect.Interface {
rhsV = rhsV.Elem()
}
}
switch e.Operator {
case "+":
if lhsV.Kind() == reflect.String || rhsV.Kind() == reflect.String {
return reflect.ValueOf(toString(lhsV) + toString(rhsV)), nil
}
if (lhsV.Kind() == reflect.Array || lhsV.Kind() == reflect.Slice) && (rhsV.Kind() != reflect.Array && rhsV.Kind() != reflect.Slice) {
return reflect.Append(lhsV, rhsV), nil
}
if (lhsV.Kind() == reflect.Array || lhsV.Kind() == reflect.Slice) && (rhsV.Kind() == reflect.Array || rhsV.Kind() == reflect.Slice) {
return reflect.AppendSlice(lhsV, rhsV), nil
}
if lhsV.Kind() == reflect.Float64 || rhsV.Kind() == reflect.Float64 {
return reflect.ValueOf(toFloat64(lhsV) + toFloat64(rhsV)), nil
}
return reflect.ValueOf(toInt64(lhsV) + toInt64(rhsV)), nil
case "-":
if lhsV.Kind() == reflect.Float64 || rhsV.Kind() == reflect.Float64 {
return reflect.ValueOf(toFloat64(lhsV) - toFloat64(rhsV)), nil
}
return reflect.ValueOf(toInt64(lhsV) - toInt64(rhsV)), nil
case "*":
if lhsV.Kind() == reflect.String && (rhsV.Kind() == reflect.Int || rhsV.Kind() == reflect.Int32 || rhsV.Kind() == reflect.Int64) {
return reflect.ValueOf(strings.Repeat(toString(lhsV), int(toInt64(rhsV)))), nil
}
if lhsV.Kind() == reflect.Float64 || rhsV.Kind() == reflect.Float64 {
return reflect.ValueOf(toFloat64(lhsV) * toFloat64(rhsV)), nil
}
return reflect.ValueOf(toInt64(lhsV) * toInt64(rhsV)), nil
case "/":
return reflect.ValueOf(toFloat64(lhsV) / toFloat64(rhsV)), nil
case "%":
return reflect.ValueOf(toInt64(lhsV) % toInt64(rhsV)), nil
case "==":
return reflect.ValueOf(equal(lhsV, rhsV)), nil
case "!=":
return reflect.ValueOf(equal(lhsV, rhsV) == false), nil
case ">":
return reflect.ValueOf(toFloat64(lhsV) > toFloat64(rhsV)), nil
case ">=":
return reflect.ValueOf(toFloat64(lhsV) >= toFloat64(rhsV)), nil
case "<":
return reflect.ValueOf(toFloat64(lhsV) < toFloat64(rhsV)), nil
case "<=":
return reflect.ValueOf(toFloat64(lhsV) <= toFloat64(rhsV)), nil
case "|":
return reflect.ValueOf(toInt64(lhsV) | toInt64(rhsV)), nil
case "||":
if toBool(lhsV) {
return lhsV, nil
}
return rhsV, nil
case "&":
return reflect.ValueOf(toInt64(lhsV) & toInt64(rhsV)), nil
case "&&":
if toBool(lhsV) {
return rhsV, nil
}
return lhsV, nil
case "**":
if lhsV.Kind() == reflect.Float64 {
return reflect.ValueOf(math.Pow(toFloat64(lhsV), toFloat64(rhsV))), nil
}
return reflect.ValueOf(int64(math.Pow(toFloat64(lhsV), toFloat64(rhsV)))), nil
case ">>":
return reflect.ValueOf(toInt64(lhsV) >> uint64(toInt64(rhsV))), nil
case "<<":
return reflect.ValueOf(toInt64(lhsV) << uint64(toInt64(rhsV))), nil
default:
return NilValue, NewStringError(expr, "Unknown operator")
}
case *ast.ConstExpr:
switch e.Value {
case "true":
return reflect.ValueOf(true), nil
case "false":
return reflect.ValueOf(false), nil
}
return reflect.ValueOf(nil), nil
case *ast.AnonCallExpr:
f, err := invokeExpr(e.Expr, env)
if err != nil {
return f, NewError(expr, err)
}
if f.Kind() == reflect.Interface {
f = f.Elem()
}
if f.Kind() != reflect.Func {
return f, NewStringError(expr, "Unknown function")
}
return invokeExpr(&ast.CallExpr{Func: f, SubExprs: e.SubExprs, VarArg: e.VarArg, Go: e.Go}, env)
case *ast.CallExpr:
f := NilValue
if e.Func != nil {
f = e.Func.(reflect.Value)
} else {
var err error
ff, err := env.Get(e.Name)
if err != nil {
return f, err
}
f = ff
}
_, isReflect := f.Interface().(Func)
args := []reflect.Value{}
l := len(e.SubExprs)
for i, expr := range e.SubExprs {
arg, err := invokeExpr(expr, env)
if err != nil {
return arg, NewError(expr, err)
}
if i < f.Type().NumIn() {
if !f.Type().IsVariadic() {
it := f.Type().In(i)
if arg.Kind().String() == "unsafe.Pointer" {
arg = reflect.New(it).Elem()
}
if arg.Kind() != it.Kind() && arg.IsValid() && arg.Type().ConvertibleTo(it) {
arg = arg.Convert(it)
} else if arg.Kind() == reflect.Func {
if _, isFunc := arg.Interface().(Func); isFunc {
rfunc := arg
arg = reflect.MakeFunc(it, func(args []reflect.Value) []reflect.Value {
for i := range args {
args[i] = reflect.ValueOf(args[i])
}
if e.Go {
go func() {
rfunc.Call(args)
}()
return []reflect.Value{}
}
return rfunc.Call(args)[:it.NumOut()]
})
}
} else if !arg.IsValid() {
arg = reflect.Zero(it)
}
}
}
if !arg.IsValid() {
arg = NilValue
}
if !isReflect {
if e.VarArg && i == l-1 {
for j := 0; j < arg.Len(); j++ {
args = append(args, arg.Index(j).Elem())
}
} else {
args = append(args, arg)
}
} else {
if arg.Kind() == reflect.Interface {
arg = arg.Elem()
}
if e.VarArg && i == l-1 {
for j := 0; j < arg.Len(); j++ {
args = append(args, reflect.ValueOf(arg.Index(j).Elem()))
}
} else {
args = append(args, reflect.ValueOf(arg))
}
}
}
ret := NilValue
var err error
fnc := func() {
defer func() {
if os.Getenv("ANKO_DEBUG") == "" {
if ex := recover(); ex != nil {
if e, ok := ex.(error); ok {
err = e
} else {
err = errors.New(fmt.Sprint(ex))
}
}
}
}()
if f.Kind() == reflect.Interface {
f = f.Elem()
}
rets := f.Call(args)
if isReflect {
ev := rets[1].Interface()
if ev != nil {
err = ev.(error)
}
ret = rets[0].Interface().(reflect.Value)
} else {
for i, expr := range e.SubExprs {
if ae, ok := expr.(*ast.AddrExpr); ok {
if id, ok := ae.Expr.(*ast.IdentExpr); ok {
invokeLetExpr(id, args[i].Elem().Elem(), env)
}
}
}
if f.Type().NumOut() == 1 {
ret = rets[0]
} else {
var result []interface{}
for _, r := range rets {
result = append(result, r.Interface())
}
ret = reflect.ValueOf(result)
}
}
}
if e.Go {
go fnc()
return NilValue, nil
}
fnc()
if err != nil {
return ret, NewError(expr, err)
}
return ret, nil
case *ast.TernaryOpExpr:
rv, err := invokeExpr(e.Expr, env)
if err != nil {
return rv, NewError(expr, err)
}
if toBool(rv) {
lhsV, err := invokeExpr(e.Lhs, env)
if err != nil {
return lhsV, NewError(expr, err)
}
return lhsV, nil
}
rhsV, err := invokeExpr(e.Rhs, env)
if err != nil {
return rhsV, NewError(expr, err)
}
return rhsV, nil
case *ast.MakeChanExpr:
typ, err := env.Type(e.Type)
if err != nil {
return NilValue, err
}
var size int
if e.SizeExpr != nil {
rv, err := invokeExpr(e.SizeExpr, env)
if err != nil {
return NilValue, err
}
size = int(toInt64(rv))
}
return func() (reflect.Value, error) {
defer func() {
if os.Getenv("ANKO_DEBUG") == "" {
if ex := recover(); ex != nil {
if e, ok := ex.(error); ok {
err = e
} else {
err = errors.New(fmt.Sprint(ex))
}
}
}
}()
return reflect.MakeChan(reflect.ChanOf(reflect.BothDir, typ), size), nil
}()
case *ast.MakeArrayExpr:
typ, err := env.Type(e.Type)
if err != nil {
return NilValue, err
}
var alen int
if e.LenExpr != nil {
rv, err := invokeExpr(e.LenExpr, env)
if err != nil {
return NilValue, err
}
alen = int(toInt64(rv))
}
var acap int
if e.CapExpr != nil {
rv, err := invokeExpr(e.CapExpr, env)
if err != nil {
return NilValue, err
}
acap = int(toInt64(rv))
} else {
acap = alen
}
return func() (reflect.Value, error) {
defer func() {
if os.Getenv("ANKO_DEBUG") == "" {
if ex := recover(); ex != nil {
if e, ok := ex.(error); ok {
err = e
} else {
err = errors.New(fmt.Sprint(ex))
}
}
}
}()
return reflect.MakeSlice(reflect.SliceOf(typ), alen, acap), nil
}()
case *ast.ChanExpr:
rhs, err := invokeExpr(e.Rhs, env)
if err != nil {
return NilValue, NewError(expr, err)
}
if e.Lhs == nil {
if rhs.Kind() == reflect.Chan {
rv, _ := rhs.Recv()
return rv, nil
}
} else {
lhs, err := invokeExpr(e.Lhs, env)
if err != nil {
return NilValue, NewError(expr, err)
}
if lhs.Kind() == reflect.Chan {
lhs.Send(rhs)
return NilValue, nil
} else if rhs.Kind() == reflect.Chan {
rv, _ := rhs.Recv()
return invokeLetExpr(e.Lhs, rv, env)
}
}
return NilValue, NewStringError(expr, "Invalid operation for chan")
default:
return NilValue, NewStringError(expr, "Unknown expression")
}
}