diff --git a/cmd/benchmark.go b/cmd/benchmark.go index c24d27f..aaacbdd 100644 --- a/cmd/benchmark.go +++ b/cmd/benchmark.go @@ -12,6 +12,7 @@ import ( func benchmarkCommand() { benchmarkHelloWorld() + benchmarkFibonacci() } func benchmarkHelloWorld() { @@ -23,9 +24,37 @@ func benchmarkHelloWorld() { fmt.Println("==============================") fmt.Printf("Go: %s\n", goTime) fmt.Printf("Ghost: %s\n", ghostTime) + fmt.Printf("Difference: %s\n", ghostTime-goTime) + fmt.Printf("Difference (%%): +%.2f%%\n", (float64(ghostTime-goTime)/float64(goTime))*100) fmt.Printf("-- Scanner: %s\n", scanTime) fmt.Printf("-- Parser: %s\n", parseTime) - fmt.Printf("-- Interpreter: %s\n", interpretTime) + fmt.Printf("-- Interpreter: %s\n\n", interpretTime) +} + +func benchmarkFibonacci() { + goTime := nativeFibonacci() + scanTime, parseTime, interpretTime, ghostTime := benchmark(` + function fibonacci(n) { + if (n <= 1) { + return n + } + + return fibonacci(n - 1) + fibonacci(n - 2) + } + + fibonacci(20) + `) + + fmt.Println("==============================") + fmt.Println("Fibonacci benchmark") + fmt.Println("==============================") + fmt.Printf("Go: %s\n", goTime) + fmt.Printf("Ghost: %s\n", ghostTime) + fmt.Printf("Difference: %s\n", ghostTime-goTime) + fmt.Printf("Difference (%%): +%.2f%%\n", (float64(ghostTime-goTime)/float64(goTime))*100) + fmt.Printf("-- Scanner: %s\n", scanTime) + fmt.Printf("-- Parser: %s\n", parseTime) + fmt.Printf("-- Interpreter: %s\n\n", interpretTime) } func nativeHelloWorld() time.Duration { @@ -35,6 +64,14 @@ func nativeHelloWorld() time.Duration { return time.Since(start) } +func nativeFibonacci() time.Duration { + start := time.Now() + + _ = fibonacci(20) + + return time.Since(start) +} + func benchmark(source string) (scanTime time.Duration, parseTime time.Duration, interpretTime time.Duration, ghostTime time.Duration) { start := time.Now() @@ -57,3 +94,11 @@ func benchmark(source string) (scanTime time.Duration, parseTime time.Duration, return scanTime, parseTime, interpretTime, ghostTime } + +func fibonacci(n int) int { + if n <= 1 { + return n + } + + return fibonacci(n-1) + fibonacci(n-2) +} diff --git a/cmd/ghost.go b/cmd/ghost.go index d514cd0..00318ec 100644 --- a/cmd/ghost.go +++ b/cmd/ghost.go @@ -47,12 +47,12 @@ func main() { if flagHelp { helpCommand() - os.Exit(2) + os.Exit(0) } if flagBenchmark { benchmarkCommand() - os.Exit(2) + os.Exit(0) } args := flag.Args() diff --git a/evaluator/method.go b/evaluator/method.go index 4f32bd7..d05379c 100644 --- a/evaluator/method.go +++ b/evaluator/method.go @@ -25,6 +25,16 @@ func evaluateMethod(node *ast.Method, scope *object.Scope) object.Object { } switch receiver := left.(type) { + case *object.Map: + method := node.Method.(*ast.Identifier) + + property := &object.String{Value: method.Value} + + if function, ok := receiver.Pairs[property.MapKey()]; ok { + return unwrapCall(node.Token, function.Value, arguments, scope) + } + + return newError("%d:%d:%s: runtime error: unknown method: %s.%s", node.Token.Line, node.Token.Column, node.Token.File, receiver.Type(), method.Value) case *object.Instance: method := node.Method.(*ast.Identifier) evaluated := evaluateInstanceMethod(node, receiver, method.Value, arguments) diff --git a/examples/scratch.ghost b/examples/scratch.ghost index 1cbb1e1..a9f1506 100644 --- a/examples/scratch.ghost +++ b/examples/scratch.ghost @@ -1,23 +1,11 @@ -bar = true -list = [1, 2, 3] +data = { + name: 'Test', + handler: function(n) { + print('n * n') -// for (i in list) { -// if (foo == true) { -// print("foo is true") -// } + return n * n + } +} -// if (bar == true) { -// print("bar is true") -// } -// } - -for (i = 0; i < 10; i = i + 1) { - foo - // if (foo == true) { - // print("foo is true") - // } - - // if (bar == true) { - // print("bar is true") - // } -} \ No newline at end of file +print(data.name) +print(data.handler(6)) \ No newline at end of file