mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-18 13:49:59 +01:00
Automatically update the string constants when a builtin module changes.
This commit is contained in:
5
Makefile
5
Makefile
@ -46,11 +46,6 @@ test: debug
|
|||||||
@ $(MAKE) -f script/wren.mk MODE=debug test
|
@ $(MAKE) -f script/wren.mk MODE=debug test
|
||||||
@ ./script/test.py $(suite)
|
@ ./script/test.py $(suite)
|
||||||
|
|
||||||
# Take the contents of the scripts under builtin/ and copy them into their
|
|
||||||
# respective wren_<name>.c source files.
|
|
||||||
builtin:
|
|
||||||
@ ./script/generate_builtins.py
|
|
||||||
|
|
||||||
# Generate the Wren site.
|
# Generate the Wren site.
|
||||||
docs:
|
docs:
|
||||||
@ ./script/generate_docs.py
|
@ ./script/generate_docs.py
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
The Wren scripts in this directory get converted to C string literals and then
|
The Wren scripts in this directory get converted to C string literals into files
|
||||||
inserted into their respective .c files so that the interpreter can load them
|
with a `.wren.inc` extension. Those are then `#includ`ed into their respective
|
||||||
directly without having to do any file IO.
|
`.c` files so that the interpreter can load them directly without having to do
|
||||||
|
any file IO.
|
||||||
|
|
||||||
The script that does this copying is `script/generate_builtins.py`.
|
The script that does this translation is `script/wren_to_c_string.py`.
|
||||||
|
|
||||||
You can invoke using `make builtin`.
|
When any of the ".wren" files in here are changed, the Makefile automatically
|
||||||
|
updates the generated C headers.
|
||||||
|
|||||||
@ -1,45 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# coding: utf-8
|
|
||||||
|
|
||||||
import glob
|
|
||||||
import os.path
|
|
||||||
import re
|
|
||||||
|
|
||||||
PATTERN = re.compile(r'LibSource =\n("(.|[\n])*?);')
|
|
||||||
|
|
||||||
def copy_builtin(filename, out_prefix):
|
|
||||||
name = os.path.basename(filename)
|
|
||||||
name = name.split('.')[0]
|
|
||||||
|
|
||||||
with open(filename, "r") as f:
|
|
||||||
lines = f.readlines()
|
|
||||||
|
|
||||||
wren_source = ""
|
|
||||||
for line in lines:
|
|
||||||
line = line.replace('"', "\\\"")
|
|
||||||
line = line.replace("\n", "\\n\"")
|
|
||||||
if wren_source: wren_source += "\n"
|
|
||||||
wren_source += '"' + line
|
|
||||||
|
|
||||||
# re.sub() will unescape escape sequences, but we want them to stay escapes
|
|
||||||
# in the C string literal.
|
|
||||||
wren_source = wren_source.replace('\\', '\\\\')
|
|
||||||
|
|
||||||
constant = "LibSource =\n" + wren_source + ";"
|
|
||||||
|
|
||||||
with open(out_prefix + name + ".c", "r") as f:
|
|
||||||
c_source = f.read()
|
|
||||||
|
|
||||||
c_source = PATTERN.sub(constant, c_source)
|
|
||||||
|
|
||||||
with open(out_prefix + name + ".c", "w") as f:
|
|
||||||
f.write(c_source)
|
|
||||||
|
|
||||||
print(filename.ljust(25) + " → " + out_prefix + name + ".c")
|
|
||||||
|
|
||||||
|
|
||||||
for f in glob.iglob("builtin/*.wren"):
|
|
||||||
copy_builtin(f, "src/vm/wren_")
|
|
||||||
|
|
||||||
for f in glob.iglob("src/module/*.wren"):
|
|
||||||
copy_builtin(f, "src/module/")
|
|
||||||
@ -22,10 +22,10 @@
|
|||||||
CLI_HEADERS := $(wildcard src/cli/*.h)
|
CLI_HEADERS := $(wildcard src/cli/*.h)
|
||||||
CLI_SOURCES := $(wildcard src/cli/*.c)
|
CLI_SOURCES := $(wildcard src/cli/*.c)
|
||||||
|
|
||||||
MODULE_HEADERS := $(wildcard src/module/*.h)
|
MODULE_HEADERS := $(wildcard src/module/*.h) $(wildcard src/module/*.wren.inc)
|
||||||
MODULE_SOURCES := $(wildcard src/module/*.c)
|
MODULE_SOURCES := $(wildcard src/module/*.c)
|
||||||
|
|
||||||
VM_HEADERS := $(wildcard src/vm/*.h)
|
VM_HEADERS := $(wildcard src/vm/*.h) $(wildcard src/vm/*.wren.inc)
|
||||||
VM_SOURCES := $(wildcard src/vm/*.c)
|
VM_SOURCES := $(wildcard src/vm/*.c)
|
||||||
|
|
||||||
TEST_HEADERS := $(wildcard test/api/*.h)
|
TEST_HEADERS := $(wildcard test/api/*.h)
|
||||||
@ -192,4 +192,11 @@ $(LIBUV_DIR)/build/gyp/gyp: script/libuv.py
|
|||||||
$(LIBUV): $(LIBUV_DIR)/build/gyp/gyp script/libuv.py
|
$(LIBUV): $(LIBUV_DIR)/build/gyp/gyp script/libuv.py
|
||||||
@ ./script/libuv.py build $(LIBUV_ARCH)
|
@ ./script/libuv.py build $(LIBUV_ARCH)
|
||||||
|
|
||||||
|
# Wren modules that get compiled into the binary as C strings.
|
||||||
|
src/vm/wren_%.wren.inc: builtin/%.wren script/wren_to_c_string.py
|
||||||
|
@ ./script/wren_to_c_string.py $@ $<
|
||||||
|
|
||||||
|
src/module/%.wren.inc: src/module/%.wren script/wren_to_c_string.py
|
||||||
|
@ ./script/wren_to_c_string.py $@ $<
|
||||||
|
|
||||||
.PHONY: all cli test vm
|
.PHONY: all cli test vm
|
||||||
|
|||||||
53
script/wren_to_c_string.py
Executable file
53
script/wren_to_c_string.py
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import glob
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
|
||||||
|
# The source for the Wren modules that are built into the VM or CLI are turned
|
||||||
|
# include C string literals. This way they can be compiled directly into the
|
||||||
|
# code so that file IO is not needed to find and read them.
|
||||||
|
#
|
||||||
|
# These string literals are stored in files with a ".wren.inc" extension and
|
||||||
|
# #included directly by other source files. This generates a ".wren.inc" file
|
||||||
|
# given a ".wren" module.
|
||||||
|
|
||||||
|
PREAMBLE = """// Generated automatically from {0}. Do not edit.
|
||||||
|
static const char* {1}ModuleSource =
|
||||||
|
{2};
|
||||||
|
"""
|
||||||
|
|
||||||
|
def wren_to_c_string(input_path, wren_source_lines, module):
|
||||||
|
wren_source = ""
|
||||||
|
for line in wren_source_lines:
|
||||||
|
line = line.replace('"', "\\\"")
|
||||||
|
line = line.replace("\n", "\\n\"")
|
||||||
|
if wren_source: wren_source += "\n"
|
||||||
|
wren_source += '"' + line
|
||||||
|
|
||||||
|
return PREAMBLE.format(input_path, module, wren_source)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Convert a Wren library to a C string literal.")
|
||||||
|
parser.add_argument("output", help="The output file to write")
|
||||||
|
parser.add_argument("input", help="The source .wren file")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
with open(args.input, "r") as f:
|
||||||
|
wren_source_lines = f.readlines()
|
||||||
|
|
||||||
|
module = os.path.splitext(os.path.basename(args.input))[0]
|
||||||
|
c_source = wren_to_c_string(args.input, wren_source_lines, module)
|
||||||
|
|
||||||
|
with open(args.output, "w") as f:
|
||||||
|
f.write(c_source)
|
||||||
|
|
||||||
|
print(" str " + args.input)
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
||||||
@ -7,43 +7,7 @@
|
|||||||
#include "wren.h"
|
#include "wren.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
|
||||||
// This is generated from builtin/module/timer.wren. Do not edit here.
|
#include "timer.wren.inc"
|
||||||
static const char* timerLibSource =
|
|
||||||
"class Timer {\n"
|
|
||||||
" static sleep(milliseconds) {\n"
|
|
||||||
" if (!(milliseconds is Num)) Fiber.abort(\"Milliseconds must be a number.\")\n"
|
|
||||||
" if (milliseconds < 0) Fiber.abort(\"Milliseconds cannot be negative.\")\n"
|
|
||||||
" startTimer_(milliseconds, Fiber.current)\n"
|
|
||||||
"\n"
|
|
||||||
" runNextScheduled_()\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" // TODO: Once the CLI modules are more fleshed out, find a better place to\n"
|
|
||||||
" // put this.\n"
|
|
||||||
" static schedule(callable) {\n"
|
|
||||||
" if (__scheduled == null) __scheduled = []\n"
|
|
||||||
" __scheduled.add(Fiber.new {\n"
|
|
||||||
" callable.call()\n"
|
|
||||||
" runNextScheduled_()\n"
|
|
||||||
" })\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" foreign static startTimer_(milliseconds, fiber)\n"
|
|
||||||
"\n"
|
|
||||||
" // Called by native code.\n"
|
|
||||||
" static resumeTimer_(fiber) {\n"
|
|
||||||
" fiber.transfer()\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static runNextScheduled_() {\n"
|
|
||||||
" if (__scheduled == null || __scheduled.isEmpty) {\n"
|
|
||||||
" Fiber.suspend()\n"
|
|
||||||
" } else {\n"
|
|
||||||
" __scheduled.removeAt(0).transfer()\n"
|
|
||||||
" }\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n"
|
|
||||||
"\n";
|
|
||||||
|
|
||||||
// The Wren method to call when a timer has completed.
|
// The Wren method to call when a timer has completed.
|
||||||
static WrenValue* resumeTimer;
|
static WrenValue* resumeTimer;
|
||||||
@ -58,7 +22,7 @@ static void timerCloseCallback(uv_handle_t* handle)
|
|||||||
static void timerCallback(uv_timer_t* handle)
|
static void timerCallback(uv_timer_t* handle)
|
||||||
{
|
{
|
||||||
WrenValue* fiber = (WrenValue*)handle->data;
|
WrenValue* fiber = (WrenValue*)handle->data;
|
||||||
|
|
||||||
// Tell libuv that we don't need the timer anymore.
|
// Tell libuv that we don't need the timer anymore.
|
||||||
uv_close((uv_handle_t*)handle, timerCloseCallback);
|
uv_close((uv_handle_t*)handle, timerCloseCallback);
|
||||||
|
|
||||||
@ -74,24 +38,24 @@ static void startTimer(WrenVM* vm)
|
|||||||
{
|
{
|
||||||
resumeTimer = wrenGetMethod(vm, "timer", "Timer", "resumeTimer_(_)");
|
resumeTimer = wrenGetMethod(vm, "timer", "Timer", "resumeTimer_(_)");
|
||||||
}
|
}
|
||||||
|
|
||||||
int milliseconds = (int)wrenGetArgumentDouble(vm, 1);
|
int milliseconds = (int)wrenGetArgumentDouble(vm, 1);
|
||||||
WrenValue* fiber = wrenGetArgumentValue(vm, 2);
|
WrenValue* fiber = wrenGetArgumentValue(vm, 2);
|
||||||
|
|
||||||
// Store the fiber to resume when the timer completes.
|
// Store the fiber to resume when the timer completes.
|
||||||
uv_timer_t* handle = (uv_timer_t*)malloc(sizeof(uv_timer_t));
|
uv_timer_t* handle = (uv_timer_t*)malloc(sizeof(uv_timer_t));
|
||||||
handle->data = fiber;
|
handle->data = fiber;
|
||||||
|
|
||||||
uv_timer_init(getLoop(), handle);
|
uv_timer_init(getLoop(), handle);
|
||||||
uv_timer_start(handle, timerCallback, milliseconds, 0);
|
uv_timer_start(handle, timerCallback, milliseconds, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* timerGetSource()
|
char* timerGetSource()
|
||||||
{
|
{
|
||||||
size_t length = strlen(timerLibSource);
|
size_t length = strlen(timerModuleSource);
|
||||||
char* copy = (char*)malloc(length + 1);
|
char* copy = (char*)malloc(length + 1);
|
||||||
strncpy(copy, timerLibSource, length + 1);
|
strncpy(copy, timerModuleSource, length + 1);
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +65,7 @@ WrenForeignMethodFn timerBindForeign(
|
|||||||
if (strcmp(className, "Timer") != 0) return NULL;
|
if (strcmp(className, "Timer") != 0) return NULL;
|
||||||
|
|
||||||
if (isStatic && strcmp(signature, "startTimer_(_,_)") == 0) return startTimer;
|
if (isStatic && strcmp(signature, "startTimer_(_,_)") == 0) return startTimer;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,4 +32,3 @@ class Timer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
36
src/module/timer.wren.inc
Normal file
36
src/module/timer.wren.inc
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Generated automatically from src/module/timer.wren. Do not edit.
|
||||||
|
static const char* timerModuleSource =
|
||||||
|
"class Timer {\n"
|
||||||
|
" static sleep(milliseconds) {\n"
|
||||||
|
" if (!(milliseconds is Num)) Fiber.abort(\"Milliseconds must be a number.\")\n"
|
||||||
|
" if (milliseconds < 0) Fiber.abort(\"Milliseconds cannot be negative.\")\n"
|
||||||
|
" startTimer_(milliseconds, Fiber.current)\n"
|
||||||
|
"\n"
|
||||||
|
" runNextScheduled_()\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" // TODO: Once the CLI modules are more fleshed out, find a better place to\n"
|
||||||
|
" // put this.\n"
|
||||||
|
" static schedule(callable) {\n"
|
||||||
|
" if (__scheduled == null) __scheduled = []\n"
|
||||||
|
" __scheduled.add(Fiber.new {\n"
|
||||||
|
" callable.call()\n"
|
||||||
|
" runNextScheduled_()\n"
|
||||||
|
" })\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" foreign static startTimer_(milliseconds, fiber)\n"
|
||||||
|
"\n"
|
||||||
|
" // Called by native code.\n"
|
||||||
|
" static resumeTimer_(fiber) {\n"
|
||||||
|
" fiber.transfer()\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static runNextScheduled_() {\n"
|
||||||
|
" if (__scheduled == null || __scheduled.isEmpty) {\n"
|
||||||
|
" Fiber.suspend()\n"
|
||||||
|
" } else {\n"
|
||||||
|
" __scheduled.removeAt(0).transfer()\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
@ -10,223 +10,7 @@
|
|||||||
#include "wren_primitive.h"
|
#include "wren_primitive.h"
|
||||||
#include "wren_value.h"
|
#include "wren_value.h"
|
||||||
|
|
||||||
// This string literal is generated automatically from core. Do not edit.
|
#include "wren_core.wren.inc"
|
||||||
static const char* coreLibSource =
|
|
||||||
"class Bool {}\n"
|
|
||||||
"class Fiber {}\n"
|
|
||||||
"class Fn {}\n"
|
|
||||||
"class Null {}\n"
|
|
||||||
"class Num {}\n"
|
|
||||||
"\n"
|
|
||||||
"class Sequence {\n"
|
|
||||||
" all(f) {\n"
|
|
||||||
" var result = true\n"
|
|
||||||
" for (element in this) {\n"
|
|
||||||
" result = f.call(element)\n"
|
|
||||||
" if (!result) return result\n"
|
|
||||||
" }\n"
|
|
||||||
" return result\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" any(f) {\n"
|
|
||||||
" var result = false\n"
|
|
||||||
" for (element in this) {\n"
|
|
||||||
" result = f.call(element)\n"
|
|
||||||
" if (result) return result\n"
|
|
||||||
" }\n"
|
|
||||||
" return result\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" contains(element) {\n"
|
|
||||||
" for (item in this) {\n"
|
|
||||||
" if (element == item) return true\n"
|
|
||||||
" }\n"
|
|
||||||
" return false\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" count {\n"
|
|
||||||
" var result = 0\n"
|
|
||||||
" for (element in this) {\n"
|
|
||||||
" result = result + 1\n"
|
|
||||||
" }\n"
|
|
||||||
" return result\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" count(f) {\n"
|
|
||||||
" var result = 0\n"
|
|
||||||
" for (element in this) {\n"
|
|
||||||
" if (f.call(element)) result = result + 1\n"
|
|
||||||
" }\n"
|
|
||||||
" return result\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" each(f) {\n"
|
|
||||||
" for (element in this) {\n"
|
|
||||||
" f.call(element)\n"
|
|
||||||
" }\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" isEmpty { iterate(null) ? false : true }\n"
|
|
||||||
"\n"
|
|
||||||
" map(transformation) { MapSequence.new(this, transformation) }\n"
|
|
||||||
"\n"
|
|
||||||
" where(predicate) { WhereSequence.new(this, predicate) }\n"
|
|
||||||
"\n"
|
|
||||||
" reduce(acc, f) {\n"
|
|
||||||
" for (element in this) {\n"
|
|
||||||
" acc = f.call(acc, element)\n"
|
|
||||||
" }\n"
|
|
||||||
" return acc\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" reduce(f) {\n"
|
|
||||||
" var iter = iterate(null)\n"
|
|
||||||
" if (!iter) Fiber.abort(\"Can't reduce an empty sequence.\")\n"
|
|
||||||
"\n"
|
|
||||||
" // Seed with the first element.\n"
|
|
||||||
" var result = iteratorValue(iter)\n"
|
|
||||||
" while (iter = iterate(iter)) {\n"
|
|
||||||
" result = f.call(result, iteratorValue(iter))\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" return result\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" join { join(\"\") }\n"
|
|
||||||
"\n"
|
|
||||||
" join(sep) {\n"
|
|
||||||
" var first = true\n"
|
|
||||||
" var result = \"\"\n"
|
|
||||||
"\n"
|
|
||||||
" for (element in this) {\n"
|
|
||||||
" if (!first) result = result + sep\n"
|
|
||||||
" first = false\n"
|
|
||||||
" result = result + element.toString\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" return result\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" toList {\n"
|
|
||||||
" var result = List.new()\n"
|
|
||||||
" for (element in this) {\n"
|
|
||||||
" result.add(element)\n"
|
|
||||||
" }\n"
|
|
||||||
" return result\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"class MapSequence is Sequence {\n"
|
|
||||||
" construct new(sequence, fn) {\n"
|
|
||||||
" _sequence = sequence\n"
|
|
||||||
" _fn = fn\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" iterate(iterator) { _sequence.iterate(iterator) }\n"
|
|
||||||
" iteratorValue(iterator) { _fn.call(_sequence.iteratorValue(iterator)) }\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"class WhereSequence is Sequence {\n"
|
|
||||||
" construct new(sequence, fn) {\n"
|
|
||||||
" _sequence = sequence\n"
|
|
||||||
" _fn = fn\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" iterate(iterator) {\n"
|
|
||||||
" while (iterator = _sequence.iterate(iterator)) {\n"
|
|
||||||
" if (_fn.call(_sequence.iteratorValue(iterator))) break\n"
|
|
||||||
" }\n"
|
|
||||||
" return iterator\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" iteratorValue(iterator) { _sequence.iteratorValue(iterator) }\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"class String is Sequence {\n"
|
|
||||||
" bytes { StringByteSequence.new(this) }\n"
|
|
||||||
" codePoints { StringCodePointSequence.new(this) }\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"class StringByteSequence is Sequence {\n"
|
|
||||||
" construct new(string) {\n"
|
|
||||||
" _string = string\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" [index] { _string.byteAt_(index) }\n"
|
|
||||||
" iterate(iterator) { _string.iterateByte_(iterator) }\n"
|
|
||||||
" iteratorValue(iterator) { _string.byteAt_(iterator) }\n"
|
|
||||||
"\n"
|
|
||||||
" count { _string.byteCount_ }\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"class StringCodePointSequence is Sequence {\n"
|
|
||||||
" construct new(string) {\n"
|
|
||||||
" _string = string\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" [index] { _string.codePointAt_(index) }\n"
|
|
||||||
" iterate(iterator) { _string.iterate(iterator) }\n"
|
|
||||||
" iteratorValue(iterator) { _string.codePointAt_(iterator) }\n"
|
|
||||||
"\n"
|
|
||||||
" count { _string.count }\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"class List is Sequence {\n"
|
|
||||||
" addAll(other) {\n"
|
|
||||||
" for (element in other) {\n"
|
|
||||||
" add(element)\n"
|
|
||||||
" }\n"
|
|
||||||
" return other\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" toString { \"[\" + join(\", \") + \"]\" }\n"
|
|
||||||
"\n"
|
|
||||||
" +(other) {\n"
|
|
||||||
" var result = this[0..-1]\n"
|
|
||||||
" for (element in other) {\n"
|
|
||||||
" result.add(element)\n"
|
|
||||||
" }\n"
|
|
||||||
" return result\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"class Map {\n"
|
|
||||||
" keys { MapKeySequence.new(this) }\n"
|
|
||||||
" values { MapValueSequence.new(this) }\n"
|
|
||||||
"\n"
|
|
||||||
" toString {\n"
|
|
||||||
" var first = true\n"
|
|
||||||
" var result = \"{\"\n"
|
|
||||||
"\n"
|
|
||||||
" for (key in keys) {\n"
|
|
||||||
" if (!first) result = result + \", \"\n"
|
|
||||||
" first = false\n"
|
|
||||||
" result = result + key.toString + \": \" + this[key].toString\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" return result + \"}\"\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"class MapKeySequence is Sequence {\n"
|
|
||||||
" construct new(map) {\n"
|
|
||||||
" _map = map\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" iterate(n) { _map.iterate_(n) }\n"
|
|
||||||
" iteratorValue(iterator) { _map.keyIteratorValue_(iterator) }\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"class MapValueSequence is Sequence {\n"
|
|
||||||
" construct new(map) {\n"
|
|
||||||
" _map = map\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" iterate(n) { _map.iterate_(n) }\n"
|
|
||||||
" iteratorValue(iterator) { _map.valueIteratorValue_(iterator) }\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"class Range is Sequence {}\n";
|
|
||||||
|
|
||||||
DEF_PRIMITIVE(bool_not)
|
DEF_PRIMITIVE(bool_not)
|
||||||
{
|
{
|
||||||
@ -304,7 +88,7 @@ static PrimitiveResult runFiber(WrenVM* vm, ObjFiber* fiber, Value* args,
|
|||||||
if (isCall)
|
if (isCall)
|
||||||
{
|
{
|
||||||
if (fiber->caller != NULL) RETURN_ERROR("Fiber has already been called.");
|
if (fiber->caller != NULL) RETURN_ERROR("Fiber has already been called.");
|
||||||
|
|
||||||
// Remember who ran it.
|
// Remember who ran it.
|
||||||
fiber->caller = vm->fiber;
|
fiber->caller = vm->fiber;
|
||||||
}
|
}
|
||||||
@ -315,21 +99,21 @@ static PrimitiveResult runFiber(WrenVM* vm, ObjFiber* fiber, Value* args,
|
|||||||
// return below, it would overwrite the fiber being transferred to.
|
// return below, it would overwrite the fiber being transferred to.
|
||||||
if (fiber == vm->fiber) RETURN_VAL(hasValue ? args[1] : NULL_VAL);
|
if (fiber == vm->fiber) RETURN_VAL(hasValue ? args[1] : NULL_VAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fiber->numFrames == 0)
|
if (fiber->numFrames == 0)
|
||||||
{
|
{
|
||||||
args[0] = wrenStringFormat(vm, "Cannot $ a finished fiber.",
|
args[0] = wrenStringFormat(vm, "Cannot $ a finished fiber.",
|
||||||
isCall ? "call" : "transfer to");
|
isCall ? "call" : "transfer to");
|
||||||
return PRIM_ERROR;
|
return PRIM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fiber->error != NULL)
|
if (fiber->error != NULL)
|
||||||
{
|
{
|
||||||
args[0] = wrenStringFormat(vm, "Cannot $ an aborted fiber.",
|
args[0] = wrenStringFormat(vm, "Cannot $ an aborted fiber.",
|
||||||
isCall ? "call" : "transfer to");
|
isCall ? "call" : "transfer to");
|
||||||
return PRIM_ERROR;
|
return PRIM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the calling fiber resumes, we'll store the result of the call in its
|
// When the calling fiber resumes, we'll store the result of the call in its
|
||||||
// stack. If the call has two arguments (the fiber and the value), we only
|
// stack. If the call has two arguments (the fiber and the value), we only
|
||||||
// need one slot for the result, so discard the other slot now.
|
// need one slot for the result, so discard the other slot now.
|
||||||
@ -340,7 +124,7 @@ static PrimitiveResult runFiber(WrenVM* vm, ObjFiber* fiber, Value* args,
|
|||||||
{
|
{
|
||||||
*(fiber->stackTop - 1) = hasValue ? args[1] : NULL_VAL;
|
*(fiber->stackTop - 1) = hasValue ? args[1] : NULL_VAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PRIM_RUN_FIBER;
|
return PRIM_RUN_FIBER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,7 +200,7 @@ DEF_PRIMITIVE(fiber_yield)
|
|||||||
ObjFiber* caller = fiber->caller;
|
ObjFiber* caller = fiber->caller;
|
||||||
fiber->caller = NULL;
|
fiber->caller = NULL;
|
||||||
fiber->callerIsTrying = false;
|
fiber->callerIsTrying = false;
|
||||||
|
|
||||||
// If we don't have any other pending fibers, jump all the way out of the
|
// If we don't have any other pending fibers, jump all the way out of the
|
||||||
// interpreter.
|
// interpreter.
|
||||||
if (caller == NULL)
|
if (caller == NULL)
|
||||||
@ -1274,7 +1058,7 @@ static ObjClass* defineClass(WrenVM* vm, ObjModule* module, const char* name)
|
|||||||
void wrenInitializeCore(WrenVM* vm)
|
void wrenInitializeCore(WrenVM* vm)
|
||||||
{
|
{
|
||||||
ObjModule* coreModule = wrenGetCoreModule(vm);
|
ObjModule* coreModule = wrenGetCoreModule(vm);
|
||||||
|
|
||||||
// Define the root Object class. This has to be done a little specially
|
// Define the root Object class. This has to be done a little specially
|
||||||
// because it has no superclass.
|
// because it has no superclass.
|
||||||
vm->objectClass = defineClass(vm, coreModule, "Object");
|
vm->objectClass = defineClass(vm, coreModule, "Object");
|
||||||
@ -1329,7 +1113,7 @@ void wrenInitializeCore(WrenVM* vm)
|
|||||||
// '---------' '-------------------' -'
|
// '---------' '-------------------' -'
|
||||||
|
|
||||||
// The rest of the classes can now be defined normally.
|
// The rest of the classes can now be defined normally.
|
||||||
wrenInterpret(vm, "", coreLibSource);
|
wrenInterpret(vm, "", coreModuleSource);
|
||||||
|
|
||||||
vm->boolClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Bool"));
|
vm->boolClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Bool"));
|
||||||
PRIMITIVE(vm->boolClass, "toString", bool_toString);
|
PRIMITIVE(vm->boolClass, "toString", bool_toString);
|
||||||
|
|||||||
217
src/vm/wren_core.wren.inc
Normal file
217
src/vm/wren_core.wren.inc
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
// Generated automatically from builtin/core.wren. Do not edit.
|
||||||
|
static const char* coreModuleSource =
|
||||||
|
"class Bool {}\n"
|
||||||
|
"class Fiber {}\n"
|
||||||
|
"class Fn {}\n"
|
||||||
|
"class Null {}\n"
|
||||||
|
"class Num {}\n"
|
||||||
|
"\n"
|
||||||
|
"class Sequence {\n"
|
||||||
|
" all(f) {\n"
|
||||||
|
" var result = true\n"
|
||||||
|
" for (element in this) {\n"
|
||||||
|
" result = f.call(element)\n"
|
||||||
|
" if (!result) return result\n"
|
||||||
|
" }\n"
|
||||||
|
" return result\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" any(f) {\n"
|
||||||
|
" var result = false\n"
|
||||||
|
" for (element in this) {\n"
|
||||||
|
" result = f.call(element)\n"
|
||||||
|
" if (result) return result\n"
|
||||||
|
" }\n"
|
||||||
|
" return result\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" contains(element) {\n"
|
||||||
|
" for (item in this) {\n"
|
||||||
|
" if (element == item) return true\n"
|
||||||
|
" }\n"
|
||||||
|
" return false\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" count {\n"
|
||||||
|
" var result = 0\n"
|
||||||
|
" for (element in this) {\n"
|
||||||
|
" result = result + 1\n"
|
||||||
|
" }\n"
|
||||||
|
" return result\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" count(f) {\n"
|
||||||
|
" var result = 0\n"
|
||||||
|
" for (element in this) {\n"
|
||||||
|
" if (f.call(element)) result = result + 1\n"
|
||||||
|
" }\n"
|
||||||
|
" return result\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" each(f) {\n"
|
||||||
|
" for (element in this) {\n"
|
||||||
|
" f.call(element)\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" isEmpty { iterate(null) ? false : true }\n"
|
||||||
|
"\n"
|
||||||
|
" map(transformation) { MapSequence.new(this, transformation) }\n"
|
||||||
|
"\n"
|
||||||
|
" where(predicate) { WhereSequence.new(this, predicate) }\n"
|
||||||
|
"\n"
|
||||||
|
" reduce(acc, f) {\n"
|
||||||
|
" for (element in this) {\n"
|
||||||
|
" acc = f.call(acc, element)\n"
|
||||||
|
" }\n"
|
||||||
|
" return acc\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" reduce(f) {\n"
|
||||||
|
" var iter = iterate(null)\n"
|
||||||
|
" if (!iter) Fiber.abort(\"Can't reduce an empty sequence.\")\n"
|
||||||
|
"\n"
|
||||||
|
" // Seed with the first element.\n"
|
||||||
|
" var result = iteratorValue(iter)\n"
|
||||||
|
" while (iter = iterate(iter)) {\n"
|
||||||
|
" result = f.call(result, iteratorValue(iter))\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" return result\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" join { join(\"\") }\n"
|
||||||
|
"\n"
|
||||||
|
" join(sep) {\n"
|
||||||
|
" var first = true\n"
|
||||||
|
" var result = \"\"\n"
|
||||||
|
"\n"
|
||||||
|
" for (element in this) {\n"
|
||||||
|
" if (!first) result = result + sep\n"
|
||||||
|
" first = false\n"
|
||||||
|
" result = result + element.toString\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" return result\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" toList {\n"
|
||||||
|
" var result = List.new()\n"
|
||||||
|
" for (element in this) {\n"
|
||||||
|
" result.add(element)\n"
|
||||||
|
" }\n"
|
||||||
|
" return result\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"class MapSequence is Sequence {\n"
|
||||||
|
" construct new(sequence, fn) {\n"
|
||||||
|
" _sequence = sequence\n"
|
||||||
|
" _fn = fn\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" iterate(iterator) { _sequence.iterate(iterator) }\n"
|
||||||
|
" iteratorValue(iterator) { _fn.call(_sequence.iteratorValue(iterator)) }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"class WhereSequence is Sequence {\n"
|
||||||
|
" construct new(sequence, fn) {\n"
|
||||||
|
" _sequence = sequence\n"
|
||||||
|
" _fn = fn\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" iterate(iterator) {\n"
|
||||||
|
" while (iterator = _sequence.iterate(iterator)) {\n"
|
||||||
|
" if (_fn.call(_sequence.iteratorValue(iterator))) break\n"
|
||||||
|
" }\n"
|
||||||
|
" return iterator\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" iteratorValue(iterator) { _sequence.iteratorValue(iterator) }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"class String is Sequence {\n"
|
||||||
|
" bytes { StringByteSequence.new(this) }\n"
|
||||||
|
" codePoints { StringCodePointSequence.new(this) }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"class StringByteSequence is Sequence {\n"
|
||||||
|
" construct new(string) {\n"
|
||||||
|
" _string = string\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" [index] { _string.byteAt_(index) }\n"
|
||||||
|
" iterate(iterator) { _string.iterateByte_(iterator) }\n"
|
||||||
|
" iteratorValue(iterator) { _string.byteAt_(iterator) }\n"
|
||||||
|
"\n"
|
||||||
|
" count { _string.byteCount_ }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"class StringCodePointSequence is Sequence {\n"
|
||||||
|
" construct new(string) {\n"
|
||||||
|
" _string = string\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" [index] { _string.codePointAt_(index) }\n"
|
||||||
|
" iterate(iterator) { _string.iterate(iterator) }\n"
|
||||||
|
" iteratorValue(iterator) { _string.codePointAt_(iterator) }\n"
|
||||||
|
"\n"
|
||||||
|
" count { _string.count }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"class List is Sequence {\n"
|
||||||
|
" addAll(other) {\n"
|
||||||
|
" for (element in other) {\n"
|
||||||
|
" add(element)\n"
|
||||||
|
" }\n"
|
||||||
|
" return other\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" toString { \"[\" + join(\", \") + \"]\" }\n"
|
||||||
|
"\n"
|
||||||
|
" +(other) {\n"
|
||||||
|
" var result = this[0..-1]\n"
|
||||||
|
" for (element in other) {\n"
|
||||||
|
" result.add(element)\n"
|
||||||
|
" }\n"
|
||||||
|
" return result\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"class Map {\n"
|
||||||
|
" keys { MapKeySequence.new(this) }\n"
|
||||||
|
" values { MapValueSequence.new(this) }\n"
|
||||||
|
"\n"
|
||||||
|
" toString {\n"
|
||||||
|
" var first = true\n"
|
||||||
|
" var result = \"{\"\n"
|
||||||
|
"\n"
|
||||||
|
" for (key in keys) {\n"
|
||||||
|
" if (!first) result = result + \", \"\n"
|
||||||
|
" first = false\n"
|
||||||
|
" result = result + key.toString + \": \" + this[key].toString\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" return result + \"}\"\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"class MapKeySequence is Sequence {\n"
|
||||||
|
" construct new(map) {\n"
|
||||||
|
" _map = map\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" iterate(n) { _map.iterate_(n) }\n"
|
||||||
|
" iteratorValue(iterator) { _map.keyIteratorValue_(iterator) }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"class MapValueSequence is Sequence {\n"
|
||||||
|
" construct new(map) {\n"
|
||||||
|
" _map = map\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" iterate(n) { _map.iterate_(n) }\n"
|
||||||
|
" iteratorValue(iterator) { _map.valueIteratorValue_(iterator) }\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"class Range is Sequence {}\n";
|
||||||
108
src/vm/wren_io.c
108
src/vm/wren_io.c
@ -9,109 +9,7 @@
|
|||||||
// TODO: This is an arbitrary limit. Do something smarter.
|
// TODO: This is an arbitrary limit. Do something smarter.
|
||||||
#define MAX_READ_LEN 1024
|
#define MAX_READ_LEN 1024
|
||||||
|
|
||||||
// This string literal is generated automatically from io.wren. Do not edit.
|
#include "wren_io.wren.inc"
|
||||||
static const char* ioLibSource =
|
|
||||||
"class IO {\n"
|
|
||||||
" static print {\n"
|
|
||||||
" writeString_(\"\n\")\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(obj) {\n"
|
|
||||||
" writeObject_(obj)\n"
|
|
||||||
" writeString_(\"\n\")\n"
|
|
||||||
" return obj\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2) {\n"
|
|
||||||
" printAll([a1, a2])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3) {\n"
|
|
||||||
" printAll([a1, a2, a3])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4, a5) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4, a5])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4, a5, a6) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4, a5, a6])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4, a5, a6, a7) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4, a5, a6, a7])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) {\n"
|
|
||||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16])\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static printAll(sequence) {\n"
|
|
||||||
" for (object in sequence) writeObject_(object)\n"
|
|
||||||
" writeString_(\"\n\")\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static write(obj) {\n"
|
|
||||||
" writeObject_(obj)\n"
|
|
||||||
" return obj\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static read(prompt) {\n"
|
|
||||||
" if (!(prompt is String)) Fiber.abort(\"Prompt must be a string.\")\n"
|
|
||||||
" write(prompt)\n"
|
|
||||||
" return read()\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" static writeObject_(obj) {\n"
|
|
||||||
" var string = obj.toString\n"
|
|
||||||
" if (string is String) {\n"
|
|
||||||
" writeString_(string)\n"
|
|
||||||
" } else {\n"
|
|
||||||
" writeString_(\"[invalid toString]\")\n"
|
|
||||||
" }\n"
|
|
||||||
" }\n"
|
|
||||||
"\n"
|
|
||||||
" foreign static writeString_(string)\n"
|
|
||||||
" foreign static clock\n"
|
|
||||||
" foreign static time\n"
|
|
||||||
" foreign static read()\n"
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
static void ioWriteString(WrenVM* vm)
|
static void ioWriteString(WrenVM* vm)
|
||||||
{
|
{
|
||||||
@ -143,14 +41,14 @@ static void ioTime(WrenVM* vm)
|
|||||||
|
|
||||||
void wrenLoadIOLibrary(WrenVM* vm)
|
void wrenLoadIOLibrary(WrenVM* vm)
|
||||||
{
|
{
|
||||||
wrenInterpret(vm, "", ioLibSource);
|
wrenInterpret(vm, "", ioModuleSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
WrenForeignMethodFn wrenBindIOForeignMethod(WrenVM* vm, const char* className,
|
WrenForeignMethodFn wrenBindIOForeignMethod(WrenVM* vm, const char* className,
|
||||||
const char* signature)
|
const char* signature)
|
||||||
{
|
{
|
||||||
if (strcmp(className, "IO") != 0) return NULL;
|
if (strcmp(className, "IO") != 0) return NULL;
|
||||||
|
|
||||||
if (strcmp(signature, "writeString_(_)") == 0) return ioWriteString;
|
if (strcmp(signature, "writeString_(_)") == 0) return ioWriteString;
|
||||||
if (strcmp(signature, "clock") == 0) return ioClock;
|
if (strcmp(signature, "clock") == 0) return ioClock;
|
||||||
if (strcmp(signature, "time") == 0) return ioTime;
|
if (strcmp(signature, "time") == 0) return ioTime;
|
||||||
|
|||||||
103
src/vm/wren_io.wren.inc
Normal file
103
src/vm/wren_io.wren.inc
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// Generated automatically from builtin/io.wren. Do not edit.
|
||||||
|
static const char* ioModuleSource =
|
||||||
|
"class IO {\n"
|
||||||
|
" static print {\n"
|
||||||
|
" writeString_(\"\n\")\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(obj) {\n"
|
||||||
|
" writeObject_(obj)\n"
|
||||||
|
" writeString_(\"\n\")\n"
|
||||||
|
" return obj\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2) {\n"
|
||||||
|
" printAll([a1, a2])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3) {\n"
|
||||||
|
" printAll([a1, a2, a3])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4, a5) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4, a5])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4, a5, a6) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4, a5, a6])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4, a5, a6, a7) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4, a5, a6, a7])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4, a5, a6, a7, a8) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4, a5, a6, a7, a8])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) {\n"
|
||||||
|
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16])\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static printAll(sequence) {\n"
|
||||||
|
" for (object in sequence) writeObject_(object)\n"
|
||||||
|
" writeString_(\"\n\")\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static write(obj) {\n"
|
||||||
|
" writeObject_(obj)\n"
|
||||||
|
" return obj\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static read(prompt) {\n"
|
||||||
|
" if (!(prompt is String)) Fiber.abort(\"Prompt must be a string.\")\n"
|
||||||
|
" write(prompt)\n"
|
||||||
|
" return read()\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" static writeObject_(obj) {\n"
|
||||||
|
" var string = obj.toString\n"
|
||||||
|
" if (string is String) {\n"
|
||||||
|
" writeString_(string)\n"
|
||||||
|
" } else {\n"
|
||||||
|
" writeString_(\"[invalid toString]\")\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
"\n"
|
||||||
|
" foreign static writeString_(string)\n"
|
||||||
|
" foreign static clock\n"
|
||||||
|
" foreign static time\n"
|
||||||
|
" foreign static read()\n"
|
||||||
|
"}\n";
|
||||||
@ -6,9 +6,7 @@
|
|||||||
|
|
||||||
#include "wren_primitive.h"
|
#include "wren_primitive.h"
|
||||||
|
|
||||||
// This string literal is generated automatically from meta.wren. Do not edit.
|
#include "wren_meta.wren.inc"
|
||||||
static const char* metaLibSource =
|
|
||||||
"class Meta {}\n";
|
|
||||||
|
|
||||||
DEF_PRIMITIVE(meta_eval)
|
DEF_PRIMITIVE(meta_eval)
|
||||||
{
|
{
|
||||||
@ -43,10 +41,10 @@ DEF_PRIMITIVE(meta_eval)
|
|||||||
|
|
||||||
void wrenLoadMetaLibrary(WrenVM* vm)
|
void wrenLoadMetaLibrary(WrenVM* vm)
|
||||||
{
|
{
|
||||||
wrenInterpret(vm, "", metaLibSource);
|
wrenInterpret(vm, "", metaModuleSource);
|
||||||
|
|
||||||
ObjModule* coreModule = wrenGetCoreModule(vm);
|
ObjModule* coreModule = wrenGetCoreModule(vm);
|
||||||
|
|
||||||
// The methods on "Meta" are static, so get the metaclass for the Meta class.
|
// The methods on "Meta" are static, so get the metaclass for the Meta class.
|
||||||
ObjClass* meta = AS_CLASS(wrenFindVariable(vm, coreModule, "Meta"));
|
ObjClass* meta = AS_CLASS(wrenFindVariable(vm, coreModule, "Meta"));
|
||||||
PRIMITIVE(meta->obj.classObj, "eval(_)", meta_eval);
|
PRIMITIVE(meta->obj.classObj, "eval(_)", meta_eval);
|
||||||
|
|||||||
3
src/vm/wren_meta.wren.inc
Normal file
3
src/vm/wren_meta.wren.inc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Generated automatically from builtin/meta.wren. Do not edit.
|
||||||
|
static const char* metaModuleSource =
|
||||||
|
"class Meta {}\n";
|
||||||
@ -634,7 +634,7 @@ static void bindForeignClass(WrenVM* vm, ObjClass* classObj, ObjModule* module)
|
|||||||
// occurred.
|
// occurred.
|
||||||
//
|
//
|
||||||
// Returns false if the result is an error.
|
// Returns false if the result is an error.
|
||||||
static bool defineClass(WrenVM* vm, ObjFiber* fiber, int numFields,
|
static bool createClass(WrenVM* vm, ObjFiber* fiber, int numFields,
|
||||||
ObjModule* module)
|
ObjModule* module)
|
||||||
{
|
{
|
||||||
// Pull the name and superclass off the stack.
|
// Pull the name and superclass off the stack.
|
||||||
@ -1195,13 +1195,13 @@ static WrenInterpretResult runInterpreter(WrenVM* vm, register ObjFiber* fiber)
|
|||||||
|
|
||||||
CASE_CODE(CLASS):
|
CASE_CODE(CLASS):
|
||||||
{
|
{
|
||||||
if (!defineClass(vm, fiber, READ_BYTE(), NULL)) RUNTIME_ERROR(PEEK());
|
if (!createClass(vm, fiber, READ_BYTE(), NULL)) RUNTIME_ERROR(PEEK());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE_CODE(FOREIGN_CLASS):
|
CASE_CODE(FOREIGN_CLASS):
|
||||||
{
|
{
|
||||||
if (!defineClass(vm, fiber, -1, fn->module)) RUNTIME_ERROR(PEEK());
|
if (!createClass(vm, fiber, -1, fn->module)) RUNTIME_ERROR(PEEK());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user