diff options
author | Wim <wim@42.be> | 2019-02-23 16:39:44 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-23 16:39:44 +0100 |
commit | 1bb39eba8717f62336cc98c5bb7cfbef194f3626 (patch) | |
tree | 0437ae89473b8e25ad1c9597e1049a23a7933f6a /vendor/github.com/d5/tengo/compiler/symbol_table.go | |
parent | 3190703dc8618896c932a23d8ca155fbbf6fab13 (diff) | |
download | matterbridge-msglm-1bb39eba8717f62336cc98c5bb7cfbef194f3626.tar.gz matterbridge-msglm-1bb39eba8717f62336cc98c5bb7cfbef194f3626.tar.bz2 matterbridge-msglm-1bb39eba8717f62336cc98c5bb7cfbef194f3626.zip |
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
Diffstat (limited to 'vendor/github.com/d5/tengo/compiler/symbol_table.go')
-rw-r--r-- | vendor/github.com/d5/tengo/compiler/symbol_table.go | 145 |
1 files changed, 145 insertions, 0 deletions
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 +} |