From 1bb39eba8717f62336cc98c5bb7cfbef194f3626 Mon Sep 17 00:00:00 2001 From: Wim Date: Sat, 23 Feb 2019 16:39:44 +0100 Subject: Add scripting (tengo) support for every incoming message (#731) TengoModifyMessage allows you to specify the location of a tengo (https://github.com/d5/tengo/) script. This script will receive every incoming message and can be used to modify the Username and the Text of that message. The script will have the following global variables: to modify: msgUsername and msgText to read: msgChannel and msgAccount The script is reloaded on every message, so you can modify the script on the fly. Example script can be found in https://github.com/42wim/matterbridge/tree/master/gateway/bench.tengo and https://github.com/42wim/matterbridge/tree/master/contrib/example.tengo The example below will check if the text contains blah and if so, it'll replace the text and the username of that message. text := import("text") if text.re_match("blah",msgText) { msgText="replaced by this" msgUsername="fakeuser" } More information about tengo on: https://github.com/d5/tengo/blob/master/docs/tutorial.md and https://github.com/d5/tengo/blob/master/docs/stdlib.md --- .../github.com/d5/tengo/compiler/symbol_table.go | 145 +++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 vendor/github.com/d5/tengo/compiler/symbol_table.go (limited to 'vendor/github.com/d5/tengo/compiler/symbol_table.go') diff --git a/vendor/github.com/d5/tengo/compiler/symbol_table.go b/vendor/github.com/d5/tengo/compiler/symbol_table.go new file mode 100644 index 00000000..da55a826 --- /dev/null +++ b/vendor/github.com/d5/tengo/compiler/symbol_table.go @@ -0,0 +1,145 @@ +package compiler + +// SymbolTable represents a symbol table. +type SymbolTable struct { + parent *SymbolTable + block bool + store map[string]*Symbol + numDefinition int + maxDefinition int + freeSymbols []*Symbol +} + +// NewSymbolTable creates a SymbolTable. +func NewSymbolTable() *SymbolTable { + return &SymbolTable{ + store: make(map[string]*Symbol), + } +} + +// Define adds a new symbol in the current scope. +func (t *SymbolTable) Define(name string) *Symbol { + symbol := &Symbol{Name: name, Index: t.nextIndex()} + t.numDefinition++ + + if t.Parent(true) == nil { + symbol.Scope = ScopeGlobal + } else { + symbol.Scope = ScopeLocal + } + + t.store[name] = symbol + + t.updateMaxDefs(symbol.Index + 1) + + return symbol +} + +// DefineBuiltin adds a symbol for builtin function. +func (t *SymbolTable) DefineBuiltin(index int, name string) *Symbol { + symbol := &Symbol{ + Name: name, + Index: index, + Scope: ScopeBuiltin, + } + + t.store[name] = symbol + + return symbol +} + +// Resolve resolves a symbol with a given name. +func (t *SymbolTable) Resolve(name string) (symbol *Symbol, depth int, ok bool) { + symbol, ok = t.store[name] + if !ok && t.parent != nil { + symbol, depth, ok = t.parent.Resolve(name) + if !ok { + return + } + + if !t.block { + depth++ + } + + // if symbol is defined in parent table and if it's not global/builtin + // then it's free variable. + if !t.block && depth > 0 && symbol.Scope != ScopeGlobal && symbol.Scope != ScopeBuiltin { + return t.defineFree(symbol), depth, true + } + + return + } + + return +} + +// Fork creates a new symbol table for a new scope. +func (t *SymbolTable) Fork(block bool) *SymbolTable { + return &SymbolTable{ + store: make(map[string]*Symbol), + parent: t, + block: block, + } +} + +// Parent returns the outer scope of the current symbol table. +func (t *SymbolTable) Parent(skipBlock bool) *SymbolTable { + if skipBlock && t.block { + return t.parent.Parent(skipBlock) + } + + return t.parent +} + +// MaxSymbols returns the total number of symbols defined in the scope. +func (t *SymbolTable) MaxSymbols() int { + return t.maxDefinition +} + +// FreeSymbols returns free symbols for the scope. +func (t *SymbolTable) FreeSymbols() []*Symbol { + return t.freeSymbols +} + +// Names returns the name of all the symbols. +func (t *SymbolTable) Names() []string { + var names []string + for name := range t.store { + names = append(names, name) + } + return names +} + +func (t *SymbolTable) nextIndex() int { + if t.block { + return t.parent.nextIndex() + t.numDefinition + } + + return t.numDefinition +} + +func (t *SymbolTable) updateMaxDefs(numDefs int) { + if numDefs > t.maxDefinition { + t.maxDefinition = numDefs + } + + if t.block { + t.parent.updateMaxDefs(numDefs) + } +} + +func (t *SymbolTable) defineFree(original *Symbol) *Symbol { + // TODO: should we check duplicates? + + t.freeSymbols = append(t.freeSymbols, original) + + symbol := &Symbol{ + Name: original.Name, + Index: len(t.freeSymbols) - 1, + Scope: ScopeFree, + } + + t.store[original.Name] = symbol + + return symbol +} -- cgit v1.2.3