1
0
forked from Mirror/wren

Merge branch 'master' into foreign-methods

This commit is contained in:
Bob Nystrom
2015-03-25 20:06:55 -07:00
11 changed files with 115 additions and 37 deletions

View File

@ -9,4 +9,5 @@ Evan Shaw <edsrzf@gmail.com>
Gavin Schulz <gavin.schulz@gmail.com>
Lukas Werling <lukas.werling@gmail.com>
Marco Lizza <marco.lizza@gmail.com>
Raymond Sohn <raymondsohn@gmail.com
Raymond Sohn <raymondsohn@gmail.com>
Thorbjørn Lindeijer <bjorn@lindeijer.nl>

1
builtin/meta.wren Normal file
View File

@ -0,0 +1 @@
class Meta {}

View File

@ -17,6 +17,7 @@
29205C9F1AB4E6430073018D /* wren_vm.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C981AB4E6430073018D /* wren_vm.c */; };
29C8A92F1AB71C1C00DEC81D /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 29C8A92E1AB71C1C00DEC81D /* io.c */; };
29C8A9331AB71FFF00DEC81D /* vm.c in Sources */ = {isa = PBXBuildFile; fileRef = 29C8A9311AB71FFF00DEC81D /* vm.c */; };
29DE39531AC3A50A00987D41 /* wren_meta.c in Sources */ = {isa = PBXBuildFile; fileRef = 29DE39511AC3A50A00987D41 /* wren_meta.c */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -54,6 +55,8 @@
29C8A9301AB71C3300DEC81D /* io.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = io.h; path = ../../src/cli/io.h; sourceTree = "<group>"; };
29C8A9311AB71FFF00DEC81D /* vm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vm.c; path = ../../src/cli/vm.c; sourceTree = "<group>"; };
29C8A9321AB71FFF00DEC81D /* vm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vm.h; path = ../../src/cli/vm.h; sourceTree = "<group>"; };
29DE39511AC3A50A00987D41 /* wren_meta.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = wren_meta.c; path = ../../src/vm/wren_meta.c; sourceTree = "<group>"; };
29DE39521AC3A50A00987D41 /* wren_meta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_meta.h; path = ../../src/vm/wren_meta.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -79,6 +82,8 @@
29205C941AB4E6430073018D /* wren_debug.c */,
29205CA51AB4E65E0073018D /* wren_io.h */,
29205C951AB4E6430073018D /* wren_io.c */,
29DE39521AC3A50A00987D41 /* wren_meta.h */,
29DE39511AC3A50A00987D41 /* wren_meta.c */,
29205CA61AB4E65E0073018D /* wren_utils.h */,
29205C961AB4E6430073018D /* wren_utils.c */,
29205CA71AB4E65E0073018D /* wren_value.h */,
@ -187,6 +192,7 @@
29205C9E1AB4E6430073018D /* wren_value.c in Sources */,
29205C9F1AB4E6430073018D /* wren_vm.c in Sources */,
29C8A92F1AB71C1C00DEC81D /* io.c in Sources */,
29DE39531AC3A50A00987D41 /* wren_meta.c in Sources */,
29205C8F1AB4E5C90073018D /* main.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -39,6 +39,7 @@ import sys
# To generate a baseline file, run this script with "--generate-baseline".
WREN_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
WREN_BIN = os.path.join(WREN_DIR, 'bin')
BENCHMARK_DIR = os.path.join(WREN_DIR, 'test', 'benchmark')
# How many times to run a given benchmark.
@ -78,7 +79,7 @@ BENCHMARK("map_string", r"""3645600""")
BENCHMARK("string_equals", r"""3000000""")
LANGUAGES = [
("wren", [os.path.join(WREN_DIR, 'wren')], ".wren"),
("wren", [os.path.join(WREN_BIN, 'wren')], ".wren"),
("lua", ["lua"], ".lua"),
("luajit (-joff)", ["luajit", "-joff"], ".lua"),
("python", ["python"], ".py"),
@ -88,20 +89,22 @@ LANGUAGES = [
results = {}
if sys.platform == 'win32':
GREEN = NORMAL = RED = YELLOW = ''
else:
GREEN = '\033[32m'
NORMAL = '\033[0m'
RED = '\033[31m'
YELLOW = '\033[33m'
def green(text):
if sys.platform == 'win32':
return text
return '\033[32m' + text + '\033[0m'
return GREEN + text + NORMAL
def red(text):
if sys.platform == 'win32':
return text
return '\033[31m' + text + '\033[0m'
return RED + text + NORMAL
def yellow(text):
if sys.platform == 'win32':
return text
return '\033[33m' + text + '\033[0m'
return YELLOW + text + NORMAL
def get_score(time):
@ -113,6 +116,20 @@ def get_score(time):
return 1000.0 / time
def standard_deviation(times):
"""
Calculates the standard deviation of a list of numbers.
"""
mean = sum(times) / len(times)
# Sum the squares of the differences from the mean.
result = 0
for time in times:
result += (time - mean) ** 2
return math.sqrt(result / len(times))
def run_trial(benchmark, language):
"""Runs one benchmark one time for one language."""
args = []
@ -180,7 +197,10 @@ def run_benchmark_language(benchmark, language, benchmark_result):
if ratio < 95:
comparison = red(comparison)
print(" {:5.0f} {:4.2f}s {:s}".format(score, best, comparison))
print(" {:4.2f}s {:4.4f} {:s}".format(
best,
standard_deviation(times),
comparison))
benchmark_result[language[0]] = {
"desc": name,
@ -191,7 +211,7 @@ def run_benchmark_language(benchmark, language, benchmark_result):
return score
def run_benchmark(benchmark, languages):
def run_benchmark(benchmark, languages, graph):
"""Runs one benchmark for the given languages (or all of them)."""
benchmark_result = {}
@ -203,7 +223,7 @@ def run_benchmark(benchmark, languages):
num_languages += 1
run_benchmark_language(benchmark, language, benchmark_result)
if num_languages > 1:
if num_languages > 1 and graph:
graph_results(benchmark_result)
@ -300,6 +320,9 @@ def main():
parser.add_argument("--generate-baseline",
action="store_true",
help="Generate a baseline file")
parser.add_argument("--graph",
action="store_true",
help="Display graph results.")
parser.add_argument("-l", "--language",
action="append",
help="Which language(s) to run benchmarks for")
@ -318,7 +341,7 @@ def main():
# Run the benchmarks.
for benchmark in BENCHMARKS:
if benchmark[0] == args.benchmark or args.benchmark == "all":
run_benchmark(benchmark, args.language)
run_benchmark(benchmark, args.language, args.graph)
if args.output_html:
print_html()

View File

@ -243,7 +243,7 @@ def run_test(path):
print('')
for dir in ['core', 'io', 'language', 'limit']:
for dir in ['core', 'io', 'language', 'limit', 'meta']:
walk(join(WREN_DIR, 'test', dir), run_test)
print_line()

View File

@ -14,20 +14,19 @@ typedef struct WrenMethod WrenMethod;
// A generic allocation function that handles all explicit memory management
// used by Wren. It's used like so:
//
// - To allocate new memory, [memory] is NULL and [oldSize] is zero. It should
// return the allocated memory or NULL on failure.
// - To allocate new memory, [memory] is NULL and [newSize] is the desired
// size. It should return the allocated memory or NULL on failure.
//
// - To attempt to grow an existing allocation, [memory] is the memory,
// [oldSize] is its previous size, and [newSize] is the desired size.
// It should return [memory] if it was able to grow it in place, or a new
// pointer if it had to move it.
// - To attempt to grow an existing allocation, [memory] is the memory, and
// [newSize] is the desired size. It should return [memory] if it was able to
// grow it in place, or a new pointer if it had to move it.
//
// - To shrink memory, [memory], [oldSize], and [newSize] are the same as above
// but it will always return [memory].
// - To shrink memory, [memory] and [newSize] are the same as above but it will
// always return [memory].
//
// - To free memory, [memory] will be the memory to free and [newSize] and
// [oldSize] will be zero. It should return NULL.
typedef void* (*WrenReallocateFn)(void* memory, size_t oldSize, size_t newSize);
// - To free memory, [memory] will be the memory to free and [newSize] will be
// zero. It should return NULL.
typedef void* (*WrenReallocateFn)(void* memory, size_t newSize);
// A function callable from Wren code, but implemented in C.
typedef void (*WrenForeignMethodFn)(WrenVM* vm);

View File

@ -51,6 +51,13 @@
#define WREN_USE_LIB_IO 1
#endif
// If true, loads the "Meta" class in the standard library.
//
// Defaults to on.
#ifndef WREN_USE_LIB_META
#define WREN_USE_LIB_META 1
#endif
// These flags are useful for debugging and hacking on Wren itself. They are not
// intended to be used for production code. They default to off.

22
src/vm/wren_meta.c Normal file
View File

@ -0,0 +1,22 @@
#include "wren_meta.h"
#if WREN_USE_LIB_META
// This string literal is generated automatically from meta.wren. Do not edit.
static const char* libSource =
"class Meta {}\n";
void metaEval(WrenVM* vm)
{
const char* source = wrenGetArgumentString(vm, 1);
// TODO: Type check argument.
wrenInterpret(vm, "Meta", source);
}
void wrenLoadMetaLibrary(WrenVM* vm)
{
wrenInterpret(vm, "", libSource);
wrenDefineStaticMethod(vm, "Meta", "eval(_)", metaEval);
}
#endif

14
src/vm/wren_meta.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef wren_meta_h
#define wren_meta_h
#include "wren.h"
#include "wren_common.h"
// This module defines the Meta class and its associated methods.
#if WREN_USE_LIB_META
void wrenLoadMetaLibrary(WrenVM* vm);
#endif
#endif

View File

@ -14,26 +14,23 @@
#include "wren_io.h"
#endif
#if WREN_USE_LIB_META
#include "wren_meta.h"
#endif
#if WREN_DEBUG_TRACE_MEMORY || WREN_DEBUG_TRACE_GC
#include <time.h>
#endif
// The built-in reallocation function used when one is not provided by the
// configuration.
static void* defaultReallocate(void* memory, size_t oldSize, size_t newSize)
{
return realloc(memory, newSize);
}
WrenVM* wrenNewVM(WrenConfiguration* configuration)
{
WrenReallocateFn reallocate = defaultReallocate;
WrenReallocateFn reallocate = realloc;
if (configuration->reallocateFn != NULL)
{
reallocate = configuration->reallocateFn;
}
WrenVM* vm = (WrenVM*)reallocate(NULL, 0, sizeof(*vm));
WrenVM* vm = (WrenVM*)reallocate(NULL, sizeof(*vm));
memset(vm, 0, sizeof(WrenVM));
vm->reallocate = reallocate;
@ -80,6 +77,9 @@ WrenVM* wrenNewVM(WrenConfiguration* configuration)
#if WREN_USE_LIB_IO
wrenLoadIOLibrary(vm);
#endif
#if WREN_USE_LIB_META
wrenLoadMetaLibrary(vm);
#endif
return vm;
}
@ -214,7 +214,7 @@ void* wrenReallocate(WrenVM* vm, void* memory, size_t oldSize, size_t newSize)
if (newSize > 0 && vm->bytesAllocated > vm->nextGC) collectGarbage(vm);
#endif
return vm->reallocate(memory, oldSize, newSize);
return vm->reallocate(memory, newSize);
}
// Captures the local variable [local] into an [Upvalue]. If that local is

View File

@ -0,0 +1,5 @@
var y
Meta.eval("y = 2")
IO.print(y) // expect: 2