Switching to wsl
Some checks failed
Build / build (push) Successful in 10m47s
Publish Image / publish (push) Failing after 30s
Test / build (push) Successful in 11m0s

This commit is contained in:
Charles Smith
2024-03-31 19:35:04 -04:00
parent 7a32cce8a1
commit a85dc73954
15 changed files with 91 additions and 85 deletions

View File

@@ -42,7 +42,7 @@ signs:
- artifacts: checksum - artifacts: checksum
release: release:
gitea: gitea:
owner: unflavoredmeson owner: UnflavoredMeson
name: monkey name: monkey
gitea_urls: gitea_urls:
api: https://gitea.unflavoredmeson.com/api/v1/ api: https://gitea.unflavoredmeson.com/api/v1/

7
Benchmark.md Normal file
View File

@@ -0,0 +1,7 @@
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|:---|---:|---:|---:|---:|
| `c` | 36.7 ± 0.6 | 36.0 | 37.8 | 1.00 |
| `go` | 230.2 ± 14.0 | 206.2 | 252.9 | 6.28 ± 0.40 |
| `python` | 1366.9 ± 30.8 | 1330.9 | 1411.3 | 37.27 ± 1.06 |
| `tengo` | 1704.3 ± 16.0 | 1687.2 | 1739.3 | 46.47 ± 0.91 |
| `monkey` | 3347.6 ± 22.3 | 3314.0 | 3396.0 | 91.27 ± 1.69 |

View File

@@ -7,14 +7,14 @@ VERSION ?= $(shell git describe 2>/dev/null || echo "")
DESTDIR ?= $(GOBIN) DESTDIR ?= $(GOBIN)
ifeq ($(LOCAL), 1) ifeq ($(LOCAL), 1)
IMAGE := r.mills.io/prologic/monkey IMAGE := r.unflavoredmeson.com/UnflavoredMeson/monkey
TAG := dev TAG := dev
else else
ifeq ($(BRANCH), master) ifeq ($(BRANCH), master)
IMAGE := prologic/monkey IMAGE := UnflavoredMeson/monkey
TAG := latest TAG := latest
else else
IMAGE := prologic/monkey IMAGE := UnflavoredMeson/monkey
TAG := dev TAG := dev
endif endif
endif endif
@@ -33,14 +33,14 @@ build: clean cli server ## Build monkey
cli: ## Build monkey CLI cli: ## Build monkey CLI
@go build \ @go build \
-tags "netgo static_build" -installsuffix netgo \ -tags "netgo static_build" -installsuffix netgo \
-ldflags "-w -X go.mills.io/monkey/v2.MonkeyVersion=$(VERSION)" \ -ldflags "-w -X go.unflavoredmeson.com/monkey/v2.MonkeyVersion=$(VERSION)" \
./cmd/monkey/... ./cmd/monkey/...
server: ## Build Monkey server server: ## Build Monkey server
@go build \ @go build \
-tags "netgo static_build" -installsuffix netgo \ -tags "netgo static_build" -installsuffix netgo \
-ldflags "-w -X go.mills.io/monkey/v2.MonkeyVersion=$(VERSION)" \ -ldflags "-w -X go.unflavoredmeson.com/monkey/v2.MonkeyVersion=$(VERSION)" \
./cmd/monkey-server/... ./cmd/monkey/...
install: cli server ## Install monkey to $DESTDIR install: cli server ## Install monkey to $DESTDIR
@install -D -m 755 monkey $(DESTDIR)/monkey @install -D -m 755 monkey $(DESTDIR)/monkey
@@ -66,16 +66,14 @@ profile: ## Run tests with profiling enabled
@go test -cpuprofile cpu.prof -memprofile mem.prof -v -bench ./... @go test -cpuprofile cpu.prof -memprofile mem.prof -v -bench ./...
compare: ## Run benchmarks comparing Monkey with other languages compare: ## Run benchmarks comparing Monkey with other languages
@hyperfine -w 5 -p 'make build; gcc -o examples/fib examples/fib.c' \ @hyperfine -w 3 -p 'make build; gcc -o examples/fib examples/fib.c' \
-n c -n go -n tengo -n python -n tauc -n taugo -n monkey \ -n c -n go -n tengo -n python -n monkey \
--sort mean-time --export-markdown Benchmark.md \ --sort mean-time --export-markdown Benchmark.md \
'./examples/fib' \ './examples/fib' \
'go run examples/fib.go' \ 'go run examples/fib.go' \
'tengo examples/fib.tengo' \ 'tengo examples/fib.tengo' \
'python3 examples/fib.py' \ 'python3 examples/fib.py' \
'tauc examples/fib.tau' \ './monkey examples/fib.monkey'
'taugo examples/fib.tau' \
'./monkey examples/fib.m'
bench: # Run test benchmarks bench: # Run test benchmarks
@go test -v -benchmem -bench=. ./... @go test -v -benchmem -bench=. ./...

1
go.sum
View File

@@ -17,6 +17,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tebeka/atexit v0.3.0 h1:jleL99H7Ywt80oJKR+VWmJNnezcCOG0CuzcN3CIpsdI=
github.com/tebeka/atexit v0.3.0/go.mod h1:WJmSUSmMT7WoR7etUOaGBVXk+f5/ZJ+67qwuedq7Fbs= github.com/tebeka/atexit v0.3.0/go.mod h1:WJmSUSmMT7WoR7etUOaGBVXk+f5/ZJ+67qwuedq7Fbs=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=

View File

@@ -17,13 +17,13 @@ func Accept(args ...object.Object) object.Object {
} }
var ( var (
nfd syscall.Handle nfd int
err error err error
) )
fd := int(args[0].(*object.Integer).Value) fd := int(args[0].(*object.Integer).Value)
nfd, _, err = syscall.Accept(syscall.Handle(fd)) nfd, _, err = syscall.Accept(fd)
if err != nil { if err != nil {
return newError("SocketError: %s", err) return newError("SocketError: %s", err)
} }

View File

@@ -24,7 +24,7 @@ func Bind(args ...object.Object) object.Object {
fd := int(args[0].(*object.Integer).Value) fd := int(args[0].(*object.Integer).Value)
address := args[1].(*object.String).Value address := args[1].(*object.String).Value
sockaddr, err = syscall.Getsockname(syscall.Handle(fd)) sockaddr, err = syscall.Getsockname(fd)
if err != nil { if err != nil {
return newError("ValueError: %s", err) return newError("ValueError: %s", err)
} }
@@ -45,7 +45,7 @@ func Bind(args ...object.Object) object.Object {
return newError("ValueError: Invalid socket type %T for bind '%s'", sockaddr, address) return newError("ValueError: Invalid socket type %T for bind '%s'", sockaddr, address)
} }
err = syscall.Bind(syscall.Handle(fd), sockaddr) err = syscall.Bind(fd, sockaddr)
if err != nil { if err != nil {
return newError("SocketError: %s", err) return newError("SocketError: %s", err)
} }

View File

@@ -18,7 +18,7 @@ func Close(args ...object.Object) object.Object {
fd := int(args[0].(*object.Integer).Value) fd := int(args[0].(*object.Integer).Value)
err := syscall.Close(syscall.Handle(fd)) err := syscall.Close(fd)
if err != nil { if err != nil {
return newError("IOError: %s", err) return newError("IOError: %s", err)
} }

View File

@@ -21,7 +21,7 @@ func Connect(args ...object.Object) object.Object {
fd := int(args[0].(*object.Integer).Value) fd := int(args[0].(*object.Integer).Value)
address := args[1].(*object.String).Value address := args[1].(*object.String).Value
sockaddr, err := syscall.Getsockname(syscall.Handle(fd)) sockaddr, err := syscall.Getsockname(fd)
if err != nil { if err != nil {
return newError("ValueError: %s", err) return newError("ValueError: %s", err)
} }
@@ -42,7 +42,7 @@ func Connect(args ...object.Object) object.Object {
return newError("ValueError: Invalid socket type %T for bind '%s'", sockaddr, address) return newError("ValueError: Invalid socket type %T for bind '%s'", sockaddr, address)
} }
if err = syscall.Connect(syscall.Handle(fd), sa); err != nil { if err = syscall.Connect(fd, sa); err != nil {
return newError("SocketError: %s", err) return newError("SocketError: %s", err)
} }

View File

@@ -19,7 +19,7 @@ func Listen(args ...object.Object) object.Object {
fd := int(args[0].(*object.Integer).Value) fd := int(args[0].(*object.Integer).Value)
backlog := int(args[1].(*object.Integer).Value) backlog := int(args[1].(*object.Integer).Value)
if err := syscall.Listen(syscall.Handle(fd), backlog); err != nil { if err := syscall.Listen(fd, backlog); err != nil {
return newError("SocketError: %s", err) return newError("SocketError: %s", err)
} }

View File

@@ -31,7 +31,7 @@ func Read(args ...object.Object) object.Object {
} }
buf := make([]byte, n) buf := make([]byte, n)
n, err := syscall.Read(syscall.Handle(fd), buf) n, err := syscall.Read(fd, buf)
if err != nil { if err != nil {
return newError("IOError: %s", err) return newError("IOError: %s", err)
} }

View File

@@ -28,7 +28,7 @@ func Seek(args ...object.Object) object.Object {
whence = int(args[2].(*object.Integer).Value) whence = int(args[2].(*object.Integer).Value)
} }
offset, err := syscall.Seek(syscall.Handle(fd), offset, whence) offset, err := syscall.Seek(fd, offset, whence)
if err != nil { if err != nil {
return newError("IOError: %s", err) return newError("IOError: %s", err)
} }

View File

@@ -19,7 +19,7 @@ func Write(args ...object.Object) object.Object {
fd := int(args[0].(*object.Integer).Value) fd := int(args[0].(*object.Integer).Value)
data := []byte(args[1].(*object.String).Value) data := []byte(args[1].(*object.String).Value)
n, err := syscall.Write(syscall.Handle(fd), data) n, err := syscall.Write(fd, data)
if err != nil { if err != nil {
return newError("IOError: %s", err) return newError("IOError: %s", err)
} }

View File

@@ -11,7 +11,7 @@ type BinaryOpError struct {
} }
func (e BinaryOpError) Error() string { func (e BinaryOpError) Error() string {
return fmt.Sprintf("unsupported types for binary operation: %s %s %s", e.left.Type(), e.op, e.right.Type()) return fmt.Sprintf("unsupported types for binary operation: %s %s %s %s %s", e.left.Type(), e.left.Inspect(), e.op, e.right.Type(), e.right.Inspect())
} }
// NewBinaryOpError returns a new BinaryOpError // NewBinaryOpError returns a new BinaryOpError

View File

@@ -3,14 +3,21 @@
package main package main
import ( import (
"monkey/internal/compiler" "flag"
"monkey/internal/parser" "fmt"
"monkey/internal/vm" "log"
"os" "os"
"runtime"
"runtime/pprof" "runtime/pprof"
"strings"
"git.mills.io/prologic/monkey-lang/internal/compiler"
"git.mills.io/prologic/monkey-lang/internal/object"
"git.mills.io/prologic/monkey-lang/internal/parser"
"git.mills.io/prologic/monkey-lang/internal/vm"
) )
const fib = ` const defaultCode = `
fib := fn(n) { fib := fn(n) {
if (n < 2) { if (n < 2) {
return n return n
@@ -18,44 +25,64 @@ fib := fn(n) {
return fib(n-1) + fib(n-2) return fib(n-1) + fib(n-2)
} }
print(fib(35))` print(fib(%d))`
func check(err error) { func checkErr(err error) {
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
func code(path string) string { func readFile(path string) string {
b, err := os.ReadFile(path) b, err := os.ReadFile(path)
check(err) checkErr(err)
return string(b) return string(b)
} }
func fileOrDefault() string { func fileOrDefault() string {
if len(os.Args) > 1 { if flag.NArg() > 0 {
return code(os.Args[1]) log.Printf("Using %s as program input...", flag.Arg(0))
object.Args = flag.Args()[1:]
return readFile(flag.Arg(0))
} }
return fib return defaultCode
} }
func main() { func main() {
n := flag.Int("n", 35, "Set n for fib(n) [Default: 35]")
flag.Parse()
cpuf, err := os.Create("cpu.prof") cpuf, err := os.Create("cpu.prof")
check(err) checkErr(err)
heapf, err := os.Create("heap.prof")
checkErr(err)
log.Printf("Using %d as n", *n)
code := fileOrDefault() code := fileOrDefault()
if strings.Count(code, "%d") > 0 {
code = fmt.Sprintf(code, *n)
}
log.Printf("Code:\n%s\n", code)
tree, errs := parser.Parse("<profiler>", code) tree, errs := parser.Parse("<profiler>", code)
if len(errs) > 0 { if len(errs) > 0 {
for _, err := range errs {
log.Println(err)
}
panic("parser errors") panic("parser errors")
} }
c := compiler.New() c := compiler.New()
c.SetFileInfo("<profiler>", code) c.SetFileInfo("<profiler>", code)
check(c.Compile(tree)) checkErr(c.Compile(tree))
checkErr(pprof.StartCPUProfile(cpuf))
check(pprof.StartCPUProfile(cpuf))
defer pprof.StopCPUProfile() defer pprof.StopCPUProfile()
mvm := vm.New("<profiler>", c.Bytecode()) mvm := vm.New("<profiler>", c.Bytecode())
mvm.Run() checkErr(mvm.Run())
runtime.GC()
checkErr(pprof.WriteHeapProfile(heapf))
log.Println("CPU Profile written to cpu.prof")
log.Println("Heap Profile written to heap.prof")
} }

View File

@@ -1,52 +1,25 @@
" Vim Syntax File #!/bin/sh
" Language: monkey
" Creator: James Mills, prologic at shortcircuit dot net dot au
" Last Change: 31st January 2019
if version < 600 # Get the highest tag number
syntax clear VERSION="$(git describe --abbrev=0 --tags)"
elseif exists("b:current_syntax") VERSION=${VERSION:-'0.0.0'}
finish
endif
syntax case match # Get number parts
MAJOR="${VERSION%%.*}"; VERSION="${VERSION#*.}"
MINOR="${VERSION%%.*}"; VERSION="${VERSION#*.}"
PATCH="${VERSION%%.*}"; VERSION="${VERSION#*.}"
syntax keyword xType true false null int str bool array hash # Increase version
PATCH=$((PATCH+1))
syntax keyword xKeyword fn if else return while TAG="${1}"
syntax keyword xFunction len input print first last rest push pop exit assert if [ "${TAG}" = "" ]; then
syntax keyword xFunction bool int str typeof args lower upper join split find TAG="${MAJOR}.${MINOR}.${PATCH}"
syntax keyword xFunction read write fi
syntax match xOperator "\v\=\=" echo "Releasing ${TAG} ..."
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=/"/ git tag -a -s -m "Release ${TAG}" "${TAG}"
git push --tags
syntax region xComment start='#' end='$' keepend goreleaser release --rm-dist
syntax region xComment start='//' end='$' keepend
highlight link xType Type
highlight link xKeyword Keyword
highlight link xFunction Function
highlight link xString String
highlight link xComment Comment
highlight link xOperator Operator
let b:current_syntax = "monkey"