aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-08-17 00:07:35 +0000
committerMel <einebeere@gmail.com>2022-08-17 00:07:35 +0000
commitbe6cd2217b6bb1bb411d46ebd9d003dfd928af96 (patch)
tree94e5807aae0fb65d2768adce594e245052ecf578
parentd84c0f36afcde4e5af2907d70931de75957d5277 (diff)
downloadjinx-be6cd2217b6bb1bb411d46ebd9d003dfd928af96.tar.zst
jinx-be6cd2217b6bb1bb411d46ebd9d003dfd928af96.zip
Add different "say" outputs to VM
-rw-r--r--cmd/lang/main.go26
-rw-r--r--cmd/vm/main.go9
-rw-r--r--pkg/bot/cmds.go32
-rw-r--r--pkg/bot/output.go19
-rw-r--r--pkg/lang/modules/core/natives.go14
-rw-r--r--pkg/lang/vm/exe.go4
-rw-r--r--pkg/lang/vm/executor/executor.go2
-rw-r--r--pkg/lang/vm/output.go45
-rw-r--r--pkg/lang/vm/vm.go6
-rw-r--r--pkg/lang/vm/vm_test.go28
10 files changed, 134 insertions, 51 deletions
diff --git a/cmd/lang/main.go b/cmd/lang/main.go
index f5046a7..c5c0fe6 100644
--- a/cmd/lang/main.go
+++ b/cmd/lang/main.go
@@ -8,6 +8,8 @@ import (
"jinx/pkg/lang/scanner"
"jinx/pkg/lang/vm"
"os"
+ "os/user"
+ "path"
)
func main() {
@@ -20,12 +22,12 @@ func main() {
exit("nothing to do, either -c or -r is required")
}
- path := flag.Arg(0)
- if path == "" {
+ filePath := flag.Arg(0)
+ if filePath == "" {
exit("no file specified")
}
- file, err := os.Open(path)
+ file, err := os.Open(filePath)
if err != nil {
exit("could not open file: %v", err)
}
@@ -43,7 +45,7 @@ func main() {
exit("error during parsing: %v", err)
}
- comp := compiler.New("program", "noone", program)
+ comp := compiler.New(path.Base(filePath), getUsername(), program)
module, err := comp.Compile()
if err != nil {
exit("compilation failed: %v", err)
@@ -62,18 +64,20 @@ func main() {
}
if *run {
- vm := vm.New(module)
+ vm := vm.New(module, vm.NewConsoleOutput())
if err := vm.Run(); err != nil {
exit("execution failed: %v", err)
}
+ }
+}
- res, err := vm.GetResult()
- if err != nil {
- exit("could not get result: %v", err)
- }
-
- fmt.Println(res)
+func getUsername() string {
+ me, err := user.Current()
+ if err != nil {
+ return "unknown"
}
+
+ return me.Username
}
func exit(format string, args ...any) {
diff --git a/cmd/vm/main.go b/cmd/vm/main.go
index ecebcbf..bb8f142 100644
--- a/cmd/vm/main.go
+++ b/cmd/vm/main.go
@@ -91,17 +91,10 @@ func main() {
}
if *run {
- vm := vm.New(modules.NewUnknownModule(&bc))
+ vm := vm.New(modules.NewUnknownModule(&bc), vm.NewConsoleOutput())
if err := vm.Run(); err != nil {
exit("execution failed: %v", err)
}
-
- res, err := vm.GetResult()
- if err != nil {
- exit("could not get result: %v", err)
- }
-
- fmt.Println(res)
}
}
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()