forked from Mirror/wren
Merge branch 'master' into foreign-methods
This commit is contained in:
3
AUTHORS
3
AUTHORS
@ -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
1
builtin/meta.wren
Normal file
@ -0,0 +1 @@
|
||||
class Meta {}
|
||||
@ -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;
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
22
src/vm/wren_meta.c
Normal 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
14
src/vm/wren_meta.h
Normal 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
|
||||
@ -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
|
||||
|
||||
5
test/meta/eval_existing_scoped_variable.wren
Normal file
5
test/meta/eval_existing_scoped_variable.wren
Normal file
@ -0,0 +1,5 @@
|
||||
var y
|
||||
|
||||
Meta.eval("y = 2")
|
||||
|
||||
IO.print(y) // expect: 2
|
||||
Reference in New Issue
Block a user