diff --git a/Makefile b/Makefile index 12d27b4..3df785e 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: dev build install image profile bench test clean +.PHONY: dev build install image release profile bench test clean CGO_ENABLED=0 COMMIT=$(shell git rev-parse --short HEAD) @@ -20,6 +20,9 @@ install: build image: @docker build -t prologic/monkey-lang . +release: + @./tools/release.sh + profile: @go test -cpuprofile cpu.prof -memprofile mem.prof -v -bench ./... diff --git a/examples/primes.monkey b/examples/primes.monkey new file mode 100644 index 0000000..8ddb7b8 --- /dev/null +++ b/examples/primes.monkey @@ -0,0 +1,41 @@ +#!./monkey-lang + +prime := fn(n) { + # Corner cases + if (n <= 1) { + return false + } + if (n <= 3) { + return true + } + + # This is checked so that we can skip + # middle five numbers in below loop + if (n % 2 == 0 || n % 3 == 0) { + return false + } + + i := 5 + while (i * i <= n) { + if (n % i == 0 || n % (i + 2) == 0) { + return false + } + i = i + 6 + } + + return true +} + +if (len(args()) == 1) { + N := int(args()[0]) +} else { + N := 100 +} + +n := 1 +while (n < N) { + if (prime(n)) { + print(n) + } + n = n + 1 +} \ No newline at end of file diff --git a/foo.monkey b/foo.monkey deleted file mode 100644 index 234a305..0000000 --- a/foo.monkey +++ /dev/null @@ -1,3 +0,0 @@ -#!./monkey-lang - -print(args()) \ No newline at end of file diff --git a/main.go b/main.go index 0b60b1d..b6ae08b 100644 --- a/main.go +++ b/main.go @@ -70,11 +70,6 @@ func main() { args := flag.Args() - copy(object.Arguments, args) - object.StandardInput = os.Stdin - object.StandardOutput = os.Stdout - object.ExitFunction = os.Exit - if compile { if len(args) < 1 { log.Fatal("no source file given to compile") diff --git a/repl/repl.go b/repl/repl.go index d1d5ec1..f9228cf 100644 --- a/repl/repl.go +++ b/repl/repl.go @@ -7,7 +7,6 @@ import ( "bufio" "fmt" "io" - "io/ioutil" "log" "monkey/compiler" "monkey/evaluator" @@ -68,6 +67,10 @@ type REPL struct { } func New(user string, args []string, opts *Options) *REPL { + object.StandardInput = os.Stdin + object.StandardOutput = os.Stdout + object.ExitFunction = os.Exit + return &REPL{user, args, opts} } @@ -76,7 +79,7 @@ func New(user string, args []string, opts *Options) *REPL { func (r *REPL) Eval(f io.Reader) (env *object.Environment) { env = object.NewEnvironment() - b, err := ioutil.ReadAll(f) + b, err := io.ReadAll(f) if err != nil { fmt.Fprintf(os.Stderr, "error reading source file: %s", err) return @@ -98,7 +101,7 @@ func (r *REPL) Eval(f io.Reader) (env *object.Environment) { // Exec parses, compiles and executes the program given by f and returns // the resulting virtual machine, any errors are printed to stderr func (r *REPL) Exec(f io.Reader) (state *VMState) { - b, err := ioutil.ReadAll(f) + b, err := io.ReadAll(f) if err != nil { fmt.Fprintf(os.Stderr, "error reading source file: %s", err) return @@ -225,12 +228,30 @@ func (r *REPL) StartExecLoop(in io.Reader, out io.Writer, state *VMState) { } func (r *REPL) Run() { - if len(r.args) == 1 { + object.Arguments = make([]string, len(r.args)) + copy(object.Arguments, r.args) + + if len(r.args) == 0 { + fmt.Printf("Hello %s! This is the Monkey programming language!\n", r.user) + fmt.Printf("Feel free to type in commands\n") + if r.opts.Engine == "eval" { + r.StartEvalLoop(os.Stdin, os.Stdout, nil) + } else { + r.StartExecLoop(os.Stdin, os.Stdout, nil) + } + return + } + + if len(r.args) > 0 { f, err := os.Open(r.args[0]) if err != nil { log.Fatalf("could not open source file %s: %s", r.args[0], err) } + // Remove program argument (zero) + r.args = r.args[1:] + object.Arguments = object.Arguments[1:] + if r.opts.Engine == "eval" { env := r.Eval(f) if r.opts.Interactive { @@ -242,14 +263,6 @@ func (r *REPL) Run() { r.StartExecLoop(os.Stdin, os.Stdout, state) } } - } else { - fmt.Printf("Hello %s! This is the Monkey programming language!\n", r.user) - fmt.Printf("Feel free to type in commands\n") - if r.opts.Engine == "eval" { - r.StartEvalLoop(os.Stdin, os.Stdout, nil) - } else { - r.StartExecLoop(os.Stdin, os.Stdout, nil) - } } } diff --git a/tools/release.sh b/tools/release.sh index 4ae4fb5..a18742b 100644 --- a/tools/release.sh +++ b/tools/release.sh @@ -22,4 +22,4 @@ echo "Releasing ${TAG} ..." git tag -a -s -m "Release ${TAG}" "${TAG}" git push --tags -goreleaser \ No newline at end of file +goreleaser release --rm-dist \ No newline at end of file diff --git a/vim/monkey.vim b/vim/monkey.vim index 951f052..20499fd 100644 --- a/vim/monkey.vim +++ b/vim/monkey.vim @@ -1,3 +1,4 @@ + " Vim Syntax File " Language: monkey " Creator: James Mills, prologic at shortcircuit dot net dot au @@ -11,15 +12,31 @@ endif syntax case match -syntax keyword xType true false null +syntax keyword xType true false null int str bool array hash syntax keyword xKeyword fn if else return while syntax keyword xFunction len input print first last rest push pop exit assert +syntax keyword xFunction bool int str typeof args lower upper join split find +syntax keyword xFunction read write -syntax keyword xOperator == != < > ! -syntax keyword xOperator + - * / -syntax keyword xOperator := = +syntax match xOperator "\v\=\=" +syntax match xOperator "\v!\=" +syntax match xOperator "\v<" +syntax match xOperator "\v>" +syntax match xOperator "\v!" +syntax match xOperator "\v\+" +syntax match xOperator "\v-" +syntax match xOperator "\v\*" +syntax match xOperator "\v/" +syntax match xOperator "\v:\=" +syntax match xOperator "\v\=" +syntax match xOperator "\v&" +syntax match xOperator "\v\|" +syntax match xOperator "\v^" +syntax match xOperator "\v\~" +syntax match xOperator "\v&&" +syntax match xOperator "\v\|\|" syntax region xString start=/"/ skip=/\\./ end=/"/ @@ -30,8 +47,7 @@ highlight link xType Type highlight link xKeyword Keyword highlight link xFunction Function highlight link xString String - highlight link xComment Comment +highlight link xComment Comment highlight link xOperator Operator -highlight Operator ctermfg=5 let b:current_syntax = "monkey" \ No newline at end of file