Browse Source

feat: Add thread IDs

Matthias Ladkau 3 years ago
parent
commit
490ce0bb0f

+ 2 - 1
cli/tool/debug.go

@@ -146,6 +146,7 @@ func (s *debugTelnetServer) Run() {
 HandleConnection handles an incoming connection.
 HandleConnection handles an incoming connection.
 */
 */
 func (s *debugTelnetServer) HandleConnection(conn net.Conn) {
 func (s *debugTelnetServer) HandleConnection(conn net.Conn) {
+	tid := s.interpreter.RuntimeProvider.NewThreadID()
 	inputReader := bufio.NewReader(conn)
 	inputReader := bufio.NewReader(conn)
 	outputTerminal := interpreter.OutputTerminal(&bufioWriterShim{bufio.NewWriter(conn)})
 	outputTerminal := interpreter.OutputTerminal(&bufioWriterShim{bufio.NewWriter(conn)})
 
 
@@ -163,7 +164,7 @@ func (s *debugTelnetServer) HandleConnection(conn net.Conn) {
 				break
 				break
 			}
 			}
 
 
-			s.interpreter.HandleInput(outputTerminal, line)
+			s.interpreter.HandleInput(outputTerminal, line, tid)
 		}
 		}
 
 
 		if err != nil {
 		if err != nil {

+ 8 - 5
cli/tool/interpret.go

@@ -162,6 +162,8 @@ func (i *CLIInterpreter) Interpret(interactive bool) error {
 
 
 		if err = i.CreateRuntimeProvider("console"); err == nil {
 		if err = i.CreateRuntimeProvider("console"); err == nil {
 
 
+			tid := i.RuntimeProvider.NewThreadID()
+
 			if interactive {
 			if interactive {
 				if lll, ok := i.RuntimeProvider.Logger.(*util.LogLevelLogger); ok {
 				if lll, ok := i.RuntimeProvider.Logger.(*util.LogLevelLogger); ok {
 					fmt.Print(fmt.Sprintf("Log level: %v - ", lll.Level()))
 					fmt.Print(fmt.Sprintf("Log level: %v - ", lll.Level()))
@@ -185,7 +187,7 @@ func (i *CLIInterpreter) Interpret(interactive bool) error {
 
 
 				if ast, err = parser.ParseWithRuntime(initFileName, string(initFile), i.RuntimeProvider); err == nil {
 				if ast, err = parser.ParseWithRuntime(initFileName, string(initFile), i.RuntimeProvider); err == nil {
 					if err = ast.Runtime.Validate(); err == nil {
 					if err = ast.Runtime.Validate(); err == nil {
-						_, err = ast.Runtime.Eval(i.GlobalVS, make(map[string]interface{}))
+						_, err = ast.Runtime.Eval(i.GlobalVS, make(map[string]interface{}), tid)
 					}
 					}
 				}
 				}
 			}
 			}
@@ -221,7 +223,7 @@ func (i *CLIInterpreter) Interpret(interactive bool) error {
 								for err == nil && !isExitLine(line) {
 								for err == nil && !isExitLine(line) {
 									trimmedLine := strings.TrimSpace(line)
 									trimmedLine := strings.TrimSpace(line)
 
 
-									i.HandleInput(clt, trimmedLine)
+									i.HandleInput(clt, trimmedLine, tid)
 
 
 									line, err = clt.NextLine()
 									line, err = clt.NextLine()
 								}
 								}
@@ -238,9 +240,10 @@ func (i *CLIInterpreter) Interpret(interactive bool) error {
 
 
 /*
 /*
 HandleInput handles input to this interpreter. It parses a given input line
 HandleInput handles input to this interpreter. It parses a given input line
-and outputs on the given output terminal.
+and outputs on the given output terminal. Requires a thread ID of the executing
+thread - use the RuntimeProvider to generate a unique one.
 */
 */
-func (i *CLIInterpreter) HandleInput(ot interpreter.OutputTerminal, line string) {
+func (i *CLIInterpreter) HandleInput(ot interpreter.OutputTerminal, line string, tid uint64) {
 
 
 	// Process the entered line
 	// Process the entered line
 
 
@@ -278,7 +281,7 @@ func (i *CLIInterpreter) HandleInput(ot interpreter.OutputTerminal, line string)
 
 
 			if ierr = ast.Runtime.Validate(); ierr == nil {
 			if ierr = ast.Runtime.Validate(); ierr == nil {
 
 
-				if res, ierr = ast.Runtime.Eval(i.GlobalVS, make(map[string]interface{})); ierr == nil && res != nil {
+				if res, ierr = ast.Runtime.Eval(i.GlobalVS, make(map[string]interface{}), tid); ierr == nil && res != nil {
 					ot.WriteString(fmt.Sprintln(res))
 					ot.WriteString(fmt.Sprintln(res))
 				}
 				}
 			}
 			}

+ 27 - 9
engine/pool/threadpool.go

@@ -33,9 +33,10 @@ Task is a task which should be run in a thread.
 type Task interface {
 type Task interface {
 
 
 	/*
 	/*
-		Run the task.
+		Run the task. The function gets the unique thread ID of the worker
+		which executes the task.
 	*/
 	*/
-	Run() error
+	Run(tid uint64) error
 
 
 	/*
 	/*
 		HandleError handles an error which occurred during the run method.
 		HandleError handles an error which occurred during the run method.
@@ -124,7 +125,9 @@ type ThreadPool struct {
 
 
 	// Worker regulation
 	// Worker regulation
 
 
-	workerIDCount uint64                       // Id counter for worker tasks
+	workerIDCount uint64      // Id counter for worker tasks
+	workerIDLock  *sync.Mutex // Lock for ID generation
+
 	workerMap     map[uint64]*ThreadPoolWorker // Map of all workers
 	workerMap     map[uint64]*ThreadPoolWorker // Map of all workers
 	workerIdleMap map[uint64]*ThreadPoolWorker // Map of all idle workers
 	workerIdleMap map[uint64]*ThreadPoolWorker // Map of all idle workers
 	workerMapLock *sync.Mutex                  // Lock for worker map
 	workerMapLock *sync.Mutex                  // Lock for worker map
@@ -156,7 +159,7 @@ NewThreadPoolWithQueue creates a new thread pool with a specific task queue.
 */
 */
 func NewThreadPoolWithQueue(q TaskQueue) *ThreadPool {
 func NewThreadPoolWithQueue(q TaskQueue) *ThreadPool {
 	return &ThreadPool{q, &sync.Mutex{},
 	return &ThreadPool{q, &sync.Mutex{},
-		0, make(map[uint64]*ThreadPoolWorker),
+		0, &sync.Mutex{}, make(map[uint64]*ThreadPoolWorker),
 		make(map[uint64]*ThreadPoolWorker), &sync.Mutex{},
 		make(map[uint64]*ThreadPoolWorker), &sync.Mutex{},
 		0, sync.NewCond(&sync.Mutex{}), &sync.Mutex{},
 		0, sync.NewCond(&sync.Mutex{}), &sync.Mutex{},
 		math.MaxInt32, func() {}, false, 0, func() {}, false}
 		math.MaxInt32, func() {}, false, 0, func() {}, false}
@@ -254,6 +257,21 @@ func (tp *ThreadPool) getTask() Task {
 	return nil
 	return nil
 }
 }
 
 
+/*
+NewThreadID creates a new thread ID unique to this pool.
+*/
+func (tp *ThreadPool) NewThreadID() uint64 {
+
+	tp.workerIDLock.Lock()
+
+	res := tp.workerIDCount
+	tp.workerIDCount++
+
+	tp.workerIDLock.Unlock()
+
+	return res
+}
+
 /*
 /*
 SetWorkerCount sets the worker count of this pool. If the wait flag is true then
 SetWorkerCount sets the worker count of this pool. If the wait flag is true then
 this call will return after the pool has reached the requested worker count.
 this call will return after the pool has reached the requested worker count.
@@ -279,10 +297,10 @@ func (tp *ThreadPool) SetWorkerCount(count int, wait bool) {
 		tp.workerKill = 0
 		tp.workerKill = 0
 
 
 		for len(tp.workerMap) != count {
 		for len(tp.workerMap) != count {
-			worker := &ThreadPoolWorker{tp.workerIDCount, tp}
+			tid := tp.NewThreadID()
+			worker := &ThreadPoolWorker{tid, tp}
 			go worker.run()
 			go worker.run()
-			tp.workerMap[tp.workerIDCount] = worker
-			tp.workerIDCount++
+			tp.workerMap[tid] = worker
 		}
 		}
 
 
 		tp.workerMapLock.Unlock()
 		tp.workerMapLock.Unlock()
@@ -480,7 +498,7 @@ func (w *ThreadPoolWorker) run() {
 
 
 		// Run the task
 		// Run the task
 
 
-		if err := task.Run(); err != nil {
+		if err := task.Run(w.id); err != nil {
 			task.HandleError(err)
 			task.HandleError(err)
 		}
 		}
 
 
@@ -508,7 +526,7 @@ type idleTask struct {
 /*
 /*
 Run the idle task.
 Run the idle task.
 */
 */
-func (t *idleTask) Run() error {
+func (t *idleTask) Run(tid uint64) error {
 	t.tp.newTaskCond.L.Lock()
 	t.tp.newTaskCond.L.Lock()
 	t.tp.newTaskCond.Wait()
 	t.tp.newTaskCond.Wait()
 	t.tp.newTaskCond.L.Unlock()
 	t.tp.newTaskCond.L.Unlock()

+ 4 - 4
engine/pool/threadpool_test.go

@@ -23,7 +23,7 @@ type testTask struct {
 	errorHandler func(e error)
 	errorHandler func(e error)
 }
 }
 
 
-func (t *testTask) Run() error {
+func (t *testTask) Run(tid uint64) error {
 	return t.task()
 	return t.task()
 }
 }
 
 
@@ -77,21 +77,21 @@ func TestDefaultTaskQueue(t *testing.T) {
 
 
 	// Execute the functions
 	// Execute the functions
 
 
-	tq.Pop().Run()
+	tq.Pop().Run(0)
 
 
 	if res := tq.Size(); res != 2 {
 	if res := tq.Size(); res != 2 {
 		t.Error("Unexpected result: ", res)
 		t.Error("Unexpected result: ", res)
 		return
 		return
 	}
 	}
 
 
-	tq.Pop().Run()
+	tq.Pop().Run(0)
 
 
 	if res := tq.Size(); res != 1 {
 	if res := tq.Size(); res != 1 {
 		t.Error("Unexpected result: ", res)
 		t.Error("Unexpected result: ", res)
 		return
 		return
 	}
 	}
 
 
-	tq.Pop().Run()
+	tq.Pop().Run(0)
 
 
 	if res := tq.Size(); res != 0 {
 	if res := tq.Size(); res != 0 {
 		t.Error("Unexpected result: ", res)
 		t.Error("Unexpected result: ", res)

+ 18 - 5
engine/processor.go

@@ -30,6 +30,11 @@ type Processor interface {
 	*/
 	*/
 	ID() uint64
 	ID() uint64
 
 
+	/*
+	   ThreadPool returns the thread pool which this processor is using.
+	*/
+	ThreadPool() *pool.ThreadPool
+
 	/*
 	/*
 	   Workers returns the number of threads of this processor.
 	   Workers returns the number of threads of this processor.
 	*/
 	*/
@@ -110,10 +115,11 @@ type Processor interface {
 	IsTriggering(event *Event) bool
 	IsTriggering(event *Event) bool
 
 
 	/*
 	/*
-	   ProcessEvent processes an event by determining which rules trigger and match
-	   the given event.
+		ProcessEvent processes an event by determining which rules trigger and match
+		the given event. This function must receive a unique thread ID from the
+		executing thread.
 	*/
 	*/
-	ProcessEvent(event *Event, parent Monitor) map[string]error
+	ProcessEvent(tid uint64, event *Event, parent Monitor) map[string]error
 
 
 	/*
 	/*
 	   String returns a string representation the processor.
 	   String returns a string representation the processor.
@@ -157,6 +163,13 @@ func (p *eventProcessor) ID() uint64 {
 	return p.id
 	return p.id
 }
 }
 
 
+/*
+ThreadPool returns the thread pool which this processor is using.
+*/
+func (p *eventProcessor) ThreadPool() *pool.ThreadPool {
+	return p.pool
+}
+
 /*
 /*
 Workers returns the number of threads of this processor.
 Workers returns the number of threads of this processor.
 */
 */
@@ -414,7 +427,7 @@ func (p *eventProcessor) IsTriggering(event *Event) bool {
 ProcessEvent processes an event by determining which rules trigger and match
 ProcessEvent processes an event by determining which rules trigger and match
 the given event.
 the given event.
 */
 */
-func (p *eventProcessor) ProcessEvent(event *Event, parent Monitor) map[string]error {
+func (p *eventProcessor) ProcessEvent(tid uint64, event *Event, parent Monitor) map[string]error {
 	var rulesTriggering []*Rule
 	var rulesTriggering []*Rule
 	var rulesExecuting []*Rule
 	var rulesExecuting []*Rule
 
 
@@ -459,7 +472,7 @@ func (p *eventProcessor) ProcessEvent(event *Event, parent Monitor) map[string]e
 	EventTracer.record(event, "eventProcessor.ProcessEvent", "Running rules: ", rulesExecuting)
 	EventTracer.record(event, "eventProcessor.ProcessEvent", "Running rules: ", rulesExecuting)
 
 
 	for _, rule := range rulesExecuting {
 	for _, rule := range rulesExecuting {
-		if err := rule.Action(p, parent, event); err != nil {
+		if err := rule.Action(p, parent, event, tid); err != nil {
 			errors[rule.Name] = err
 			errors[rule.Name] = err
 		}
 		}
 		if p.failOnFirstError && len(errors) > 0 {
 		if p.failOnFirstError && len(errors) > 0 {

+ 17 - 12
engine/processor_test.go

@@ -64,7 +64,7 @@ func TestProcessorSimpleCascade(t *testing.T) {
 		nil,                                    // No state match
 		nil,                                    // No state match
 		2,                                      // Priority of the rule
 		2,                                      // Priority of the rule
 		[]string{"TestRule3", "TestRule3Copy"}, // List of suppressed rules by this rule
 		[]string{"TestRule3", "TestRule3Copy"}, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			log.WriteString("TestRule1\n")
 			log.WriteString("TestRule1\n")
 
 
 			// Add another event
 			// Add another event
@@ -90,7 +90,7 @@ func TestProcessorSimpleCascade(t *testing.T) {
 		nil,                     // No state match
 		nil,                     // No state match
 		5,                       // Priority of the rule
 		5,                       // Priority of the rule
 		nil,                     // List of suppressed rules by this rule
 		nil,                     // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			log.WriteString("TestRule2\n")
 			log.WriteString("TestRule2\n")
 			return nil
 			return nil
 		},
 		},
@@ -104,7 +104,7 @@ func TestProcessorSimpleCascade(t *testing.T) {
 		nil,                     // No state match
 		nil,                     // No state match
 		0,                       // Priority of the rule
 		0,                       // Priority of the rule
 		nil,                     // List of suppressed rules by this rule
 		nil,                     // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			log.WriteString("TestRule3\n")
 			log.WriteString("TestRule3\n")
 			return nil
 			return nil
 		},
 		},
@@ -272,7 +272,7 @@ func TestProcessorSimplePriorities(t *testing.T) {
 			nil,                          // No state match
 			nil,                          // No state match
 			0,                            // Priority of the rule
 			0,                            // Priority of the rule
 			nil,                          // List of suppressed rules by this rule
 			nil,                          // List of suppressed rules by this rule
-			func(p Processor, m Monitor, e *Event) error { // Action of the rule
+			func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 				logLock.Lock()
 				logLock.Lock()
 				log.WriteString("TestRule1\n")
 				log.WriteString("TestRule1\n")
 				logLock.Unlock()
 				logLock.Unlock()
@@ -289,7 +289,7 @@ func TestProcessorSimplePriorities(t *testing.T) {
 			nil,                          // No state match
 			nil,                          // No state match
 			0,                            // Priority of the rule
 			0,                            // Priority of the rule
 			nil,                          // List of suppressed rules by this rule
 			nil,                          // List of suppressed rules by this rule
-			func(p Processor, m Monitor, e *Event) error { // Action of the rule
+			func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 				logLock.Lock()
 				logLock.Lock()
 				log.WriteString("TestRule2\n")
 				log.WriteString("TestRule2\n")
 				logLock.Unlock()
 				logLock.Unlock()
@@ -411,7 +411,7 @@ func TestProcessorScopeHandling(t *testing.T) {
 		nil,                     // No state match
 		nil,                     // No state match
 		0,                       // Priority of the rule
 		0,                       // Priority of the rule
 		nil,                     // List of suppressed rules by this rule
 		nil,                     // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			logLock.Lock()
 			logLock.Lock()
 			log.WriteString("TestRule1\n")
 			log.WriteString("TestRule1\n")
 			logLock.Unlock()
 			logLock.Unlock()
@@ -428,7 +428,7 @@ func TestProcessorScopeHandling(t *testing.T) {
 		nil,                     // No state match
 		nil,                     // No state match
 		0,                       // Priority of the rule
 		0,                       // Priority of the rule
 		nil,                     // List of suppressed rules by this rule
 		nil,                     // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			logLock.Lock()
 			logLock.Lock()
 			log.WriteString("TestRule2\n")
 			log.WriteString("TestRule2\n")
 			logLock.Unlock()
 			logLock.Unlock()
@@ -538,7 +538,7 @@ func TestProcessorStateMatching(t *testing.T) {
 		map[string]interface{}{"name": nil, "test": 1}, // Simple state match
 		map[string]interface{}{"name": nil, "test": 1}, // Simple state match
 		0,   // Priority of the rule
 		0,   // Priority of the rule
 		nil, // List of suppressed rules by this rule
 		nil, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			logLock.Lock()
 			logLock.Lock()
 			log.WriteString("TestRule1\n")
 			log.WriteString("TestRule1\n")
 			logLock.Unlock()
 			logLock.Unlock()
@@ -555,7 +555,7 @@ func TestProcessorStateMatching(t *testing.T) {
 		map[string]interface{}{"name": nil, "test": "123"}, // Simple state match
 		map[string]interface{}{"name": nil, "test": "123"}, // Simple state match
 		0,   // Priority of the rule
 		0,   // Priority of the rule
 		nil, // List of suppressed rules by this rule
 		nil, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			logLock.Lock()
 			logLock.Lock()
 			log.WriteString("TestRule2\n")
 			log.WriteString("TestRule2\n")
 			logLock.Unlock()
 			logLock.Unlock()
@@ -623,6 +623,11 @@ func TestProcessorSimpleErrorHandling(t *testing.T) {
 
 
 	proc := NewProcessor(10)
 	proc := NewProcessor(10)
 
 
+	if proc.ThreadPool() == nil {
+		t.Error("Should have a thread pool")
+		return
+	}
+
 	// Add rules to the processor
 	// Add rules to the processor
 
 
 	rule1 := &Rule{
 	rule1 := &Rule{
@@ -633,7 +638,7 @@ func TestProcessorSimpleErrorHandling(t *testing.T) {
 		nil,
 		nil,
 		0,   // Priority of the rule
 		0,   // Priority of the rule
 		nil, // List of suppressed rules by this rule
 		nil, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			p.AddEvent(&Event{
 			p.AddEvent(&Event{
 				"event2",
 				"event2",
 				[]string{"core", "main", "event2"},
 				[]string{"core", "main", "event2"},
@@ -651,7 +656,7 @@ func TestProcessorSimpleErrorHandling(t *testing.T) {
 		nil,
 		nil,
 		0,   // Priority of the rule
 		0,   // Priority of the rule
 		nil, // List of suppressed rules by this rule
 		nil, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			p.AddEvent(&Event{
 			p.AddEvent(&Event{
 				"event3",
 				"event3",
 				[]string{"core", "main", "event3"},
 				[]string{"core", "main", "event3"},
@@ -669,7 +674,7 @@ func TestProcessorSimpleErrorHandling(t *testing.T) {
 		nil,
 		nil,
 		0,   // Priority of the rule
 		0,   // Priority of the rule
 		nil, // List of suppressed rules by this rule
 		nil, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			return errors.New("testerror2")
 			return errors.New("testerror2")
 		},
 		},
 	}
 	}

+ 3 - 2
engine/rule.go

@@ -72,9 +72,10 @@ func (r *Rule) String() string {
 }
 }
 
 
 /*
 /*
-RuleAction is an action which is executed by a matching rule.
+RuleAction is an action which is executed by a matching rule. The action gets
+a unique thread ID from the executing thread.
 */
 */
-type RuleAction func(p Processor, m Monitor, e *Event) error
+type RuleAction func(p Processor, m Monitor, e *Event, tid uint64) error
 
 
 /*
 /*
 RuleIndex is an index for rules. It takes the form of a tree structure in which
 RuleIndex is an index for rules. It takes the form of a tree structure in which

+ 8 - 8
engine/rule_test.go

@@ -33,7 +33,7 @@ func TestRuleIndexSimple(t *testing.T) {
 		nil,
 		nil,
 		0,                      // Priority of the rule
 		0,                      // Priority of the rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			return nil
 			return nil
 		},
 		},
 	}
 	}
@@ -52,7 +52,7 @@ func TestRuleIndexSimple(t *testing.T) {
 		nil,
 		nil,
 		0,                      // Priority of the rule
 		0,                      // Priority of the rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			return nil
 			return nil
 		},
 		},
 	})
 	})
@@ -69,7 +69,7 @@ func TestRuleIndexSimple(t *testing.T) {
 		nil,
 		nil,
 		0,                      // Priority of the rule
 		0,                      // Priority of the rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			return nil
 			return nil
 		},
 		},
 	})
 	})
@@ -216,7 +216,7 @@ func TestRuleIndexStateMatch(t *testing.T) {
 		},
 		},
 		0,                      // Priority of the rule
 		0,                      // Priority of the rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			return nil
 			return nil
 		},
 		},
 	}
 	}
@@ -233,7 +233,7 @@ func TestRuleIndexStateMatch(t *testing.T) {
 		},
 		},
 		0,                      // Priority of the rule
 		0,                      // Priority of the rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			return nil
 			return nil
 		},
 		},
 	}
 	}
@@ -251,7 +251,7 @@ func TestRuleIndexStateMatch(t *testing.T) {
 		},
 		},
 		0,                      // Priority of the rule
 		0,                      // Priority of the rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			return nil
 			return nil
 		},
 		},
 	}
 	}
@@ -376,7 +376,7 @@ func TestRuleIndexStateRegexMatch(t *testing.T) {
 		},
 		},
 		0,                      // Priority of the rule
 		0,                      // Priority of the rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			return nil
 			return nil
 		},
 		},
 	}
 	}
@@ -392,7 +392,7 @@ func TestRuleIndexStateRegexMatch(t *testing.T) {
 		},
 		},
 		0,                      // Priority of the rule
 		0,                      // Priority of the rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
 		[]string{"TestRule66"}, // List of suppressed rules by this rule
-		func(p Processor, m Monitor, e *Event) error { // Action of the rule
+		func(p Processor, m Monitor, e *Event, tid uint64) error { // Action of the rule
 			return nil
 			return nil
 		},
 		},
 	}
 	}

+ 2 - 2
engine/taskqueue.go

@@ -73,10 +73,10 @@ type Task struct {
 /*
 /*
 Run the task.
 Run the task.
 */
 */
-func (t *Task) Run() error {
+func (t *Task) Run(tid uint64) error {
 	EventTracer.record(t.e, "Task.Run", "Running task")
 	EventTracer.record(t.e, "Task.Run", "Running task")
 
 
-	errors := t.p.ProcessEvent(t.e, t.m)
+	errors := t.p.ProcessEvent(tid, t.e, t.m)
 
 
 	if len(errors) > 0 {
 	if len(errors) > 0 {
 
 

+ 15 - 15
interpreter/func_provider.go

@@ -112,7 +112,7 @@ type rangeFunc struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (rf *rangeFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (rf *rangeFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	var currVal, to float64
 	var currVal, to float64
 	var err error
 	var err error
 
 
@@ -195,7 +195,7 @@ type newFunc struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (rf *newFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (rf *newFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
 	err := fmt.Errorf("Need a map as first parameter")
 	err := fmt.Errorf("Need a map as first parameter")
@@ -214,7 +214,7 @@ func (rf *newFunc) Run(instanceID string, vs parser.Scope, is map[string]interfa
 					initvs := scope.NewScope(fmt.Sprintf("newfunc: %v", instanceID))
 					initvs := scope.NewScope(fmt.Sprintf("newfunc: %v", instanceID))
 					initis := make(map[string]interface{})
 					initis := make(map[string]interface{})
 
 
-					_, err = initFunc.Run(instanceID, initvs, initis, args[1:])
+					_, err = initFunc.Run(instanceID, initvs, initis, tid, args[1:])
 				}
 				}
 			}
 			}
 		}
 		}
@@ -292,7 +292,7 @@ type lenFunc struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (rf *lenFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (rf *lenFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	var res float64
 	var res float64
 
 
 	err := fmt.Errorf("Need a list or a map as first parameter")
 	err := fmt.Errorf("Need a list or a map as first parameter")
@@ -333,7 +333,7 @@ type delFunc struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (rf *delFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (rf *delFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
 	err := fmt.Errorf("Need a list or a map as first parameter and an index or key as second parameter")
 	err := fmt.Errorf("Need a list or a map as first parameter and an index or key as second parameter")
@@ -380,7 +380,7 @@ type addFunc struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (rf *addFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (rf *addFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
 	err := fmt.Errorf("Need a list as first parameter and a value as second parameter")
 	err := fmt.Errorf("Need a list as first parameter and a value as second parameter")
@@ -427,7 +427,7 @@ type concatFunc struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (rf *concatFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (rf *concatFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
 	err := fmt.Errorf("Need at least two lists as parameters")
 	err := fmt.Errorf("Need at least two lists as parameters")
@@ -474,7 +474,7 @@ type dumpenvFunc struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (rf *dumpenvFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (rf *dumpenvFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	return vs.String(), nil
 	return vs.String(), nil
 }
 }
 
 
@@ -498,7 +498,7 @@ type docFunc struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (rf *docFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (rf *docFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 	err := fmt.Errorf("Need a function as parameter")
 	err := fmt.Errorf("Need a function as parameter")
 
 
@@ -555,7 +555,7 @@ type sleepFunc struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (rf *sleepFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (rf *sleepFunc) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 	err := fmt.Errorf("Need number of micro seconds as parameter")
 	err := fmt.Errorf("Need number of micro seconds as parameter")
 
 
@@ -595,7 +595,7 @@ type raise struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (rf *raise) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (rf *raise) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	var err error
 	var err error
 	var detailMsg string
 	var detailMsg string
 	var detail interface{}
 	var detail interface{}
@@ -644,7 +644,7 @@ type addevent struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (rf *addevent) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (rf *addevent) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	return rf.addEvent(func(proc engine.Processor, event *engine.Event, scope *engine.RuleScope) (interface{}, error) {
 	return rf.addEvent(func(proc engine.Processor, event *engine.Event, scope *engine.RuleScope) (interface{}, error) {
 		var monitor engine.Monitor
 		var monitor engine.Monitor
 
 
@@ -735,7 +735,7 @@ type addeventandwait struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (rf *addeventandwait) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (rf *addeventandwait) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	return rf.addEvent(func(proc engine.Processor, event *engine.Event, scope *engine.RuleScope) (interface{}, error) {
 	return rf.addEvent(func(proc engine.Processor, event *engine.Event, scope *engine.RuleScope) (interface{}, error) {
 		var res []interface{}
 		var res []interface{}
 		rm := proc.NewRootMonitor(nil, scope)
 		rm := proc.NewRootMonitor(nil, scope)
@@ -800,7 +800,7 @@ type setCronTrigger struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (ct *setCronTrigger) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (ct *setCronTrigger) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 	err := fmt.Errorf("Need a cronspec, an event name and an event scope as parameters")
 	err := fmt.Errorf("Need a cronspec, an event name and an event scope as parameters")
 
 
@@ -863,7 +863,7 @@ type setPulseTrigger struct {
 /*
 /*
 Run executes this function.
 Run executes this function.
 */
 */
-func (pt *setPulseTrigger) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (pt *setPulseTrigger) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	err := fmt.Errorf("Need micro second interval, an event name and an event scope as parameters")
 	err := fmt.Errorf("Need micro second interval, an event name and an event scope as parameters")
 
 
 	if len(args) > 2 {
 	if len(args) > 2 {

+ 2 - 2
interpreter/func_provider_test.go

@@ -455,12 +455,12 @@ func TestErrorConditions(t *testing.T) {
 
 
 	rf := &rangeFunc{&inbuildBaseFunc{}}
 	rf := &rangeFunc{&inbuildBaseFunc{}}
 
 
-	if _, err := rf.Run("", nil, nil, nil); err == nil || err.Error() != "Need at least an end range as first parameter" {
+	if _, err := rf.Run("", nil, nil, 0, nil); err == nil || err.Error() != "Need at least an end range as first parameter" {
 		t.Error("Unexpected result:", err)
 		t.Error("Unexpected result:", err)
 		return
 		return
 	}
 	}
 
 
-	if _, err := rf.Run("", nil, nil, []interface{}{"bob"}); err == nil || err.Error() != "Parameter 1 should be a number" {
+	if _, err := rf.Run("", nil, nil, 0, []interface{}{"bob"}); err == nil || err.Error() != "Parameter 1 should be a number" {
 		t.Error("Unexpected result:", err)
 		t.Error("Unexpected result:", err)
 		return
 		return
 	}
 	}

+ 2 - 2
interpreter/main_test.go

@@ -124,7 +124,7 @@ func UnitTestEvalAndASTAndImport(input string, vs parser.Scope, expectedAST stri
 		vs = scope.NewScope(scope.GlobalScope)
 		vs = scope.NewScope(scope.GlobalScope)
 	}
 	}
 
 
-	return ast.Runtime.Eval(vs, make(map[string]interface{}))
+	return ast.Runtime.Eval(vs, make(map[string]interface{}), 0)
 }
 }
 
 
 /*
 /*
@@ -143,7 +143,7 @@ type TestLogger struct {
 	buf *datautil.RingBuffer
 	buf *datautil.RingBuffer
 }
 }
 
 
-func (tl *TestLogger) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (tl *TestLogger) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	tl.buf.Add(fmt.Sprint(args...))
 	tl.buf.Add(fmt.Sprint(args...))
 	return nil, nil
 	return nil, nil
 }
 }

+ 9 - 0
interpreter/provider.go

@@ -193,3 +193,12 @@ NewRuntimeError creates a new RuntimeError object.
 func (erp *ECALRuntimeProvider) NewRuntimeError(t error, d string, node *parser.ASTNode) error {
 func (erp *ECALRuntimeProvider) NewRuntimeError(t error, d string, node *parser.ASTNode) error {
 	return util.NewRuntimeError(erp.Name, t, d, node)
 	return util.NewRuntimeError(erp.Name, t, d, node)
 }
 }
+
+/*
+NewThreadID creates a new thread ID unique to this runtime provider instance.
+This ID can be safely used for the thread ID when calling Eval on a
+parser.Runtime instance.
+*/
+func (erp *ECALRuntimeProvider) NewThreadID() uint64 {
+	return erp.Processor.ThreadPool().NewThreadID()
+}

+ 20 - 20
interpreter/rt_arithmetic.go

@@ -33,10 +33,10 @@ func plusOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Ru
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *plusOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *plusOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		// Use as prefix
 		// Use as prefix
@@ -44,14 +44,14 @@ func (rt *plusOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (inter
 		if len(rt.node.Children) == 1 {
 		if len(rt.node.Children) == 1 {
 			return rt.numVal(func(n float64) interface{} {
 			return rt.numVal(func(n float64) interface{} {
 				return n
 				return n
-			}, vs, is)
+			}, vs, is, tid)
 		}
 		}
 
 
 		// Use as operation
 		// Use as operation
 
 
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 			return n1 + n2
 			return n1 + n2
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -71,10 +71,10 @@ func minusOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.R
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *minusOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *minusOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
@@ -83,14 +83,14 @@ func (rt *minusOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (inte
 		if len(rt.node.Children) == 1 {
 		if len(rt.node.Children) == 1 {
 			return rt.numVal(func(n float64) interface{} {
 			return rt.numVal(func(n float64) interface{} {
 				return -n
 				return -n
-			}, vs, is)
+			}, vs, is, tid)
 		}
 		}
 
 
 		// Use as operation
 		// Use as operation
 
 
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 			return n1 - n2
 			return n1 - n2
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -110,16 +110,16 @@ func timesOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.R
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *timesOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *timesOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 			return n1 * n2
 			return n1 * n2
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -139,16 +139,16 @@ func divOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Run
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *divOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *divOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 			return n1 / n2
 			return n1 / n2
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -168,16 +168,16 @@ func divintOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *divintOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *divintOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 			return math.Floor(n1 / n2)
 			return math.Floor(n1 / n2)
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -197,16 +197,16 @@ func modintOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *modintOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *modintOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 			return float64(int64(n1) % int64(n2))
 			return float64(int64(n1) % int64(n2))
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err

+ 5 - 5
interpreter/rt_assign.go

@@ -75,18 +75,18 @@ func (rt *assignmentRuntime) Validate() error {
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *assignmentRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+func (rt *assignmentRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		var val interface{}
 		var val interface{}
 
 
-		val, err = rt.node.Children[1].Runtime.Eval(vs, is)
+		val, err = rt.node.Children[1].Runtime.Eval(vs, is, tid)
 
 
 		if err == nil {
 		if err == nil {
 			if len(rt.leftSide) == 1 {
 			if len(rt.leftSide) == 1 {
 
 
-				err = rt.leftSide[0].Set(vs, is, val)
+				err = rt.leftSide[0].Set(vs, is, tid, val)
 
 
 			} else if valList, ok := val.([]interface{}); ok {
 			} else if valList, ok := val.([]interface{}); ok {
 
 
@@ -101,7 +101,7 @@ func (rt *assignmentRuntime) Eval(vs parser.Scope, is map[string]interface{}) (i
 
 
 					for i, v := range rt.leftSide {
 					for i, v := range rt.leftSide {
 
 
-						if err = v.Set(vs, is, valList[i]); err != nil {
+						if err = v.Set(vs, is, tid, valList[i]); err != nil {
 							err = rt.erp.NewRuntimeError(util.ErrVarAccess,
 							err = rt.erp.NewRuntimeError(util.ErrVarAccess,
 								err.Error(), rt.node)
 								err.Error(), rt.node)
 							break
 							break

+ 47 - 47
interpreter/rt_boolean.go

@@ -36,21 +36,21 @@ func greaterequalOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) p
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *greaterequalOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *greaterequalOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 			return n1 >= n2
 			return n1 >= n2
-		}, vs, is)
+		}, vs, is, tid)
 
 
 		if err != nil {
 		if err != nil {
 			res, err = rt.strOp(func(n1 string, n2 string) interface{} {
 			res, err = rt.strOp(func(n1 string, n2 string) interface{} {
 				return n1 >= n2
 				return n1 >= n2
-			}, vs, is)
+			}, vs, is, tid)
 		}
 		}
 	}
 	}
 
 
@@ -71,21 +71,21 @@ func greaterOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *greaterOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *greaterOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 			return n1 > n2
 			return n1 > n2
-		}, vs, is)
+		}, vs, is, tid)
 
 
 		if err != nil {
 		if err != nil {
 			res, err = rt.strOp(func(n1 string, n2 string) interface{} {
 			res, err = rt.strOp(func(n1 string, n2 string) interface{} {
 				return n1 > n2
 				return n1 > n2
-			}, vs, is)
+			}, vs, is, tid)
 		}
 		}
 	}
 	}
 
 
@@ -106,21 +106,21 @@ func lessequalOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) pars
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *lessequalOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *lessequalOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 			return n1 <= n2
 			return n1 <= n2
-		}, vs, is)
+		}, vs, is, tid)
 
 
 		if err != nil {
 		if err != nil {
 			res, err = rt.strOp(func(n1 string, n2 string) interface{} {
 			res, err = rt.strOp(func(n1 string, n2 string) interface{} {
 				return n1 <= n2
 				return n1 <= n2
-			}, vs, is)
+			}, vs, is, tid)
 		}
 		}
 	}
 	}
 
 
@@ -141,21 +141,21 @@ func lessOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Ru
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *lessOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *lessOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 		res, err = rt.numOp(func(n1 float64, n2 float64) interface{} {
 			return n1 < n2
 			return n1 < n2
-		}, vs, is)
+		}, vs, is, tid)
 
 
 		if err != nil {
 		if err != nil {
 			res, err = rt.strOp(func(n1 string, n2 string) interface{} {
 			res, err = rt.strOp(func(n1 string, n2 string) interface{} {
 				return n1 < n2
 				return n1 < n2
-			}, vs, is)
+			}, vs, is, tid)
 		}
 		}
 	}
 	}
 
 
@@ -176,16 +176,16 @@ func equalOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.R
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *equalOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *equalOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.genOp(func(n1 interface{}, n2 interface{}) interface{} {
 		res, err = rt.genOp(func(n1 interface{}, n2 interface{}) interface{} {
 			return n1 == n2
 			return n1 == n2
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -205,16 +205,16 @@ func notequalOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parse
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *notequalOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *notequalOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.genOp(func(n1 interface{}, n2 interface{}) interface{} {
 		res, err = rt.genOp(func(n1 interface{}, n2 interface{}) interface{} {
 			return n1 != n2
 			return n1 != n2
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -234,16 +234,16 @@ func andOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Run
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *andOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *andOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.boolOp(func(b1 bool, b2 bool) interface{} {
 		res, err = rt.boolOp(func(b1 bool, b2 bool) interface{} {
 			return b1 && b2
 			return b1 && b2
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -263,16 +263,16 @@ func orOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runt
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *orOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *orOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.boolOp(func(b1 bool, b2 bool) interface{} {
 		res, err = rt.boolOp(func(b1 bool, b2 bool) interface{} {
 			return b1 || b2
 			return b1 || b2
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -292,16 +292,16 @@ func notOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Run
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *notOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *notOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
 		res, err = rt.boolVal(func(b bool) interface{} {
 		res, err = rt.boolVal(func(b bool) interface{} {
 			return !b
 			return !b
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -329,20 +329,20 @@ func likeOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Ru
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *likeOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *likeOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		errorutil.AssertTrue(len(rt.node.Children) == 2,
 		errorutil.AssertTrue(len(rt.node.Children) == 2,
 			fmt.Sprint("Operation requires 2 operands", rt.node))
 			fmt.Sprint("Operation requires 2 operands", rt.node))
 
 
-		str, err := rt.node.Children[0].Runtime.Eval(vs, is)
+		str, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
 		if err == nil {
 		if err == nil {
 			var pattern interface{}
 			var pattern interface{}
 
 
-			pattern, err = rt.node.Children[1].Runtime.Eval(vs, is)
+			pattern, err = rt.node.Children[1].Runtime.Eval(vs, is, tid)
 			if err == nil {
 			if err == nil {
 				var re *regexp.Regexp
 				var re *regexp.Regexp
 
 
@@ -372,15 +372,15 @@ func beginswithOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) par
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *beginswithOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *beginswithOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		res, err = rt.strOp(func(s1 string, s2 string) interface{} {
 		res, err = rt.strOp(func(s1 string, s2 string) interface{} {
 			return strings.HasPrefix(s1, s2)
 			return strings.HasPrefix(s1, s2)
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -400,15 +400,15 @@ func endswithOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parse
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *endswithOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *endswithOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		res, err = rt.strOp(func(s1 string, s2 string) interface{} {
 		res, err = rt.strOp(func(s1 string, s2 string) interface{} {
 			return strings.HasSuffix(s1, s2)
 			return strings.HasSuffix(s1, s2)
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -428,10 +428,10 @@ func inOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runt
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *inOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *inOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		res, err = rt.listOp(func(val interface{}, list []interface{}) interface{} {
 		res, err = rt.listOp(func(val interface{}, list []interface{}) interface{} {
@@ -441,7 +441,7 @@ func (rt *inOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfa
 				}
 				}
 			}
 			}
 			return false
 			return false
-		}, vs, is)
+		}, vs, is, tid)
 	}
 	}
 
 
 	return res, err
 	return res, err
@@ -461,13 +461,13 @@ func notinOpRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.R
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *notinOpRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *notinOpRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
-		if res, err = rt.inOpRuntime.Eval(vs, is); err == nil {
+		if res, err = rt.inOpRuntime.Eval(vs, is, tid); err == nil {
 			res = !res.(bool)
 			res = !res.(bool)
 		}
 		}
 	}
 	}

+ 6 - 6
interpreter/rt_const.go

@@ -29,8 +29,8 @@ func trueRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runt
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *trueRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+func (rt *trueRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 	return true, err
 	return true, err
 }
 }
 
 
@@ -51,8 +51,8 @@ func falseRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Run
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *falseRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+func (rt *falseRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 	return false, err
 	return false, err
 }
 }
 
 
@@ -73,7 +73,7 @@ func nullRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runt
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *nullRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+func (rt *nullRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 	return nil, err
 	return nil, err
 }
 }

+ 8 - 8
interpreter/rt_func.go

@@ -44,14 +44,14 @@ func (rt *returnRuntime) Validate() error {
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *returnRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *returnRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		var res interface{}
 		var res interface{}
 
 
-		if res, err = rt.node.Children[0].Runtime.Eval(vs, is); err == nil {
+		if res, err = rt.node.Children[0].Runtime.Eval(vs, is, tid); err == nil {
 			rerr := rt.erp.NewRuntimeError(util.ErrReturn, fmt.Sprintf("Return value: %v", res), rt.node)
 			rerr := rt.erp.NewRuntimeError(util.ErrReturn, fmt.Sprintf("Return value: %v", res), rt.node)
 			err = &returnValue{
 			err = &returnValue{
 				rerr.(*util.RuntimeError),
 				rerr.(*util.RuntimeError),
@@ -86,10 +86,10 @@ func funcRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runt
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *funcRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *funcRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var fc interface{}
 	var fc interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		name := ""
 		name := ""
@@ -123,7 +123,7 @@ type function struct {
 Run executes this function. The function is called with parameters and might also
 Run executes this function. The function is called with parameters and might also
 have a reference to a context state - this.
 have a reference to a context state - this.
 */
 */
-func (f *function) Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error) {
+func (f *function) Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 	var err error
 	var err error
 
 
@@ -164,7 +164,7 @@ func (f *function) Run(instanceID string, vs parser.Scope, is map[string]interfa
 				if i < len(args) {
 				if i < len(args) {
 					val = args[i]
 					val = args[i]
 				} else {
 				} else {
-					val, err = p.Children[1].Runtime.Eval(vs, is)
+					val, err = p.Children[1].Runtime.Eval(vs, is, tid)
 				}
 				}
 			}
 			}
 
 
@@ -178,7 +178,7 @@ func (f *function) Run(instanceID string, vs parser.Scope, is map[string]interfa
 
 
 		scope.SetParentOfScope(fvs, f.declarationVS)
 		scope.SetParentOfScope(fvs, f.declarationVS)
 
 
-		res, err = body.Runtime.Eval(fvs, make(map[string]interface{}))
+		res, err = body.Runtime.Eval(fvs, make(map[string]interface{}), tid)
 
 
 		// Check for return value (delivered as error object)
 		// Check for return value (delivered as error object)
 
 

+ 29 - 29
interpreter/rt_general.go

@@ -52,7 +52,7 @@ func (rt *baseRuntime) Validate() error {
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *baseRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *baseRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	return nil, nil
 	return nil, nil
 }
 }
 
 
@@ -92,8 +92,8 @@ func (rt *voidRuntime) Validate() error {
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *voidRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	return rt.baseRuntime.Eval(vs, is)
+func (rt *voidRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
+	return rt.baseRuntime.Eval(vs, is, tid)
 }
 }
 
 
 // Import Runtime
 // Import Runtime
@@ -123,8 +123,8 @@ func (rt *importRuntime) Validate() error {
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *importRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+func (rt *importRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if rt.erp.ImportLocator == nil {
 	if rt.erp.ImportLocator == nil {
 		err = rt.erp.NewRuntimeError(util.ErrRuntimeError, "No import locator was specified", rt.node)
 		err = rt.erp.NewRuntimeError(util.ErrRuntimeError, "No import locator was specified", rt.node)
@@ -133,7 +133,7 @@ func (rt *importRuntime) Eval(vs parser.Scope, is map[string]interface{}) (inter
 	if err == nil {
 	if err == nil {
 
 
 		var importPath interface{}
 		var importPath interface{}
-		if importPath, err = rt.node.Children[0].Runtime.Eval(vs, is); err == nil {
+		if importPath, err = rt.node.Children[0].Runtime.Eval(vs, is, tid); err == nil {
 
 
 			var codeText string
 			var codeText string
 			if codeText, err = rt.erp.ImportLocator.Resolve(fmt.Sprint(importPath)); err == nil {
 			if codeText, err = rt.erp.ImportLocator.Resolve(fmt.Sprint(importPath)); err == nil {
@@ -143,9 +143,9 @@ func (rt *importRuntime) Eval(vs parser.Scope, is map[string]interface{}) (inter
 					if err = ast.Runtime.Validate(); err == nil {
 					if err = ast.Runtime.Validate(); err == nil {
 
 
 						ivs := scope.NewScope(scope.GlobalScope)
 						ivs := scope.NewScope(scope.GlobalScope)
-						if _, err = ast.Runtime.Eval(ivs, make(map[string]interface{})); err == nil {
+						if _, err = ast.Runtime.Eval(ivs, make(map[string]interface{}), tid); err == nil {
 							irt := rt.node.Children[1].Runtime.(*identifierRuntime)
 							irt := rt.node.Children[1].Runtime.(*identifierRuntime)
-							irt.Set(vs, is, scope.ToObject(ivs))
+							irt.Set(vs, is, tid, scope.ToObject(ivs))
 						}
 						}
 					}
 					}
 				}
 				}
@@ -188,8 +188,8 @@ func (rt *invalidRuntime) Validate() error {
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *invalidRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+func (rt *invalidRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 	if err == nil {
 	if err == nil {
 		err = rt.erp.NewRuntimeError(util.ErrInvalidConstruct, fmt.Sprintf("Unknown node: %s", rt.node.Name), rt.node)
 		err = rt.erp.NewRuntimeError(util.ErrInvalidConstruct, fmt.Sprintf("Unknown node: %s", rt.node.Name), rt.node)
 	}
 	}
@@ -225,14 +225,14 @@ func (rt *operatorRuntime) errorDetailString(token *parser.LexToken, opVal inter
 numVal returns a transformed number value.
 numVal returns a transformed number value.
 */
 */
 func (rt *operatorRuntime) numVal(op func(float64) interface{}, vs parser.Scope,
 func (rt *operatorRuntime) numVal(op func(float64) interface{}, vs parser.Scope,
-	is map[string]interface{}) (interface{}, error) {
+	is map[string]interface{}, tid uint64) (interface{}, error) {
 
 
 	var ret interface{}
 	var ret interface{}
 
 
 	errorutil.AssertTrue(len(rt.node.Children) == 1,
 	errorutil.AssertTrue(len(rt.node.Children) == 1,
 		fmt.Sprint("Operation requires 1 operand", rt.node))
 		fmt.Sprint("Operation requires 1 operand", rt.node))
 
 
-	res, err := rt.node.Children[0].Runtime.Eval(vs, is)
+	res, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
 	if err == nil {
 	if err == nil {
 
 
 		// Check if the value is a number
 		// Check if the value is a number
@@ -257,14 +257,14 @@ func (rt *operatorRuntime) numVal(op func(float64) interface{}, vs parser.Scope,
 boolVal returns a transformed boolean value.
 boolVal returns a transformed boolean value.
 */
 */
 func (rt *operatorRuntime) boolVal(op func(bool) interface{},
 func (rt *operatorRuntime) boolVal(op func(bool) interface{},
-	vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+	vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 
 
 	var ret interface{}
 	var ret interface{}
 
 
 	errorutil.AssertTrue(len(rt.node.Children) == 1,
 	errorutil.AssertTrue(len(rt.node.Children) == 1,
 		fmt.Sprint("Operation requires 1 operand", rt.node))
 		fmt.Sprint("Operation requires 1 operand", rt.node))
 
 
-	res, err := rt.node.Children[0].Runtime.Eval(vs, is)
+	res, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
 	if err == nil {
 	if err == nil {
 
 
 		resBool, ok := res.(bool)
 		resBool, ok := res.(bool)
@@ -284,7 +284,7 @@ func (rt *operatorRuntime) boolVal(op func(bool) interface{},
 numOp executes an operation on two number values.
 numOp executes an operation on two number values.
 */
 */
 func (rt *operatorRuntime) numOp(op func(float64, float64) interface{},
 func (rt *operatorRuntime) numOp(op func(float64, float64) interface{},
-	vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+	vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var ok bool
 	var ok bool
 	var res1, res2 interface{}
 	var res1, res2 interface{}
 	var err error
 	var err error
@@ -292,8 +292,8 @@ func (rt *operatorRuntime) numOp(op func(float64, float64) interface{},
 	errorutil.AssertTrue(len(rt.node.Children) == 2,
 	errorutil.AssertTrue(len(rt.node.Children) == 2,
 		fmt.Sprint("Operation requires 2 operands", rt.node))
 		fmt.Sprint("Operation requires 2 operands", rt.node))
 
 
-	if res1, err = rt.node.Children[0].Runtime.Eval(vs, is); err == nil {
-		if res2, err = rt.node.Children[1].Runtime.Eval(vs, is); err == nil {
+	if res1, err = rt.node.Children[0].Runtime.Eval(vs, is, tid); err == nil {
+		if res2, err = rt.node.Children[1].Runtime.Eval(vs, is, tid); err == nil {
 			var res1Num, res2Num float64
 			var res1Num, res2Num float64
 
 
 			if res1Num, ok = res1.(float64); !ok {
 			if res1Num, ok = res1.(float64); !ok {
@@ -320,18 +320,18 @@ func (rt *operatorRuntime) numOp(op func(float64, float64) interface{},
 genOp executes an operation on two general values.
 genOp executes an operation on two general values.
 */
 */
 func (rt *operatorRuntime) genOp(op func(interface{}, interface{}) interface{},
 func (rt *operatorRuntime) genOp(op func(interface{}, interface{}) interface{},
-	vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+	vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 
 
 	var ret interface{}
 	var ret interface{}
 
 
 	errorutil.AssertTrue(len(rt.node.Children) == 2,
 	errorutil.AssertTrue(len(rt.node.Children) == 2,
 		fmt.Sprint("Operation requires 2 operands", rt.node))
 		fmt.Sprint("Operation requires 2 operands", rt.node))
 
 
-	res1, err := rt.node.Children[0].Runtime.Eval(vs, is)
+	res1, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
 	if err == nil {
 	if err == nil {
 		var res2 interface{}
 		var res2 interface{}
 
 
-		if res2, err = rt.node.Children[1].Runtime.Eval(vs, is); err == nil {
+		if res2, err = rt.node.Children[1].Runtime.Eval(vs, is, tid); err == nil {
 			ret = op(res1, res2)
 			ret = op(res1, res2)
 		}
 		}
 	}
 	}
@@ -343,18 +343,18 @@ func (rt *operatorRuntime) genOp(op func(interface{}, interface{}) interface{},
 strOp executes an operation on two string values.
 strOp executes an operation on two string values.
 */
 */
 func (rt *operatorRuntime) strOp(op func(string, string) interface{},
 func (rt *operatorRuntime) strOp(op func(string, string) interface{},
-	vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+	vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 
 
 	var ret interface{}
 	var ret interface{}
 
 
 	errorutil.AssertTrue(len(rt.node.Children) == 2,
 	errorutil.AssertTrue(len(rt.node.Children) == 2,
 		fmt.Sprint("Operation requires 2 operands", rt.node))
 		fmt.Sprint("Operation requires 2 operands", rt.node))
 
 
-	res1, err := rt.node.Children[0].Runtime.Eval(vs, is)
+	res1, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
 	if err == nil {
 	if err == nil {
 		var res2 interface{}
 		var res2 interface{}
 
 
-		if res2, err = rt.node.Children[1].Runtime.Eval(vs, is); err == nil {
+		if res2, err = rt.node.Children[1].Runtime.Eval(vs, is, tid); err == nil {
 			ret = op(fmt.Sprint(res1), fmt.Sprint(res2))
 			ret = op(fmt.Sprint(res1), fmt.Sprint(res2))
 		}
 		}
 	}
 	}
@@ -366,18 +366,18 @@ func (rt *operatorRuntime) strOp(op func(string, string) interface{},
 boolOp executes an operation on two boolean values.
 boolOp executes an operation on two boolean values.
 */
 */
 func (rt *operatorRuntime) boolOp(op func(bool, bool) interface{},
 func (rt *operatorRuntime) boolOp(op func(bool, bool) interface{},
-	vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+	vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 
 
 	var res interface{}
 	var res interface{}
 
 
 	errorutil.AssertTrue(len(rt.node.Children) == 2,
 	errorutil.AssertTrue(len(rt.node.Children) == 2,
 		fmt.Sprint("Operation requires 2 operands", rt.node))
 		fmt.Sprint("Operation requires 2 operands", rt.node))
 
 
-	res1, err := rt.node.Children[0].Runtime.Eval(vs, is)
+	res1, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
 	if err == nil {
 	if err == nil {
 		var res2 interface{}
 		var res2 interface{}
 
 
-		if res2, err = rt.node.Children[1].Runtime.Eval(vs, is); err == nil {
+		if res2, err = rt.node.Children[1].Runtime.Eval(vs, is, tid); err == nil {
 
 
 			res1bool, ok := res1.(bool)
 			res1bool, ok := res1.(bool)
 			if !ok {
 			if !ok {
@@ -402,18 +402,18 @@ func (rt *operatorRuntime) boolOp(op func(bool, bool) interface{},
 listOp executes an operation on a value and a list.
 listOp executes an operation on a value and a list.
 */
 */
 func (rt *operatorRuntime) listOp(op func(interface{}, []interface{}) interface{},
 func (rt *operatorRuntime) listOp(op func(interface{}, []interface{}) interface{},
-	vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+	vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 
 
 	var res interface{}
 	var res interface{}
 
 
 	errorutil.AssertTrue(len(rt.node.Children) == 2,
 	errorutil.AssertTrue(len(rt.node.Children) == 2,
 		fmt.Sprint("Operation requires 2 operands", rt.node))
 		fmt.Sprint("Operation requires 2 operands", rt.node))
 
 
-	res1, err := rt.node.Children[0].Runtime.Eval(vs, is)
+	res1, err := rt.node.Children[0].Runtime.Eval(vs, is, tid)
 	if err == nil {
 	if err == nil {
 		var res2 interface{}
 		var res2 interface{}
 
 
-		if res2, err = rt.node.Children[1].Runtime.Eval(vs, is); err == nil {
+		if res2, err = rt.node.Children[1].Runtime.Eval(vs, is, tid); err == nil {
 
 
 			res2list, ok := res2.([]interface{})
 			res2list, ok := res2.([]interface{})
 			if !ok {
 			if !ok {

+ 14 - 5
interpreter/rt_general_test.go

@@ -18,17 +18,26 @@ import (
 	"devt.de/krotik/ecal/util"
 	"devt.de/krotik/ecal/util"
 )
 )
 
 
-func TestGeneralErrorCases(t *testing.T) {
+func TestGeneralCases(t *testing.T) {
+
+	rt := NewECALRuntimeProvider("a", nil, nil)
+	id1 := rt.NewThreadID()
+	id2 := rt.NewThreadID()
+
+	if id1 == id2 {
+		t.Error("Thread ids should not be the same:", id1)
+		return
+	}
 
 
 	n, _ := parser.Parse("a", "a")
 	n, _ := parser.Parse("a", "a")
-	inv := &invalidRuntime{newBaseRuntime(NewECALRuntimeProvider("a", nil, nil), n)}
+	inv := &invalidRuntime{newBaseRuntime(rt, n)}
 
 
 	if err := inv.Validate().Error(); err != "ECAL error in a: Invalid construct (Unknown node: identifier) (Line:1 Pos:1)" {
 	if err := inv.Validate().Error(); err != "ECAL error in a: Invalid construct (Unknown node: identifier) (Line:1 Pos:1)" {
 		t.Error("Unexpected result:", err)
 		t.Error("Unexpected result:", err)
 		return
 		return
 	}
 	}
 
 
-	if _, err := inv.Eval(nil, nil); err.Error() != "ECAL error in a: Invalid construct (Unknown node: identifier) (Line:1 Pos:1)" {
+	if _, err := inv.Eval(nil, nil, 0); err.Error() != "ECAL error in a: Invalid construct (Unknown node: identifier) (Line:1 Pos:1)" {
 		t.Error("Unexpected result:", err)
 		t.Error("Unexpected result:", err)
 		return
 		return
 	}
 	}
@@ -51,7 +60,7 @@ func TestGeneralErrorCases(t *testing.T) {
 	void := &voidRuntime{newBaseRuntime(NewECALRuntimeProvider("a", nil, nil), n)}
 	void := &voidRuntime{newBaseRuntime(NewECALRuntimeProvider("a", nil, nil), n)}
 	n.Runtime = void
 	n.Runtime = void
 
 
-	if res, err := void.Eval(nil, nil); err != nil || res != nil {
+	if res, err := void.Eval(nil, nil, 0); err != nil || res != nil {
 		t.Error("Unexpected result:", res, err)
 		t.Error("Unexpected result:", res, err)
 		return
 		return
 	}
 	}
@@ -95,7 +104,7 @@ statements
 	imp.erp = NewECALRuntimeProvider("ECALTestRuntime", nil, nil)
 	imp.erp = NewECALRuntimeProvider("ECALTestRuntime", nil, nil)
 	imp.erp.ImportLocator = nil
 	imp.erp.ImportLocator = nil
 
 
-	if res, err := imp.Eval(nil, nil); err == nil || err.Error() != "ECAL error in ECALTestRuntime: Runtime error (No import locator was specified) (Line:1 Pos:1)" {
+	if res, err := imp.Eval(nil, nil, 0); err == nil || err.Error() != "ECAL error in ECALTestRuntime: Runtime error (No import locator was specified) (Line:1 Pos:1)" {
 		t.Error("Unexpected result:", res, err)
 		t.Error("Unexpected result:", res, err)
 		return
 		return
 	}
 	}

+ 16 - 16
interpreter/rt_identifier.go

@@ -38,11 +38,11 @@ func identifierRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parse
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *identifierRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *identifierRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 	if err == nil {
 	if err == nil {
-		res, err = rt.resolveValue(vs, is, rt.node)
+		res, err = rt.resolveValue(vs, is, tid, rt.node)
 	}
 	}
 	return res, err
 	return res, err
 }
 }
@@ -50,7 +50,7 @@ func (rt *identifierRuntime) Eval(vs parser.Scope, is map[string]interface{}) (i
 /*
 /*
 resolveValue resolves the value of this identifier.
 resolveValue resolves the value of this identifier.
 */
 */
-func (rt *identifierRuntime) resolveValue(vs parser.Scope, is map[string]interface{}, node *parser.ASTNode) (interface{}, error) {
+func (rt *identifierRuntime) resolveValue(vs parser.Scope, is map[string]interface{}, tid uint64, node *parser.ASTNode) (interface{}, error) {
 	var anode *parser.ASTNode
 	var anode *parser.ASTNode
 	var astring string
 	var astring string
 	var result interface{}
 	var result interface{}
@@ -80,7 +80,7 @@ func (rt *identifierRuntime) resolveValue(vs parser.Scope, is map[string]interfa
 		return res
 		return res
 	}
 	}
 
 
-	anode, astring, err = buildAccessString(rt.erp, vs, is, node, node.Token.Val)
+	anode, astring, err = buildAccessString(rt.erp, vs, is, tid, node, node.Token.Val)
 
 
 	if len(node.Children) == 0 {
 	if len(node.Children) == 0 {
 
 
@@ -101,7 +101,7 @@ func (rt *identifierRuntime) resolveValue(vs parser.Scope, is map[string]interfa
 
 
 				if funcCallInAccessStringExecuted {
 				if funcCallInAccessStringExecuted {
 
 
-					result, err = rt.resolveFunction(astring, vs, is, rerr.Node, result, err)
+					result, err = rt.resolveFunction(astring, vs, is, tid, rerr.Node, result, err)
 
 
 					node = functionResolved(astring, anode)
 					node = functionResolved(astring, anode)
 
 
@@ -112,11 +112,11 @@ func (rt *identifierRuntime) resolveValue(vs parser.Scope, is map[string]interfa
 						vs = scope.NewScope("funcresult")
 						vs = scope.NewScope("funcresult")
 						vs.SetValue(node.Token.Val, result)
 						vs.SetValue(node.Token.Val, result)
 
 
-						result, err = rt.resolveValue(vs, is, node)
+						result, err = rt.resolveValue(vs, is, tid, node)
 					}
 					}
 				} else {
 				} else {
 
 
-					result, err = rt.resolveFunction(astring, vs, is, node, result, err)
+					result, err = rt.resolveFunction(astring, vs, is, tid, node, result, err)
 				}
 				}
 			}
 			}
 		}
 		}
@@ -129,7 +129,7 @@ func (rt *identifierRuntime) resolveValue(vs parser.Scope, is map[string]interfa
 resolveFunction execute function calls and return the result.
 resolveFunction execute function calls and return the result.
 */
 */
 func (rt *identifierRuntime) resolveFunction(astring string, vs parser.Scope, is map[string]interface{},
 func (rt *identifierRuntime) resolveFunction(astring string, vs parser.Scope, is map[string]interface{},
-	node *parser.ASTNode, result interface{}, err error) (interface{}, error) {
+	tid uint64, node *parser.ASTNode, result interface{}, err error) (interface{}, error) {
 
 
 	is["erp"] = rt.erp      // All functions have access to the ECAL Runtime Provider
 	is["erp"] = rt.erp      // All functions have access to the ECAL Runtime Provider
 	is["astnode"] = rt.node // ... and the AST node
 	is["astnode"] = rt.node // ... and the AST node
@@ -169,7 +169,7 @@ func (rt *identifierRuntime) resolveFunction(astring string, vs parser.Scope, is
 					var val interface{}
 					var val interface{}
 
 
 					if err == nil {
 					if err == nil {
-						val, err = c.Runtime.Eval(vs, make(map[string]interface{}))
+						val, err = c.Runtime.Eval(vs, make(map[string]interface{}), tid)
 						args = append(args, val)
 						args = append(args, val)
 					}
 					}
 				}
 				}
@@ -198,7 +198,7 @@ func (rt *identifierRuntime) resolveFunction(astring string, vs parser.Scope, is
 
 
 						// Execute the function and
 						// Execute the function and
 
 
-						result, err = funcObj.Run(rt.instanceID, vs, is, args)
+						result, err = funcObj.Run(rt.instanceID, vs, is, tid, args)
 
 
 						_, ok1 := err.(*util.RuntimeErrorWithDetail)
 						_, ok1 := err.(*util.RuntimeErrorWithDetail)
 						_, ok2 := err.(*util.RuntimeErrorWithDetail)
 						_, ok2 := err.(*util.RuntimeErrorWithDetail)
@@ -235,7 +235,7 @@ func (rt *identifierRuntime) resolveFunction(astring string, vs parser.Scope, is
 /*
 /*
 Set sets a value to this identifier.
 Set sets a value to this identifier.
 */
 */
-func (rt *identifierRuntime) Set(vs parser.Scope, is map[string]interface{}, value interface{}) error {
+func (rt *identifierRuntime) Set(vs parser.Scope, is map[string]interface{}, tid uint64, value interface{}) error {
 	var err error
 	var err error
 
 
 	if len(rt.node.Children) == 0 {
 	if len(rt.node.Children) == 0 {
@@ -247,7 +247,7 @@ func (rt *identifierRuntime) Set(vs parser.Scope, is map[string]interface{}, val
 	} else {
 	} else {
 		var as string
 		var as string
 
 
-		_, as, err = buildAccessString(rt.erp, vs, is, rt.node, rt.node.Token.Val)
+		_, as, err = buildAccessString(rt.erp, vs, is, tid, rt.node, rt.node.Token.Val)
 
 
 		if err == nil {
 		if err == nil {
 
 
@@ -264,7 +264,7 @@ func (rt *identifierRuntime) Set(vs parser.Scope, is map[string]interface{}, val
 buildAccessString builds an access string using a given node and a prefix.
 buildAccessString builds an access string using a given node and a prefix.
 */
 */
 func buildAccessString(erp *ECALRuntimeProvider, vs parser.Scope, is map[string]interface{},
 func buildAccessString(erp *ECALRuntimeProvider, vs parser.Scope, is map[string]interface{},
-	node *parser.ASTNode, prefix string) (*parser.ASTNode, string, error) {
+	tid uint64, node *parser.ASTNode, prefix string) (*parser.ASTNode, string, error) {
 
 
 	var err error
 	var err error
 	res := prefix
 	res := prefix
@@ -281,7 +281,7 @@ func buildAccessString(erp *ECALRuntimeProvider, vs parser.Scope, is map[string]
 
 
 			if c.Name == parser.NodeCOMPACCESS {
 			if c.Name == parser.NodeCOMPACCESS {
 				var val interface{}
 				var val interface{}
-				val, err = c.Children[0].Runtime.Eval(vs, is)
+				val, err = c.Children[0].Runtime.Eval(vs, is, tid)
 				res = fmt.Sprintf("%v.%v", res, val)
 				res = fmt.Sprintf("%v.%v", res, val)
 
 
 				if len(node.Children) > i+1 && node.Children[i+1].Name == parser.NodeFUNCCALL {
 				if len(node.Children) > i+1 && node.Children[i+1].Name == parser.NodeFUNCCALL {
@@ -303,7 +303,7 @@ func buildAccessString(erp *ECALRuntimeProvider, vs parser.Scope, is map[string]
 					break
 					break
 				}
 				}
 
 
-				node, res, err = buildAccessString(erp, vs, is, c, res)
+				node, res, err = buildAccessString(erp, vs, is, tid, c, res)
 			}
 			}
 		}
 		}
 	}
 	}

+ 10 - 10
interpreter/rt_sink.go

@@ -72,13 +72,13 @@ func (rt *sinkRuntime) Validate() error {
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *sinkRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *sinkRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var kindMatch, scopeMatch, suppresses []string
 	var kindMatch, scopeMatch, suppresses []string
 	var stateMatch map[string]interface{}
 	var stateMatch map[string]interface{}
 	var priority int
 	var priority int
 	var statements *parser.ASTNode
 	var statements *parser.ASTNode
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		// Create default scope
 		// Create default scope
@@ -94,7 +94,7 @@ func (rt *sinkRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfa
 		makeStringList := func(child *parser.ASTNode) ([]string, error) {
 		makeStringList := func(child *parser.ASTNode) ([]string, error) {
 			var ret []string
 			var ret []string
 
 
-			val, err := child.Runtime.Eval(vs, is)
+			val, err := child.Runtime.Eval(vs, is, tid)
 
 
 			if err == nil {
 			if err == nil {
 				for _, v := range val.([]interface{}) {
 				for _, v := range val.([]interface{}) {
@@ -123,7 +123,7 @@ func (rt *sinkRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfa
 				var val interface{}
 				var val interface{}
 				stateMatch = make(map[string]interface{})
 				stateMatch = make(map[string]interface{})
 
 
-				if val, err = child.Runtime.Eval(vs, is); err == nil {
+				if val, err = child.Runtime.Eval(vs, is, tid); err == nil {
 					for k, v := range val.(map[interface{}]interface{}) {
 					for k, v := range val.(map[interface{}]interface{}) {
 						stateMatch[fmt.Sprint(k)] = v
 						stateMatch[fmt.Sprint(k)] = v
 					}
 					}
@@ -133,7 +133,7 @@ func (rt *sinkRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfa
 			case parser.NodePRIORITY:
 			case parser.NodePRIORITY:
 				var val interface{}
 				var val interface{}
 
 
-				if val, err = child.Runtime.Eval(vs, is); err == nil {
+				if val, err = child.Runtime.Eval(vs, is, tid); err == nil {
 					priority = int(math.Floor(val.(float64)))
 					priority = int(math.Floor(val.(float64)))
 				}
 				}
 				break
 				break
@@ -171,7 +171,7 @@ func (rt *sinkRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfa
 				StateMatch:      stateMatch, // No state match
 				StateMatch:      stateMatch, // No state match
 				Priority:        priority,   // Priority of the rule
 				Priority:        priority,   // Priority of the rule
 				SuppressionList: suppresses, // List of suppressed rules by this rule
 				SuppressionList: suppresses, // List of suppressed rules by this rule
-				Action: func(p engine.Processor, m engine.Monitor, e *engine.Event) error { // Action of the rule
+				Action: func(p engine.Processor, m engine.Monitor, e *engine.Event, tid uint64) error { // Action of the rule
 
 
 					// Create a new root variable scope
 					// Create a new root variable scope
 
 
@@ -193,7 +193,7 @@ func (rt *sinkRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfa
 					if err == nil {
 					if err == nil {
 						scope.SetParentOfScope(sinkVS, vs)
 						scope.SetParentOfScope(sinkVS, vs)
 
 
-						if _, err = statements.Runtime.Eval(sinkVS, sinkIs); err != nil {
+						if _, err = statements.Runtime.Eval(sinkVS, sinkIs, tid); err != nil {
 
 
 							if sre, ok := err.(*util.RuntimeErrorWithDetail); ok {
 							if sre, ok := err.(*util.RuntimeErrorWithDetail); ok {
 								sre.Environment = sinkVS
 								sre.Environment = sinkVS
@@ -238,14 +238,14 @@ type sinkDetailRuntime struct {
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *sinkDetailRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *sinkDetailRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var ret interface{}
 	var ret interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
-		if ret, err = rt.node.Children[0].Runtime.Eval(vs, is); err == nil {
+		if ret, err = rt.node.Children[0].Runtime.Eval(vs, is, tid); err == nil {
 
 
 			// Check value is of expected type
 			// Check value is of expected type
 
 

+ 30 - 30
interpreter/rt_statements.go

@@ -40,13 +40,13 @@ func statementsRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parse
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *statementsRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *statementsRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		for _, child := range rt.node.Children {
 		for _, child := range rt.node.Children {
-			if res, err = child.Runtime.Eval(vs, is); err != nil {
+			if res, err = child.Runtime.Eval(vs, is, tid); err != nil {
 				return nil, err
 				return nil, err
 			}
 			}
 		}
 		}
@@ -75,8 +75,8 @@ func ifRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runtim
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *ifRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+func (rt *ifRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 
 
@@ -90,13 +90,13 @@ func (rt *ifRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface
 			// Evaluate guard
 			// Evaluate guard
 
 
 			if err == nil {
 			if err == nil {
-				guardres, err = rt.node.Children[offset].Runtime.Eval(vs, is)
+				guardres, err = rt.node.Children[offset].Runtime.Eval(vs, is, tid)
 
 
 				if err == nil && guardres.(bool) {
 				if err == nil && guardres.(bool) {
 
 
 					// The guard holds true so we execture its statements
 					// The guard holds true so we execture its statements
 
 
-					return rt.node.Children[offset+1].Runtime.Eval(vs, is)
+					return rt.node.Children[offset+1].Runtime.Eval(vs, is, tid)
 				}
 				}
 			}
 			}
 		}
 		}
@@ -125,17 +125,17 @@ func guardRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Run
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *guardRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *guardRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		var ret interface{}
 		var ret interface{}
 
 
 		// Evaluate the condition
 		// Evaluate the condition
 
 
-		ret, err = rt.node.Children[0].Runtime.Eval(vs, is)
+		ret, err = rt.node.Children[0].Runtime.Eval(vs, is, tid)
 
 
 		// Guard returns always a boolean
 		// Guard returns always a boolean
 
 
@@ -206,9 +206,9 @@ func (rt *loopRuntime) Validate() error {
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *loopRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *loopRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		var guardres interface{}
 		var guardres interface{}
@@ -225,13 +225,13 @@ func (rt *loopRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfa
 
 
 			// Evaluate guard
 			// Evaluate guard
 
 
-			guardres, err = rt.node.Children[0].Runtime.Eval(vs, is)
+			guardres, err = rt.node.Children[0].Runtime.Eval(vs, is, tid)
 
 
 			for err == nil && guardres.(bool) {
 			for err == nil && guardres.(bool) {
 
 
 				// Execute block
 				// Execute block
 
 
-				_, err = rt.node.Children[1].Runtime.Eval(vs, is)
+				_, err = rt.node.Children[1].Runtime.Eval(vs, is, tid)
 
 
 				// Check for continue
 				// Check for continue
 
 
@@ -247,7 +247,7 @@ func (rt *loopRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfa
 
 
 					// Evaluate guard
 					// Evaluate guard
 
 
-					guardres, err = rt.node.Children[0].Runtime.Eval(vs, is)
+					guardres, err = rt.node.Children[0].Runtime.Eval(vs, is, tid)
 				}
 				}
 			}
 			}
 
 
@@ -257,7 +257,7 @@ func (rt *loopRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfa
 
 
 			it := rt.node.Children[0].Children[1]
 			it := rt.node.Children[0].Children[1]
 
 
-			val, err = it.Runtime.Eval(vs, is)
+			val, err = it.Runtime.Eval(vs, is, tid)
 
 
 			// Create an iterator object
 			// Create an iterator object
 
 
@@ -266,7 +266,7 @@ func (rt *loopRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfa
 				// We got an iterator - all subsequent calls will return values
 				// We got an iterator - all subsequent calls will return values
 
 
 				iterator = func() (interface{}, error) {
 				iterator = func() (interface{}, error) {
-					return it.Runtime.Eval(vs, is)
+					return it.Runtime.Eval(vs, is, tid)
 				}
 				}
 				err = nil
 				err = nil
 
 
@@ -374,7 +374,7 @@ func (rt *loopRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfa
 
 
 					// Execute block
 					// Execute block
 
 
-					_, err = rt.node.Children[1].Runtime.Eval(vs, is)
+					_, err = rt.node.Children[1].Runtime.Eval(vs, is, tid)
 				}
 				}
 
 
 				// Check for continue
 				// Check for continue
@@ -421,8 +421,8 @@ func breakRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Run
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *breakRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+func (rt *breakRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		err = rt.erp.NewRuntimeError(util.ErrEndOfIteration, "", rt.node)
 		err = rt.erp.NewRuntimeError(util.ErrEndOfIteration, "", rt.node)
@@ -451,8 +451,8 @@ func continueRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *continueRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+func (rt *continueRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		err = rt.erp.NewRuntimeError(util.ErrContinueIteration, "", rt.node)
 		err = rt.erp.NewRuntimeError(util.ErrContinueIteration, "", rt.node)
@@ -481,7 +481,7 @@ func tryRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.Runti
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *tryRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
+func (rt *tryRuntime) Eval(vs parser.Scope, is map[string]interface{}, tid uint64) (interface{}, error) {
 	var res interface{}
 	var res interface{}
 
 
 	evalExcept := func(errObj map[interface{}]interface{}, except *parser.ASTNode) bool {
 	evalExcept := func(errObj map[interface{}]interface{}, except *parser.ASTNode) bool {
@@ -493,7 +493,7 @@ func (rt *tryRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfac
 
 
 			evs := vs.NewChild(scope.NameFromASTNode(except))
 			evs := vs.NewChild(scope.NameFromASTNode(except))
 
 
-			except.Children[0].Runtime.Eval(evs, is)
+			except.Children[0].Runtime.Eval(evs, is, tid)
 
 
 			ret = true
 			ret = true
 
 
@@ -504,7 +504,7 @@ func (rt *tryRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfac
 			evs := vs.NewChild(scope.NameFromASTNode(except))
 			evs := vs.NewChild(scope.NameFromASTNode(except))
 			evs.SetValue(except.Children[0].Token.Val, errObj)
 			evs.SetValue(except.Children[0].Token.Val, errObj)
 
 
-			except.Children[1].Runtime.Eval(evs, is)
+			except.Children[1].Runtime.Eval(evs, is, tid)
 
 
 			ret = true
 			ret = true
 
 
@@ -515,7 +515,7 @@ func (rt *tryRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfac
 				child := except.Children[i]
 				child := except.Children[i]
 
 
 				if !ret && child.Name == parser.NodeSTRING {
 				if !ret && child.Name == parser.NodeSTRING {
-					exceptError, evalErr := child.Runtime.Eval(vs, is)
+					exceptError, evalErr := child.Runtime.Eval(vs, is, tid)
 
 
 					// If we fail evaluating the string we panic as otherwise
 					// If we fail evaluating the string we panic as otherwise
 					// we would need to generate a new error while trying to handle another error
 					// we would need to generate a new error while trying to handle another error
@@ -533,7 +533,7 @@ func (rt *tryRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfac
 						evs.SetValue(errorVar, errObj)
 						evs.SetValue(errorVar, errObj)
 					}
 					}
 
 
-					child.Runtime.Eval(evs, is)
+					child.Runtime.Eval(evs, is, tid)
 				}
 				}
 			}
 			}
 		}
 		}
@@ -545,15 +545,15 @@ func (rt *tryRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interfac
 
 
 	if finally := rt.node.Children[len(rt.node.Children)-1]; finally.Name == parser.NodeFINALLY {
 	if finally := rt.node.Children[len(rt.node.Children)-1]; finally.Name == parser.NodeFINALLY {
 		fvs := vs.NewChild(scope.NameFromASTNode(finally))
 		fvs := vs.NewChild(scope.NameFromASTNode(finally))
-		defer finally.Children[0].Runtime.Eval(fvs, is)
+		defer finally.Children[0].Runtime.Eval(fvs, is, tid)
 	}
 	}
 
 
-	_, err := rt.baseRuntime.Eval(vs, is)
+	_, err := rt.baseRuntime.Eval(vs, is, tid)
 
 
 	if err == nil {
 	if err == nil {
 		tvs := vs.NewChild(scope.NameFromASTNode(rt.node))
 		tvs := vs.NewChild(scope.NameFromASTNode(rt.node))
 
 
-		res, err = rt.node.Children[0].Runtime.Eval(tvs, is)
+		res, err = rt.node.Children[0].Runtime.Eval(tvs, is, tid)
 
 
 		// Evaluate except clauses
 		// Evaluate except clauses
 
 

+ 12 - 12
interpreter/rt_value.go

@@ -50,8 +50,8 @@ func (rt *numberValueRuntime) Validate() error {
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *numberValueRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+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
 	return rt.numValue, err
 }
 }
@@ -73,8 +73,8 @@ func stringValueRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) pars
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *stringValueRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+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
 	ret := rt.node.Token.Val
 
 
@@ -100,7 +100,7 @@ func (rt *stringValueRuntime) Eval(vs parser.Scope, is map[string]interface{}) (
 
 
 					res, ierr = ast.Runtime.Eval(
 					res, ierr = ast.Runtime.Eval(
 						vs.NewChild(scope.NameFromASTNode(rt.node)),
 						vs.NewChild(scope.NameFromASTNode(rt.node)),
-						make(map[string]interface{}))
+						make(map[string]interface{}), tid)
 
 
 					if ierr == nil {
 					if ierr == nil {
 						replace = fmt.Sprint(res)
 						replace = fmt.Sprint(res)
@@ -150,8 +150,8 @@ func mapValueRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser.
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *mapValueRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+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{})
 	m := make(map[interface{}]interface{})
 
 
@@ -160,8 +160,8 @@ func (rt *mapValueRuntime) Eval(vs parser.Scope, is map[string]interface{}) (int
 			var key, val interface{}
 			var key, val interface{}
 
 
 			if err == nil {
 			if err == nil {
-				if key, err = kvp.Children[0].Runtime.Eval(vs, is); err == nil {
-					if val, err = kvp.Children[1].Runtime.Eval(vs, is); 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
 						m[key] = val
 					}
 					}
 				}
 				}
@@ -189,8 +189,8 @@ func listValueRuntimeInst(erp *ECALRuntimeProvider, node *parser.ASTNode) parser
 /*
 /*
 Eval evaluate this runtime component.
 Eval evaluate this runtime component.
 */
 */
-func (rt *listValueRuntime) Eval(vs parser.Scope, is map[string]interface{}) (interface{}, error) {
-	_, err := rt.baseRuntime.Eval(vs, is)
+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{}
 	var l []interface{}
 
 
@@ -198,7 +198,7 @@ func (rt *listValueRuntime) Eval(vs parser.Scope, is map[string]interface{}) (in
 		for _, item := range rt.node.Children {
 		for _, item := range rt.node.Children {
 			if err == nil {
 			if err == nil {
 				var val interface{}
 				var val interface{}
-				if val, err = item.Runtime.Eval(vs, is); err == nil {
+				if val, err = item.Runtime.Eval(vs, is, tid); err == nil {
 					l = append(l, val)
 					l = append(l, val)
 				}
 				}
 
 

+ 6 - 3
parser/runtime.go

@@ -33,12 +33,15 @@ type Runtime interface {
 
 
 	/*
 	/*
 		Eval evaluate this runtime component. It gets passed the current variable
 		Eval evaluate this runtime component. It gets passed the current variable
-		scope and the instance state.
+		scope an instance state and a thread ID.
 
 
 		The instance state is created per execution instance and can be used
 		The instance state is created per execution instance and can be used
-		for generator functions to store their current state.
+		for generator functions to store their current state. It gets replaced
+		by a new object in certain situations (e.g. a function call).
+
+		The thread ID can be used to identify a running process.
 	*/
 	*/
-	Eval(Scope, map[string]interface{}) (interface{}, error)
+	Eval(Scope, map[string]interface{}, uint64) (interface{}, error)
 }
 }
 
 
 /*
 /*

+ 1 - 1
stdlib/adapter.go

@@ -36,7 +36,7 @@ func NewECALFunctionAdapter(funcval reflect.Value, docstring string) *ECALFuncti
 Run executes this function.
 Run executes this function.
 */
 */
 func (ea *ECALFunctionAdapter) Run(instanceID string, vs parser.Scope,
 func (ea *ECALFunctionAdapter) Run(instanceID string, vs parser.Scope,
-	is map[string]interface{}, args []interface{}) (ret interface{}, err error) {
+	is map[string]interface{}, tid uint64, args []interface{}) (ret interface{}, err error) {
 
 
 	defer func() {
 	defer func() {
 		if r := recover(); r != nil {
 		if r := recover(); r != nil {

+ 1 - 1
stdlib/adapter_test.go

@@ -249,7 +249,7 @@ func TestECALFunctionAdapter(t *testing.T) {
 
 
 func runAdapterTest(afunc reflect.Value, args []interface{}) (interface{}, error) {
 func runAdapterTest(afunc reflect.Value, args []interface{}) (interface{}, error) {
 	afuncEcal := &ECALFunctionAdapter{afunc, ""}
 	afuncEcal := &ECALFunctionAdapter{afunc, ""}
-	return afuncEcal.Run("test", scope.NewScope(""), make(map[string]interface{}), args)
+	return afuncEcal.Run("test", scope.NewScope(""), make(map[string]interface{}), 0, args)
 
 
 }
 }
 
 

+ 1 - 1
util/types.go

@@ -41,7 +41,7 @@ type ECALFunction interface {
 		to store instance specific state (e.g. for iterator functions) and a list
 		to store instance specific state (e.g. for iterator functions) and a list
 		of argument values which were passed to the function by the calling code.
 		of argument values which were passed to the function by the calling code.
 	*/
 	*/
-	Run(instanceID string, vs parser.Scope, is map[string]interface{}, args []interface{}) (interface{}, error)
+	Run(instanceID string, vs parser.Scope, is map[string]interface{}, tid uint64, args []interface{}) (interface{}, error)
 
 
 	/*
 	/*
 	   DocString returns a descriptive text about this function.
 	   DocString returns a descriptive text about this function.