/* * 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 ecal import ( "fmt" "io/ioutil" "path/filepath" "strings" "devt.de/krotik/common/fileutil" "devt.de/krotik/ecal/cli/tool" "devt.de/krotik/ecal/stdlib" "devt.de/krotik/ecal/util" "devt.de/krotik/eliasdb/config" "devt.de/krotik/eliasdb/ecal/dbfunc" "devt.de/krotik/eliasdb/graph" ) /* ScriptingInterpreter models a ECAL script interpreter instance. */ type ScriptingInterpreter struct { GM *graph.Manager // GraphManager for the interpreter Dir string // Root dir for interpreter EntryFile string // Entry file for the program LogLevel string // Log level string (Debug, Info, Error) LogFile string // Logfile (blank for stdout) RunDebugServer bool // Run a debug server DebugServerHost string // Debug server host DebugServerPort string // Debug server port } /* NewScriptingInterpreter returns a new ECAL scripting interpreter. */ func NewScriptingInterpreter(scriptFolder string, gm *graph.Manager) *ScriptingInterpreter { return &ScriptingInterpreter{ GM: gm, Dir: scriptFolder, EntryFile: filepath.Join(scriptFolder, config.Str(config.ECALEntryScript)), LogLevel: config.Str(config.ECALLogLevel), LogFile: config.Str(config.ECALLogFile), RunDebugServer: config.Bool(config.EnableECALDebugServer), DebugServerHost: config.Str(config.ECALDebugServerHost), DebugServerPort: config.Str(config.ECALDebugServerPort), } } /* dummyEntryFile is a small valid ECAL which does not do anything. It is used as the default entry file if no entry file exists. */ const dummyEntryFile = `0 # Write your ECAL code here ` /* Run runs the ECAL scripting interpreter. */ func (si *ScriptingInterpreter) Run() error { var err error // Ensure we have a dummy entry point if ok, _ := fileutil.PathExists(si.EntryFile); !ok { err = ioutil.WriteFile(si.EntryFile, []byte(dummyEntryFile), 0600) } if err == nil { i := tool.NewCLIInterpreter() i.Dir = &si.Dir i.LogFile = &si.LogFile i.LogLevel = &si.LogLevel i.EntryFile = si.EntryFile i.LoadPlugins = true i.CreateRuntimeProvider("eliasdb-runtime") // Adding functions stdlib.AddStdlibPkg("db", "EliasDB related functions") stdlib.AddStdlibFunc("db", "storeNode", &dbfunc.StoreNodeFunc{GM: si.GM}) stdlib.AddStdlibFunc("db", "removeNode", &dbfunc.RemoveNodeFunc{GM: si.GM}) stdlib.AddStdlibFunc("db", "fetchNode", &dbfunc.FetchNodeFunc{GM: si.GM}) stdlib.AddStdlibFunc("db", "storeEdge", &dbfunc.StoreEdgeFunc{GM: si.GM}) stdlib.AddStdlibFunc("db", "removeEdge", &dbfunc.RemoveEdgeFunc{GM: si.GM}) stdlib.AddStdlibFunc("db", "fetchEdge", &dbfunc.FetchEdgeFunc{GM: si.GM}) stdlib.AddStdlibFunc("db", "traverse", &dbfunc.TraverseFunc{GM: si.GM}) stdlib.AddStdlibFunc("db", "newTrans", &dbfunc.NewTransFunc{GM: si.GM}) stdlib.AddStdlibFunc("db", "newRollingTrans", &dbfunc.NewRollingTransFunc{GM: si.GM}) stdlib.AddStdlibFunc("db", "commit", &dbfunc.CommitTransFunc{GM: si.GM}) stdlib.AddStdlibFunc("db", "query", &dbfunc.QueryFunc{GM: si.GM}) stdlib.AddStdlibFunc("db", "graphQL", &dbfunc.GraphQLFunc{GM: si.GM}) stdlib.AddStdlibFunc("db", "raiseGraphEventHandled", &dbfunc.RaiseGraphEventHandledFunc{}) if err == nil { if si.RunDebugServer { di := tool.NewCLIDebugInterpreter(i) addr := fmt.Sprintf("%v:%v", si.DebugServerHost, si.DebugServerPort) di.DebugServerAddr = &addr di.RunDebugServer = &si.RunDebugServer falseFlag := false di.EchoDebugServer = &falseFlag di.Interactive = &falseFlag di.BreakOnStart = &falseFlag trueFlag := true di.BreakOnError = &trueFlag err = di.Interpret() } else { err = i.Interpret(false) } // Rules for the GraphManager are loaded after the code has been // executed and all rules have been added. The ECA processor can now be started. i.RuntimeProvider.Processor.Start() // EliasDB graph events can not be forwarded to ECAL via the eventbridge. si.GM.SetGraphRule(&EventBridge{ Processor: i.RuntimeProvider.Processor, Logger: i.RuntimeProvider.Logger, }) } } // Include a traceback if possible if ss, ok := err.(util.TraceableRuntimeError); ok { err = fmt.Errorf("%v\n %v", err.Error(), strings.Join(ss.GetTraceString(), "\n ")) } return err }