mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-11 06:08:41 +01:00
Merge branch 'master' into constructor-methods
This commit is contained in:
15
.travis.yml
15
.travis.yml
@ -2,10 +2,11 @@ language: c
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
before_install:
|
||||
# Travis VMs are 64-bit but we compile both for 32 and 64 bit. To enable the
|
||||
# 32-bit builds to work, we need gcc-multilib.
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq gcc-multilib
|
||||
|
||||
script: make all && make test
|
||||
# Travis VMs are 64-bit but we compile both for 32 and 64 bit. To enable the
|
||||
# 32-bit builds to work, we need gcc-multilib.
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-multilib
|
||||
sudo: false # Enable container-based builds.
|
||||
script: make all && make test
|
||||
|
||||
10
README.md
10
README.md
@ -40,8 +40,9 @@ while (!adjectives.isDone) IO.print(adjectives.call())
|
||||
and [an easy-to-use C API][embedding]. It compiles cleanly as C99, C++98
|
||||
or anything later.
|
||||
|
||||
If you like the sound of this, [give it a try][try]! Even better, you can
|
||||
[contribute to Wren itself][contribute].
|
||||
If you like the sound of this, [let's get started][started]. You can even try
|
||||
it [in your browser][browser]! Excited? Well, come on and [get
|
||||
involved][contribute]!
|
||||
|
||||
[](https://travis-ci.org/munificent/wren)
|
||||
|
||||
@ -52,5 +53,6 @@ If you like the sound of this, [give it a try][try]! Even better, you can
|
||||
[classes]: http://munificent.github.io/wren/classes.html
|
||||
[fibers]: http://munificent.github.io/wren/fibers.html
|
||||
[embedding]: http://munificent.github.io/wren/embedding-api.html
|
||||
[try]: http://munificent.github.io/wren/getting-started.html
|
||||
[contribute]: http://munificent.github.io/wren/contributing.html
|
||||
[started]: getting-started.html
|
||||
[browser]: http://ppvk.github.io/wren-nest/
|
||||
[contribute]: contributing.html
|
||||
|
||||
@ -1,101 +1,101 @@
|
||||
class IO {
|
||||
static print {
|
||||
IO.writeString_("\n")
|
||||
writeString_("\n")
|
||||
}
|
||||
|
||||
static print(obj) {
|
||||
IO.writeObject_(obj)
|
||||
IO.writeString_("\n")
|
||||
writeObject_(obj)
|
||||
writeString_("\n")
|
||||
return obj
|
||||
}
|
||||
|
||||
static print(a1, a2) {
|
||||
printList_([a1, a2])
|
||||
printAll([a1, a2])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3) {
|
||||
printList_([a1, a2, a3])
|
||||
printAll([a1, a2, a3])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4) {
|
||||
printList_([a1, a2, a3, a4])
|
||||
printAll([a1, a2, a3, a4])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5) {
|
||||
printList_([a1, a2, a3, a4, a5])
|
||||
printAll([a1, a2, a3, a4, a5])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5, a6) {
|
||||
printList_([a1, a2, a3, a4, a5, a6])
|
||||
printAll([a1, a2, a3, a4, a5, a6])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5, a6, a7) {
|
||||
printList_([a1, a2, a3, a4, a5, a6, a7])
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5, a6, a7, a8) {
|
||||
printList_([a1, a2, a3, a4, a5, a6, a7, a8])
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7, a8])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
|
||||
printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9])
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
|
||||
printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10])
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) {
|
||||
printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11])
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) {
|
||||
printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12])
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) {
|
||||
printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13])
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) {
|
||||
printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14])
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) {
|
||||
printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15])
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) {
|
||||
printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16])
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16])
|
||||
}
|
||||
|
||||
static printList_(objects) {
|
||||
for (object in objects) IO.writeObject_(object)
|
||||
IO.writeString_("\n")
|
||||
static printAll(sequence) {
|
||||
for (object in sequence) writeObject_(object)
|
||||
writeString_("\n")
|
||||
}
|
||||
|
||||
static write(obj) {
|
||||
IO.writeObject_(obj)
|
||||
writeObject_(obj)
|
||||
return obj
|
||||
}
|
||||
|
||||
static read(prompt) {
|
||||
if (!(prompt is String)) Fiber.abort("Prompt must be a string.")
|
||||
IO.write(prompt)
|
||||
return IO.read
|
||||
write(prompt)
|
||||
return read()
|
||||
}
|
||||
|
||||
static writeObject_(obj) {
|
||||
var string = obj.toString
|
||||
if (string is String) {
|
||||
IO.writeString_(string)
|
||||
writeString_(string)
|
||||
} else {
|
||||
IO.writeString_("[invalid toString]")
|
||||
writeString_("[invalid toString]")
|
||||
}
|
||||
}
|
||||
|
||||
foreign static writeString_(string)
|
||||
foreign static clock
|
||||
foreign static time
|
||||
foreign static read
|
||||
foreign static read()
|
||||
}
|
||||
|
||||
@ -10,18 +10,21 @@ There's one Wren user group, and it's the [official Wren mailing
|
||||
list](https://groups.google.com/forum/#!forum/wren-lang). Please join it and
|
||||
say hello! There are no strangers to Wren, just friends we haven't met yet.
|
||||
|
||||
## Third-party libraries
|
||||
## Libraries
|
||||
|
||||
There are some third-party libraries that are written in Wren. Here's the list:
|
||||
|
||||
- [wren-test](https://github.com/gsmaverick/wren-test), a testing framework
|
||||
- [Please](https://github.com/EvanHahn/wren-please), an assertion library
|
||||
- [wren-colors](https://github.com/gsmaverick/wren-colors) for printing colored
|
||||
messages to the terminal
|
||||
- [3D vectors for Wren](https://github.com/EvanHahn/wren-vector3d)
|
||||
- [Please](https://github.com/EvanHahn/wren-please): An assertion library.
|
||||
- [wren-colors](https://github.com/gsmaverick/wren-colors): Print colored
|
||||
messages to the terminal.
|
||||
- [wren-test](https://github.com/gsmaverick/wren-test): A testing framework.
|
||||
- [wren-vector3d](https://github.com/EvanHahn/wren-vector3d): 3D vectors.
|
||||
|
||||
A few people have also added Wren bindings for other languages:
|
||||
## Language bindings
|
||||
|
||||
Want to host a Wren VM within another language. Try these:
|
||||
|
||||
- [JavaScript: ppvk/wrenjs](https://github.com/ppvk/wrenjs)
|
||||
- [Rust: tilpner/wren-sys](https://github.com/tilpner/wren-sys)
|
||||
- [Rust: pwoolcoc/wren-sys](https://github.com/pwoolcoc/wren-sys)
|
||||
- [Rust: pwoolcoc/wren-rs](https://github.com/pwoolcoc/wren-rs)
|
||||
@ -30,8 +33,16 @@ A few people have also added Wren bindings for other languages:
|
||||
|
||||
If you want Wren syntax highlighting in your editor, look no further:
|
||||
|
||||
- [Vim](https://github.com/lluchs/vim-wren)
|
||||
- [Emacs](https://github.com/v2e4lisp/wren-mode.el)
|
||||
- [Sublime Text](https://github.com/munificent/wren-sublime)
|
||||
- [Vim](https://github.com/lluchs/vim-wren)
|
||||
|
||||
## Tools and Utilities
|
||||
|
||||
Things that make life easier:
|
||||
|
||||
- [The Wren Nest](http://ppvk.github.io/wren-nest/): Run and share Wren in your
|
||||
browser.
|
||||
|
||||
Do you have anything to add here? Send a [pull request][]!
|
||||
|
||||
|
||||
@ -7,38 +7,54 @@ The IO class can be used to read and write to and from the console.
|
||||
|
||||
### IO.**print**(objects...)
|
||||
|
||||
Prints any number of things to the console and then prints a newline
|
||||
character. If you don't pass it a string, it will be converted to a string for
|
||||
you. When passed multiple things, Wren outputs one after another.
|
||||
Prints a series of objects to the console followed by a newline. Each object is
|
||||
converted to a string by calling `toString` on it. This is overloaded to
|
||||
support up to 16 objects. To pass more, use `printAll()`.
|
||||
|
||||
> IO.print("I like bananas")
|
||||
I like bananas
|
||||
> IO.print("Oranges", 10)
|
||||
Oranges10
|
||||
|
||||
> IO.print("I like bananas")
|
||||
I like bananas
|
||||
> IO.print("Oranges", 10)
|
||||
Oranges10
|
||||
>
|
||||
### IO.**printAll**(sequence)
|
||||
|
||||
Iterates over [sequence] and prints each element, then prints a single newline
|
||||
at the end. Each element is converted to a string by calling `toString` on it.
|
||||
|
||||
> IO.printAll([1, [2, 3], 4])
|
||||
1[2, 3]4
|
||||
|
||||
### IO.**write**(object)
|
||||
|
||||
Prints a single thing to the console, but does not print a newline character
|
||||
afterwards. If you pass it something that isn't a string, it will convert it to
|
||||
a string.
|
||||
Prints a single value to the console, but does not print a newline character
|
||||
afterwards. Converts the value to a string by calling `toString` on it.
|
||||
|
||||
> IO.write(4 + 5)
|
||||
9>
|
||||
> IO.write(4 + 5)
|
||||
9>
|
||||
|
||||
In the above example, the result of `4 + 5` is printed, and then the prompt is
|
||||
printed on the same line because no newline character was printed afterwards.
|
||||
|
||||
### IO.**read**()
|
||||
|
||||
Reads in a line of text from stdin. Note that the returned text includes the
|
||||
trailing newline.
|
||||
|
||||
> var name = IO.read()
|
||||
John
|
||||
> IO.print("Hello " + name + "!")
|
||||
Hello John
|
||||
!
|
||||
>
|
||||
|
||||
### IO.**read**(prompt)
|
||||
|
||||
Reads in and returns a line of text from the console. Takes a single string to
|
||||
be used as a prompt. Pass an empty string for no prompt. Note that the returned
|
||||
line of text includes the newline character at the end.
|
||||
Displays `prompt` then reads in a line of text from stdin. Note that the
|
||||
returned text includes the trailing newline.
|
||||
|
||||
> var name = IO.read("Enter your name: ")
|
||||
Enter your name: John
|
||||
> IO.print("Hello " + name + "!")
|
||||
Hello John
|
||||
!
|
||||
>
|
||||
> var name = IO.read("Enter your name: ")
|
||||
Enter your name: John
|
||||
> IO.print("Hello " + name + "!")
|
||||
Hello John
|
||||
!
|
||||
>
|
||||
|
||||
@ -113,7 +113,7 @@ of the `yield()` call:
|
||||
|
||||
This prints "sent". Note that the first value sent to the fiber through call is
|
||||
ignored. That's because the fiber isn't waiting on a `yield()` call, so there's
|
||||
no where for the sent value to go.
|
||||
nowhere for the sent value to go.
|
||||
|
||||
Fibers can also pass values *back* when they yield. If you pass an argument to
|
||||
`yield()`, that will become the return value of the `call` that was used to
|
||||
|
||||
@ -41,8 +41,9 @@ a familiar, modern [syntax][].
|
||||
and [an easy-to-use C API][embedding]. It compiles cleanly as C99, C++98
|
||||
or anything later.
|
||||
|
||||
If you like the sound of this, [give it a try][try]! Even better, you can
|
||||
[contribute to Wren itself][contribute].
|
||||
If you like the sound of this, [let's get started][started]. You can even try
|
||||
it [in your browser][browser]! Excited? Well, come on and [get
|
||||
involved][contribute]!
|
||||
|
||||
[syntax]: syntax.html
|
||||
[src]: https://github.com/munificent/wren/tree/master/src
|
||||
@ -51,5 +52,6 @@ If you like the sound of this, [give it a try][try]! Even better, you can
|
||||
[classes]: classes.html
|
||||
[fibers]: fibers.html
|
||||
[embedding]: embedding-api.html
|
||||
[try]: getting-started.html
|
||||
[started]: getting-started.html
|
||||
[browser]: http://ppvk.github.io/wren-nest/
|
||||
[contribute]: contributing.html
|
||||
|
||||
@ -234,7 +234,7 @@ def color_text(text, color):
|
||||
|
||||
# No ANSI escapes on Windows.
|
||||
if sys.platform == 'win32':
|
||||
return text
|
||||
return str(text)
|
||||
|
||||
return color + str(text) + '\033[0m'
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
//
|
||||
// Defaults to on.
|
||||
#ifndef WREN_NAN_TAGGING
|
||||
#define WREN_NAN_TAGGING 1
|
||||
#define WREN_NAN_TAGGING 1
|
||||
#endif
|
||||
|
||||
// If true, the VM's interpreter loop uses computed gotos. See this for more:
|
||||
@ -48,14 +48,14 @@
|
||||
//
|
||||
// Defaults to on.
|
||||
#ifndef WREN_USE_LIB_IO
|
||||
#define WREN_USE_LIB_IO 1
|
||||
#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
|
||||
#define WREN_USE_LIB_META 1
|
||||
#endif
|
||||
|
||||
// These flags are useful for debugging and hacking on Wren itself. They are not
|
||||
@ -136,18 +136,18 @@
|
||||
// The Microsoft compiler does not support the "inline" modifier when compiling
|
||||
// as plain C.
|
||||
#if defined( _MSC_VER ) && !defined(__cplusplus)
|
||||
#define inline _inline
|
||||
#define inline _inline
|
||||
#endif
|
||||
|
||||
// This is used to clearly mark flexible-sized arrays that appear at the end of
|
||||
// some dynamically-allocated structs, known as the "struct hack".
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
// In C99, a flexible array member is just "[]".
|
||||
#define FLEXIBLE_ARRAY
|
||||
// In C99, a flexible array member is just "[]".
|
||||
#define FLEXIBLE_ARRAY
|
||||
#else
|
||||
// Elsewhere, use a zero-sized array. It's technically undefined behavior, but
|
||||
// works reliably in most known compilers.
|
||||
#define FLEXIBLE_ARRAY 0
|
||||
// Elsewhere, use a zero-sized array. It's technically undefined behavior,
|
||||
// but works reliably in most known compilers.
|
||||
#define FLEXIBLE_ARRAY 0
|
||||
#endif
|
||||
|
||||
// Assertions are used to validate program invariants. They indicate things the
|
||||
@ -157,34 +157,46 @@
|
||||
// Assertions add significant overhead, so are only enabled in debug builds.
|
||||
#ifdef DEBUG
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define ASSERT(condition, message) \
|
||||
do \
|
||||
{ \
|
||||
if (!(condition)) \
|
||||
#define ASSERT(condition, message) \
|
||||
do \
|
||||
{ \
|
||||
fprintf(stderr, "[%s:%d] Assert failed in %s(): %s\n", \
|
||||
__FILE__, __LINE__, __func__, message); \
|
||||
if (!(condition)) \
|
||||
{ \
|
||||
fprintf(stderr, "[%s:%d] Assert failed in %s(): %s\n", \
|
||||
__FILE__, __LINE__, __func__, message); \
|
||||
abort(); \
|
||||
} \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
// Indicates that we know execution should never reach this point in the
|
||||
// program. In debug mode, we assert this fact because it's a bug to get here.
|
||||
//
|
||||
// In release mode, we use compiler-specific built in functions to tell the
|
||||
// compiler the code can't be reached. This avoids "missing return" warnings
|
||||
// in some cases and also lets it perform some optimizations by assuming the
|
||||
// code is never reached.
|
||||
#define UNREACHABLE() \
|
||||
do \
|
||||
{ \
|
||||
fprintf(stderr, "[%s:%d] This code should not be reached in %s()\n", \
|
||||
__FILE__, __LINE__, __func__); \
|
||||
abort(); \
|
||||
} \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
// Assertion to indicate that the given point in the code should never be
|
||||
// reached.
|
||||
#define UNREACHABLE() \
|
||||
do \
|
||||
{ \
|
||||
fprintf(stderr, "This line should not be reached.\n"); \
|
||||
abort(); \
|
||||
} \
|
||||
while (0)
|
||||
while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define ASSERT(condition, message) do { } while (0)
|
||||
#define UNREACHABLE() do { } while (0)
|
||||
#define ASSERT(condition, message) do {} while (0)
|
||||
|
||||
// Tell the compiler that this part of the code will never be reached.
|
||||
#if defined( _MSC_VER )
|
||||
#define UNREACHABLE() __assume(0)
|
||||
#else
|
||||
#define UNREACHABLE() __builtin_unreachable()
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -2673,7 +2673,6 @@ static int getNumArguments(const uint8_t* bytecode, const Value* constants,
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,15 +9,7 @@ void wrenDebugPrintStackTrace(ObjFiber* fiber)
|
||||
for (int i = fiber->numFrames - 1; i >= 0; i--)
|
||||
{
|
||||
CallFrame* frame = &fiber->frames[i];
|
||||
ObjFn* fn;
|
||||
if (frame->fn->type == OBJ_FN)
|
||||
{
|
||||
fn = (ObjFn*)frame->fn;
|
||||
}
|
||||
else
|
||||
{
|
||||
fn = ((ObjClosure*)frame->fn)->fn;
|
||||
}
|
||||
ObjFn* fn = wrenGetFrameFunction(frame);
|
||||
|
||||
// Built-in libraries and method call stubs have no source path and are
|
||||
// explicitly omitted from stack traces since we don't want to highlight to
|
||||
@ -70,21 +62,21 @@ void wrenDumpValue(Value value)
|
||||
{
|
||||
switch (GET_TAG(value))
|
||||
{
|
||||
case TAG_FALSE: printf("false"); break;
|
||||
case TAG_NAN: printf("NaN"); break;
|
||||
case TAG_NULL: printf("null"); break;
|
||||
case TAG_TRUE: printf("true"); break;
|
||||
case TAG_FALSE: printf("false"); break;
|
||||
case TAG_NAN: printf("NaN"); break;
|
||||
case TAG_NULL: printf("null"); break;
|
||||
case TAG_TRUE: printf("true"); break;
|
||||
case TAG_UNDEFINED: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
#else
|
||||
switch (value.type)
|
||||
{
|
||||
case VAL_FALSE: printf("false"); break;
|
||||
case VAL_NULL: printf("null"); break;
|
||||
case VAL_NUM: printf("%.14g", AS_NUM(value)); break;
|
||||
case VAL_TRUE: printf("true"); break;
|
||||
case VAL_OBJ: printObject(AS_OBJ(value)); break;
|
||||
case VAL_FALSE: printf("false"); break;
|
||||
case VAL_NULL: printf("null"); break;
|
||||
case VAL_NUM: printf("%.14g", AS_NUM(value)); break;
|
||||
case VAL_TRUE: printf("true"); break;
|
||||
case VAL_OBJ: dumpObject(AS_OBJ(value)); break;
|
||||
case VAL_UNDEFINED: UNREACHABLE();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -6,111 +6,111 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
// TODO: This is an arbitrary limit Do something smarter.
|
||||
// TODO: This is an arbitrary limit. Do something smarter.
|
||||
#define MAX_READ_LEN 1024
|
||||
|
||||
// This string literal is generated automatically from io.wren. Do not edit.
|
||||
static const char* ioLibSource =
|
||||
"class IO {\n"
|
||||
" static print {\n"
|
||||
" IO.writeString_(\"\n\")\n"
|
||||
" writeString_(\"\n\")\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(obj) {\n"
|
||||
" IO.writeObject_(obj)\n"
|
||||
" IO.writeString_(\"\n\")\n"
|
||||
" writeObject_(obj)\n"
|
||||
" writeString_(\"\n\")\n"
|
||||
" return obj\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2) {\n"
|
||||
" printList_([a1, a2])\n"
|
||||
" printAll([a1, a2])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3) {\n"
|
||||
" printList_([a1, a2, a3])\n"
|
||||
" printAll([a1, a2, a3])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4) {\n"
|
||||
" printList_([a1, a2, a3, a4])\n"
|
||||
" printAll([a1, a2, a3, a4])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5])\n"
|
||||
" printAll([a1, a2, a3, a4, a5])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5, a6) {\n"
|
||||
" printList_([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"
|
||||
" printList_([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"
|
||||
" printList_([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"
|
||||
" printList_([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"
|
||||
" printList_([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"
|
||||
" printList_([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"
|
||||
" printList_([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"
|
||||
" printList_([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"
|
||||
" printList_([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"
|
||||
" printList_([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"
|
||||
" printList_([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 printList_(objects) {\n"
|
||||
" for (object in objects) IO.writeObject_(object)\n"
|
||||
" IO.writeString_(\"\n\")\n"
|
||||
" static printAll(sequence) {\n"
|
||||
" for (object in sequence) writeObject_(object)\n"
|
||||
" writeString_(\"\n\")\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static write(obj) {\n"
|
||||
" IO.writeObject_(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"
|
||||
" IO.write(prompt)\n"
|
||||
" return IO.read\n"
|
||||
" write(prompt)\n"
|
||||
" return read()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static writeObject_(obj) {\n"
|
||||
" var string = obj.toString\n"
|
||||
" if (string is String) {\n"
|
||||
" IO.writeString_(string)\n"
|
||||
" writeString_(string)\n"
|
||||
" } else {\n"
|
||||
" IO.writeString_(\"[invalid toString]\")\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"
|
||||
" foreign static read()\n"
|
||||
"}\n";
|
||||
|
||||
static void ioWriteString(WrenVM* vm)
|
||||
@ -125,7 +125,8 @@ static void ioRead(WrenVM* vm)
|
||||
char buffer[MAX_READ_LEN];
|
||||
char* result = fgets(buffer, MAX_READ_LEN, stdin);
|
||||
|
||||
if (result != NULL) {
|
||||
if (result != NULL)
|
||||
{
|
||||
wrenReturnString(vm, buffer, (int)strlen(buffer));
|
||||
}
|
||||
}
|
||||
@ -153,7 +154,7 @@ WrenForeignMethodFn wrenBindIOForeignMethod(WrenVM* vm, const char* className,
|
||||
if (strcmp(signature, "writeString_(_)") == 0) return ioWriteString;
|
||||
if (strcmp(signature, "clock") == 0) return ioClock;
|
||||
if (strcmp(signature, "time") == 0) return ioTime;
|
||||
if (strcmp(signature, "read") == 0) return ioRead;
|
||||
if (strcmp(signature, "read()") == 0) return ioRead;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -359,13 +359,11 @@ static uint32_t hashValue(Value value)
|
||||
switch (value.type)
|
||||
{
|
||||
case VAL_FALSE: return 0;
|
||||
case VAL_NULL: return 1;
|
||||
case VAL_NUM: return hashNumber(AS_NUM(value));
|
||||
case VAL_TRUE: return 2;
|
||||
case VAL_OBJ: return hashObject(AS_OBJ(value));
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
case VAL_NULL: return 1;
|
||||
case VAL_NUM: return hashNumber(AS_NUM(value));
|
||||
case VAL_TRUE: return 2;
|
||||
case VAL_OBJ: return hashObject(AS_OBJ(value));
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -586,10 +586,10 @@ typedef struct
|
||||
#define IS_UNDEFINED(value) ((value).type == VAL_UNDEFINED)
|
||||
|
||||
// Singleton values.
|
||||
#define FALSE_VAL ((Value){ VAL_FALSE })
|
||||
#define NULL_VAL ((Value){ VAL_NULL })
|
||||
#define TRUE_VAL ((Value){ VAL_TRUE })
|
||||
#define UNDEFINED_VAL ((Value){ VAL_UNDEFINED })
|
||||
#define FALSE_VAL ((Value){ VAL_FALSE, { 0 } })
|
||||
#define NULL_VAL ((Value){ VAL_NULL, { 0 } })
|
||||
#define TRUE_VAL ((Value){ VAL_TRUE, { 0 } })
|
||||
#define UNDEFINED_VAL ((Value){ VAL_UNDEFINED, { 0 } })
|
||||
|
||||
#endif
|
||||
|
||||
@ -628,6 +628,16 @@ ObjFiber* wrenNewFiber(WrenVM* vm, Obj* fn);
|
||||
// Resets [fiber] back to an initial state where it is ready to invoke [fn].
|
||||
void wrenResetFiber(WrenVM* vm, ObjFiber* fiber, Obj* fn);
|
||||
|
||||
static inline ObjFn* wrenGetFrameFunction(CallFrame* frame)
|
||||
{
|
||||
switch (frame->fn->type)
|
||||
{
|
||||
case OBJ_FN: return (ObjFn*)frame->fn;
|
||||
case OBJ_CLOSURE: return ((ObjClosure*)frame->fn)->fn;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a new [CallFrame] to [fiber] invoking [function] whose stack starts at
|
||||
// [stackStart].
|
||||
static inline void wrenAppendCallFrame(WrenVM* vm, ObjFiber* fiber,
|
||||
@ -639,14 +649,7 @@ static inline void wrenAppendCallFrame(WrenVM* vm, ObjFiber* fiber,
|
||||
CallFrame* frame = &fiber->frames[fiber->numFrames++];
|
||||
frame->stackStart = stackStart;
|
||||
frame->fn = function;
|
||||
if (function->type == OBJ_FN)
|
||||
{
|
||||
frame->ip = ((ObjFn*)function)->bytecode;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame->ip = ((ObjClosure*)function)->fn->bytecode;
|
||||
}
|
||||
frame->ip = wrenGetFrameFunction(frame)->bytecode;
|
||||
}
|
||||
|
||||
// TODO: The argument list here is getting a bit gratuitous.
|
||||
|
||||
@ -613,14 +613,7 @@ static WrenInterpretResult runInterpreter(WrenVM* vm, register ObjFiber* fiber)
|
||||
frame = &fiber->frames[fiber->numFrames - 1]; \
|
||||
stackStart = frame->stackStart; \
|
||||
ip = frame->ip; \
|
||||
if (frame->fn->type == OBJ_FN) \
|
||||
{ \
|
||||
fn = (ObjFn*)frame->fn; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
fn = ((ObjClosure*)frame->fn)->fn; \
|
||||
}
|
||||
fn = wrenGetFrameFunction(frame);
|
||||
|
||||
// Terminates the current fiber with error string [error]. If another calling
|
||||
// fiber is willing to catch the error, transfers control to it, otherwise
|
||||
@ -1164,7 +1157,6 @@ static WrenInterpretResult runInterpreter(WrenVM* vm, register ObjFiber* fiber)
|
||||
// We should only exit this function from an explicit return from CODE_RETURN
|
||||
// or a runtime error.
|
||||
UNREACHABLE();
|
||||
return WREN_RESULT_RUNTIME_ERROR;
|
||||
|
||||
#undef READ_BYTE
|
||||
#undef READ_SHORT
|
||||
|
||||
@ -195,26 +195,25 @@ static inline ObjClass* wrenGetClassInline(WrenVM* vm, Value value)
|
||||
#if WREN_NAN_TAGGING
|
||||
switch (GET_TAG(value))
|
||||
{
|
||||
case TAG_FALSE: return vm->boolClass; break;
|
||||
case TAG_NAN: return vm->numClass; break;
|
||||
case TAG_NULL: return vm->nullClass; break;
|
||||
case TAG_TRUE: return vm->boolClass; break;
|
||||
case TAG_FALSE: return vm->boolClass; break;
|
||||
case TAG_NAN: return vm->numClass; break;
|
||||
case TAG_NULL: return vm->nullClass; break;
|
||||
case TAG_TRUE: return vm->boolClass; break;
|
||||
case TAG_UNDEFINED: UNREACHABLE();
|
||||
}
|
||||
#else
|
||||
switch (value.type)
|
||||
{
|
||||
case VAL_FALSE: return vm->boolClass;
|
||||
case VAL_NULL: return vm->nullClass;
|
||||
case VAL_NUM: return vm->numClass;
|
||||
case VAL_TRUE: return vm->boolClass;
|
||||
case VAL_OBJ: return AS_OBJ(value)->classObj;
|
||||
case VAL_FALSE: return vm->boolClass;
|
||||
case VAL_NULL: return vm->nullClass;
|
||||
case VAL_NUM: return vm->numClass;
|
||||
case VAL_TRUE: return vm->boolClass;
|
||||
case VAL_OBJ: return AS_OBJ(value)->classObj;
|
||||
case VAL_UNDEFINED: UNREACHABLE();
|
||||
}
|
||||
#endif
|
||||
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
35
test/benchmark/string_equals.py
Normal file
35
test/benchmark/string_equals.py
Normal file
@ -0,0 +1,35 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import time
|
||||
start = time.clock()
|
||||
|
||||
count = 0
|
||||
for i in range(0, 1000000):
|
||||
if "abc" == "abc":
|
||||
count = count + 1
|
||||
if "a slightly longer string" == \
|
||||
"a slightly longer string":
|
||||
count = count + 1
|
||||
if "a significantly longer string but still not overwhelmingly long string" == \
|
||||
"a significantly longer string but still not overwhelmingly long string":
|
||||
count = count + 1
|
||||
|
||||
if "" == "abc":
|
||||
count = count + 1
|
||||
if "abc" == "abcd":
|
||||
count = count + 1
|
||||
if "changed one character" == "changed %ne character":
|
||||
count = count + 1
|
||||
if "123" == 123: count = count + 1
|
||||
if "a slightly longer string" == \
|
||||
"a slightly longer string!":
|
||||
count = count + 1
|
||||
if "a slightly longer string" == \
|
||||
"a slightly longer strinh":
|
||||
count = count + 1
|
||||
if "a significantly longer string but still not overwhelmingly long string" == \
|
||||
"another":
|
||||
count = count + 1
|
||||
|
||||
print(count)
|
||||
print("elapsed: " + str(time.clock() - start))
|
||||
@ -1 +1 @@
|
||||
IO.write(IO.read) // expect: null
|
||||
IO.write(IO.read()) // expect: null
|
||||
|
||||
Reference in New Issue
Block a user