From be6cd2217b6bb1bb411d46ebd9d003dfd928af96 Mon Sep 17 00:00:00 2001 From: Mel Date: Wed, 17 Aug 2022 00:07:35 +0000 Subject: Add different "say" outputs to VM --- pkg/bot/cmds.go | 32 +++++++++++++++------------- pkg/bot/output.go | 19 +++++++++++++++++ pkg/lang/modules/core/natives.go | 14 ++++++++++--- pkg/lang/vm/exe.go | 4 ++++ pkg/lang/vm/executor/executor.go | 2 ++ pkg/lang/vm/output.go | 45 ++++++++++++++++++++++++++++++++++++++++ pkg/lang/vm/vm.go | 6 +++++- pkg/lang/vm/vm_test.go | 28 ++++++++++++------------- 8 files changed, 118 insertions(+), 32 deletions(-) create mode 100644 pkg/bot/output.go create mode 100644 pkg/lang/vm/output.go (limited to 'pkg') diff --git a/pkg/bot/cmds.go b/pkg/bot/cmds.go index 32b1bfe..7d451a9 100644 --- a/pkg/bot/cmds.go +++ b/pkg/bot/cmds.go @@ -36,20 +36,23 @@ func vmCmd(b *Bot, content string, msg events.Message) error { return err } - vm := vm.New(modules.NewUnknownModule(&bc)) - - if err := vm.Run(); err != nil { - return err + output := &chatOutput{ + logger: b.logger, + client: b.client, + channel: msg.ChannelID, } - res, err := vm.GetResult() - if err != nil { + vm := vm.New(modules.NewUnknownModule(&bc), output) + + b.logger.Info().Msgf("executing vm bytecode from user %s...", msg.Author.Username) + + if err := vm.Run(); err != nil { return err } b.logger.Debug().Msg("executed code") - return b.client.SendMessage(msg.ChannelID, res) + return nil } func langCmd(b *Bot, content string, msg events.Message) error { @@ -81,20 +84,21 @@ func langCmd(b *Bot, content string, msg events.Message) error { b.client.SendMessage(msg.ChannelID, fmt.Sprintf("resulting decompiled bytecode:\n```\n%s\n```", decompRes)) - vm := vm.New(module) + output := &chatOutput{ + logger: b.logger, + client: b.client, + channel: msg.ChannelID, + } + vm := vm.New(module, output) + b.logger.Info().Msgf("executing code from user %s...", msg.Author.Username) b.client.SendMessage(msg.ChannelID, "executing code...") if err := vm.Run(); err != nil { return err } - res, err := vm.GetResult() - if err != nil { - return err - } - b.logger.Debug().Msg("executed code") - return b.client.SendMessage(msg.ChannelID, res) + return nil } diff --git a/pkg/bot/output.go b/pkg/bot/output.go new file mode 100644 index 0000000..d29a625 --- /dev/null +++ b/pkg/bot/output.go @@ -0,0 +1,19 @@ +package bot + +import ( + "jinx/pkg/discord" + "jinx/pkg/discord/entities" + + "github.com/rs/zerolog" +) + +type chatOutput struct { + logger *zerolog.Logger + client *discord.Discord + channel entities.Snowflake +} + +func (c *chatOutput) Write(p string) error { + c.logger.Info().Msgf("writing lang output: %s", p) + return c.client.SendMessage(c.channel, p) +} diff --git a/pkg/lang/modules/core/natives.go b/pkg/lang/modules/core/natives.go index c06b35c..8a24663 100644 --- a/pkg/lang/modules/core/natives.go +++ b/pkg/lang/modules/core/natives.go @@ -116,13 +116,21 @@ var Natives = []any{ n(":core:say", 1, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { message := args[0] - s, err := message.Data().String(exe.Mem()) + + // We don't want strings to have the "". + var err error + var s string + if message.Type() == value.StringType { + s, err = message.Data().(value.StringData).RawString(exe.Mem()) + } else { + s, err = message.Data().String(exe.Mem()) + } + if err != nil { return value.Value{}, err } - fmt.Println(s) - return value.Value{}, nil + return value.Value{}, exe.Write(s) }), } diff --git a/pkg/lang/vm/exe.go b/pkg/lang/vm/exe.go index 7d6fc61..5d40133 100644 --- a/pkg/lang/vm/exe.go +++ b/pkg/lang/vm/exe.go @@ -60,3 +60,7 @@ func (vm *VM) GetGlobal(name string) (value.Value, bool, error) { return v, true, nil } + +func (vm *VM) Write(message string) error { + return vm.output.Write(message) +} diff --git a/pkg/lang/vm/executor/executor.go b/pkg/lang/vm/executor/executor.go index 0b7ccef..1ab3773 100644 --- a/pkg/lang/vm/executor/executor.go +++ b/pkg/lang/vm/executor/executor.go @@ -14,4 +14,6 @@ type Exectutor interface { AddGlobal(name string, v value.Value) error GetGlobal(name string) (value.Value, bool, error) + + Write(message string) error } diff --git a/pkg/lang/vm/output.go b/pkg/lang/vm/output.go new file mode 100644 index 0000000..1ef2357 --- /dev/null +++ b/pkg/lang/vm/output.go @@ -0,0 +1,45 @@ +package vm + +type Output interface { + Write(message string) error +} + +type EmptyOutput struct{} + +func NewEmptyOutput() *EmptyOutput { + return &EmptyOutput{} +} + +func (o *EmptyOutput) Write(message string) error { + return nil +} + +type GatheringOutput struct { + messages []string +} + +func NewGatheringOutput() *GatheringOutput { + return &GatheringOutput{ + messages: make([]string, 0, 8), + } +} + +func (o *GatheringOutput) Messages() []string { + return o.messages +} + +func (o *GatheringOutput) Write(message string) error { + o.messages = append(o.messages, message) + return nil +} + +type ConsoleOutput struct{} + +func NewConsoleOutput() *ConsoleOutput { + return &ConsoleOutput{} +} + +func (o *ConsoleOutput) Write(message string) error { + println(message) + return nil +} diff --git a/pkg/lang/vm/vm.go b/pkg/lang/vm/vm.go index f24095d..4d4d5ca 100644 --- a/pkg/lang/vm/vm.go +++ b/pkg/lang/vm/vm.go @@ -21,9 +21,11 @@ type VM struct { globals map[string]mem.Ptr corePtrs value.CorePtrs + + output Output } -func New(main modules.Module) *VM { +func New(main modules.Module, output Output) *VM { vm := &VM{ pos: code.NewPos(-1, 0), @@ -37,6 +39,8 @@ func New(main modules.Module) *VM { globals: make(map[string]mem.Ptr), corePtrs: value.CorePtrs{}, + + output: output, } if err := vm.setup(); err != nil { diff --git a/pkg/lang/vm/vm_test.go b/pkg/lang/vm/vm_test.go index 8f961ef..8c31d1f 100644 --- a/pkg/lang/vm/vm_test.go +++ b/pkg/lang/vm/vm_test.go @@ -5,7 +5,6 @@ import ( "jinx/pkg/lang/vm" "jinx/pkg/lang/vm/code" "jinx/pkg/lang/vm/text" - "os" "strings" "testing" @@ -496,18 +495,7 @@ func TestCoreSay(t *testing.T) { halt ` - previous := os.Stdout - r, w, _ := os.Pipe() - defer w.Close() - os.Stdout = w - test(t, src, "0") - os.Stdout = previous - - result := make([]byte, 8) - _, err := r.Read(result) - require.NoError(t, err) - - require.Equal(t, "\"Meow!!\"", string(result)) + testOutput(t, src, "Meow!!") } func TestSetAtArray(t *testing.T) { @@ -539,7 +527,7 @@ func TestSetAtArray(t *testing.T) { func test(t *testing.T, src string, expected string) { bc := compile(t, src) - vm := vm.New(modules.NewUnknownModule(&bc)) + vm := vm.New(modules.NewUnknownModule(&bc), vm.NewEmptyOutput()) err := vm.Run() require.NoError(t, err) @@ -549,6 +537,18 @@ func test(t *testing.T, src string, expected string) { require.Equal(t, expected, res) } +func testOutput(t *testing.T, src string, expected string) { + output := vm.NewGatheringOutput() + + bc := compile(t, src) + vm := vm.New(modules.NewUnknownModule(&bc), output) + err := vm.Run() + require.NoError(t, err) + + lastMessage := output.Messages()[len(output.Messages())-1] + require.Equal(t, expected, lastMessage) +} + func compile(t *testing.T, src string) code.Code { comp := text.NewCompiler(strings.NewReader(src)) bc, err := comp.Compile() -- cgit 1.4.1