| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 | /* * EliasDB * * Copyright 2016 Matthias Ladkau. All rights reserved. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */package interpreterimport (	"devt.de/krotik/common/datautil"	"devt.de/krotik/eliasdb/eql/parser"	"devt.de/krotik/eliasdb/graph/data")// Not Implemented Runtime// =======================/*Special runtime for not implemented constructs.*/type invalidRuntime struct {	rtp  *eqlRuntimeProvider	node *parser.ASTNode}/*invalidRuntimeInst returns a new runtime component instance.*/func invalidRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {	return &invalidRuntime{rtp, node}}/*Validate this node and all its child nodes.*/func (rt *invalidRuntime) Validate() error {	return rt.rtp.newRuntimeError(ErrInvalidConstruct, rt.node.Name, rt.node)}/*Eval evaluate this runtime component.*/func (rt *invalidRuntime) Eval() (interface{}, error) {	return nil, rt.rtp.newRuntimeError(ErrInvalidConstruct, rt.node.Name, rt.node)}/*Evaluate the value as a condition component.*/func (rt *invalidRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {	return nil, rt.rtp.newRuntimeError(ErrInvalidConstruct, rt.node.Name, rt.node)}// Value Runtime// =============/*Runtime for values*/type valueRuntime struct {	rtp             *eqlRuntimeProvider	node            *parser.ASTNode	isNodeAttrValue bool	isEdgeAttrValue bool	nestedValuePath []string	condVal         string}/*valueRuntimeInst returns a new runtime component instance.*/func valueRuntimeInst(rtp *eqlRuntimeProvider, node *parser.ASTNode) parser.Runtime {	return &valueRuntime{rtp, node, false, false, nil, ""}}/*Validate this node and all its child nodes.*/func (rt *valueRuntime) Validate() error {	return nil}/*Eval evaluate this runtime component.*/func (rt *valueRuntime) Eval() (interface{}, error) {	return rt.node.Token.Val, nil}/*Evaluate the value as a condition component.*/func (rt *valueRuntime) CondEval(node data.Node, edge data.Edge) (interface{}, error) {	// Check known constants	if rt.node.Token.ID == parser.TokenAT {		// Try to lookup a function		funcName := rt.node.Children[0].Token.Val		funcInst, ok := whereFunc[funcName]		if !ok {			return nil, rt.rtp.newRuntimeError(ErrInvalidConstruct,				"Unknown function: "+funcName, rt.node)		}		// Execute the function and return its result value		return funcInst(rt.node, rt.rtp, node, edge)	} else if rt.node.Token.ID == parser.TokenTRUE {		return true, nil	} else if rt.node.Token.ID == parser.TokenFALSE {		return false, nil	} else if rt.node.Token.ID == parser.TokenNULL {		return nil, nil	} else if rt.node.Name == parser.NodeLIST {		// Collect items of a list		var list []interface{}		for _, item := range rt.node.Children {			val, _ := item.Runtime.(CondRuntime).CondEval(node, edge)			list = append(list, val)		}		return list, nil	}	// Check if this is describing a node or edge value	var valRet interface{}	if rt.isNodeAttrValue {		// Check for nested values		if rt.nestedValuePath != nil {			if valMap, ok := node.Attr(rt.nestedValuePath[0]).(map[string]interface{}); ok {				valRet, _ = datautil.GetNestedValue(valMap, rt.nestedValuePath[1:])			}		} else {			valRet = node.Attr(rt.condVal)		}		return valRet, nil	} else if rt.isEdgeAttrValue {		if edge == nil {			return nil, rt.rtp.newRuntimeError(ErrInvalidWhere,				"No edge data available at this level", rt.node)		}		return edge.Attr(rt.condVal), nil	}	// Must be a constant value	return rt.condVal, nil}
 |