From fc6ceee02ccfa8647e6703741c8f6db6286c64fd Mon Sep 17 00:00:00 2001 From: Chuck Smith Date: Thu, 28 Mar 2024 16:20:09 -0400 Subject: [PATCH] restructure project --- .gitignore | 8 +- main.go => cmd/monkey/main.go | 17 +- examples/fib.monkey | 8 +- {ast => internal/ast}/ast.go | 2 +- {ast => internal/ast}/ast_test.go | 2 +- {builtins => internal/builtins}/abs.go | 4 +- {builtins => internal/builtins}/accept.go | 4 +- {builtins => internal/builtins}/args.go | 4 +- {builtins => internal/builtins}/assert.go | 7 +- {builtins => internal/builtins}/bin.go | 4 +- {builtins => internal/builtins}/bind.go | 4 +- {builtins => internal/builtins}/bool.go | 4 +- {builtins => internal/builtins}/builtins.go | 2 +- {builtins => internal/builtins}/chr.go | 4 +- {builtins => internal/builtins}/close.go | 4 +- {builtins => internal/builtins}/connect.go | 4 +- {builtins => internal/builtins}/divmod.go | 4 +- {builtins => internal/builtins}/exit.go | 4 +- {builtins => internal/builtins}/ffi.go | 4 +- {builtins => internal/builtins}/find.go | 4 +- {builtins => internal/builtins}/first.go | 4 +- {builtins => internal/builtins}/hash.go | 4 +- {builtins => internal/builtins}/hex.go | 4 +- {builtins => internal/builtins}/id.go | 4 +- {builtins => internal/builtins}/input.go | 7 +- {builtins => internal/builtins}/int.go | 7 +- {builtins => internal/builtins}/join.go | 7 +- {builtins => internal/builtins}/last.go | 4 +- {builtins => internal/builtins}/len.go | 4 +- {builtins => internal/builtins}/listen.go | 4 +- {builtins => internal/builtins}/lower.go | 7 +- {builtins => internal/builtins}/max.go | 4 +- {builtins => internal/builtins}/min.go | 4 +- {builtins => internal/builtins}/oct.go | 4 +- {builtins => internal/builtins}/open.go | 4 +- {builtins => internal/builtins}/ord.go | 4 +- {builtins => internal/builtins}/pop.go | 4 +- {builtins => internal/builtins}/pow.go | 4 +- {builtins => internal/builtins}/print.go | 7 +- {builtins => internal/builtins}/push.go | 4 +- {builtins => internal/builtins}/read.go | 4 +- {builtins => internal/builtins}/readfile.go | 4 +- {builtins => internal/builtins}/rest.go | 4 +- {builtins => internal/builtins}/reversed.go | 4 +- {builtins => internal/builtins}/seek.go | 4 +- {builtins => internal/builtins}/socket.go | 4 +- .../builtins}/socket_utils.go | 0 {builtins => internal/builtins}/sorted.go | 4 +- {builtins => internal/builtins}/split.go | 7 +- {builtins => internal/builtins}/str.go | 4 +- {builtins => internal/builtins}/typeof.go | 4 +- {builtins => internal/builtins}/upper.go | 4 +- {builtins => internal/builtins}/write.go | 4 +- {builtins => internal/builtins}/writefile.go | 4 +- {code => internal/code}/code.go | 0 {code => internal/code}/code_test.go | 0 {compiler => internal/compiler}/compiler.go | 8 +- .../compiler}/compiler_test.go | 10 +- .../compiler}/symbol_table.go | 0 .../compiler}/symbol_table_test.go | 0 .../evaluator}/evaluator.go | 12 +- .../evaluator}/evaluator_test.go | 16 +- {lexer => internal/lexer}/lexer.go | 2 +- {lexer => internal/lexer}/lexer_test.go | 2 +- {object => internal/object}/array.go | 0 {object => internal/object}/bool.go | 0 {object => internal/object}/builtin.go | 0 {object => internal/object}/closure.go | 2 +- {object => internal/object}/environment.go | 0 {object => internal/object}/error.go | 0 {object => internal/object}/function.go | 2 +- {object => internal/object}/hash.go | 0 {object => internal/object}/int.go | 0 {object => internal/object}/module.go | 0 {object => internal/object}/null.go | 0 {object => internal/object}/object.go | 0 {object => internal/object}/object_test.go | 0 {object => internal/object}/state.go | 0 {object => internal/object}/str.go | 0 {parser => internal/parser}/parser.go | 6 +- {parser => internal/parser}/parser_test.go | 4 +- {parser => internal/parser}/parser_tracing.go | 0 {plugins => internal/plugins}/hello.go | 4 +- {repl => internal/repl}/repl.go | 12 +- {token => internal/token}/token.go | 0 {typing => internal/typing}/typing.go | 2 +- {utils => internal/utils}/utils.go | 0 version.go => internal/version.go | 2 +- internal/vm/cache.go | 270 ++++++++++++++++++ {vm => internal/vm}/frame.go | 35 ++- {vm => internal/vm}/vm.go | 14 +- {vm => internal/vm}/vm_test.go | 22 +- {vim => syntax}/monkey.vim | 0 93 files changed, 479 insertions(+), 194 deletions(-) rename main.go => cmd/monkey/main.go (92%) rename {ast => internal/ast}/ast.go (99%) rename {ast => internal/ast}/ast_test.go (96%) rename {builtins => internal/builtins}/abs.go (87%) rename {builtins => internal/builtins}/accept.go (90%) rename {builtins => internal/builtins}/args.go (88%) rename {builtins => internal/builtins}/assert.go (89%) rename {builtins => internal/builtins}/bin.go (87%) rename {builtins => internal/builtins}/bind.go (96%) rename {builtins => internal/builtins}/bool.go (83%) rename {builtins => internal/builtins}/builtins.go (98%) rename {builtins => internal/builtins}/chr.go (87%) rename {builtins => internal/builtins}/close.go (89%) rename {builtins => internal/builtins}/connect.go (96%) rename {builtins => internal/builtins}/divmod.go (91%) rename {builtins => internal/builtins}/exit.go (88%) rename {builtins => internal/builtins}/ffi.go (92%) rename {builtins => internal/builtins}/find.go (95%) rename {builtins => internal/builtins}/first.go (87%) rename {builtins => internal/builtins}/hash.go (88%) rename {builtins => internal/builtins}/hex.go (87%) rename {builtins => internal/builtins}/id.go (95%) rename {builtins => internal/builtins}/input.go (92%) rename {builtins => internal/builtins}/int.go (90%) rename {builtins => internal/builtins}/join.go (90%) rename {builtins => internal/builtins}/last.go (87%) rename {builtins => internal/builtins}/len.go (88%) rename {builtins => internal/builtins}/listen.go (90%) rename {builtins => internal/builtins}/lower.go (84%) rename {builtins => internal/builtins}/max.go (92%) rename {builtins => internal/builtins}/min.go (92%) rename {builtins => internal/builtins}/oct.go (87%) rename {builtins => internal/builtins}/open.go (96%) rename {builtins => internal/builtins}/ord.go (89%) rename {builtins => internal/builtins}/pop.go (90%) rename {builtins => internal/builtins}/pow.go (90%) rename {builtins => internal/builtins}/print.go (83%) rename {builtins => internal/builtins}/push.go (86%) rename {builtins => internal/builtins}/read.go (93%) rename {builtins => internal/builtins}/readfile.go (90%) rename {builtins => internal/builtins}/rest.go (86%) rename {builtins => internal/builtins}/reversed.go (87%) rename {builtins => internal/builtins}/seek.go (92%) rename {builtins => internal/builtins}/socket.go (96%) rename {builtins => internal/builtins}/socket_utils.go (100%) rename {builtins => internal/builtins}/sorted.go (87%) rename {builtins => internal/builtins}/split.go (92%) rename {builtins => internal/builtins}/str.go (83%) rename {builtins => internal/builtins}/typeof.go (83%) rename {builtins => internal/builtins}/upper.go (86%) rename {builtins => internal/builtins}/write.go (91%) rename {builtins => internal/builtins}/writefile.go (91%) rename {code => internal/code}/code.go (100%) rename {code => internal/code}/code_test.go (100%) rename {compiler => internal/compiler}/compiler.go (99%) rename {compiler => internal/compiler}/compiler_test.go (99%) rename {compiler => internal/compiler}/symbol_table.go (100%) rename {compiler => internal/compiler}/symbol_table_test.go (100%) rename {evaluator => internal/evaluator}/evaluator.go (99%) rename {evaluator => internal/evaluator}/evaluator_test.go (98%) rename {lexer => internal/lexer}/lexer.go (99%) rename {lexer => internal/lexer}/lexer_test.go (99%) rename {object => internal/object}/array.go (100%) rename {object => internal/object}/bool.go (100%) rename {object => internal/object}/builtin.go (100%) rename {object => internal/object}/closure.go (96%) rename {object => internal/object}/environment.go (100%) rename {object => internal/object}/error.go (100%) rename {object => internal/object}/function.go (97%) rename {object => internal/object}/hash.go (100%) rename {object => internal/object}/int.go (100%) rename {object => internal/object}/module.go (100%) rename {object => internal/object}/null.go (100%) rename {object => internal/object}/object.go (100%) rename {object => internal/object}/object_test.go (100%) rename {object => internal/object}/state.go (100%) rename {object => internal/object}/str.go (100%) rename {parser => internal/parser}/parser.go (99%) rename {parser => internal/parser}/parser_test.go (99%) rename {parser => internal/parser}/parser_tracing.go (100%) rename {plugins => internal/plugins}/hello.go (69%) rename {repl => internal/repl}/repl.go (97%) rename {token => internal/token}/token.go (100%) rename {typing => internal/typing}/typing.go (98%) rename {utils => internal/utils}/utils.go (100%) rename version.go => internal/version.go (94%) create mode 100644 internal/vm/cache.go rename {vm => internal/vm}/frame.go (50%) rename {vm => internal/vm}/vm.go (99%) rename {vm => internal/vm}/vm_test.go (98%) rename {vim => syntax}/monkey.vim (100%) diff --git a/.gitignore b/.gitignore index eab4e41..fcae1b9 100644 --- a/.gitignore +++ b/.gitignore @@ -81,11 +81,13 @@ fabric.properties *-e *.so *.bak -*.txt +*.out *.swo *.swn -.DS_Store +*.prof + +**/.DS_Store /dist /.vscode -/monkey-lang \ No newline at end of file +/monkey \ No newline at end of file diff --git a/main.go b/cmd/monkey/main.go similarity index 92% rename from main.go rename to cmd/monkey/main.go index 761d4d6..1e3d4be 100644 --- a/main.go +++ b/cmd/monkey/main.go @@ -3,18 +3,21 @@ package main import ( "flag" "fmt" - "github.com/pkg/profile" "io" "log" - "monkey/compiler" - "monkey/lexer" - "monkey/object" - "monkey/parser" - "monkey/repl" "os" "os/user" "path" "strings" + + "github.com/pkg/profile" + + "monkey/internal" + "monkey/internal/compiler" + "monkey/internal/lexer" + "monkey/internal/object" + "monkey/internal/parser" + "monkey/internal/repl" ) var ( @@ -66,7 +69,7 @@ func main() { flag.Parse() if version { - fmt.Printf("%s %s", path.Base(os.Args[0]), FullVersion()) + fmt.Printf("%s %s", path.Base(os.Args[0]), internal.FullVersion()) os.Exit(0) } diff --git a/examples/fib.monkey b/examples/fib.monkey index a635d3c..f20d3c4 100644 --- a/examples/fib.monkey +++ b/examples/fib.monkey @@ -5,4 +5,10 @@ fib := fn(x) { return fib(x-1) + fib(x-2) } -print(fib(35)) \ No newline at end of file +N := 35 + +if (len(args()) == 1) { + N = int(args()[0]) +} + +print(fib(N)) \ No newline at end of file diff --git a/ast/ast.go b/internal/ast/ast.go similarity index 99% rename from ast/ast.go rename to internal/ast/ast.go index 9bcf0ca..174be7f 100644 --- a/ast/ast.go +++ b/internal/ast/ast.go @@ -3,7 +3,7 @@ package ast import ( "bytes" "fmt" - "monkey/token" + "monkey/internal/token" "strings" ) diff --git a/ast/ast_test.go b/internal/ast/ast_test.go similarity index 96% rename from ast/ast_test.go rename to internal/ast/ast_test.go index f0bc121..234589a 100644 --- a/ast/ast_test.go +++ b/internal/ast/ast_test.go @@ -2,7 +2,7 @@ package ast import ( "github.com/stretchr/testify/assert" - "monkey/token" + "monkey/internal/token" "testing" ) diff --git a/builtins/abs.go b/internal/builtins/abs.go similarity index 87% rename from builtins/abs.go rename to internal/builtins/abs.go index f767ed5..6adfe33 100644 --- a/builtins/abs.go +++ b/internal/builtins/abs.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Abs ... diff --git a/builtins/accept.go b/internal/builtins/accept.go similarity index 90% rename from builtins/accept.go rename to internal/builtins/accept.go index 7b776af..e1e5599 100644 --- a/builtins/accept.go +++ b/internal/builtins/accept.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "syscall" ) diff --git a/builtins/args.go b/internal/builtins/args.go similarity index 88% rename from builtins/args.go rename to internal/builtins/args.go index 1fcc398..acdb9fa 100644 --- a/builtins/args.go +++ b/internal/builtins/args.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Args ... diff --git a/builtins/assert.go b/internal/builtins/assert.go similarity index 89% rename from builtins/assert.go rename to internal/builtins/assert.go index bee2b19..5e4ef81 100644 --- a/builtins/assert.go +++ b/internal/builtins/assert.go @@ -1,12 +1,9 @@ package builtins -import ( - "monkey/object" - "monkey/typing" -) - import ( "fmt" + "monkey/internal/object" + "monkey/internal/typing" "os" ) diff --git a/builtins/bin.go b/internal/builtins/bin.go similarity index 87% rename from builtins/bin.go rename to internal/builtins/bin.go index 535ad13..a520b5e 100644 --- a/builtins/bin.go +++ b/internal/builtins/bin.go @@ -2,8 +2,8 @@ package builtins import ( "fmt" - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "strconv" ) diff --git a/builtins/bind.go b/internal/builtins/bind.go similarity index 96% rename from builtins/bind.go rename to internal/builtins/bind.go index fda7f83..e8a0d74 100644 --- a/builtins/bind.go +++ b/internal/builtins/bind.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "syscall" ) diff --git a/builtins/bool.go b/internal/builtins/bool.go similarity index 83% rename from builtins/bool.go rename to internal/builtins/bool.go index 6744e61..0c361d9 100644 --- a/builtins/bool.go +++ b/internal/builtins/bool.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Bool ... diff --git a/builtins/builtins.go b/internal/builtins/builtins.go similarity index 98% rename from builtins/builtins.go rename to internal/builtins/builtins.go index f3275dc..0382b51 100644 --- a/builtins/builtins.go +++ b/internal/builtins/builtins.go @@ -2,7 +2,7 @@ package builtins import ( "fmt" - "monkey/object" + "monkey/internal/object" "sort" ) diff --git a/builtins/chr.go b/internal/builtins/chr.go similarity index 87% rename from builtins/chr.go rename to internal/builtins/chr.go index f647560..11e992e 100644 --- a/builtins/chr.go +++ b/internal/builtins/chr.go @@ -2,8 +2,8 @@ package builtins import ( "fmt" - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Chr ... diff --git a/builtins/close.go b/internal/builtins/close.go similarity index 89% rename from builtins/close.go rename to internal/builtins/close.go index 94b6019..66d6644 100644 --- a/builtins/close.go +++ b/internal/builtins/close.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "syscall" ) diff --git a/builtins/connect.go b/internal/builtins/connect.go similarity index 96% rename from builtins/connect.go rename to internal/builtins/connect.go index eee9dd6..fe2b347 100644 --- a/builtins/connect.go +++ b/internal/builtins/connect.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "syscall" ) diff --git a/builtins/divmod.go b/internal/builtins/divmod.go similarity index 91% rename from builtins/divmod.go rename to internal/builtins/divmod.go index b1906d1..c35617b 100644 --- a/builtins/divmod.go +++ b/internal/builtins/divmod.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Divmod ... diff --git a/builtins/exit.go b/internal/builtins/exit.go similarity index 88% rename from builtins/exit.go rename to internal/builtins/exit.go index b84c662..43c0de9 100644 --- a/builtins/exit.go +++ b/internal/builtins/exit.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Exit ... diff --git a/builtins/ffi.go b/internal/builtins/ffi.go similarity index 92% rename from builtins/ffi.go rename to internal/builtins/ffi.go index 6f5c136..2c3e43c 100644 --- a/builtins/ffi.go +++ b/internal/builtins/ffi.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) import ( diff --git a/builtins/find.go b/internal/builtins/find.go similarity index 95% rename from builtins/find.go rename to internal/builtins/find.go index dc2e7be..3e1b33a 100644 --- a/builtins/find.go +++ b/internal/builtins/find.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "sort" ) diff --git a/builtins/first.go b/internal/builtins/first.go similarity index 87% rename from builtins/first.go rename to internal/builtins/first.go index a82149e..ca1e6c5 100644 --- a/builtins/first.go +++ b/internal/builtins/first.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // First ... diff --git a/builtins/hash.go b/internal/builtins/hash.go similarity index 88% rename from builtins/hash.go rename to internal/builtins/hash.go index d7433ae..85cf451 100644 --- a/builtins/hash.go +++ b/internal/builtins/hash.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // HashOf ... diff --git a/builtins/hex.go b/internal/builtins/hex.go similarity index 87% rename from builtins/hex.go rename to internal/builtins/hex.go index 8483014..b801350 100644 --- a/builtins/hex.go +++ b/internal/builtins/hex.go @@ -2,8 +2,8 @@ package builtins import ( "fmt" - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "strconv" ) diff --git a/builtins/id.go b/internal/builtins/id.go similarity index 95% rename from builtins/id.go rename to internal/builtins/id.go index f620af6..ab41d0b 100644 --- a/builtins/id.go +++ b/internal/builtins/id.go @@ -2,8 +2,8 @@ package builtins import ( "fmt" - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // IdOf ... diff --git a/builtins/input.go b/internal/builtins/input.go similarity index 92% rename from builtins/input.go rename to internal/builtins/input.go index b5bd2f1..bc8236f 100644 --- a/builtins/input.go +++ b/internal/builtins/input.go @@ -1,14 +1,11 @@ package builtins -import ( - "monkey/object" - "monkey/typing" -) - import ( "bufio" "fmt" "io" + "monkey/internal/object" + "monkey/internal/typing" "os" ) diff --git a/builtins/int.go b/internal/builtins/int.go similarity index 90% rename from builtins/int.go rename to internal/builtins/int.go index 5e3cbc7..b77be9a 100644 --- a/builtins/int.go +++ b/internal/builtins/int.go @@ -1,12 +1,11 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" + "strconv" ) -import "strconv" - // Int ... func Int(args ...object.Object) object.Object { if err := typing.Check( diff --git a/builtins/join.go b/internal/builtins/join.go similarity index 90% rename from builtins/join.go rename to internal/builtins/join.go index c814c43..2640d59 100644 --- a/builtins/join.go +++ b/internal/builtins/join.go @@ -1,11 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" -) - -import ( + "monkey/internal/object" + "monkey/internal/typing" "strings" ) diff --git a/builtins/last.go b/internal/builtins/last.go similarity index 87% rename from builtins/last.go rename to internal/builtins/last.go index 0fafeec..f7d121c 100644 --- a/builtins/last.go +++ b/internal/builtins/last.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Last ... diff --git a/builtins/len.go b/internal/builtins/len.go similarity index 88% rename from builtins/len.go rename to internal/builtins/len.go index 980eafd..a73fd15 100644 --- a/builtins/len.go +++ b/internal/builtins/len.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Len ... diff --git a/builtins/listen.go b/internal/builtins/listen.go similarity index 90% rename from builtins/listen.go rename to internal/builtins/listen.go index 0103351..624b72d 100644 --- a/builtins/listen.go +++ b/internal/builtins/listen.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "syscall" ) diff --git a/builtins/lower.go b/internal/builtins/lower.go similarity index 84% rename from builtins/lower.go rename to internal/builtins/lower.go index 2dcfa7b..af52a68 100644 --- a/builtins/lower.go +++ b/internal/builtins/lower.go @@ -1,12 +1,11 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" + "strings" ) -import "strings" - // Lower ... func Lower(args ...object.Object) object.Object { if err := typing.Check( diff --git a/builtins/max.go b/internal/builtins/max.go similarity index 92% rename from builtins/max.go rename to internal/builtins/max.go index b83e9ec..f373134 100644 --- a/builtins/max.go +++ b/internal/builtins/max.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "sort" ) diff --git a/builtins/min.go b/internal/builtins/min.go similarity index 92% rename from builtins/min.go rename to internal/builtins/min.go index 423518a..47d5c87 100644 --- a/builtins/min.go +++ b/internal/builtins/min.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "sort" ) diff --git a/builtins/oct.go b/internal/builtins/oct.go similarity index 87% rename from builtins/oct.go rename to internal/builtins/oct.go index 6c9f949..9434f5c 100644 --- a/builtins/oct.go +++ b/internal/builtins/oct.go @@ -2,8 +2,8 @@ package builtins import ( "fmt" - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "strconv" ) diff --git a/builtins/open.go b/internal/builtins/open.go similarity index 96% rename from builtins/open.go rename to internal/builtins/open.go index 125a21c..988a871 100644 --- a/builtins/open.go +++ b/internal/builtins/open.go @@ -3,8 +3,8 @@ package builtins import ( "fmt" "log" - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "os" "syscall" ) diff --git a/builtins/ord.go b/internal/builtins/ord.go similarity index 89% rename from builtins/ord.go rename to internal/builtins/ord.go index c12e71b..616d346 100644 --- a/builtins/ord.go +++ b/internal/builtins/ord.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Ord ... diff --git a/builtins/pop.go b/internal/builtins/pop.go similarity index 90% rename from builtins/pop.go rename to internal/builtins/pop.go index de2557c..70d855c 100644 --- a/builtins/pop.go +++ b/internal/builtins/pop.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Pop ... diff --git a/builtins/pow.go b/internal/builtins/pow.go similarity index 90% rename from builtins/pow.go rename to internal/builtins/pow.go index f25c3e5..90eb239 100644 --- a/builtins/pow.go +++ b/internal/builtins/pow.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) func pow(x, y int64) int64 { diff --git a/builtins/print.go b/internal/builtins/print.go similarity index 83% rename from builtins/print.go rename to internal/builtins/print.go index c37d757..0d4e5ca 100644 --- a/builtins/print.go +++ b/internal/builtins/print.go @@ -1,12 +1,11 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "fmt" + "monkey/internal/object" + "monkey/internal/typing" ) -import "fmt" - // Print ... func Print(args ...object.Object) object.Object { if err := typing.Check( diff --git a/builtins/push.go b/internal/builtins/push.go similarity index 86% rename from builtins/push.go rename to internal/builtins/push.go index 1c660da..8298149 100644 --- a/builtins/push.go +++ b/internal/builtins/push.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Push ... diff --git a/builtins/read.go b/internal/builtins/read.go similarity index 93% rename from builtins/read.go rename to internal/builtins/read.go index 135f9aa..48bdbae 100644 --- a/builtins/read.go +++ b/internal/builtins/read.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "syscall" ) diff --git a/builtins/readfile.go b/internal/builtins/readfile.go similarity index 90% rename from builtins/readfile.go rename to internal/builtins/readfile.go index 7a0cddd..e934649 100644 --- a/builtins/readfile.go +++ b/internal/builtins/readfile.go @@ -2,8 +2,8 @@ package builtins import ( "io/ioutil" - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // ReadFile ... diff --git a/builtins/rest.go b/internal/builtins/rest.go similarity index 86% rename from builtins/rest.go rename to internal/builtins/rest.go index 21c80e1..4f8aeb6 100644 --- a/builtins/rest.go +++ b/internal/builtins/rest.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Rest ... diff --git a/builtins/reversed.go b/internal/builtins/reversed.go similarity index 87% rename from builtins/reversed.go rename to internal/builtins/reversed.go index f5ee375..b9b0108 100644 --- a/builtins/reversed.go +++ b/internal/builtins/reversed.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Reversed ... diff --git a/builtins/seek.go b/internal/builtins/seek.go similarity index 92% rename from builtins/seek.go rename to internal/builtins/seek.go index e9b85d3..61023a1 100644 --- a/builtins/seek.go +++ b/internal/builtins/seek.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "syscall" ) diff --git a/builtins/socket.go b/internal/builtins/socket.go similarity index 96% rename from builtins/socket.go rename to internal/builtins/socket.go index 4e71d16..8b43631 100644 --- a/builtins/socket.go +++ b/internal/builtins/socket.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "strings" "syscall" ) diff --git a/builtins/socket_utils.go b/internal/builtins/socket_utils.go similarity index 100% rename from builtins/socket_utils.go rename to internal/builtins/socket_utils.go diff --git a/builtins/sorted.go b/internal/builtins/sorted.go similarity index 87% rename from builtins/sorted.go rename to internal/builtins/sorted.go index 0280b05..52350d6 100644 --- a/builtins/sorted.go +++ b/internal/builtins/sorted.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "sort" ) diff --git a/builtins/split.go b/internal/builtins/split.go similarity index 92% rename from builtins/split.go rename to internal/builtins/split.go index dcef498..865759b 100644 --- a/builtins/split.go +++ b/internal/builtins/split.go @@ -1,11 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" -) - -import ( + "monkey/internal/object" + "monkey/internal/typing" "strings" ) diff --git a/builtins/str.go b/internal/builtins/str.go similarity index 83% rename from builtins/str.go rename to internal/builtins/str.go index a2e56ed..01e74dd 100644 --- a/builtins/str.go +++ b/internal/builtins/str.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // Str ... diff --git a/builtins/typeof.go b/internal/builtins/typeof.go similarity index 83% rename from builtins/typeof.go rename to internal/builtins/typeof.go index ace5799..7d3fa09 100644 --- a/builtins/typeof.go +++ b/internal/builtins/typeof.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // TypeOf ... diff --git a/builtins/upper.go b/internal/builtins/upper.go similarity index 86% rename from builtins/upper.go rename to internal/builtins/upper.go index 711ea79..3771ca9 100644 --- a/builtins/upper.go +++ b/internal/builtins/upper.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "strings" ) diff --git a/builtins/write.go b/internal/builtins/write.go similarity index 91% rename from builtins/write.go rename to internal/builtins/write.go index 47772c3..cef0782 100644 --- a/builtins/write.go +++ b/internal/builtins/write.go @@ -1,8 +1,8 @@ package builtins import ( - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" "syscall" ) diff --git a/builtins/writefile.go b/internal/builtins/writefile.go similarity index 91% rename from builtins/writefile.go rename to internal/builtins/writefile.go index 66d0cda..02b2fc2 100644 --- a/builtins/writefile.go +++ b/internal/builtins/writefile.go @@ -2,8 +2,8 @@ package builtins import ( "io/ioutil" - "monkey/object" - "monkey/typing" + "monkey/internal/object" + "monkey/internal/typing" ) // WriteFile ... diff --git a/code/code.go b/internal/code/code.go similarity index 100% rename from code/code.go rename to internal/code/code.go diff --git a/code/code_test.go b/internal/code/code_test.go similarity index 100% rename from code/code_test.go rename to internal/code/code_test.go diff --git a/compiler/compiler.go b/internal/compiler/compiler.go similarity index 99% rename from compiler/compiler.go rename to internal/compiler/compiler.go index 9833e62..640d51e 100644 --- a/compiler/compiler.go +++ b/internal/compiler/compiler.go @@ -3,10 +3,10 @@ package compiler import ( "fmt" "log" - "monkey/ast" - "monkey/builtins" - "monkey/code" - "monkey/object" + "monkey/internal/ast" + "monkey/internal/builtins" + "monkey/internal/code" + "monkey/internal/object" "sort" "strings" ) diff --git a/compiler/compiler_test.go b/internal/compiler/compiler_test.go similarity index 99% rename from compiler/compiler_test.go rename to internal/compiler/compiler_test.go index 8100aba..e596058 100644 --- a/compiler/compiler_test.go +++ b/internal/compiler/compiler_test.go @@ -3,11 +3,11 @@ package compiler import ( "fmt" "github.com/stretchr/testify/assert" - "monkey/ast" - "monkey/code" - "monkey/lexer" - "monkey/object" - "monkey/parser" + "monkey/internal/ast" + "monkey/internal/code" + "monkey/internal/lexer" + "monkey/internal/object" + "monkey/internal/parser" "testing" ) diff --git a/compiler/symbol_table.go b/internal/compiler/symbol_table.go similarity index 100% rename from compiler/symbol_table.go rename to internal/compiler/symbol_table.go diff --git a/compiler/symbol_table_test.go b/internal/compiler/symbol_table_test.go similarity index 100% rename from compiler/symbol_table_test.go rename to internal/compiler/symbol_table_test.go diff --git a/evaluator/evaluator.go b/internal/evaluator/evaluator.go similarity index 99% rename from evaluator/evaluator.go rename to internal/evaluator/evaluator.go index 9a7a565..ad40871 100644 --- a/evaluator/evaluator.go +++ b/internal/evaluator/evaluator.go @@ -2,12 +2,12 @@ package evaluator import ( "fmt" - "monkey/ast" - "monkey/builtins" - "monkey/lexer" - "monkey/object" - "monkey/parser" - "monkey/utils" + "monkey/internal/ast" + "monkey/internal/builtins" + "monkey/internal/lexer" + "monkey/internal/object" + "monkey/internal/parser" + "monkey/internal/utils" "os" "strings" ) diff --git a/evaluator/evaluator_test.go b/internal/evaluator/evaluator_test.go similarity index 98% rename from evaluator/evaluator_test.go rename to internal/evaluator/evaluator_test.go index 0e6a864..dd50d9e 100644 --- a/evaluator/evaluator_test.go +++ b/internal/evaluator/evaluator_test.go @@ -3,10 +3,10 @@ package evaluator import ( "errors" "github.com/stretchr/testify/assert" - "monkey/lexer" - "monkey/object" - "monkey/parser" - "monkey/utils" + "monkey/internal/lexer" + "monkey/internal/object" + "monkey/internal/parser" + "monkey/internal/utils" "os" "path" "path/filepath" @@ -862,9 +862,9 @@ func TestImportExpressions(t *testing.T) { input string expected interface{} }{ - {`mod := import("../testdata/mod"); mod.A`, 5}, - {`mod := import("../testdata/mod"); mod.Sum(2, 3)`, 5}, - {`mod := import("../testdata/mod"); mod.a`, nil}, + {`mod := import("../../testdata/mod"); mod.A`, 5}, + {`mod := import("../../testdata/mod"); mod.Sum(2, 3)`, 5}, + {`mod := import("../../testdata/mod"); mod.a`, nil}, } for _, tt := range tests { @@ -890,7 +890,7 @@ func TestImportSearchPaths(t *testing.T) { } func TestExamples(t *testing.T) { - matches, err := filepath.Glob("./examples/*.monkey") + matches, err := filepath.Glob("../../examples/*.monkey") if err != nil { t.Error(err) } diff --git a/lexer/lexer.go b/internal/lexer/lexer.go similarity index 99% rename from lexer/lexer.go rename to internal/lexer/lexer.go index 2753ae8..e5d5092 100644 --- a/lexer/lexer.go +++ b/internal/lexer/lexer.go @@ -2,7 +2,7 @@ package lexer import ( "encoding/hex" - "monkey/token" + "monkey/internal/token" "strings" ) diff --git a/lexer/lexer_test.go b/internal/lexer/lexer_test.go similarity index 99% rename from lexer/lexer_test.go rename to internal/lexer/lexer_test.go index 1393cd3..55b0b6d 100644 --- a/lexer/lexer_test.go +++ b/internal/lexer/lexer_test.go @@ -1,7 +1,7 @@ package lexer import ( - "monkey/token" + "monkey/internal/token" "testing" ) diff --git a/object/array.go b/internal/object/array.go similarity index 100% rename from object/array.go rename to internal/object/array.go diff --git a/object/bool.go b/internal/object/bool.go similarity index 100% rename from object/bool.go rename to internal/object/bool.go diff --git a/object/builtin.go b/internal/object/builtin.go similarity index 100% rename from object/builtin.go rename to internal/object/builtin.go diff --git a/object/closure.go b/internal/object/closure.go similarity index 96% rename from object/closure.go rename to internal/object/closure.go index 2eb3ad3..90ecad1 100644 --- a/object/closure.go +++ b/internal/object/closure.go @@ -2,7 +2,7 @@ package object import ( "fmt" - "monkey/code" + "monkey/internal/code" ) type CompiledFunction struct { diff --git a/object/environment.go b/internal/object/environment.go similarity index 100% rename from object/environment.go rename to internal/object/environment.go diff --git a/object/error.go b/internal/object/error.go similarity index 100% rename from object/error.go rename to internal/object/error.go diff --git a/object/function.go b/internal/object/function.go similarity index 97% rename from object/function.go rename to internal/object/function.go index 160815a..225fbc7 100644 --- a/object/function.go +++ b/internal/object/function.go @@ -2,7 +2,7 @@ package object import ( "bytes" - "monkey/ast" + "monkey/internal/ast" "strings" ) diff --git a/object/hash.go b/internal/object/hash.go similarity index 100% rename from object/hash.go rename to internal/object/hash.go diff --git a/object/int.go b/internal/object/int.go similarity index 100% rename from object/int.go rename to internal/object/int.go diff --git a/object/module.go b/internal/object/module.go similarity index 100% rename from object/module.go rename to internal/object/module.go diff --git a/object/null.go b/internal/object/null.go similarity index 100% rename from object/null.go rename to internal/object/null.go diff --git a/object/object.go b/internal/object/object.go similarity index 100% rename from object/object.go rename to internal/object/object.go diff --git a/object/object_test.go b/internal/object/object_test.go similarity index 100% rename from object/object_test.go rename to internal/object/object_test.go diff --git a/object/state.go b/internal/object/state.go similarity index 100% rename from object/state.go rename to internal/object/state.go diff --git a/object/str.go b/internal/object/str.go similarity index 100% rename from object/str.go rename to internal/object/str.go diff --git a/parser/parser.go b/internal/parser/parser.go similarity index 99% rename from parser/parser.go rename to internal/parser/parser.go index 20702de..3349808 100644 --- a/parser/parser.go +++ b/internal/parser/parser.go @@ -2,9 +2,9 @@ package parser import ( "fmt" - "monkey/ast" - "monkey/lexer" - "monkey/token" + "monkey/internal/ast" + "monkey/internal/lexer" + "monkey/internal/token" "strconv" ) diff --git a/parser/parser_test.go b/internal/parser/parser_test.go similarity index 99% rename from parser/parser_test.go rename to internal/parser/parser_test.go index 831d41e..004ce9d 100644 --- a/parser/parser_test.go +++ b/internal/parser/parser_test.go @@ -3,8 +3,8 @@ package parser import ( "fmt" "github.com/stretchr/testify/assert" - "monkey/ast" - "monkey/lexer" + "monkey/internal/ast" + "monkey/internal/lexer" "testing" ) diff --git a/parser/parser_tracing.go b/internal/parser/parser_tracing.go similarity index 100% rename from parser/parser_tracing.go rename to internal/parser/parser_tracing.go diff --git a/plugins/hello.go b/internal/plugins/hello.go similarity index 69% rename from plugins/hello.go rename to internal/plugins/hello.go index 0360bea..f91f6c8 100644 --- a/plugins/hello.go +++ b/internal/plugins/hello.go @@ -1,6 +1,6 @@ -package main +package internal -import "monkey/object" +import "monkey/internal/object" // Hello ... func Hello(args ...object.Object) object.Object { diff --git a/repl/repl.go b/internal/repl/repl.go similarity index 97% rename from repl/repl.go rename to internal/repl/repl.go index 7f7a475..a4e146f 100644 --- a/repl/repl.go +++ b/internal/repl/repl.go @@ -8,12 +8,12 @@ import ( "fmt" "io" "log" - "monkey/compiler" - "monkey/evaluator" - "monkey/lexer" - "monkey/object" - "monkey/parser" - "monkey/vm" + "monkey/internal/compiler" + "monkey/internal/evaluator" + "monkey/internal/lexer" + "monkey/internal/object" + "monkey/internal/parser" + "monkey/internal/vm" "os" ) diff --git a/token/token.go b/internal/token/token.go similarity index 100% rename from token/token.go rename to internal/token/token.go diff --git a/typing/typing.go b/internal/typing/typing.go similarity index 98% rename from typing/typing.go rename to internal/typing/typing.go index 5bd88c7..1383786 100644 --- a/typing/typing.go +++ b/internal/typing/typing.go @@ -2,7 +2,7 @@ package typing import ( "fmt" - "monkey/object" + "monkey/internal/object" ) type CheckFunc func(name string, args []object.Object) error diff --git a/utils/utils.go b/internal/utils/utils.go similarity index 100% rename from utils/utils.go rename to internal/utils/utils.go diff --git a/version.go b/internal/version.go similarity index 94% rename from version.go rename to internal/version.go index 50a8887..e7ee508 100644 --- a/version.go +++ b/internal/version.go @@ -1,4 +1,4 @@ -package main +package internal import ( "fmt" diff --git a/internal/vm/cache.go b/internal/vm/cache.go new file mode 100644 index 0000000..cf09c32 --- /dev/null +++ b/internal/vm/cache.go @@ -0,0 +1,270 @@ +package vm + +import ( + "container/list" + "fmt" + "sync" +) + +type cachedFrame struct { + Key uint // pointer to key + Value *Frame // pointer to value + Frequency uint // frequency of access +} + +type frequencyNode struct { + count uint // frequency count - never decreases + valuesList *list.List // valuesList contains pointer to the head of values linked list + inner *list.Element // actual content of the next element +} + +// creates a new frequency list node with the given count +func newFrequencyNode(count uint) *frequencyNode { + return &frequencyNode{ + count: count, + valuesList: list.New(), + inner: nil, + } +} + +type keyRefNode struct { + inner *list.Element // contains the actual value wrapped by a list element + parentFreqNode *list.Element // contains reference to the frequency node element + keyRef uint // contains pointer to the key + valueRef *Frame // value +} + +// creates a new KeyRef node which is used to represent the value in linked list +func newKeyRefNode(keyRef uint, valueRef *Frame, parent *list.Element) *keyRefNode { + return &keyRefNode{ + inner: nil, + parentFreqNode: parent, + keyRef: keyRef, + valueRef: valueRef, + } +} + +// FrameCache implements all the methods and data-structures required for a LFU cache for caching frames. +type FrameCache struct { + rwLock sync.RWMutex // rwLock is a read-write mutex which provides concurrent reads but exclusive writes + lookupTable map[uint]*keyRefNode // a hash table of for quick reference of values based on keys + frequencies *list.List // internal linked list that contains frequency mapping + maxSize uint // maxSize represents the maximum number of elements that can be in the cache before eviction +} + +// MaxSize returns the maximum size of the cache at that point in time +func (lfu *FrameCache) MaxSize() uint { + lfu.rwLock.RLock() + defer lfu.rwLock.RUnlock() + + return lfu.maxSize +} + +// CurrentSize returns the number of elements in that cache +func (lfu *FrameCache) CurrentSize() uint { + lfu.rwLock.RLock() + defer lfu.rwLock.RUnlock() + + return uint(len(lfu.lookupTable)) +} + +// IsFull checks if the LFU cache is full +func (lfu *FrameCache) IsFull() bool { + lfu.rwLock.RLock() + defer lfu.rwLock.RUnlock() + + return uint(len(lfu.lookupTable)) == lfu.maxSize +} + +// SetMaxSize updates the max size of the LFU cache +func (lfu *FrameCache) SetMaxSize(size uint) { + lfu.rwLock.Lock() + defer lfu.rwLock.Unlock() + + lfu.maxSize = size +} + +// evict the least recently used element from the cache, this function is unsafe to be called externally +// because it doesn't provide locking mechanism. +func (lfu *FrameCache) unsafeEvict() error { + // WARNING: This function assumes that a write lock has been held by the caller already + + // get the head node of the list + headFreq := lfu.frequencies.Front() + if headFreq == nil { + // list is empty, this is a very unusual condition + return fmt.Errorf("internal error: failed to evict, empty frequency list") + } + + headFreqInner := (headFreq.Value).(*frequencyNode) + + if headFreqInner.valuesList.Len() == 0 { + // again this is a very unusual condition + return fmt.Errorf("internal error: failed to evict, empty values list") + } + + headValuesList := headFreqInner.valuesList + // pop the head of this this values list + headValueNode := headValuesList.Front() + removeResult := headValuesList.Remove(headValueNode).(*keyRefNode) + + // update the values list + headFreqInner.valuesList = headValuesList + + if headFreqInner.valuesList.Len() == 0 && headFreqInner.count > 1 { + // this node can be removed from the frequency list + freqList := lfu.frequencies + freqList.Remove(headFreq) + lfu.frequencies = freqList + } + + // remove the key from lookup table + key := removeResult.keyRef + delete(lfu.lookupTable, key) + return nil +} + +// Put method inserts a `` to the LFU cache and updates internal +// data structures to keep track of access frequencies, if the cache is full, it evicts the +// least frequently used value from the cache. +func (lfu *FrameCache) Put(key uint, value *Frame) error { + // get write lock + lfu.rwLock.Lock() + defer lfu.rwLock.Unlock() + + if _, ok := lfu.lookupTable[key]; ok { + // update the cache value + lfu.lookupTable[key].valueRef = value + return nil + } + + if lfu.maxSize == uint(len(lfu.lookupTable)) { + lfu.unsafeEvict() + } + + valueNode := newKeyRefNode(key, value, nil) + + head := lfu.frequencies.Front() + if head == nil { + // fresh linked list + freqNode := newFrequencyNode(1) + head = lfu.frequencies.PushFront(freqNode) + freqNode.inner = head + + } else { + node := head.Value.(*frequencyNode) + if node.count != 1 { + freqNode := newFrequencyNode(1) + head = lfu.frequencies.PushFront(freqNode) + freqNode.inner = head + } + } + + valueNode.parentFreqNode = head + node := head.Value.(*frequencyNode) + head = node.valuesList.PushBack(valueNode) + valueNode.inner = head + + lfu.lookupTable[key] = valueNode + return nil +} + +// Evict can be called to manually perform eviction +func (lfu *FrameCache) Evict() error { + lfu.rwLock.Lock() + defer lfu.rwLock.Unlock() + + return lfu.unsafeEvict() +} + +func (lfu *FrameCache) unsafeUpdateFrequency(valueNode *keyRefNode) { + parentFreqNode := valueNode.parentFreqNode + currentNode := parentFreqNode.Value.(*frequencyNode) + nextParentFreqNode := parentFreqNode.Next() + + var newParent *list.Element = nil + + if nextParentFreqNode == nil { + // this is the last node + // create a new node with frequency + 1 + newFreqNode := newFrequencyNode(currentNode.count + 1) + lfu.frequencies.PushBack(newFreqNode) + newParent = parentFreqNode.Next() + + } else { + nextNode := nextParentFreqNode.Value.(*frequencyNode) + if nextNode.count == (currentNode.count + 1) { + newParent = nextParentFreqNode + } else { + // insert a node in between + newFreqNode := newFrequencyNode(currentNode.count + 1) + + lfu.frequencies.InsertAfter(newFreqNode, parentFreqNode) + newParent = parentFreqNode.Next() + } + } + + // remove from the existing list + currentNode.valuesList.Remove(valueNode.inner) + + newParentNode := newParent.Value.(*frequencyNode) + valueNode.parentFreqNode = newParent + newValueNode := newParentNode.valuesList.PushBack(valueNode) + valueNode.inner = newValueNode + + // check if the current node is empty + if currentNode.valuesList.Len() == 0 { + // remove the current node + lfu.frequencies.Remove(parentFreqNode) + } +} + +// Get can be called to obtain the value for given key +func (lfu *FrameCache) Get(key uint) (*Frame, bool) { + lfu.rwLock.Lock() + defer lfu.rwLock.Unlock() + + // check if data is in the map + valueNode, found := lfu.lookupTable[key] + if !found { + return nil, false + } + + lfu.unsafeUpdateFrequency(valueNode) + + return valueNode.valueRef, true +} + +// Delete removes the specified entry from LFU cache +func (lfu *FrameCache) Delete(key uint) error { + lfu.rwLock.Lock() + defer lfu.rwLock.Unlock() + + // check if the key is in the map + valueNode, found := lfu.lookupTable[key] + if !found { + return fmt.Errorf("key %v not found", key) + } + + parentFreqNode := valueNode.parentFreqNode + + currentNode := (parentFreqNode.Value).(*frequencyNode) + currentNode.valuesList.Remove(valueNode.inner) + + if currentNode.valuesList.Len() == 0 { + lfu.frequencies.Remove(parentFreqNode) + } + + delete(lfu.lookupTable, key) + return nil +} + +// NewFrameCache ... +func NewFrameCache(maxSize uint) *FrameCache { + return &FrameCache{ + rwLock: sync.RWMutex{}, + lookupTable: make(map[uint]*keyRefNode), + maxSize: maxSize, + frequencies: list.New(), + } +} diff --git a/vm/frame.go b/internal/vm/frame.go similarity index 50% rename from vm/frame.go rename to internal/vm/frame.go index 9f6a8ca..6d57b12 100644 --- a/vm/frame.go +++ b/internal/vm/frame.go @@ -1,10 +1,13 @@ package vm import ( - "monkey/code" - "monkey/object" + "monkey/internal/code" + "monkey/internal/object" + "unsafe" ) +var cache = NewFrameCache(32) + type Frame struct { cl *object.Closure ip int @@ -12,16 +15,32 @@ type Frame struct { } func NewFrame(cl *object.Closure, basePointer int) *Frame { - return &Frame{ + key := uint(uintptr(unsafe.Pointer(cl))) + uint(basePointer) + if frame, ok := cache.Get(key); ok { + frame.Reset() + return frame + } + + frame := &Frame{ cl: cl, ip: -1, - basePointer: basePointer} + basePointer: basePointer, + } + + cache.Put(key, frame) + + return frame +} + +// NextOp ... +func (f *Frame) NextOp() code.Opcode { + return code.Opcode(f.Instructions()[f.ip+1]) +} + +func (f *Frame) Reset() { + f.ip = -1 } func (f *Frame) Instructions() code.Instructions { return f.cl.Fn.Instructions } - -func (f *Frame) NextOp() code.Opcode { - return code.Opcode(f.Instructions()[f.ip+1]) -} diff --git a/vm/vm.go b/internal/vm/vm.go similarity index 99% rename from vm/vm.go rename to internal/vm/vm.go index c933514..a33ff21 100644 --- a/vm/vm.go +++ b/internal/vm/vm.go @@ -4,13 +4,13 @@ import ( "fmt" "io/ioutil" "log" - "monkey/builtins" - "monkey/code" - "monkey/compiler" - "monkey/lexer" - "monkey/object" - "monkey/parser" - "monkey/utils" + "monkey/internal/builtins" + "monkey/internal/code" + "monkey/internal/compiler" + "monkey/internal/lexer" + "monkey/internal/object" + "monkey/internal/parser" + "monkey/internal/utils" "strings" "unicode" ) diff --git a/vm/vm_test.go b/internal/vm/vm_test.go similarity index 98% rename from vm/vm_test.go rename to internal/vm/vm_test.go index 7a2617f..51916da 100644 --- a/vm/vm_test.go +++ b/internal/vm/vm_test.go @@ -2,12 +2,12 @@ package vm import ( "fmt" - "monkey/ast" - "monkey/compiler" - "monkey/lexer" - "monkey/object" - "monkey/parser" - "monkey/utils" + "monkey/internal/ast" + "monkey/internal/compiler" + "monkey/internal/lexer" + "monkey/internal/object" + "monkey/internal/parser" + "monkey/internal/utils" "os" "path" "path/filepath" @@ -1185,15 +1185,15 @@ func BenchmarkFibonacci(b *testing.B) { func TestImportExpressions(t *testing.T) { tests := []vmTestCase{ { - input: `mod := import("../testdata/mod"); mod.A`, + input: `mod := import("../../testdata/mod"); mod.A`, expected: 5, }, { - input: `mod := import("../testdata/mod"); mod.Sum(2, 3)`, + input: `mod := import("../../testdata/mod"); mod.Sum(2, 3)`, expected: 5, }, { - input: `mod := import("../testdata/mod"); mod.a`, + input: `mod := import("../../testdata/mod"); mod.a`, expected: nil, }, } @@ -1202,11 +1202,11 @@ func TestImportExpressions(t *testing.T) { } func TestImportSearchPaths(t *testing.T) { - utils.AddPath("../testdata") + utils.AddPath("../../testdata") tests := []vmTestCase{ { - input: `mod := import("../testdata/mod"); mod.A`, + input: `mod := import("../../testdata/mod"); mod.A`, expected: 5, }, } diff --git a/vim/monkey.vim b/syntax/monkey.vim similarity index 100% rename from vim/monkey.vim rename to syntax/monkey.vim