refactor: cleaning up some old issues and stndardizing.

This commit is contained in:
James Wells 2023-03-20 16:00:15 -07:00
parent b95d3950c5
commit 8640d42132
Signed by: jwells
GPG key ID: 73196D10B8E65666
6 changed files with 190 additions and 113 deletions

View file

@ -1,10 +1,10 @@
package main package main
import ( import (
fmt "fmt"
log "log" log "log"
http "net/http" http "net/http"
os "os" os "os"
strconv "strconv"
sync "sync" sync "sync"
autorestart "github.com/slayer/autorestart" autorestart "github.com/slayer/autorestart"
@ -290,7 +290,7 @@ func init() {
if config.MonitorPort != 0 { if config.MonitorPort != 0 {
go func() { go func() {
log.Printf("[INFO] Starting Prometheus metrics exporter on port %d\n", config.MonitorPort) log.Printf("[INFO] Starting Prometheus metrics exporter on port %d\n", config.MonitorPort)
log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%d", config.ListenAddr, config.MonitorPort), nil)) log.Fatal(http.ListenAndServe(string(config.ListenAddr)+strconv.FormatInt(config.MonitorPort, 10), nil))
}() }()
} }
} }

View file

@ -7,8 +7,8 @@ type GagentConfig struct {
Name string `hcl:"name,optional"` Name string `hcl:"name,optional"`
Mode string `hcl:"mode,attr"` Mode string `hcl:"mode,attr"`
UUID string `hcl:"uuid,optional"` UUID string `hcl:"uuid,optional"`
MonitorPort int `hcl:"monitorport,optional"`
ListenAddr string `hcl:"listenaddr,optional"` ListenAddr string `hcl:"listenaddr,optional"`
MonitorPort int64 `hcl:"monitorport,optional"`
ClientPort int64 `hcl:"clientport,optional"` ClientPort int64 `hcl:"clientport,optional"`
RouterPort int64 `hcl:"routerport,optional"` RouterPort int64 `hcl:"routerport,optional"`
WorkerPort int64 `hcl:"workerport,optional"` WorkerPort int64 `hcl:"workerport,optional"`

View file

@ -1,8 +1,8 @@
package worker package worker
import ( import (
fmt "fmt"
log "log" log "log"
strconv "strconv"
sync "sync" sync "sync"
gstructs "github.com/dragonheim/gagent/internal/gstructs" gstructs "github.com/dragonheim/gagent/internal/gstructs"
@ -43,13 +43,13 @@ func Main(wg *sync.WaitGroup, config gstructs.GagentConfig) {
/* /*
* Generate connect string for this router. * Generate connect string for this router.
*/ */
connectString := fmt.Sprintf("tcp://%s:%d", config.Routers[key].RouterAddr, rport) connectString := "tcp://" + config.Routers[key].RouterAddr + ":" + strconv.FormatInt(rport, 10)
wg.Add(1) wg.Add(1)
go getAgent(wg, config.UUID, connectString) go getAgent(wg, config.UUID, connectString)
} }
/* /*
* workerListener := fmt.Sprintf("tcp://%s:%d", config.ListenAddr, config.WorkerPort) * workerListener := "tcp://" + config.ListenAddr + ":" + strconv.FormatInt(config.WorkerPort, 10)
*/ */
} }

View file

@ -7,13 +7,18 @@ import (
"testing" "testing"
) )
func arityErr(i *Interp, name string, argv []string) error { /*
* incorrectArgCountError returns an error message indicating the incorrect
* number of arguments provided for a given function. It takes an interpreter
* instance 'i', the function name 'name', and a slice of argument values 'argv'.
*/
func incorrectArgCountError(i *Interpreter, name string, argv []string) error {
return fmt.Errorf("wrong number of args for %s %s", name, argv) return fmt.Errorf("wrong number of args for %s %s", name, argv)
} }
/* /*
needleInHaystack returns true if the string is in a slice * needleInHaystack returns true if the string is in a slice
*/ */
func needleInHaystack(needle string, haystack []string) bool { func needleInHaystack(needle string, haystack []string) bool {
for _, haystackMember := range haystack { for _, haystackMember := range haystack {
if haystackMember == needle { if haystackMember == needle {
@ -24,9 +29,9 @@ func needleInHaystack(needle string, haystack []string) bool {
} }
/* /*
TestneedleInHaystack tests the return value of needleInHaystack * Test_needleInHaystack tests the return value of needleInHaystack
*/ */
func TestneedleInHaystack(t *testing.T) { func Test_needleInHaystack(t *testing.T) {
var haystack = []string{"a", "b", "c"} var haystack = []string{"a", "b", "c"}
var needle = "a" var needle = "a"
if !needleInHaystack(needle, haystack) { if !needleInHaystack(needle, haystack) {
@ -44,10 +49,12 @@ func TestneedleInHaystack(t *testing.T) {
} }
} }
// CommandMath is the math command for TCL /*
func CommandMath(i *Interp, argv []string, pd interface{}) (string, error) { * CommandMath is the math command for TCL
*/
func CommandMath(i *Interpreter, argv []string, pd interface{}) (string, error) {
if len(argv) != 3 { if len(argv) != 3 {
return "", arityErr(i, argv[0], argv) return "", incorrectArgCountError(i, argv[0], argv)
} }
a, _ := strconv.Atoi(argv[1]) a, _ := strconv.Atoi(argv[1])
b, _ := strconv.Atoi(argv[2]) b, _ := strconv.Atoi(argv[2])
@ -91,28 +98,34 @@ func CommandMath(i *Interp, argv []string, pd interface{}) (string, error) {
return fmt.Sprintf("%d", c), nil return fmt.Sprintf("%d", c), nil
} }
// CommandSet is the set command for TCL /*
func CommandSet(i *Interp, argv []string, pd interface{}) (string, error) { * CommandSet is the set command for TCL
*/
func CommandSet(i *Interpreter, argv []string, pd interface{}) (string, error) {
if len(argv) != 3 { if len(argv) != 3 {
return "", arityErr(i, argv[0], argv) return "", incorrectArgCountError(i, argv[0], argv)
} }
i.SetVar(argv[1], argv[2]) i.SetVariable(argv[1], argv[2])
return argv[2], nil return argv[2], nil
} }
// CommandUnset is the unset command for TCL /*
func CommandUnset(i *Interp, argv []string, pd interface{}) (string, error) { * CommandUnset is the unset command for TCL
*/
func CommandUnset(i *Interpreter, argv []string, pd interface{}) (string, error) {
if len(argv) != 2 { if len(argv) != 2 {
return "", arityErr(i, argv[0], argv) return "", incorrectArgCountError(i, argv[0], argv)
} }
i.UnsetVar(argv[1]) i.UnsetVariable(argv[1])
return "", nil return "", nil
} }
// CommandIf is the if command for TCL /*
func CommandIf(i *Interp, argv []string, pd interface{}) (string, error) { * CommandIf is the if command for TCL
*/
func CommandIf(i *Interpreter, argv []string, pd interface{}) (string, error) {
if len(argv) != 3 && len(argv) != 5 { if len(argv) != 3 && len(argv) != 5 {
return "", arityErr(i, argv[0], argv) return "", incorrectArgCountError(i, argv[0], argv)
} }
result, err := i.Eval(argv[1]) result, err := i.Eval(argv[1])
@ -129,10 +142,12 @@ func CommandIf(i *Interp, argv []string, pd interface{}) (string, error) {
return result, nil return result, nil
} }
// CommandWhile is the while command for TCL /*
func CommandWhile(i *Interp, argv []string, pd interface{}) (string, error) { * CommandWhile is the while command for TCL
*/
func CommandWhile(i *Interpreter, argv []string, pd interface{}) (string, error) {
if len(argv) != 3 { if len(argv) != 3 {
return "", arityErr(i, argv[0], argv) return "", incorrectArgCountError(i, argv[0], argv)
} }
for { for {
@ -143,9 +158,11 @@ func CommandWhile(i *Interp, argv []string, pd interface{}) (string, error) {
if r, _ := strconv.Atoi(result); r != 0 { if r, _ := strconv.Atoi(result); r != 0 {
result, err := i.Eval(argv[2]) result, err := i.Eval(argv[2])
switch err { switch err {
case errContinue, nil: case ErrContinue, nil:
//pass /*
case errBreak: * pass
*/
case ErrBreak:
return result, nil return result, nil
default: default:
return result, err return result, err
@ -156,22 +173,26 @@ func CommandWhile(i *Interp, argv []string, pd interface{}) (string, error) {
} }
} }
// CommandRetCodes is a function to get the return codes for TCL /*
func CommandRetCodes(i *Interp, argv []string, pd interface{}) (string, error) { * CommandRetCodes is a function to get the return codes for TCL
*/
func CommandRetCodes(i *Interpreter, argv []string, pd interface{}) (string, error) {
if len(argv) != 1 { if len(argv) != 1 {
return "", arityErr(i, argv[0], argv) return "", incorrectArgCountError(i, argv[0], argv)
} }
switch argv[0] { switch argv[0] {
case "break": case "break":
return "", errBreak return "", ErrBreak
case "continue": case "continue":
return "", errContinue return "", ErrContinue
} }
return "", nil return "", nil
} }
// CommandCallProc is a function to call proc commands for TCL /*
func CommandCallProc(i *Interp, argv []string, pd interface{}) (string, error) { * CommandCallProc is a function to call proc commands for TCL
*/
func CommandCallProc(i *Interpreter, argv []string, pd interface{}) (string, error) {
var x []string var x []string
if pd, ok := pd.([]string); ok { if pd, ok := pd.([]string); ok {
@ -180,7 +201,7 @@ func CommandCallProc(i *Interp, argv []string, pd interface{}) (string, error) {
return "", nil return "", nil
} }
i.callframe = &CallFrame{vars: make(map[string]Var), parent: i.callframe} i.callframe = &CallFrame{vars: make(map[string]Variable), parent: i.callframe}
defer func() { i.callframe = i.callframe.parent }() // remove the called proc callframe defer func() { i.callframe = i.callframe.parent }() // remove the called proc callframe
arity := 0 arity := 0
@ -189,7 +210,7 @@ func CommandCallProc(i *Interp, argv []string, pd interface{}) (string, error) {
continue continue
} }
arity++ arity++
i.SetVar(arg, argv[arity]) i.SetVariable(arg, argv[arity])
} }
if arity != len(argv)-1 { if arity != len(argv)-1 {
@ -198,42 +219,50 @@ func CommandCallProc(i *Interp, argv []string, pd interface{}) (string, error) {
body := x[1] body := x[1]
result, err := i.Eval(body) result, err := i.Eval(body)
if err == errReturn { if err == ErrReturn {
err = nil err = nil
} }
return result, err return result, err
} }
// CommandProc is a function to register proc commands for TCL /*
func CommandProc(i *Interp, argv []string, pd interface{}) (string, error) { * CommandProc is a function to register proc commands for TCL
*/
func CommandProc(i *Interpreter, argv []string, pd interface{}) (string, error) {
if len(argv) != 4 { if len(argv) != 4 {
return "", arityErr(i, argv[0], argv) return "", incorrectArgCountError(i, argv[0], argv)
} }
return "", i.RegisterCommand(argv[1], CommandCallProc, []string{argv[2], argv[3]}) return "", i.RegisterCommand(argv[1], CommandCallProc, []string{argv[2], argv[3]})
} }
// CommandReturn is a function to register return codes for commands for TCL /*
func CommandReturn(i *Interp, argv []string, pd interface{}) (string, error) { * CommandReturn is a function to register return codes for commands for TCL
*/
func CommandReturn(i *Interpreter, argv []string, pd interface{}) (string, error) {
if len(argv) != 1 && len(argv) != 2 { if len(argv) != 1 && len(argv) != 2 {
return "", arityErr(i, argv[0], argv) return "", incorrectArgCountError(i, argv[0], argv)
} }
var r string var r string
if len(argv) == 2 { if len(argv) == 2 {
r = argv[1] r = argv[1]
} }
return r, errReturn return r, ErrReturn
} }
// CommandError is a function to return error codes for commands for TCL /*
func CommandError(i *Interp, argv []string, pd interface{}) (string, error) { * CommandError is a function to return error codes for commands for TCL
*/
func CommandError(i *Interpreter, argv []string, pd interface{}) (string, error) {
if len(argv) != 1 && len(argv) != 2 { if len(argv) != 1 && len(argv) != 2 {
return "", arityErr(i, argv[0], argv) return "", incorrectArgCountError(i, argv[0], argv)
} }
return "", fmt.Errorf(argv[1]) return "", fmt.Errorf(argv[1])
} }
// CommandPuts is a function to print strings for TCL /*
func CommandPuts(i *Interp, argv []string, pd interface{}) (string, error) { * CommandPuts is a function to print strings for TCL
*/
func CommandPuts(i *Interpreter, argv []string, pd interface{}) (string, error) {
if len(argv) != 2 { if len(argv) != 2 {
return "", fmt.Errorf("wrong number of args for %s %s", argv[0], argv) return "", fmt.Errorf("wrong number of args for %s %s", argv[0], argv)
} }
@ -241,8 +270,10 @@ func CommandPuts(i *Interp, argv []string, pd interface{}) (string, error) {
return "", nil return "", nil
} }
// RegisterCoreCommands is a callable to register TCL commands. /*
func (i *Interp) RegisterCoreCommands() { * RegisterCoreCommands is a callable to register TCL commands.
*/
func (i *Interpreter) RegisterCoreCommands() {
name := [...]string{"+", "-", "*", "/", ">", ">=", "<", "<=", "==", "!="} name := [...]string{"+", "-", "*", "/", ">", ">=", "<", "<=", "==", "!="}
for _, n := range name { for _, n := range name {
_ = i.RegisterCommand(n, CommandMath, nil) _ = i.RegisterCommand(n, CommandMath, nil)

View file

@ -6,38 +6,66 @@ import (
"strings" "strings"
) )
/*
* Error variables
*/
var ( var (
errReturn = errors.New("RETURN") ErrReturn = errors.New("RETURN")
errBreak = errors.New("BREAK") ErrBreak = errors.New("BREAK")
errContinue = errors.New("CONTINUE") ErrContinue = errors.New("CONTINUE")
) )
type Var string /*
type CmdFunc func(i *Interp, argv []string, privdata interface{}) (string, error) * Variable type
type Cmd struct { */
fn CmdFunc type Variable string
/*
* CommandFunc type
*/
type CommandFunc func(interp *Interpreter, argv []string, privdata interface{}) (string, error)
/*
* Command structure
*/
type Command struct {
fn CommandFunc
privdata interface{} privdata interface{}
} }
/*
* CallFrame structure
*/
type CallFrame struct { type CallFrame struct {
vars map[string]Var vars map[string]Variable
parent *CallFrame parent *CallFrame
} }
type Interp struct {
/*
* Interpreter structure
*/
type Interpreter struct {
level int level int
callframe *CallFrame callframe *CallFrame
commands map[string]Cmd commands map[string]Command
} }
func InitInterp() *Interp { /*
return &Interp{ * NewInterpreter initializes a new Interpreter
*/
func NewInterpreter() *Interpreter {
return &Interpreter{
level: 0, level: 0,
callframe: &CallFrame{vars: make(map[string]Var)}, callframe: &CallFrame{vars: make(map[string]Variable)},
commands: make(map[string]Cmd), commands: make(map[string]Command),
} }
} }
func (i *Interp) Var(name string) (Var, bool) { /*
for frame := i.callframe; frame != nil; frame = frame.parent { * Variable retrieves a variable's value
*/
func (interp *Interpreter) Variable(name string) (Variable, bool) {
for frame := interp.callframe; frame != nil; frame = frame.parent {
v, ok := frame.vars[name] v, ok := frame.vars[name]
if ok { if ok {
return v, ok return v, ok
@ -45,94 +73,112 @@ func (i *Interp) Var(name string) (Var, bool) {
} }
return "", false return "", false
} }
func (i *Interp) SetVar(name, val string) {
i.callframe.vars[name] = Var(val) /*
* SetVariable sets a variable's value
*/
func (interp *Interpreter) SetVariable(name, val string) {
interp.callframe.vars[name] = Variable(val)
} }
func (i *Interp) UnsetVar(name string) { /*
delete(i.callframe.vars, name) * UnsetVariable removes a variable
*/
func (interp *Interpreter) UnsetVariable(name string) {
delete(interp.callframe.vars, name)
} }
func (i *Interp) Command(name string) *Cmd { /*
v, ok := i.commands[name] * Command retrieves a command
*/
func (interp *Interpreter) Command(name string) *Command {
v, ok := interp.commands[name]
if !ok { if !ok {
return nil return nil
} }
return &v return &v
} }
func (i *Interp) RegisterCommand(name string, fn CmdFunc, privdata interface{}) error { /*
c := i.Command(name) * RegisterCommand registers a new command
if c != nil { */
func (interp *Interpreter) RegisterCommand(name string, fn CommandFunc, privdata interface{}) error {
cmd := interp.Command(name)
if cmd != nil {
return fmt.Errorf("Command '%s' already defined", name) return fmt.Errorf("Command '%s' already defined", name)
} }
i.commands[name] = Cmd{fn, privdata} interp.commands[name] = Command{fn, privdata}
return nil return nil
} }
/* EVAL! */ /*
func (i *Interp) Eval(t string) (string, error) { * Eval evaluates a script
p := initParser(t) */
func (interp *Interpreter) Eval(script string) (string, error) {
parser := initParser(script)
var result string var result string
var err error var err error
argv := []string{} argv := []string{}
for { for {
prevtype := p.Type prevType := parser.Type
// XXX token := parser.GetToken()
t = p.GetToken() if parser.Type == ptEOF {
if p.Type == ptEOF {
break break
} }
switch p.Type { switch parser.Type {
case ptVAR: case ptVAR:
v, ok := i.Var(t) v, ok := interp.Variable(token)
if !ok { if !ok {
return "", fmt.Errorf("no such variable '%s'", t) return "", fmt.Errorf("no such variable '%s'", token)
} }
t = string(v) token = string(v)
case ptCMD: case ptCMD:
result, err = i.Eval(t) result, err = interp.Eval(token)
if err != nil { if err != nil {
return result, err return result, err
} else {
t = result
} }
token = result
case ptESC: case ptESC:
// XXX: escape handling missing! /*
* TODO: escape handling missing!
*/
case ptSEP: case ptSEP:
prevtype = p.Type prevType = parser.Type
continue continue
} }
// We have a complete command + args. Call it! if parser.Type == ptEOL {
if p.Type == ptEOL { prevType = parser.Type
prevtype = p.Type
if len(argv) != 0 { if len(argv) != 0 {
c := i.Command(argv[0]) cmd := interp.Command(argv[0])
if c == nil { if cmd == nil {
return "", fmt.Errorf("no such command '%s'", argv[0]) return "", fmt.Errorf("no such command '%s'", argv[0])
} }
result, err = c.fn(i, argv, c.privdata) result, err = cmd.fn(interp, argv, cmd.privdata)
if err != nil { if err != nil {
return result, err return result, err
} }
} }
// Prepare for the next command /*
* Prepare for the next command
*/
argv = []string{} argv = []string{}
continue continue
} }
// We have a new token, append to the previous or as new arg? /*
if prevtype == ptSEP || prevtype == ptEOL { * We have a new token, append to the previous or as new arg?
argv = append(argv, t) */
if prevType == ptSEP || prevType == ptEOL {
argv = append(argv, token)
} else { // Interpolation } else { // Interpolation
argv[len(argv)-1] = strings.Join([]string{argv[len(argv)-1], t}, "") argv[len(argv)-1] = strings.Join([]string{argv[len(argv)-1], token}, "")
} }
prevtype = p.Type prevType = parser.Type
} }
return result, nil return result, nil
} }

View file

@ -7,13 +7,13 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
picol "github.com/dragonheim/gagent/src/picol" picol "github.com/dragonheim/gagent/pkg/picol"
) )
var fname = flag.String("f", "", "file name") var fname = flag.String("f", "", "file name")
// CommandPuts is a simple version of the TCL puts function. // CommandPuts is a simple version of the TCL puts function.
func CommandPuts(i *picol.Interp, argv []string, pd interface{}) (string, error) { func CommandPuts(i *picol.Interpreter, argv []string, pd interface{}) (string, error) {
if len(argv) != 2 { if len(argv) != 2 {
return "", fmt.Errorf("wrong number of args for %s %s", argv[0], argv) return "", fmt.Errorf("wrong number of args for %s %s", argv[0], argv)
} }
@ -23,7 +23,7 @@ func CommandPuts(i *picol.Interp, argv []string, pd interface{}) (string, error)
func main() { func main() {
flag.Parse() flag.Parse()
interp := picol.InitInterp() interp := picol.NewInterpreter()
interp.RegisterCoreCommands() interp.RegisterCoreCommands()
interp.RegisterCommand("puts", CommandPuts, nil) interp.RegisterCommand("puts", CommandPuts, nil)