github.com/informationsea/shellflow@v0.1.3/flowscript/flowscript_evaluate.go (about)

     1  package flowscript
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  )
     8  
     9  var emptyEvaluableArray []Evaluable
    10  
    11  // Evaluable is interface of evaluable blocks
    12  type Evaluable interface {
    13  	Evaluate(env Environment) (Value, error)
    14  	String() string
    15  	SubEvaluable() []Evaluable
    16  }
    17  
    18  type BadEvaluable struct{}
    19  
    20  func (x BadEvaluable) Evaluate(env Environment) (Value, error) {
    21  	return nil, errors.New("bad access")
    22  }
    23  
    24  func (x BadEvaluable) String() string {
    25  	return "bad access"
    26  }
    27  
    28  func (x BadEvaluable) SubEvaluable() []Evaluable {
    29  	return emptyEvaluableArray
    30  }
    31  
    32  type ValueEvaluable struct {
    33  	value Value
    34  }
    35  
    36  func (x ValueEvaluable) String() string {
    37  	return x.value.String()
    38  }
    39  
    40  func (x ValueEvaluable) Evaluate(env Environment) (Value, error) {
    41  	return x.value, nil
    42  }
    43  
    44  func (x ValueEvaluable) SubEvaluable() []Evaluable {
    45  	return emptyEvaluableArray
    46  }
    47  
    48  // Variable is one of Evaluable value
    49  type Variable struct {
    50  	Name string
    51  }
    52  
    53  // Evaluate variable and get value
    54  func (v *Variable) Evaluate(env Environment) (Value, error) {
    55  	return env.Value(v.Name)
    56  }
    57  
    58  func (v *Variable) String() string {
    59  	return v.Name
    60  }
    61  
    62  func (x Variable) SubEvaluable() []Evaluable {
    63  	return emptyEvaluableArray
    64  }
    65  
    66  type ArrayAccess struct {
    67  	Array      Evaluable
    68  	ArrayIndex Evaluable
    69  }
    70  
    71  func (v *ArrayAccess) String() string {
    72  	return fmt.Sprintf("%s[%s]", v.Array, v.ArrayIndex)
    73  }
    74  
    75  func (v *ArrayAccess) Evaluate(env Environment) (Value, error) {
    76  	array, err := v.Array.Evaluate(env)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	index, err2 := v.ArrayIndex.Evaluate(env)
    81  	if err2 != nil {
    82  		return nil, err2
    83  	}
    84  
    85  	if array, ok := array.(ArrayValue); ok {
    86  		if index, ok := index.(IntValue); ok {
    87  			if int64(len(array.value)) <= index.value || index.value < 0 {
    88  				return nil, fmt.Errorf("out of index error %s %d", v.Array, v.ArrayIndex)
    89  			}
    90  			return array.value[index.value], nil
    91  		}
    92  		return nil, fmt.Errorf("%s is not int", v.ArrayIndex)
    93  	}
    94  
    95  	if mapValue, ok := array.(MapValue); ok {
    96  		if mapKey, err := index.AsString(); err == nil {
    97  			value, ok := mapValue.value[mapKey]
    98  			if !ok {
    99  				return nil, fmt.Errorf("%s is not found in %s", mapKey, v.Array)
   100  			}
   101  			return value, nil
   102  		}
   103  		return nil, fmt.Errorf("%s is not string", v.ArrayIndex)
   104  	}
   105  	return nil, fmt.Errorf("%s is not array or map", v.Array)
   106  }
   107  
   108  func (x *ArrayAccess) SubEvaluable() []Evaluable {
   109  	evaluables := [...]Evaluable{x.Array, x.ArrayIndex}
   110  	return evaluables[:]
   111  }
   112  
   113  type AssignExpression struct {
   114  	variable Evaluable
   115  	exp      Evaluable
   116  }
   117  
   118  func (v *AssignExpression) String() string {
   119  	return fmt.Sprintf("%s = %s", v.variable, v.exp)
   120  }
   121  
   122  func (v *AssignExpression) Evaluate(env Environment) (Value, error) {
   123  	r, e := v.exp.Evaluate(env)
   124  	if e != nil {
   125  		return nil, e
   126  	}
   127  
   128  	variable, ok := v.variable.(*Variable)
   129  	if !ok {
   130  		return nil, fmt.Errorf("%s is not variable", v.variable)
   131  	}
   132  
   133  	e = env.Assign(variable.Name, r)
   134  	if e != nil {
   135  		return nil, e
   136  	}
   137  
   138  	return r, nil
   139  }
   140  
   141  func (x *AssignExpression) SubEvaluable() []Evaluable {
   142  	evaluables := [...]Evaluable{x.variable, x.exp}
   143  	return evaluables[:]
   144  }
   145  
   146  type JoinedExpression struct {
   147  	exp1 Evaluable
   148  	exp2 Evaluable
   149  }
   150  
   151  func (v *JoinedExpression) String() string {
   152  	return fmt.Sprintf("%s; %s", v.exp1, v.exp2)
   153  }
   154  
   155  func (v *JoinedExpression) Evaluate(env Environment) (Value, error) {
   156  	_, e := v.exp1.Evaluate(env)
   157  	if e != nil {
   158  		return nil, e
   159  	}
   160  	return v.exp2.Evaluate(env)
   161  }
   162  
   163  func (x *JoinedExpression) SubEvaluable() []Evaluable {
   164  	evaluables := [...]Evaluable{x.exp1, x.exp2}
   165  	return evaluables[:]
   166  }
   167  
   168  type PlusExpression struct {
   169  	exp1 Evaluable
   170  	exp2 Evaluable
   171  }
   172  
   173  func (v *PlusExpression) String() string {
   174  	return fmt.Sprintf("%s + %s", v.exp1, v.exp2)
   175  }
   176  
   177  func (v *PlusExpression) Evaluate(env Environment) (Value, error) {
   178  	r1, e := v.exp1.Evaluate(env)
   179  	if e != nil {
   180  		return nil, e
   181  	}
   182  	r2, e := v.exp2.Evaluate(env)
   183  	if e != nil {
   184  		return nil, e
   185  	}
   186  
   187  	if i1, ok := r1.(IntValue); ok {
   188  		if i2, ok := r2.(IntValue); ok {
   189  			return IntValue{i1.value + i2.value}, nil
   190  		}
   191  	}
   192  
   193  	if s1, err := r1.AsString(); err == nil {
   194  		if s2, err2 := r2.AsString(); err2 == nil {
   195  			return StringValue{s1 + s2}, nil
   196  		}
   197  	}
   198  	return nil, fmt.Errorf("cannot combine %s and %s", v.exp1, v.exp2)
   199  }
   200  
   201  func (x *PlusExpression) SubEvaluable() []Evaluable {
   202  	evaluables := [...]Evaluable{x.exp1, x.exp2}
   203  	return evaluables[:]
   204  }
   205  
   206  type NumericOperationExpression struct {
   207  	exp1     Evaluable
   208  	exp2     Evaluable
   209  	operator string
   210  }
   211  
   212  func (v *NumericOperationExpression) String() string {
   213  	return fmt.Sprintf("%s %s %s", v.exp1, v.operator, v.exp2)
   214  }
   215  
   216  func (v *NumericOperationExpression) Evaluate(env Environment) (Value, error) {
   217  	r1, e := v.exp1.Evaluate(env)
   218  	if e != nil {
   219  		return nil, e
   220  	}
   221  	r2, e := v.exp2.Evaluate(env)
   222  	if e != nil {
   223  		return nil, e
   224  	}
   225  
   226  	if i1, err := r1.AsInt(); err == nil {
   227  		if i2, err2 := r2.AsInt(); err2 == nil {
   228  			switch v.operator {
   229  			case "+":
   230  				return IntValue{i1 + i2}, nil
   231  			case "-":
   232  				return IntValue{i1 - i2}, nil
   233  			case "*":
   234  				return IntValue{i1 * i2}, nil
   235  			case "/":
   236  				return IntValue{i1 / i2}, nil
   237  			}
   238  
   239  		}
   240  	}
   241  
   242  	return nil, fmt.Errorf("cannot calculate %s", v.String())
   243  }
   244  
   245  func (x *NumericOperationExpression) SubEvaluable() []Evaluable {
   246  	evaluables := [...]Evaluable{x.exp1, x.exp2}
   247  	return evaluables[:]
   248  }
   249  
   250  type FunctionCall struct {
   251  	function Evaluable
   252  	args     []Evaluable
   253  }
   254  
   255  func (v *FunctionCall) String() string {
   256  	var b strings.Builder
   257  	b.WriteString(v.function.String())
   258  	b.WriteString("(")
   259  	first := true
   260  	for _, x := range v.args {
   261  		if !first {
   262  			b.WriteString(", ")
   263  		}
   264  		first = false
   265  		b.WriteString(x.String())
   266  	}
   267  
   268  	b.WriteString(")")
   269  	return b.String()
   270  }
   271  
   272  func (v *FunctionCall) Evaluate(env Environment) (Value, error) {
   273  	functionValue, err := v.function.Evaluate(env)
   274  	if err != nil {
   275  		return nil, err
   276  	}
   277  
   278  	if function, ok := functionValue.(FunctionValue); ok {
   279  		values := make([]Value, len(v.args))
   280  		for i, x := range v.args {
   281  			ev, ee := x.Evaluate(env)
   282  			if ee != nil {
   283  				return nil, ee
   284  			}
   285  			values[i] = ev
   286  		}
   287  
   288  		return function.value.call(values)
   289  	}
   290  	return nil, fmt.Errorf("%s is not function", functionValue)
   291  }
   292  
   293  func (x *FunctionCall) SubEvaluable() []Evaluable {
   294  	evaluables := append(x.args, x.function)
   295  	return evaluables[:]
   296  }
   297  
   298  type ArrayExpression struct {
   299  	values []Evaluable
   300  }
   301  
   302  func (v *ArrayExpression) String() string {
   303  	var b strings.Builder
   304  	b.WriteString("[")
   305  	first := true
   306  	for _, x := range v.values {
   307  		if !first {
   308  			b.WriteString(", ")
   309  		}
   310  		first = false
   311  		b.WriteString(x.String())
   312  	}
   313  
   314  	b.WriteString("]")
   315  	return b.String()
   316  }
   317  
   318  func (v *ArrayExpression) Evaluate(env Environment) (Value, error) {
   319  	values := make([]Value, len(v.values))
   320  	for i, x := range v.values {
   321  		ev, ee := x.Evaluate(env)
   322  		if ee != nil {
   323  			return nil, ee
   324  		}
   325  		values[i] = ev
   326  	}
   327  
   328  	return ArrayValue{values}, nil
   329  }
   330  
   331  func (x *ArrayExpression) SubEvaluable() []Evaluable {
   332  	return x.values
   333  }