123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- /*
- * ECAL
- *
- * Copyright 2020 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the MIT
- * License, If a copy of the MIT License was not distributed with this
- * file, You can obtain one at https://opensource.org/licenses/MIT.
- */
- package interpreter
- import (
- "fmt"
- "strconv"
- "strings"
- "devt.de/krotik/ecal/parser"
- "devt.de/krotik/ecal/scope"
- )
- /*
- numberValueRuntime is the runtime component for constant numeric values.
- */
- type numberValueRuntime struct {
- *baseRuntime
- numValue float64 // Numeric value
- }
- /*
- numberValueRuntimeInst returns a new runtime component instance.
- */
- func numberValueRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &numberValueRuntime{newBaseRuntime(erp, node), 0}
- }
- /*
- Validate this node and all its child nodes.
- */
- func (rt *numberValueRuntime) Validate() error {
- err := rt.baseRuntime.Validate()
- if err == nil {
- rt.numValue, err = strconv.ParseFloat(rt.node.Token.Val, 64)
- }
- return err
- }
- /*
- Eval evaluate this runtime component.
- */
- func (rt *numberValueRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
- _, err := rt.baseRuntime.Eval(vs, is, tid)
- return rt.numValue, err
- }
- /*
- stringValueRuntime is the runtime component for constant string values.
- */
- type stringValueRuntime struct {
- *baseRuntime
- }
- /*
- stringValueRuntimeInst returns a new runtime component instance.
- */
- func stringValueRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &stringValueRuntime{newBaseRuntime(erp, node)}
- }
- /*
- Eval evaluate this runtime component.
- */
- func (rt *stringValueRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
- _, err := rt.baseRuntime.Eval(vs, is, tid)
- ret := rt.node.Token.Val
- if rt.node.Token.AllowEscapes {
- // Do allow string interpolation if escape sequences are allowed
- for {
- var replace string
- code, ok := rt.GetInfix(ret, "{{", "}}")
- if !ok {
- break
- }
- ast, ierr := parser.ParseWithRuntime(
- fmt.Sprintf("String interpolation: %v", code), code, rt.erp)
- if ierr == nil {
- if ierr = ast.Runtime.Validate(); ierr == nil {
- var res interface{}
- res, ierr = ast.Runtime.Eval(
- vs.NewChild(scope.NameFromASTNode(rt.node)),
- make(map[string]interface{}), tid)
- if ierr == nil {
- replace = fmt.Sprint(res)
- }
- }
- }
- if ierr != nil {
- replace = fmt.Sprintf("#%v", ierr.Error())
- }
- ret = strings.Replace(ret, fmt.Sprintf("{{%v}}", code), replace, 1)
- }
- }
- return ret, err
- }
- func (rt *stringValueRuntime) GetInfix(str string, start string, end string) (string, bool) {
- res := str
- if s := strings.Index(str, start); s >= 0 {
- s += len(start)
- if e := strings.Index(str, end); e >= 0 {
- res = str[s:e]
- }
- }
- return res, res != str
- }
- /*
- mapValueRuntime is the runtime component for map values.
- */
- type mapValueRuntime struct {
- *baseRuntime
- }
- /*
- mapValueRuntimeInst returns a new runtime component instance.
- */
- func mapValueRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &mapValueRuntime{newBaseRuntime(erp, node)}
- }
- /*
- Eval evaluate this runtime component.
- */
- func (rt *mapValueRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
- _, err := rt.baseRuntime.Eval(vs, is, tid)
- m := make(map[interface{}]interface{})
- if err == nil {
- for _, kvp := range rt.node.Children {
- var key, val interface{}
- if err == nil {
- if key, err = kvp.Children[0].Runtime.Eval(vs, is, tid); err == nil {
- if val, err = kvp.Children[1].Runtime.Eval(vs, is, tid); err == nil {
- m[key] = val
- }
- }
- }
- }
- }
- return m, err
- }
- /*
- listValueRuntime is the runtime component for list values.
- */
- type listValueRuntime struct {
- *baseRuntime
- }
- /*
- listValueRuntimeInst returns a new runtime component instance.
- */
- func listValueRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &listValueRuntime{newBaseRuntime(erp, node)}
- }
- /*
- Eval evaluate this runtime component.
- */
- func (rt *listValueRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
- _, err := rt.baseRuntime.Eval(vs, is, tid)
- var l []interface{}
- if err == nil {
- for _, item := range rt.node.Children {
- if err == nil {
- var val interface{}
- if val, err = item.Runtime.Eval(vs, is, tid); err == nil {
- l = append(l, val)
- }
- }
- }
- }
- return l, err
- }
|