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 }