forked from Mirror/wren
"IO" -> "System".
Get rid of the separate opt-in IO class and replace it with a core System class. - Remove wren_io.c, wren_io.h, and io.wren. - Remove the flags that disable it. - Remove the overloads for print() with different arity. (It was an experiment, but I don't think it's that useful.) - Remove IO.read(). That will reappear using libuv in the CLI at some point. - Remove IO.time. Doesn't seem to have been used. - Update all of the tests, docs, etc. I'm sorry for all the breakage this causes, but I think "System" is a better name for this class (it makes it natural to add things like "System.gc()") and frees up "IO" for referring to the CLI's IO module.
This commit is contained in:
@ -4,11 +4,11 @@ Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in
|
||||
a familiar, modern [syntax][].
|
||||
|
||||
```dart
|
||||
IO.print("Hello, world!")
|
||||
System.print("Hello, world!")
|
||||
|
||||
class Wren {
|
||||
flyTo(city) {
|
||||
IO.print("Flying to ", city)
|
||||
System.print("Flying to ", city)
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ var adjectives = Fiber.new {
|
||||
["small", "clean", "fast"].each {|word| Fiber.yield(word) }
|
||||
}
|
||||
|
||||
while (!adjectives.isDone) IO.print(adjectives.call())
|
||||
while (!adjectives.isDone) System.print(adjectives.call())
|
||||
```
|
||||
|
||||
* **Wren is small.** The VM implementation is under [4,000 semicolons][src].
|
||||
|
||||
@ -213,3 +213,38 @@ class MapValueSequence is Sequence {
|
||||
}
|
||||
|
||||
class Range is Sequence {}
|
||||
|
||||
class System {
|
||||
static print() {
|
||||
writeString_("\n")
|
||||
}
|
||||
|
||||
static print(obj) {
|
||||
writeObject_(obj)
|
||||
writeString_("\n")
|
||||
return obj
|
||||
}
|
||||
|
||||
static printAll(sequence) {
|
||||
for (object in sequence) writeObject_(object)
|
||||
writeString_("\n")
|
||||
}
|
||||
|
||||
static write(obj) {
|
||||
writeObject_(obj)
|
||||
return obj
|
||||
}
|
||||
|
||||
static writeAll(sequence) {
|
||||
for (object in sequence) writeObject_(object)
|
||||
}
|
||||
|
||||
static writeObject_(obj) {
|
||||
var string = obj.toString
|
||||
if (string is String) {
|
||||
writeString_(string)
|
||||
} else {
|
||||
writeString_("[invalid toString]")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
101
builtin/io.wren
101
builtin/io.wren
@ -1,101 +0,0 @@
|
||||
class IO {
|
||||
static print {
|
||||
writeString_("\n")
|
||||
}
|
||||
|
||||
static print(obj) {
|
||||
writeObject_(obj)
|
||||
writeString_("\n")
|
||||
return obj
|
||||
}
|
||||
|
||||
static print(a1, a2) {
|
||||
printAll([a1, a2])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3) {
|
||||
printAll([a1, a2, a3])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4) {
|
||||
printAll([a1, a2, a3, a4])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5) {
|
||||
printAll([a1, a2, a3, a4, a5])
|
||||
}
|
||||
|
||||
static print(a1, a2, a3, a4, a5, a6) {
|
||||
printAll([a1, a2, a3, a4, a5, a6])
|
||||
}
|
||||
|
||||
static print(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) {
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7, a8])
|
||||
}
|
||||
|
||||
static print(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) {
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10])
|
||||
}
|
||||
|
||||
static print(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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16])
|
||||
}
|
||||
|
||||
static printAll(sequence) {
|
||||
for (object in sequence) writeObject_(object)
|
||||
writeString_("\n")
|
||||
}
|
||||
|
||||
static write(obj) {
|
||||
writeObject_(obj)
|
||||
return obj
|
||||
}
|
||||
|
||||
static read(prompt) {
|
||||
if (!(prompt is String)) Fiber.abort("Prompt must be a string.")
|
||||
write(prompt)
|
||||
return read()
|
||||
}
|
||||
|
||||
static writeObject_(obj) {
|
||||
var string = obj.toString
|
||||
if (string is String) {
|
||||
writeString_(string)
|
||||
} else {
|
||||
writeString_("[invalid toString]")
|
||||
}
|
||||
}
|
||||
|
||||
foreign static writeString_(string)
|
||||
foreign static clock
|
||||
foreign static time
|
||||
foreign static read()
|
||||
}
|
||||
@ -25,7 +25,7 @@ To let our unicorn do stuff, we need to give it methods.
|
||||
:::dart
|
||||
class Unicorn {
|
||||
prance() {
|
||||
IO.print("The unicorn prances in a fancy manner!")
|
||||
System.print("The unicorn prances in a fancy manner!")
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ parameters, put their names inside the parentheses:
|
||||
:::dart
|
||||
class Unicorn {
|
||||
prance(where, when) {
|
||||
IO.print("The unicorn prances in " + where + " at " + when)
|
||||
System.print("The unicorn prances in " + where + " at " + when)
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,15 +49,15 @@ fine:
|
||||
:::dart
|
||||
class Unicorn {
|
||||
prance() {
|
||||
IO.print("The unicorn prances in a fancy manner!")
|
||||
System.print("The unicorn prances in a fancy manner!")
|
||||
}
|
||||
|
||||
prance(where) {
|
||||
IO.print("The unicorn prances in " + where)
|
||||
System.print("The unicorn prances in " + where)
|
||||
}
|
||||
|
||||
prance(where, when) {
|
||||
IO.print("The unicorn prances in " + where + " at " + when)
|
||||
System.print("The unicorn prances in " + where + " at " + when)
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ Many methods on a class exist to expose or compute some property of the object.
|
||||
For example:
|
||||
|
||||
:::dart
|
||||
IO.print("string".count) // "6".
|
||||
System.print("string".count) // "6".
|
||||
|
||||
These *getters* are just another kind of method—one without a parameter
|
||||
list. You can define them like so:
|
||||
@ -152,12 +152,12 @@ You can define operators in your class like so:
|
||||
class Unicorn {
|
||||
// Infix:
|
||||
+(other) {
|
||||
IO.print("Adding to a unicorn?")
|
||||
System.print("Adding to a unicorn?")
|
||||
}
|
||||
|
||||
// Prefix:
|
||||
! {
|
||||
IO.print("Negating a unicorn?!")
|
||||
System.print("Negating a unicorn?!")
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,7 +191,7 @@ like so:
|
||||
:::dart
|
||||
class Unicorn {
|
||||
construct new(name, color) {
|
||||
IO.print("My name is " + name + " and I am " + color + ".")
|
||||
System.print("My name is " + name + " and I am " + color + ".")
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,7 +210,7 @@ and each can clarify how it creates the instance:
|
||||
:::dart
|
||||
class Unicorn {
|
||||
construct brown(name) {
|
||||
IO.print("My name is " + name + " and I am brown.")
|
||||
System.print("My name is " + name + " and I am brown.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,13 +326,13 @@ not the instance. They can be used in *both* instance and static methods.
|
||||
Just like instance fields, static fields are initially `null`:
|
||||
|
||||
:::dart
|
||||
IO.print(Foo.bar) // null.
|
||||
System.print(Foo.bar) // null.
|
||||
|
||||
They can be used from static methods:
|
||||
|
||||
:::dart
|
||||
Foo.set("foo")
|
||||
IO.print(Foo.bar) // foo.
|
||||
System.print(Foo.bar) // foo.
|
||||
|
||||
And also instance methods. When you do so, there is still only one static field
|
||||
shared among all instances of the class:
|
||||
@ -342,7 +342,7 @@ shared among all instances of the class:
|
||||
var foo2 = Foo.new()
|
||||
|
||||
foo1.setFromInstance("updated")
|
||||
IO.print(foo2.baz) // updated.
|
||||
System.print(foo2.baz) // updated.
|
||||
|
||||
## Inheritance
|
||||
|
||||
@ -381,7 +381,7 @@ This also means constructors are not inherited:
|
||||
:::dart
|
||||
class Unicorn {
|
||||
this new(name) {
|
||||
IO.print("My name is " + name + ".")
|
||||
System.print("My name is " + name + ".")
|
||||
}
|
||||
}
|
||||
|
||||
@ -398,7 +398,7 @@ This means you can do `super` calls inside a constructor:
|
||||
:::dart
|
||||
class Unicorn {
|
||||
this new(name) {
|
||||
IO.print("My name is " + name + ".")
|
||||
System.print("My name is " + name + ".")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ The simplest branching statement, `if` lets you conditionally skip a chunk of
|
||||
code. It looks like this:
|
||||
|
||||
:::dart
|
||||
if (ready) IO.print("go!")
|
||||
if (ready) System.print("go!")
|
||||
|
||||
That evaluates the parenthesized expression after `if`. If it's true, then the
|
||||
statement after the condition is evaluated. Otherwise it is skipped. Instead of
|
||||
@ -39,23 +39,23 @@ a statement, you can have a [block](syntax.html#blocks):
|
||||
|
||||
:::dart
|
||||
if (ready) {
|
||||
IO.print("getSet")
|
||||
IO.print("go!")
|
||||
System.print("getSet")
|
||||
System.print("go!")
|
||||
}
|
||||
|
||||
You may also provide an `else` branch. It will be executed if the condition is
|
||||
false:
|
||||
|
||||
:::dart
|
||||
if (ready) IO.print("go!") else IO.print("not ready!")
|
||||
if (ready) System.print("go!") else System.print("not ready!")
|
||||
|
||||
And, of course, it can take a block too:
|
||||
|
||||
:::dart
|
||||
if (ready) {
|
||||
IO.print("go!")
|
||||
System.print("go!")
|
||||
} else {
|
||||
IO.print("not ready!")
|
||||
System.print("not ready!")
|
||||
}
|
||||
|
||||
## While statements
|
||||
@ -100,7 +100,7 @@ That's what `for` is for. It looks like this:
|
||||
|
||||
:::dart
|
||||
for (beatle in ["george", "john", "paul", "ringo"]) {
|
||||
IO.print(beatle)
|
||||
System.print(beatle)
|
||||
}
|
||||
|
||||
A `for` loop has three components:
|
||||
@ -124,7 +124,7 @@ keyword all by itself. That will immediately exit out of the nearest enclosing
|
||||
|
||||
:::dart
|
||||
for (i in [1, 2, 3, 4]) {
|
||||
IO.print(i)
|
||||
System.print(i)
|
||||
if (i == 3) break
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ sequence of numbers, or loop a number of times. For that, you can create a
|
||||
|
||||
:::dart
|
||||
for (i in 1..100) {
|
||||
IO.print(i)
|
||||
System.print(i)
|
||||
}
|
||||
|
||||
This loops over the numbers from 1 to 100, including 100 itself. If you want to
|
||||
@ -146,7 +146,7 @@ leave off the last value, use three dots instead of two:
|
||||
|
||||
:::dart
|
||||
for (i in 1...100) {
|
||||
IO.print(i)
|
||||
System.print(i)
|
||||
}
|
||||
|
||||
This looks like some special "range" syntax in the `for` loop, but it's
|
||||
@ -168,7 +168,7 @@ When you write a loop like this:
|
||||
|
||||
:::dart
|
||||
for (i in 1..100) {
|
||||
IO.print(i)
|
||||
System.print(i)
|
||||
}
|
||||
|
||||
Wren sees it something like this:
|
||||
@ -178,7 +178,7 @@ Wren sees it something like this:
|
||||
var seq_ = 1..100
|
||||
while (iter_ = seq_.iterate(iter_)) {
|
||||
var i = seq_.iteratorValue(iter_)
|
||||
IO.print(i)
|
||||
System.print(i)
|
||||
}
|
||||
|
||||
First, Wren evaluates the sequence expression and stores it in a hidden
|
||||
|
||||
@ -9,10 +9,9 @@ Boolean values. There are two instances, `true` and `false`.
|
||||
|
||||
Returns the logical complement of the value.
|
||||
|
||||
> !true
|
||||
false
|
||||
> !false
|
||||
true
|
||||
:::dart
|
||||
System.print(!true) // "false".
|
||||
System.print(!false) // "true".
|
||||
|
||||
### toString
|
||||
|
||||
|
||||
@ -15,14 +15,14 @@ The superclass of this class.
|
||||
class Crustacean {}
|
||||
class Crab is Crustacean {}
|
||||
|
||||
IO.print(Crab.supertype) // "Crustacean"
|
||||
System.print(Crab.supertype) // "Crustacean".
|
||||
|
||||
A class with no explicit superclass implicitly inherits Object:
|
||||
|
||||
:::dart
|
||||
IO.print(Crustacean.supertype) // "Object"
|
||||
System.print(Crustacean.supertype) // "Object".
|
||||
|
||||
Object forms the root of the class hierarchy and has no supertype:
|
||||
|
||||
:::dart
|
||||
IO.print(Object.supertype) // "null"
|
||||
System.print(Object.supertype) // "null".
|
||||
|
||||
@ -10,7 +10,7 @@ fiber is run. Does not immediately start running the fiber.
|
||||
|
||||
:::dart
|
||||
var fiber = Fiber.new {
|
||||
IO.print("I won't get printed")
|
||||
System.print("I won't get printed")
|
||||
}
|
||||
|
||||
## Static Methods
|
||||
@ -34,14 +34,14 @@ here means the last fiber that was started using `call` and not `run`.
|
||||
|
||||
:::dart
|
||||
var fiber = Fiber.new {
|
||||
IO.print("Before yield")
|
||||
System.print("Before yield")
|
||||
Fiber.yield()
|
||||
IO.print("After yield")
|
||||
System.print("After yield")
|
||||
}
|
||||
|
||||
fiber.call() // "Before yield"
|
||||
IO.print("After call") // "After call"
|
||||
fiber.call() // "After yield"
|
||||
fiber.call() // "Before yield"
|
||||
System.print("After call") // "After call"
|
||||
fiber.call() // "After yield"
|
||||
|
||||
When resumed, the parent fiber's `call()` method returns `null`.
|
||||
|
||||
@ -50,7 +50,7 @@ If a yielded fiber is resumed by calling `call()` or `run()` with an argument,
|
||||
|
||||
:::dart
|
||||
var fiber = Fiber.new {
|
||||
IO.print(Fiber.yield()) // "value"
|
||||
System.print(Fiber.yield()) // "value"
|
||||
}
|
||||
|
||||
fiber.call() // Run until the first yield.
|
||||
@ -65,7 +65,7 @@ later.
|
||||
|
||||
:::dart
|
||||
Fiber.yield()
|
||||
IO.print("this does not get reached")
|
||||
System.print("this does not get reached")
|
||||
|
||||
### Fiber.**yield**(value)
|
||||
|
||||
@ -77,7 +77,7 @@ Similar to `Fiber.yield` but provides a value to return to the parent fiber's
|
||||
Fiber.yield("value")
|
||||
}
|
||||
|
||||
IO.print(fiber.call()) // "value"
|
||||
System.print(fiber.call()) // "value"
|
||||
|
||||
## Methods
|
||||
|
||||
@ -87,9 +87,9 @@ Starts or resumes the fiber if it is in a paused state.
|
||||
|
||||
:::dart
|
||||
var fiber = Fiber.new {
|
||||
IO.print("Fiber called")
|
||||
System.print("Fiber called")
|
||||
Fiber.yield()
|
||||
IO.print("Fiber called again")
|
||||
System.print("Fiber called again")
|
||||
}
|
||||
|
||||
fiber.call() // Start it.
|
||||
@ -103,7 +103,7 @@ If the called fiber is resuming from a yield, the `yield()` method returns
|
||||
|
||||
:::dart
|
||||
var fiber = Fiber.new {
|
||||
IO.print(Fiber.yield())
|
||||
System.print(Fiber.yield())
|
||||
}
|
||||
|
||||
fiber.call()
|
||||
@ -116,7 +116,7 @@ Invokes the fiber or resumes the fiber if it is in a paused state and sets
|
||||
|
||||
:::dart
|
||||
var fiber = Fiber.new {
|
||||
IO.print(Fiber.yield())
|
||||
System.print(Fiber.yield())
|
||||
}
|
||||
|
||||
fiber.call()
|
||||
|
||||
@ -13,7 +13,7 @@ argument](../functions.html#block-arguments) to some other method.
|
||||
|
||||
:::dart
|
||||
var fn = Fn.new {
|
||||
IO.print("The body")
|
||||
System.print("The body")
|
||||
}
|
||||
|
||||
It is a runtime error if `function` is not a function.
|
||||
@ -25,8 +25,8 @@ It is a runtime error if `function` is not a function.
|
||||
The number of arguments the function requires.
|
||||
|
||||
:::dart
|
||||
IO.print(Fn.new {}.arity) // 0.
|
||||
IO.print(Fn.new {|a, b, c| a }.arity) // 3.
|
||||
System.print(Fn.new {}.arity) // 0.
|
||||
System.print(Fn.new {|a, b, c| a }.arity) // 3.
|
||||
|
||||
### **call**(args...)
|
||||
|
||||
@ -34,7 +34,7 @@ Invokes the function with the given arguments.
|
||||
|
||||
:::dart
|
||||
var fn = Fn.new { |arg|
|
||||
IO.print(arg)
|
||||
System.print(arg)
|
||||
}
|
||||
|
||||
fn.call("Hello world") // Prints "Hello world".
|
||||
|
||||
@ -20,6 +20,6 @@ All Wren source files automatically have access to the following classes:
|
||||
* [Range](range.html)
|
||||
* [Sequence](sequence.html)
|
||||
* [String](string.html)
|
||||
* [IO](io.html)
|
||||
* [System](system.html)
|
||||
|
||||
[embedding]: ../embedding-api.html
|
||||
|
||||
@ -1,60 +0,0 @@
|
||||
^title IO Class
|
||||
^category core
|
||||
|
||||
The IO class can be used to read and write to and from the console.
|
||||
|
||||
## Static Methods
|
||||
|
||||
### IO.**print**(objects...)
|
||||
|
||||
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.**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 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>
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
!
|
||||
>
|
||||
@ -26,14 +26,14 @@ Inserts the `item` at `index` in the list.
|
||||
:::dart
|
||||
var list = ["a", "b", "c", "d"]
|
||||
list.insert(1, "e")
|
||||
IO.print(list) // "[a, e, b, c, d]"
|
||||
System.print(list) // "[a, e, b, c, d]".
|
||||
|
||||
The `index` may be one past the last index in the list to append an element.
|
||||
|
||||
:::dart
|
||||
var list = ["a", "b", "c"]
|
||||
list.insert(3, "d")
|
||||
IO.print(list) // "[a, b, c, d]"
|
||||
System.print(list) // "[a, b, c, d]".
|
||||
|
||||
If `index` is negative, it counts backwards from the end of the list. It bases this on the length of the list *after* inserted the element, so that `-1` will append the element, not insert it before the last element.
|
||||
|
||||
@ -41,12 +41,12 @@ If `index` is negative, it counts backwards from the end of the list. It bases t
|
||||
var list = ["a", "b"]
|
||||
list.insert(-1, "d")
|
||||
list.insert(-2, "c")
|
||||
IO.print(list) // "[a, b, c, d]"
|
||||
System.print(list) // "[a, b, c, d]".
|
||||
|
||||
Returns the inserted item.
|
||||
|
||||
:::dart
|
||||
IO.print(["a", "c"].insert(1, "b")) // "b".
|
||||
System.print(["a", "c"].insert(1, "b")) // "b".
|
||||
|
||||
It is a runtime error if the index is not an integer or is out of bounds.
|
||||
|
||||
@ -64,11 +64,11 @@ are shifted up to fill in where the removed element was.
|
||||
:::dart
|
||||
var list = ["a", "b", "c", "d"]
|
||||
list.removeAt(1)
|
||||
IO.print(list) // "[a, c, d]".
|
||||
System.print(list) // "[a, c, d]".
|
||||
|
||||
Returns the removed item.
|
||||
|
||||
IO.print(["a", "b", "c"].removeAt(1)) // "b".
|
||||
System.print(["a", "b", "c"].removeAt(1)) // "b".
|
||||
|
||||
It is a runtime error if the index is not an integer or is out of bounds.
|
||||
|
||||
@ -79,7 +79,7 @@ the end of the list where `-1` is the last element.
|
||||
|
||||
:::dart
|
||||
var list = ["a", "b", "c"]
|
||||
IO.print(list[1]) // "b".
|
||||
System.print(list[1]) // "b".
|
||||
|
||||
It is a runtime error if the index is not an integer or is out of bounds.
|
||||
|
||||
@ -91,6 +91,6 @@ backwards from the end of the list where `-1` is the last element.
|
||||
:::dart
|
||||
var list = ["a", "b", "c"]
|
||||
list[1] = "new"
|
||||
IO.print(list) // "[a, new, c]".
|
||||
System.print(list) // "[a, new, c]".
|
||||
|
||||
It is a runtime error if the index is not an integer or is out of bounds.
|
||||
|
||||
@ -50,8 +50,8 @@ map, returns `null`.
|
||||
|
||||
:::dart
|
||||
var map = {"george": "harrison", "ringo": "starr"}
|
||||
IO.print(map["ringo"]) // "starr".
|
||||
IO.print(map["pete"]) // "null".
|
||||
System.print(map["ringo"]) // "starr".
|
||||
System.print(map["pete"]) // "null".
|
||||
|
||||
### **[**key**]=**(value) operator
|
||||
|
||||
|
||||
@ -7,5 +7,5 @@
|
||||
|
||||
Returns `true`, since `null` is considered [false](../control-flow.html#truth).
|
||||
|
||||
> !null
|
||||
true
|
||||
:::dart
|
||||
System.print(!null) // "true".
|
||||
|
||||
@ -132,9 +132,9 @@ from the beginning number to the ending number.
|
||||
|
||||
:::dart
|
||||
var range = 1.2..3.4
|
||||
IO.print(range.min) // 1.2
|
||||
IO.print(range.max) // 3.4
|
||||
IO.print(range.isInclusive) // true
|
||||
System.print(range.min) // 1.2
|
||||
System.print(range.max) // 3.4
|
||||
System.print(range.isInclusive) // true
|
||||
|
||||
### **...**(other) operator
|
||||
|
||||
@ -143,6 +143,6 @@ from the beginning number to the ending number not including the ending number.
|
||||
|
||||
:::dart
|
||||
var range = 1.2...3.4
|
||||
IO.print(range.min) // 1.2
|
||||
IO.print(range.max) // 3.4
|
||||
IO.print(range.isInclusive) // false
|
||||
System.print(range.min) // 1.2
|
||||
System.print(range.max) // 3.4
|
||||
System.print(range.isInclusive) // false
|
||||
|
||||
@ -59,7 +59,7 @@ and counting the number of times the returned value evaluates to `true`.
|
||||
Iterates over the sequence, passing each element to the given `function`.
|
||||
|
||||
:::dart
|
||||
["one", "two", "three"].each {|word| IO.print(word) }
|
||||
["one", "two", "three"].each {|word| System.print(word) }
|
||||
|
||||
### **isEmpty**
|
||||
|
||||
@ -88,7 +88,7 @@ original sequence while it is iterated.
|
||||
:::dart
|
||||
var doubles = [1, 2, 3].map {|n| n * 2 }
|
||||
for (n in doubles) {
|
||||
IO.print(n) // "2", "4", "6".
|
||||
System.print(n) // "2", "4", "6".
|
||||
}
|
||||
|
||||
The returned sequence is *lazy*. It only applies the mapping when you iterate
|
||||
@ -105,7 +105,7 @@ To force eager evaluation, just call `.toList` on the result.
|
||||
var numbers = [1, 2, 3]
|
||||
var doubles = numbers.map {|n| n * 2 }.toList
|
||||
numbers.add(4)
|
||||
IO.print(doubles) // [2, 4, 6].
|
||||
System.print(doubles) // [2, 4, 6].
|
||||
|
||||
### **reduce**(function)
|
||||
|
||||
@ -142,7 +142,7 @@ function `predicate`. If it returns `false`, the element is skipped.
|
||||
:::dart
|
||||
var odds = (1..10).where {|n| n % 2 == 1 }
|
||||
for (n in odds) {
|
||||
IO.print(n) // "1", "3", "5", "7", "9".
|
||||
System.print(n) // "1", "3", "5", "7", "9".
|
||||
}
|
||||
|
||||
The returned sequence is *lazy*. It only applies the filtering when you iterate
|
||||
@ -160,4 +160,4 @@ To force eager evaluation, just call `.toList` on the result.
|
||||
var numbers = [1, 2, 3, 4, 5, 6]
|
||||
var odds = numbers.where {|n| n % 2 == 1 }.toList
|
||||
numbers.add(7)
|
||||
IO.print(odds) // [1, 3, 5].
|
||||
System.print(odds) // [1, 3, 5].
|
||||
|
||||
@ -37,7 +37,7 @@ on strings *return* byte indexes too. So, for example, this does what you want:
|
||||
:::dart
|
||||
var metalBand = "Fäcëhämmër"
|
||||
var hPosition = metalBand.indexOf("h")
|
||||
IO.print(metalBand[hPosition]) // "h"
|
||||
System.print(metalBand[hPosition]) // "h"
|
||||
|
||||
If you want to work with a string as a sequence numeric code points, call the
|
||||
`codePoints` getter. It returns a [Sequence](sequence.html) that decodes UTF-8
|
||||
@ -68,7 +68,7 @@ methods, the returned object also has a subscript operator that can be used to
|
||||
directly index bytes.
|
||||
|
||||
:::dart
|
||||
IO.print("hello".bytes[1]) // 101, for "e".
|
||||
System.print("hello".bytes[1]) // 101, for "e".
|
||||
|
||||
The `count` method on the returned sequence returns the number of bytes in the
|
||||
string. Unlike `count` on the string itself, it does not have to iterate over
|
||||
@ -83,15 +83,15 @@ single-character strings, this returns the numeric code point values.
|
||||
|
||||
:::dart
|
||||
var string = "(ᵔᴥᵔ)"
|
||||
IO.print(string.codePoints[0]) // 40, for "(".
|
||||
IO.print(string.codePoints[4]) // 7461, for "ᴥ".
|
||||
System.print(string.codePoints[0]) // 40, for "(".
|
||||
System.print(string.codePoints[4]) // 7461, for "ᴥ".
|
||||
|
||||
If the byte at `index` does not begin a valid UTF-8 sequence, or the end of the
|
||||
string is reached before the sequence is complete, returns `-1`.
|
||||
|
||||
:::dart
|
||||
var string = "(ᵔᴥᵔ)"
|
||||
IO.print(string.codePoints[2]) // -1, in the middle of "ᵔ".
|
||||
System.print(string.codePoints[2]) // -1, in the middle of "ᵔ".
|
||||
|
||||
### **contains**(other)
|
||||
|
||||
@ -132,7 +132,7 @@ for iterating over the *code points* in the string:
|
||||
codePoints.add(c)
|
||||
}
|
||||
|
||||
IO.print(codePoints) // ["(", "ᵔ", "ᴥ", "ᵔ", ")"].
|
||||
System.print(codePoints) // ["(", "ᵔ", "ᴥ", "ᵔ", ")"].
|
||||
|
||||
If the string contains any bytes that are not valid UTF-8, this iterates over
|
||||
those too, one byte at a time.
|
||||
@ -162,7 +162,7 @@ Check if the string is not equal to `other`.
|
||||
Returns a string containing the code point starting at byte `index`.
|
||||
|
||||
:::dart
|
||||
IO.print("ʕ•ᴥ•ʔ"[5]) // "ᴥ".
|
||||
System.print("ʕ•ᴥ•ʔ"[5]) // "ᴥ".
|
||||
|
||||
Since `ʕ` is two bytes in UTF-8 and `•` is three, the fifth byte points to the
|
||||
bear's nose.
|
||||
@ -171,7 +171,7 @@ If `index` points into the middle of a UTF-8 sequence or at otherwise invalid
|
||||
UTF-8, this returns a one-byte string containing the byte at that index:
|
||||
|
||||
:::dart
|
||||
IO.print("I ♥ NY"[3]) // One-byte string whose value is 153.
|
||||
System.print("I ♥ NY"[3]) // One-byte string whose value is 153.
|
||||
|
||||
It is a runtime error if `index` is greater than the number of bytes in the
|
||||
string.
|
||||
|
||||
43
doc/site/core/system.markdown
Normal file
43
doc/site/core/system.markdown
Normal file
@ -0,0 +1,43 @@
|
||||
^title System Class
|
||||
^category core
|
||||
|
||||
The System class is a grab-bag of functionality exposed by the VM, mostly for
|
||||
use during development or debugging.
|
||||
|
||||
## Static Methods
|
||||
|
||||
### System.**print**()
|
||||
|
||||
Prints a single newline to the console.
|
||||
|
||||
### System.**print**(object)
|
||||
|
||||
Prints [object] to the console followed by a newline. If not already a string,
|
||||
the object is converted to a string by calling `toString` on it.
|
||||
|
||||
:::dart
|
||||
System.print("I like bananas") // Prints "I like bananas".
|
||||
|
||||
### System.**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.
|
||||
|
||||
:::dart
|
||||
System.printAll([1, [2, 3], 4]) // Prints "1[2, 3]4".
|
||||
|
||||
### System.**write**(object)
|
||||
|
||||
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.
|
||||
|
||||
:::dart
|
||||
System.write(4 + 5) // Prints "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.
|
||||
|
||||
### System.**clock**
|
||||
|
||||
Returns the number of seconds (including fractional seconds) since the program
|
||||
was started. This is usually used for benchmarking.
|
||||
@ -70,7 +70,7 @@ You can tell the VM to execute a string of Wren source code like so:
|
||||
:::c
|
||||
WrenInterpretResult result = wrenInterpret(vm,
|
||||
"<where>",
|
||||
"IO.print(\"Hi!\")");
|
||||
"System.print(\"Hi!\")");
|
||||
|
||||
The first string parameter is a "source path". It's just an arbitrary string that describes where the source code is from. It's what shows up in stack traces if a runtime error occurs in the code. It can be whatever you want as long as it's not `NULL`.
|
||||
|
||||
|
||||
@ -108,7 +108,7 @@ For example, if you run this program:
|
||||
}
|
||||
|
||||
var error = fiber.try()
|
||||
IO.print("Caught error: ", error)
|
||||
System.print("Caught error: " + error)
|
||||
|
||||
It prints:
|
||||
|
||||
@ -120,7 +120,7 @@ usual. When a fiber has been aborted because of a runtime error, you can also
|
||||
get the error from the fiber object. Continuing the above example:
|
||||
|
||||
:::dart
|
||||
IO.print(fiber.error)
|
||||
System.print(fiber.error)
|
||||
|
||||
This also prints:
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@ Wren is object-oriented, so most code consists of method calls. Most of them
|
||||
look like so:
|
||||
|
||||
:::dart
|
||||
IO.print("hello")
|
||||
System.print("hello")
|
||||
items.add("another")
|
||||
items.insert(1, "value")
|
||||
|
||||
@ -61,7 +61,7 @@ argument](functions.html#block-arguments):
|
||||
|
||||
:::dart
|
||||
blondie.callMeAt(867, 5309) {
|
||||
IO.print("This is the body!")
|
||||
System.print("This is the body!")
|
||||
}
|
||||
|
||||
Semantically, all method calls work like so:
|
||||
@ -98,7 +98,7 @@ call:
|
||||
:::dart
|
||||
class Base {
|
||||
method {
|
||||
IO.print("base method")
|
||||
System.print("base method")
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ base class constructor:
|
||||
:::dart
|
||||
class Base {
|
||||
this new(arg) {
|
||||
IO.print("base constructor got ", arg)
|
||||
System.print("base constructor got " + arg)
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,16 +218,16 @@ A `&&` ("logical and") expression evaluates the left-hand argument. If it's
|
||||
and returns the right-hand argument.
|
||||
|
||||
:::dart
|
||||
IO.print(false && 1) // false
|
||||
IO.print(1 && 2) // 2
|
||||
System.print(false && 1) // false
|
||||
System.print(1 && 2) // 2
|
||||
|
||||
An `||` ("logical or") expression is reversed. If the left-hand argument is
|
||||
[true](control-flow.html#truth), it's returned, otherwise the right-hand
|
||||
argument is evaluated and returned:
|
||||
|
||||
:::dart
|
||||
IO.print(false || 1) // 1
|
||||
IO.print(1 || 2) // 1
|
||||
System.print(false || 1) // 1
|
||||
System.print(1 || 2) // 1
|
||||
|
||||
## The conditional operator `?:`
|
||||
|
||||
@ -236,7 +236,7 @@ the little "if statement in the form of an expression" you know and love from C
|
||||
and its brethren.
|
||||
|
||||
:::dart
|
||||
IO.print(1 != 2 ? "math is sane" : "math is not sane!")
|
||||
System.print(1 != 2 ? "math is sane" : "math is not sane!")
|
||||
|
||||
It takes a condition expression, followed by `?`, followed by a then
|
||||
expression, a `:`, then an else expression. Just like `if`, it evaluates the
|
||||
|
||||
@ -28,7 +28,7 @@ using the `Fiber` class's constructor:
|
||||
|
||||
:::dart
|
||||
var fiber = Fiber.new {
|
||||
IO.print("This runs in a separate fiber.")
|
||||
System.print("This runs in a separate fiber.")
|
||||
}
|
||||
|
||||
Creating a fiber does not immediately run it. It's just a first class bundle of
|
||||
@ -48,7 +48,7 @@ until it passes control to another fiber. If it reaches the end of its body,
|
||||
it's considered *done*:
|
||||
|
||||
:::dart
|
||||
var fiber = Fiber.new { IO.print("Hi") }
|
||||
var fiber = Fiber.new { System.print("Hi") }
|
||||
fiber.isDone // false
|
||||
fiber.call()
|
||||
fiber.isDone // true
|
||||
@ -71,16 +71,16 @@ You can make a fiber yield by calling the static `yield()` method on `Fiber`:
|
||||
|
||||
:::dart
|
||||
var fiber = Fiber.new {
|
||||
IO.print("fiber 1")
|
||||
System.print("fiber 1")
|
||||
Fiber.yield()
|
||||
IO.print("fiber 2")
|
||||
System.print("fiber 2")
|
||||
}
|
||||
|
||||
IO.print("main 1")
|
||||
System.print("main 1")
|
||||
fiber.call()
|
||||
IO.print("main 2")
|
||||
System.print("main 2")
|
||||
fiber.call()
|
||||
IO.print("main 3")
|
||||
System.print("main 3")
|
||||
|
||||
This program prints:
|
||||
|
||||
@ -105,7 +105,7 @@ of the `yield()` call:
|
||||
:::dart
|
||||
var fiber = Fiber.new {
|
||||
var result = Fiber.yield()
|
||||
IO.print(result)
|
||||
System.print(result)
|
||||
}
|
||||
|
||||
fiber.call("discarded")
|
||||
@ -124,7 +124,7 @@ invoke the fiber:
|
||||
Fiber.yield("sent")
|
||||
}
|
||||
|
||||
IO.print(fiber.call())
|
||||
System.print(fiber.call())
|
||||
|
||||
This also prints "sent".
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ a method. At its simplest, it looks like this:
|
||||
|
||||
:::dart
|
||||
blondie.callMe {
|
||||
IO.print("This is the body!")
|
||||
System.print("This is the body!")
|
||||
}
|
||||
|
||||
Here we're invoking the `callMe` method on `blondie`. We're passing one
|
||||
@ -44,7 +44,7 @@ the block just like a regular argument list. For example:
|
||||
|
||||
:::dart
|
||||
blondie.callMeAt(867, 5309) {
|
||||
IO.print("This is the body!")
|
||||
System.print("This is the body!")
|
||||
}
|
||||
|
||||
Of course, you don't *have* to use a block argument to pass a function to a
|
||||
@ -62,7 +62,7 @@ class's constructor:
|
||||
|
||||
:::dart
|
||||
var someFn = Fn.new {
|
||||
IO.print("Hi!")
|
||||
System.print("Hi!")
|
||||
}
|
||||
|
||||
As you can see it takes a block argument too! All the constructor does it
|
||||
@ -87,7 +87,7 @@ method is dynamically-dispatched like any other, so you can define your own
|
||||
:::dart
|
||||
class FakeFn {
|
||||
call() {
|
||||
IO.print("I'm feeling functional!")
|
||||
System.print("I'm feeling functional!")
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +102,7 @@ of the body, like so:
|
||||
|
||||
:::dart
|
||||
blondie.callMe {|first, last|
|
||||
IO.print("Hi, " + first + " " + last + "!")
|
||||
System.print("Hi, " + first + " " + last + "!")
|
||||
}
|
||||
|
||||
Here we're passing a function to `greet` that takes two parameters, `first` and
|
||||
@ -157,6 +157,6 @@ to`i`:
|
||||
|
||||
:::dart
|
||||
var counter = Counter.create
|
||||
IO.print(counter.call()) // Prints "1".
|
||||
IO.print(counter.call()) // Prints "2".
|
||||
IO.print(counter.call()) // Prints "3".
|
||||
System.print(counter.call()) // Prints "1".
|
||||
System.print(counter.call()) // Prints "2".
|
||||
System.print(counter.call()) // Prints "3".
|
||||
|
||||
@ -49,12 +49,12 @@ interactive mode. You can type in a line of code, and it will immediately
|
||||
execute it. Here's something to try:
|
||||
|
||||
:::dart
|
||||
IO.print("Hello, world!")
|
||||
System.print("Hello, world!")
|
||||
|
||||
Or a little more exciting:
|
||||
|
||||
:::dart
|
||||
for (i in 1..10) IO.print("Counting up ", i)
|
||||
for (i in 1..10) System.print("Counting up " + i.toString)
|
||||
|
||||
You can exit the interpreter using good old Ctrl-C or Ctrl-D, or just throw
|
||||
your computer to the ground and storm off.
|
||||
@ -80,10 +80,10 @@ your favorite text editor and paste this into it:
|
||||
y0 = y1
|
||||
iter = iter + 1
|
||||
}
|
||||
IO.write(" .-:;+=xX$& "[iter])
|
||||
System.write(" .-:;+=xX$& "[iter])
|
||||
}
|
||||
|
||||
IO.print("")
|
||||
System.print("")
|
||||
}
|
||||
|
||||
Now run:
|
||||
|
||||
@ -6,11 +6,11 @@ Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in
|
||||
a familiar, modern [syntax][].
|
||||
|
||||
:::dart
|
||||
IO.print("Hello, world!")
|
||||
System.print("Hello, world!")
|
||||
|
||||
class Wren {
|
||||
flyTo(city) {
|
||||
IO.print("Flying to ", city)
|
||||
System.print("Flying to " + city)
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ a familiar, modern [syntax][].
|
||||
["small", "clean", "fast"].each {|word| Fiber.yield(word) }
|
||||
}
|
||||
|
||||
while (!adjectives.isDone) IO.print(adjectives.call())
|
||||
while (!adjectives.isDone) System.print(adjectives.call())
|
||||
|
||||
* **Wren is small.** The VM implementation is under [4,000 semicolons][src].
|
||||
You can skim the whole thing in an afternoon. It's *small*, but not
|
||||
|
||||
@ -59,14 +59,14 @@ existing element in the list using the subscript setter:
|
||||
|
||||
:::dart
|
||||
hirsute[1] = "muttonchops"
|
||||
IO.print(hirsute[1]) // muttonchops.
|
||||
System.print(hirsute[1]) // muttonchops.
|
||||
|
||||
It's an error to set an element that's out of bounds. To grow a list, you can
|
||||
use `add` to append a single item to the end:
|
||||
|
||||
:::dart
|
||||
hirsute.add("goatee")
|
||||
IO.print(hirsute.count) // 4.
|
||||
System.print(hirsute.count) // 4.
|
||||
|
||||
You can insert a new element at a specific position using `insert`:
|
||||
|
||||
@ -84,9 +84,9 @@ back. Doing so counts back from the size of the list *after* it's grown by one:
|
||||
:::dart
|
||||
var letters = ["a", "b", "c"]
|
||||
letters.insert(3, "d") // OK: inserts at end.
|
||||
IO.print(letters) // ["a", "b", "c", "d"]
|
||||
System.print(letters) // ["a", "b", "c", "d"]
|
||||
letters.insert(-2, "e") // Counts back from size after insert.
|
||||
IO.print(letters) // ["a", "b", "c", "e", "d"]
|
||||
System.print(letters) // ["a", "b", "c", "e", "d"]
|
||||
|
||||
## Removing elements
|
||||
|
||||
@ -97,15 +97,15 @@ gap:
|
||||
:::dart
|
||||
var letters = ["a", "b", "c", "d"]
|
||||
letters.removeAt(1)
|
||||
IO.print(letters) // ["a", "c", "d"]
|
||||
System.print(letters) // ["a", "c", "d"]
|
||||
|
||||
The `removeAt` method returns the removed item:
|
||||
|
||||
:::dart
|
||||
IO.print(letters.removeAt(1)) // "c"
|
||||
System.print(letters.removeAt(1)) // "c"
|
||||
|
||||
If you want to remove everything from the list, you can clear it:
|
||||
|
||||
:::dart
|
||||
hirsute.clear()
|
||||
IO.print(hirsute) // []
|
||||
System.print(hirsute) // []
|
||||
|
||||
@ -58,7 +58,7 @@ To find the value associated with some key, again you use your friend the
|
||||
subscript operator:
|
||||
|
||||
:::dart
|
||||
IO.print(capitals["Idaho"]) // "Boise".
|
||||
System.print(capitals["Idaho"]) // "Boise".
|
||||
|
||||
If the key is present, this returns its value. Otherwise, it returns `null`. Of
|
||||
course, `null` itself can also be used as a value, so seeing `null` here
|
||||
@ -69,15 +69,15 @@ To tell definitively if a key exists, you can call `containsKey()`:
|
||||
:::dart
|
||||
var belief = {"nihilism": null}
|
||||
|
||||
IO.print(belief["nihilism"]) // "null" though key exists.
|
||||
IO.print(belief["solipsism"]) // Also "null".
|
||||
IO.print(belief.containsKey("nihilism")) // "true".
|
||||
IO.print(belief.containsKey("solipsism")) // "false".
|
||||
System.print(belief["nihilism"]) // "null" though key exists.
|
||||
System.print(belief["solipsism"]) // Also "null".
|
||||
System.print(belief.containsKey("nihilism")) // "true".
|
||||
System.print(belief.containsKey("solipsism")) // "false".
|
||||
|
||||
You can see how many entries a map contains using `count`:
|
||||
|
||||
:::dart
|
||||
IO.print(capitals.count) // "3".
|
||||
System.print(capitals.count) // "3".
|
||||
|
||||
## Removing entries
|
||||
|
||||
@ -86,12 +86,12 @@ entry you want to delete:
|
||||
|
||||
:::dart
|
||||
capitals.remove("Maine")
|
||||
IO.print(capitals.containsKey("Maine")) // "false".
|
||||
System.print(capitals.containsKey("Maine")) // "false".
|
||||
|
||||
If the key was found, this returns the value that was associated with it:
|
||||
|
||||
:::dart
|
||||
IO.print(capitals.remove("Georgia")) // "Atlanta".
|
||||
System.print(capitals.remove("Georgia")) // "Atlanta".
|
||||
|
||||
If the key wasn't in the map to begin with, `remove()` just returns `null`.
|
||||
|
||||
@ -100,7 +100,7 @@ can just call `clear()`:
|
||||
|
||||
:::dart
|
||||
capitals.clear()
|
||||
IO.print(capitals.count) // "0".
|
||||
System.print(capitals.count) // "0".
|
||||
|
||||
[lists]: lists.html
|
||||
|
||||
@ -120,14 +120,14 @@ If you want to see all of the key-value pairs in a map, the easiest way is to
|
||||
iterate over the keys and use each to look up its value:
|
||||
|
||||
:::dart
|
||||
var stateBirds = {
|
||||
var birds = {
|
||||
"Arizona": "Cactus wren",
|
||||
"Hawaii": "Nēnē",
|
||||
"Ohio": "Northern Cardinal"
|
||||
}
|
||||
|
||||
for (state in stateBirds.keys) {
|
||||
IO.print("The state bird of ", state, " is ", stateBirds[state])
|
||||
for (state in birds.keys) {
|
||||
System.print("The state bird of " + state + " is " + birds[state])
|
||||
}
|
||||
|
||||
This program will print the three states and their birds. However, the *order*
|
||||
|
||||
@ -173,7 +173,7 @@ like:
|
||||
import "shared"
|
||||
|
||||
// shared.wren
|
||||
IO.print("Shared!")
|
||||
System.print("Shared!")
|
||||
|
||||
Here, "a" and "b" both want to use "shared". If "shared" defines some top-level
|
||||
state, we only want a single copy of that in memory. To handle this, a module's
|
||||
@ -211,14 +211,14 @@ For example:
|
||||
import "a"
|
||||
|
||||
// a.wren
|
||||
IO.print("start a")
|
||||
System.print("start a")
|
||||
import "b"
|
||||
IO.print("end a")
|
||||
System.print("end a")
|
||||
|
||||
// b.wren
|
||||
IO.print("start b")
|
||||
System.print("start b")
|
||||
import "a"
|
||||
IO.print("end b")
|
||||
System.print("end b")
|
||||
|
||||
This program runs successfully and prints:
|
||||
|
||||
|
||||
@ -54,15 +54,15 @@ Newlines (`\n`) are meaningful in Wren. They are used to separate statements:
|
||||
|
||||
:::dart
|
||||
// Two statements:
|
||||
IO.print("hi") // Newline.
|
||||
IO.print("bye")
|
||||
System.print("hi") // Newline.
|
||||
System.print("bye")
|
||||
|
||||
Sometimes, though, a statement doesn't fit on a single line and jamming a
|
||||
newline in the middle would trip it up. To handle that, Wren has a very simple
|
||||
rule: It ignores a newline following any token that can't end a statement.
|
||||
|
||||
:::dart
|
||||
IO.print( // Newline here is ignored.
|
||||
System.print( // Newline here is ignored.
|
||||
"hi")
|
||||
|
||||
In practice, this means you can put each statement on its own line and wrap
|
||||
@ -79,16 +79,16 @@ statement for the else:
|
||||
:::dart
|
||||
if (happy && knowIt) {
|
||||
hands.clap
|
||||
} else IO.print("sad")
|
||||
} else System.print("sad")
|
||||
|
||||
Blocks have two similar but not identical forms. Typically, blocks contain a
|
||||
series of statements like:
|
||||
|
||||
:::dart
|
||||
{
|
||||
IO.print("one")
|
||||
IO.print("two")
|
||||
IO.print("three")
|
||||
System.print("one")
|
||||
System.print("two")
|
||||
System.print("three")
|
||||
}
|
||||
|
||||
Blocks of this form when used for method and function bodies automatically
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
<li><a href="range.html">Range</a></li>
|
||||
<li><a href="sequence.html">Sequence</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="io.html">IO</a></li>
|
||||
<li><a href="system.html">System</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
</nav>
|
||||
|
||||
@ -57,11 +57,11 @@ A handful of escape characters are supported:
|
||||
A `\u` followed by four hex digits can be used to specify a Unicode code point:
|
||||
|
||||
:::dart
|
||||
IO.print("\u0041\u0b83\u00DE") // "AஃÞ"
|
||||
System.print("\u0041\u0b83\u00DE") // "AஃÞ"
|
||||
|
||||
A `\x` followed by two hex digits specifies a single unencoded byte:
|
||||
|
||||
IO.print("\x48\x69\x2e") // "Hi."
|
||||
System.print("\x48\x69\x2e") // "Hi."
|
||||
|
||||
Strings are instances of class [String](core/string.html).
|
||||
|
||||
@ -90,7 +90,7 @@ example:
|
||||
:::dart
|
||||
var list = ["a", "b", "c", "d", "e"]
|
||||
var slice = list[1..3]
|
||||
IO.print(slice) // ["b", "c", "d"]
|
||||
System.print(slice) // ["b", "c", "d"]
|
||||
|
||||
Their class is [Range](core/range.html).
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ defined, it can be accessed by name as you would expect.
|
||||
|
||||
:::dart
|
||||
var animal = "Slow Loris"
|
||||
IO.print(animal) // Prints "Slow Loris".
|
||||
System.print(animal) // Prints "Slow Loris".
|
||||
|
||||
## Scope
|
||||
|
||||
@ -22,11 +22,11 @@ until the end of the [block](syntax.html#blocks) where that definition appears.
|
||||
|
||||
:::dart
|
||||
{
|
||||
IO.print(a) // ERROR! a doesn't exist yet.
|
||||
System.print(a) // ERROR! a doesn't exist yet.
|
||||
var a = 123
|
||||
IO.print(a) // "123"
|
||||
System.print(a) // "123"
|
||||
}
|
||||
IO.print(a) // ERROR! a doesn't exist anymore.
|
||||
System.print(a) // ERROR! a doesn't exist anymore.
|
||||
|
||||
Variables defined at the top level of a script are *top-level* and are visible
|
||||
to the [module](modules.html) system. All other variables are *local*.
|
||||
@ -38,9 +38,9 @@ intend to do much).
|
||||
var a = "outer"
|
||||
{
|
||||
var a = "inner"
|
||||
IO.print(a) // Prints "inner".
|
||||
System.print(a) // Prints "inner".
|
||||
}
|
||||
IO.print(a) // Prints "outer".
|
||||
System.print(a) // Prints "outer".
|
||||
|
||||
Declaring a variable with the same name in the *same* scope *is* an error.
|
||||
|
||||
@ -65,6 +65,6 @@ assigned value.
|
||||
|
||||
:::dart
|
||||
var a = "before"
|
||||
IO.print(a = "after") // Prints "after".
|
||||
System.print(a = "after") // Prints "after".
|
||||
|
||||
**TODO: Top-level names.**
|
||||
|
||||
@ -1 +1 @@
|
||||
IO.print("Hello, world!")
|
||||
System.print("Hello, world!")
|
||||
|
||||
@ -5,4 +5,4 @@ class Lovecraft {
|
||||
say() { Cthulu.new().message }
|
||||
}
|
||||
|
||||
IO.print(Lovecraft.new().say())
|
||||
System.print(Lovecraft.new().say())
|
||||
|
||||
@ -29,8 +29,8 @@ for (yPixel in 0...24) {
|
||||
}
|
||||
}
|
||||
|
||||
IO.write(pixel)
|
||||
System.write(pixel)
|
||||
}
|
||||
|
||||
IO.print("")
|
||||
}
|
||||
System.print()
|
||||
}
|
||||
|
||||
@ -1 +0,0 @@
|
||||
IO.print("Hello, world!")
|
||||
@ -9,7 +9,7 @@ class SyntaxExample {
|
||||
// Constructor
|
||||
construct new() {
|
||||
// Top-level name `IO`
|
||||
IO.print("I am a constructor!")
|
||||
System.print("I am a constructor!")
|
||||
|
||||
// Method calls
|
||||
variables
|
||||
@ -58,7 +58,7 @@ class SyntaxExample {
|
||||
field=(value) { _field = value }
|
||||
|
||||
// Method with arguments
|
||||
print(a, b) { IO.print(a + b) }
|
||||
print(a, b) { System.print(a + b) }
|
||||
|
||||
// Operators
|
||||
+(other) { "infix + " + other }
|
||||
@ -97,7 +97,7 @@ class ReservedWords is SyntaxExample {
|
||||
|
||||
// `for`, `in`
|
||||
for (beatle in ["george", "john", "paul", "ringo"]) {
|
||||
IO.print(beatle)
|
||||
System.print(beatle)
|
||||
// `break`
|
||||
break
|
||||
}
|
||||
@ -147,9 +147,9 @@ class Literals is SyntaxExample {
|
||||
"\t" // Tab.
|
||||
"\v" // Vertical tab.
|
||||
// Unicode code points
|
||||
IO.print("\u0041fgdg\u0b83\u00DE") // "AஃÞ"
|
||||
System.print("\u0041fgdg\u0b83\u00DE") // "AஃÞ"
|
||||
// Unencoded bytes
|
||||
IO.print("\x48\x69\x2e") // "Hi."
|
||||
System.print("\x48\x69\x2e") // "Hi."
|
||||
}
|
||||
|
||||
ranges {
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
29205C991AB4E6430073018D /* wren_compiler.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C921AB4E6430073018D /* wren_compiler.c */; };
|
||||
29205C9A1AB4E6430073018D /* wren_core.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C931AB4E6430073018D /* wren_core.c */; };
|
||||
29205C9B1AB4E6430073018D /* wren_debug.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C941AB4E6430073018D /* wren_debug.c */; };
|
||||
29205C9C1AB4E6430073018D /* wren_io.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C951AB4E6430073018D /* wren_io.c */; };
|
||||
29205C9D1AB4E6430073018D /* wren_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C961AB4E6430073018D /* wren_utils.c */; };
|
||||
29205C9E1AB4E6430073018D /* wren_value.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C971AB4E6430073018D /* wren_value.c */; };
|
||||
29205C9F1AB4E6430073018D /* wren_vm.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C981AB4E6430073018D /* wren_vm.c */; };
|
||||
@ -63,7 +62,6 @@
|
||||
29205C921AB4E6430073018D /* wren_compiler.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = wren_compiler.c; path = ../../src/vm/wren_compiler.c; sourceTree = "<group>"; };
|
||||
29205C931AB4E6430073018D /* wren_core.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = wren_core.c; path = ../../src/vm/wren_core.c; sourceTree = "<group>"; };
|
||||
29205C941AB4E6430073018D /* wren_debug.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = wren_debug.c; path = ../../src/vm/wren_debug.c; sourceTree = "<group>"; };
|
||||
29205C951AB4E6430073018D /* wren_io.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = wren_io.c; path = ../../src/vm/wren_io.c; sourceTree = "<group>"; };
|
||||
29205C961AB4E6430073018D /* wren_utils.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = wren_utils.c; path = ../../src/vm/wren_utils.c; sourceTree = "<group>"; };
|
||||
29205C971AB4E6430073018D /* wren_value.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = wren_value.c; path = ../../src/vm/wren_value.c; sourceTree = "<group>"; };
|
||||
29205C981AB4E6430073018D /* wren_vm.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = wren_vm.c; path = ../../src/vm/wren_vm.c; sourceTree = "<group>"; };
|
||||
@ -71,7 +69,6 @@
|
||||
29205CA21AB4E65E0073018D /* wren_compiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_compiler.h; path = ../../src/vm/wren_compiler.h; sourceTree = "<group>"; };
|
||||
29205CA31AB4E65E0073018D /* wren_core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_core.h; path = ../../src/vm/wren_core.h; sourceTree = "<group>"; };
|
||||
29205CA41AB4E65E0073018D /* wren_debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_debug.h; path = ../../src/vm/wren_debug.h; sourceTree = "<group>"; };
|
||||
29205CA51AB4E65E0073018D /* wren_io.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_io.h; path = ../../src/vm/wren_io.h; sourceTree = "<group>"; };
|
||||
29205CA61AB4E65E0073018D /* wren_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_utils.h; path = ../../src/vm/wren_utils.h; sourceTree = "<group>"; };
|
||||
29205CA71AB4E65E0073018D /* wren_value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_value.h; path = ../../src/vm/wren_value.h; sourceTree = "<group>"; };
|
||||
29205CA81AB4E65E0073018D /* wren_vm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_vm.h; path = ../../src/vm/wren_vm.h; sourceTree = "<group>"; };
|
||||
@ -137,8 +134,6 @@
|
||||
29205C931AB4E6430073018D /* wren_core.c */,
|
||||
29205CA41AB4E65E0073018D /* wren_debug.h */,
|
||||
29205C941AB4E6430073018D /* wren_debug.c */,
|
||||
29205CA51AB4E65E0073018D /* wren_io.h */,
|
||||
29205C951AB4E6430073018D /* wren_io.c */,
|
||||
29DE39521AC3A50A00987D41 /* wren_meta.h */,
|
||||
29DE39511AC3A50A00987D41 /* wren_meta.c */,
|
||||
296371B31AC713D000079FDA /* wren_opcodes.h */,
|
||||
@ -292,7 +287,6 @@
|
||||
29C8A9331AB71FFF00DEC81D /* vm.c in Sources */,
|
||||
291647C41BA5EA45006142EE /* scheduler.c in Sources */,
|
||||
29205C9B1AB4E6430073018D /* wren_debug.c in Sources */,
|
||||
29205C9C1AB4E6430073018D /* wren_io.c in Sources */,
|
||||
29205C9D1AB4E6430073018D /* wren_utils.c in Sources */,
|
||||
29205C9E1AB4E6430073018D /* wren_value.c in Sources */,
|
||||
29205C9F1AB4E6430073018D /* wren_vm.c in Sources */,
|
||||
|
||||
@ -14,7 +14,7 @@ WREN_DIR = dirname(dirname(realpath(__file__)))
|
||||
WREN_APP = join(WREN_DIR, 'bin', 'wrend')
|
||||
TEST_APP = join(WREN_DIR, 'build', 'debug', 'test', 'wrend')
|
||||
|
||||
EXPECT_PATTERN = re.compile(r'// expect: (.*)')
|
||||
EXPECT_PATTERN = re.compile(r'// expect: ?(.*)')
|
||||
EXPECT_ERROR_PATTERN = re.compile(r'// expect error(?! line)')
|
||||
EXPECT_ERROR_LINE_PATTERN = re.compile(r'// expect error line (\d+)')
|
||||
EXPECT_RUNTIME_ERROR_PATTERN = re.compile(r'// expect runtime error: (.+)')
|
||||
|
||||
@ -44,13 +44,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// If true, loads the "IO" class in the standard library.
|
||||
//
|
||||
// Defaults to on.
|
||||
#ifndef WREN_USE_LIB_IO
|
||||
#define WREN_USE_LIB_IO 1
|
||||
#endif
|
||||
|
||||
// If true, loads the "Meta" class in the standard library.
|
||||
//
|
||||
// Defaults to on.
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "wren_common.h"
|
||||
#include "wren_core.h"
|
||||
@ -1041,6 +1042,17 @@ DEF_PRIMITIVE(string_toString)
|
||||
RETURN_VAL(args[0]);
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(system_clock)
|
||||
{
|
||||
RETURN_NUM((double)clock() / CLOCKS_PER_SEC);
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(system_writeString)
|
||||
{
|
||||
printf("%s", AS_CSTRING(args[1]));
|
||||
RETURN_VAL(args[1]);
|
||||
}
|
||||
|
||||
// Creates either the Object or Class class in the core library with [name].
|
||||
static ObjClass* defineClass(WrenVM* vm, ObjModule* module, const char* name)
|
||||
{
|
||||
@ -1254,6 +1266,10 @@ void wrenInitializeCore(WrenVM* vm)
|
||||
PRIMITIVE(vm->rangeClass, "iteratorValue(_)", range_iteratorValue);
|
||||
PRIMITIVE(vm->rangeClass, "toString", range_toString);
|
||||
|
||||
ObjClass* systemClass = AS_CLASS(wrenFindVariable(vm, coreModule, "System"));
|
||||
PRIMITIVE(systemClass->obj.classObj, "clock", system_clock);
|
||||
PRIMITIVE(systemClass->obj.classObj, "writeString_(_)", system_writeString);
|
||||
|
||||
// While bootstrapping the core types and running the core library, a number
|
||||
// of string objects have been created, many of which were instantiated
|
||||
// before stringClass was stored in the VM. Some of them *must* be created
|
||||
|
||||
@ -214,4 +214,39 @@ static const char* coreModuleSource =
|
||||
" iteratorValue(iterator) { _map.valueIteratorValue_(iterator) }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class Range is Sequence {}\n";
|
||||
"class Range is Sequence {}\n"
|
||||
"\n"
|
||||
"class System {\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 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 writeAll(sequence) {\n"
|
||||
" for (object in sequence) writeObject_(object)\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";
|
||||
|
||||
@ -1,59 +0,0 @@
|
||||
#include "wren_io.h"
|
||||
|
||||
#if WREN_USE_LIB_IO
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
// TODO: This is an arbitrary limit. Do something smarter.
|
||||
#define MAX_READ_LEN 1024
|
||||
|
||||
#include "wren_io.wren.inc"
|
||||
|
||||
static void ioWriteString(WrenVM* vm)
|
||||
{
|
||||
const char* s = wrenGetArgumentString(vm, 1);
|
||||
// TODO: Check for null.
|
||||
printf("%s", s);
|
||||
}
|
||||
|
||||
static void ioRead(WrenVM* vm)
|
||||
{
|
||||
char buffer[MAX_READ_LEN];
|
||||
char* result = fgets(buffer, MAX_READ_LEN, stdin);
|
||||
|
||||
if (result != NULL)
|
||||
{
|
||||
wrenReturnString(vm, buffer, (int)strlen(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
static void ioClock(WrenVM* vm)
|
||||
{
|
||||
wrenReturnDouble(vm, (double)clock() / CLOCKS_PER_SEC);
|
||||
}
|
||||
|
||||
static void ioTime(WrenVM* vm)
|
||||
{
|
||||
wrenReturnDouble(vm, (double)time(NULL));
|
||||
}
|
||||
|
||||
void wrenLoadIOLibrary(WrenVM* vm)
|
||||
{
|
||||
wrenInterpret(vm, "", ioModuleSource);
|
||||
}
|
||||
|
||||
WrenForeignMethodFn wrenBindIOForeignMethod(WrenVM* vm, const char* className,
|
||||
const char* signature)
|
||||
{
|
||||
if (strcmp(className, "IO") != 0) return NULL;
|
||||
|
||||
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;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,18 +0,0 @@
|
||||
#ifndef wren_io_h
|
||||
#define wren_io_h
|
||||
|
||||
#include "wren.h"
|
||||
#include "wren_common.h"
|
||||
|
||||
// This module defines the IO class and its associated methods. They are
|
||||
// implemented using the C standard library.
|
||||
#if WREN_USE_LIB_IO
|
||||
|
||||
void wrenLoadIOLibrary(WrenVM* vm);
|
||||
|
||||
WrenForeignMethodFn wrenBindIOForeignMethod(WrenVM* vm, const char* className,
|
||||
const char* signature);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,103 +0,0 @@
|
||||
// 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";
|
||||
@ -298,20 +298,6 @@ static WrenForeignMethodFn findForeignMethod(WrenVM* vm,
|
||||
bool isStatic,
|
||||
const char* signature)
|
||||
{
|
||||
WrenForeignMethodFn fn;
|
||||
|
||||
// Bind foreign methods in the core module.
|
||||
if (strcmp(moduleName, "core") == 0)
|
||||
{
|
||||
#if WREN_USE_LIB_IO
|
||||
fn = wrenBindIOForeignMethod(vm, className, signature);
|
||||
#endif
|
||||
|
||||
ASSERT(fn != NULL, "Failed to bind core module foreign method.");
|
||||
return fn;
|
||||
}
|
||||
|
||||
// For other modules, let the host bind it.
|
||||
if (vm->bindForeignMethod == NULL) return NULL;
|
||||
|
||||
return vm->bindForeignMethod(vm, moduleName, className, isStatic, signature);
|
||||
|
||||
@ -8,9 +8,6 @@ This contains the automated validation suite for the VM and built-in libraries.
|
||||
classes. If a bug is in `wren_core.c` or `wren_value.c`, it will most likely
|
||||
break one of these tests.
|
||||
|
||||
* `io/` - Tests for the built in IO library. In other words, methods on the
|
||||
`IO` class. If a bug is in `wren_io.c`, it should break one of these tests.
|
||||
|
||||
* `language/` - Tests of the language itself, its grammar and runtime
|
||||
semantics. If a bug is in `wren_compiler.c` or `wren_vm.c`, it will most
|
||||
likely break one of these tests. This includes tests for the syntax for the
|
||||
|
||||
@ -11,27 +11,27 @@ foreign class Counter {
|
||||
}
|
||||
|
||||
var counter = Counter.new()
|
||||
IO.print(counter.value) // expect: 0
|
||||
System.print(counter.value) // expect: 0
|
||||
counter.increment(3.1)
|
||||
IO.print(counter.value) // expect: 3.1
|
||||
System.print(counter.value) // expect: 3.1
|
||||
counter.increment(1.2)
|
||||
IO.print(counter.value) // expect: 4.3
|
||||
System.print(counter.value) // expect: 4.3
|
||||
|
||||
// Foreign classes can inherit a class as long as it has no fields.
|
||||
class PointBase {
|
||||
inherited() {
|
||||
IO.print("inherited method")
|
||||
System.print("inherited method")
|
||||
}
|
||||
}
|
||||
|
||||
// Class with non-default constructor.
|
||||
foreign class Point is PointBase {
|
||||
construct new() {
|
||||
IO.print("default")
|
||||
System.print("default")
|
||||
}
|
||||
|
||||
construct new(x, y, z) {
|
||||
IO.print(x, ", ", y, ", ", z)
|
||||
System.print(x.toString + ", " + y.toString + ", " + z.toString)
|
||||
}
|
||||
|
||||
foreign translate(x, y, z)
|
||||
@ -39,19 +39,19 @@ foreign class Point is PointBase {
|
||||
}
|
||||
|
||||
var p = Point.new(1, 2, 3) // expect: 1, 2, 3
|
||||
IO.print(p) // expect: (1, 2, 3)
|
||||
System.print(p) // expect: (1, 2, 3)
|
||||
p.translate(3, 4, 5)
|
||||
IO.print(p) // expect: (4, 6, 8)
|
||||
System.print(p) // expect: (4, 6, 8)
|
||||
|
||||
p = Point.new() // expect: default
|
||||
IO.print(p) // expect: (0, 0, 0)
|
||||
System.print(p) // expect: (0, 0, 0)
|
||||
|
||||
p.inherited() // expect: inherited method
|
||||
|
||||
var error = Fiber.new {
|
||||
class Subclass is Point {}
|
||||
}.try()
|
||||
IO.print(error) // expect: Class 'Subclass' cannot inherit from foreign class 'Point'.
|
||||
System.print(error) // expect: Class 'Subclass' cannot inherit from foreign class 'Point'.
|
||||
|
||||
// Class with a finalizer.
|
||||
foreign class Resource {
|
||||
@ -65,14 +65,14 @@ var resources = [
|
||||
]
|
||||
|
||||
Api.gc()
|
||||
IO.print(Api.finalized) // expect: 0
|
||||
System.print(Api.finalized) // expect: 0
|
||||
|
||||
resources.removeAt(-1)
|
||||
|
||||
Api.gc()
|
||||
IO.print(Api.finalized) // expect: 1
|
||||
System.print(Api.finalized) // expect: 1
|
||||
|
||||
resources.clear()
|
||||
|
||||
Api.gc()
|
||||
IO.print(Api.finalized) // expect: 3
|
||||
System.print(Api.finalized) // expect: 3
|
||||
|
||||
@ -8,10 +8,10 @@ class Api {
|
||||
foreign static returnFalse
|
||||
}
|
||||
|
||||
IO.print(Api.implicitNull == null) // expect: true
|
||||
System.print(Api.implicitNull == null) // expect: true
|
||||
|
||||
IO.print(Api.returnInt) // expect: 123456
|
||||
IO.print(Api.returnFloat) // expect: 123.456
|
||||
System.print(Api.returnInt) // expect: 123456
|
||||
System.print(Api.returnFloat) // expect: 123.456
|
||||
|
||||
IO.print(Api.returnTrue) // expect: true
|
||||
IO.print(Api.returnFalse) // expect: false
|
||||
System.print(Api.returnTrue) // expect: true
|
||||
System.print(Api.returnFalse) // expect: false
|
||||
|
||||
@ -11,4 +11,4 @@ for (i in 1...10) {
|
||||
s = s + " more"
|
||||
}
|
||||
|
||||
IO.print(Api.value) // expect: [list, of, strings]
|
||||
System.print(Api.value) // expect: [list, of, strings]
|
||||
|
||||
@ -24,10 +24,10 @@ var minDepth = 4
|
||||
var maxDepth = 12
|
||||
var stretchDepth = maxDepth + 1
|
||||
|
||||
var start = IO.clock
|
||||
var start = System.clock
|
||||
|
||||
IO.print("stretch tree of depth ", stretchDepth, " check: ",
|
||||
Tree.new(0, stretchDepth).check)
|
||||
System.print("stretch tree of depth " + stretchDepth.toString + " check: " +
|
||||
Tree.new(0, stretchDepth).check.toString)
|
||||
|
||||
var longLivedTree = Tree.new(0, maxDepth)
|
||||
|
||||
@ -44,10 +44,12 @@ while (depth < stretchDepth) {
|
||||
check = check + Tree.new(i, depth).check + Tree.new(-i, depth).check
|
||||
}
|
||||
|
||||
IO.print((iterations * 2), " trees of depth ", depth, " check: ", check)
|
||||
System.print((iterations * 2).toString + " trees of depth " +
|
||||
depth.toString + " check: " + check.toString)
|
||||
iterations = iterations / 4
|
||||
depth = depth + 2
|
||||
}
|
||||
|
||||
IO.print("long lived tree of depth ", maxDepth, " check: ", longLivedTree.check)
|
||||
IO.print("elapsed: ", (IO.clock - start))
|
||||
System.print("long lived tree of depth " + maxDepth.toString + " check: " +
|
||||
longLivedTree.check.toString)
|
||||
System.print("elapsed: " + (System.clock - start).toString)
|
||||
|
||||
@ -92,7 +92,7 @@ class Constraint {
|
||||
chooseMethod(mark)
|
||||
if (!isSatisfied) {
|
||||
if (_strength == REQUIRED) {
|
||||
IO.print("Could not satisfy a required constraint!")
|
||||
System.print("Could not satisfy a required constraint!")
|
||||
}
|
||||
return null
|
||||
}
|
||||
@ -102,7 +102,7 @@ class Constraint {
|
||||
var overridden = out.determinedBy
|
||||
if (overridden != null) overridden.markUnsatisfied
|
||||
out.determinedBy = this
|
||||
if (!ThePlanner.addPropagate(this, mark)) IO.print("Cycle encountered")
|
||||
if (!ThePlanner.addPropagate(this, mark)) System.print("Cycle encountered")
|
||||
out.mark = mark
|
||||
return overridden
|
||||
}
|
||||
@ -669,31 +669,31 @@ var projectionTest = Fn.new {|n|
|
||||
|
||||
change.call(src, 17)
|
||||
total = total + dst.value
|
||||
if (dst.value != 1170) IO.print("Projection 1 failed")
|
||||
if (dst.value != 1170) System.print("Projection 1 failed")
|
||||
|
||||
change.call(dst, 1050)
|
||||
|
||||
total = total + src.value
|
||||
if (src.value != 5) IO.print("Projection 2 failed")
|
||||
if (src.value != 5) System.print("Projection 2 failed")
|
||||
|
||||
change.call(scale, 5)
|
||||
for (i in 0...n - 1) {
|
||||
total = total + dests[i].value
|
||||
if (dests[i].value != i * 5 + 1000) IO.print("Projection 3 failed")
|
||||
if (dests[i].value != i * 5 + 1000) System.print("Projection 3 failed")
|
||||
}
|
||||
|
||||
change.call(offset, 2000)
|
||||
for (i in 0...n - 1) {
|
||||
total = total + dests[i].value
|
||||
if (dests[i].value != i * 5 + 2000) IO.print("Projection 4 failed")
|
||||
if (dests[i].value != i * 5 + 2000) System.print("Projection 4 failed")
|
||||
}
|
||||
}
|
||||
|
||||
var start = IO.clock
|
||||
var start = System.clock
|
||||
for (i in 0...40) {
|
||||
chainTest.call(100)
|
||||
projectionTest.call(100)
|
||||
}
|
||||
|
||||
IO.print(total)
|
||||
IO.print("elapsed: ", IO.clock - start)
|
||||
System.print(total)
|
||||
System.print("elapsed: " + (System.clock - start).toString)
|
||||
|
||||
@ -5,8 +5,8 @@ class Fib {
|
||||
}
|
||||
}
|
||||
|
||||
var start = IO.clock
|
||||
var start = System.clock
|
||||
for (i in 1..5) {
|
||||
IO.print(Fib.get(28))
|
||||
System.print(Fib.get(28))
|
||||
}
|
||||
IO.print("elapsed: ", IO.clock - start)
|
||||
System.print("elapsed: " + (System.clock - start).toString)
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
var fibers = []
|
||||
var sum = 0
|
||||
|
||||
var start = IO.clock
|
||||
var start = System.clock
|
||||
|
||||
for (i in 0...100000) {
|
||||
fibers.add(Fiber.new {
|
||||
@ -12,5 +12,5 @@ for (i in 0...100000) {
|
||||
}
|
||||
|
||||
fibers[0].call()
|
||||
IO.print(sum)
|
||||
IO.print("elapsed: ", IO.clock - start)
|
||||
System.print(sum)
|
||||
System.print("elapsed: " + (System.clock - start).toString)
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
var list = []
|
||||
|
||||
var start = IO.clock
|
||||
var start = System.clock
|
||||
for (i in 0...1000000) list.add(i)
|
||||
|
||||
var sum = 0
|
||||
for (i in list) sum = sum + i
|
||||
|
||||
IO.print(sum)
|
||||
IO.print("elapsed: ", IO.clock - start)
|
||||
System.print(sum)
|
||||
System.print("elapsed: " + (System.clock - start).toString)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
var start = IO.clock
|
||||
var start = System.clock
|
||||
|
||||
var map = {}
|
||||
|
||||
@ -10,10 +10,10 @@ var sum = 0
|
||||
for (i in 1..1000000) {
|
||||
sum = sum + map[i]
|
||||
}
|
||||
IO.print(sum)
|
||||
System.print(sum)
|
||||
|
||||
for (i in 1..1000000) {
|
||||
map.remove(i)
|
||||
}
|
||||
|
||||
IO.print("elapsed: ", IO.clock - start)
|
||||
System.print("elapsed: " + (System.clock - start).toString)
|
||||
|
||||
@ -77,7 +77,7 @@ for (animal in animals) {
|
||||
}
|
||||
}
|
||||
|
||||
var start = IO.clock
|
||||
var start = System.clock
|
||||
|
||||
var map = {}
|
||||
|
||||
@ -96,5 +96,5 @@ for (key in keys) {
|
||||
map.remove(key)
|
||||
}
|
||||
|
||||
IO.print(sum)
|
||||
IO.print("elapsed: ", IO.clock - start)
|
||||
System.print(sum)
|
||||
System.print("elapsed: " + (System.clock - start).toString)
|
||||
|
||||
@ -28,7 +28,7 @@ class NthToggle is Toggle {
|
||||
}
|
||||
}
|
||||
|
||||
var start = IO.clock
|
||||
var start = System.clock
|
||||
var n = 100000
|
||||
var val = true
|
||||
var toggle = Toggle.new(val)
|
||||
@ -46,7 +46,7 @@ for (i in 0...n) {
|
||||
val = toggle.activate.value
|
||||
}
|
||||
|
||||
IO.print(toggle.value)
|
||||
System.print(toggle.value)
|
||||
|
||||
val = true
|
||||
var ntoggle = NthToggle.new(val, 3)
|
||||
@ -64,5 +64,5 @@ for (i in 0...n) {
|
||||
val = ntoggle.activate.value
|
||||
}
|
||||
|
||||
IO.print(ntoggle.value)
|
||||
IO.print("elapsed: ", IO.clock - start)
|
||||
System.print(ntoggle.value)
|
||||
System.print("elapsed: " + (System.clock - start).toString)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
var start = IO.clock
|
||||
var start = System.clock
|
||||
|
||||
var count = 0
|
||||
for (i in 1..1000000) {
|
||||
@ -20,5 +20,5 @@ for (i in 1..1000000) {
|
||||
"another") count = count + 1
|
||||
}
|
||||
|
||||
IO.print(count)
|
||||
IO.print("elapsed: ", IO.clock - start)
|
||||
System.print(count)
|
||||
System.print("elapsed: " + (System.clock - start).toString)
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
IO.print(true == true) // expect: true
|
||||
IO.print(true == false) // expect: false
|
||||
IO.print(false == true) // expect: false
|
||||
IO.print(false == false) // expect: true
|
||||
System.print(true == true) // expect: true
|
||||
System.print(true == false) // expect: false
|
||||
System.print(false == true) // expect: false
|
||||
System.print(false == false) // expect: true
|
||||
|
||||
// Not equal to other types.
|
||||
IO.print(true == 1) // expect: false
|
||||
IO.print(false == 0) // expect: false
|
||||
IO.print(true == "true") // expect: false
|
||||
IO.print(false == "false") // expect: false
|
||||
IO.print(false == "") // expect: false
|
||||
System.print(true == 1) // expect: false
|
||||
System.print(false == 0) // expect: false
|
||||
System.print(true == "true") // expect: false
|
||||
System.print(false == "false") // expect: false
|
||||
System.print(false == "") // expect: false
|
||||
|
||||
IO.print(true != true) // expect: false
|
||||
IO.print(true != false) // expect: true
|
||||
IO.print(false != true) // expect: true
|
||||
IO.print(false != false) // expect: false
|
||||
System.print(true != true) // expect: false
|
||||
System.print(true != false) // expect: true
|
||||
System.print(false != true) // expect: true
|
||||
System.print(false != false) // expect: false
|
||||
|
||||
// Not equal to other types.
|
||||
IO.print(true != 1) // expect: true
|
||||
IO.print(false != 0) // expect: true
|
||||
IO.print(true != "true") // expect: true
|
||||
IO.print(false != "false") // expect: true
|
||||
IO.print(false != "") // expect: true
|
||||
System.print(true != 1) // expect: true
|
||||
System.print(false != 0) // expect: true
|
||||
System.print(true != "true") // expect: true
|
||||
System.print(false != "false") // expect: true
|
||||
System.print(false != "") // expect: true
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
IO.print(!true) // expect: false
|
||||
IO.print(!false) // expect: true
|
||||
IO.print(!!true) // expect: true
|
||||
System.print(!true) // expect: false
|
||||
System.print(!false) // expect: true
|
||||
System.print(!!true) // expect: true
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
IO.print(true.toString) // expect: true
|
||||
IO.print(false.toString) // expect: false
|
||||
System.print(true.toString) // expect: true
|
||||
System.print(false.toString) // expect: false
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
IO.print(true is Bool) // expect: true
|
||||
IO.print(true is Object) // expect: true
|
||||
IO.print(true is Num) // expect: false
|
||||
IO.print(true.type == Bool) // expect: true
|
||||
System.print(true is Bool) // expect: true
|
||||
System.print(true is Object) // expect: true
|
||||
System.print(true is Num) // expect: false
|
||||
System.print(true.type == Bool) // expect: true
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
IO.print(Num == Num) // expect: true
|
||||
IO.print(Num == Bool) // expect: false
|
||||
System.print(Num == Num) // expect: true
|
||||
System.print(Num == Bool) // expect: false
|
||||
|
||||
// Not equal to other types.
|
||||
IO.print(Num == 123) // expect: false
|
||||
IO.print(Num == true) // expect: false
|
||||
System.print(Num == 123) // expect: false
|
||||
System.print(Num == true) // expect: false
|
||||
|
||||
IO.print(Num != Num) // expect: false
|
||||
IO.print(Num != Bool) // expect: true
|
||||
System.print(Num != Num) // expect: false
|
||||
System.print(Num != Bool) // expect: true
|
||||
|
||||
// Not equal to other types.
|
||||
IO.print(Num != 123) // expect: true
|
||||
IO.print(Num != true) // expect: true
|
||||
System.print(Num != 123) // expect: true
|
||||
System.print(Num != true) // expect: true
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
class Foo {}
|
||||
|
||||
IO.print(Foo.name) // expect: Foo
|
||||
IO.print(Foo.type.name) // expect: Foo metaclass
|
||||
System.print(Foo.name) // expect: Foo
|
||||
System.print(Foo.type.name) // expect: Foo metaclass
|
||||
|
||||
// Make sure the built-in classes have proper names too.
|
||||
IO.print(Object.name) // expect: Object
|
||||
IO.print(Bool.name) // expect: Bool
|
||||
IO.print(Class.name) // expect: Class
|
||||
System.print(Object.name) // expect: Object
|
||||
System.print(Bool.name) // expect: Bool
|
||||
System.print(Class.name) // expect: Class
|
||||
|
||||
// And metaclass names.
|
||||
IO.print(Object.type.name) // expect: Object metaclass
|
||||
IO.print(Bool.type.name) // expect: Bool metaclass
|
||||
System.print(Object.type.name) // expect: Object metaclass
|
||||
System.print(Bool.type.name) // expect: Bool metaclass
|
||||
|
||||
@ -5,11 +5,11 @@ class Bar is Foo {}
|
||||
class Baz is Bar {}
|
||||
|
||||
// A class with no explicit superclass inherits Object.
|
||||
IO.print(Foo.supertype == Object) // expect: true
|
||||
System.print(Foo.supertype == Object) // expect: true
|
||||
|
||||
// Otherwise, it's the superclass.
|
||||
IO.print(Bar.supertype == Foo) // expect: true
|
||||
IO.print(Baz.supertype == Bar) // expect: true
|
||||
System.print(Bar.supertype == Foo) // expect: true
|
||||
System.print(Baz.supertype == Bar) // expect: true
|
||||
|
||||
// Object has no supertype.
|
||||
IO.print(Object.supertype) // expect: null
|
||||
System.print(Object.supertype) // expect: null
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
class Foo {}
|
||||
|
||||
// A class is a class.
|
||||
IO.print(Foo is Class) // expect: true
|
||||
System.print(Foo is Class) // expect: true
|
||||
|
||||
// Its metatype is also a class.
|
||||
IO.print(Foo.type is Class) // expect: true
|
||||
System.print(Foo.type is Class) // expect: true
|
||||
|
||||
// The metatype's metatype is Class.
|
||||
IO.print(Foo.type.type == Class) // expect: true
|
||||
System.print(Foo.type.type == Class) // expect: true
|
||||
|
||||
// And Class's metatype circles back onto itself.
|
||||
IO.print(Foo.type.type.type == Class) // expect: true
|
||||
IO.print(Foo.type.type.type.type == Class) // expect: true
|
||||
IO.print(Foo.type.type.type.type.type == Class) // expect: true
|
||||
System.print(Foo.type.type.type == Class) // expect: true
|
||||
System.print(Foo.type.type.type.type == Class) // expect: true
|
||||
System.print(Foo.type.type.type.type.type == Class) // expect: true
|
||||
|
||||
@ -2,6 +2,6 @@ var fiber = Fiber.new {
|
||||
Fiber.abort("Error message.")
|
||||
}
|
||||
|
||||
IO.print(fiber.try()) // expect: Error message.
|
||||
IO.print(fiber.isDone) // expect: true
|
||||
IO.print(fiber.error) // expect: Error message.
|
||||
System.print(fiber.try()) // expect: Error message.
|
||||
System.print(fiber.isDone) // expect: true
|
||||
System.print(fiber.error) // expect: Error message.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
var fiber = Fiber.new {
|
||||
IO.print("fiber")
|
||||
System.print("fiber")
|
||||
}
|
||||
|
||||
IO.print("before") // expect: before
|
||||
System.print("before") // expect: before
|
||||
fiber.call() // expect: fiber
|
||||
IO.print("after") // expect: after
|
||||
System.print("after") // expect: after
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
var fiber = Fiber.new {
|
||||
IO.print("call")
|
||||
System.print("call")
|
||||
}
|
||||
|
||||
fiber.call() // expect: call
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
var fiber = Fiber.new {
|
||||
Fiber.abort("Error!")
|
||||
IO.print("should not get here")
|
||||
System.print("should not get here")
|
||||
}
|
||||
|
||||
fiber.try()
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
var fiber = Fiber.new {
|
||||
IO.print("fiber") // expect: fiber
|
||||
System.print("fiber") // expect: fiber
|
||||
}
|
||||
|
||||
IO.print(fiber.call()) // expect: null
|
||||
System.print(fiber.call()) // expect: null
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
var fiber = Fiber.new {
|
||||
IO.print("fiber")
|
||||
System.print("fiber")
|
||||
return "result" // expect: fiber
|
||||
}
|
||||
|
||||
IO.print(fiber.call()) // expect: result
|
||||
System.print(fiber.call()) // expect: result
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
var main = Fiber.current
|
||||
|
||||
var fiber = Fiber.new {
|
||||
IO.print("transferred")
|
||||
IO.print(main.transfer())
|
||||
IO.print("called")
|
||||
System.print("transferred")
|
||||
System.print(main.transfer())
|
||||
System.print("called")
|
||||
}
|
||||
|
||||
fiber.transfer() // expect: transferred
|
||||
IO.print("main") // expect: main
|
||||
System.print("main") // expect: main
|
||||
fiber.call() // expect: null
|
||||
// expect: called
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
var fiber = Fiber.new {
|
||||
IO.print("fiber")
|
||||
System.print("fiber")
|
||||
}
|
||||
|
||||
// The first value passed to the fiber is ignored, since there's no yield call
|
||||
// to return it.
|
||||
IO.print("before") // expect: before
|
||||
System.print("before") // expect: before
|
||||
fiber.call("ignored") // expect: fiber
|
||||
IO.print("after") // expect: after
|
||||
System.print("after") // expect: after
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
var fiber = Fiber.new {
|
||||
IO.print("call")
|
||||
System.print("call")
|
||||
}
|
||||
|
||||
fiber.call(1) // expect: call
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
var fiber = Fiber.new {
|
||||
Fiber.abort("Error!")
|
||||
IO.print("should not get here")
|
||||
System.print("should not get here")
|
||||
}
|
||||
|
||||
fiber.try()
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
var main = Fiber.current
|
||||
|
||||
var fiber = Fiber.new {
|
||||
IO.print("transferred")
|
||||
IO.print(main.transfer())
|
||||
IO.print("called")
|
||||
System.print("transferred")
|
||||
System.print(main.transfer())
|
||||
System.print("called")
|
||||
}
|
||||
|
||||
fiber.transfer() // expect: transferred
|
||||
IO.print("main") // expect: main
|
||||
System.print("main") // expect: main
|
||||
fiber.call("value") // expect: value
|
||||
// expect: called
|
||||
|
||||
@ -2,6 +2,6 @@ var fiber = Fiber.new {
|
||||
"s".unknown
|
||||
}
|
||||
|
||||
IO.print(fiber.error) // expect: null
|
||||
IO.print(fiber.try()) // expect: String does not implement 'unknown'.
|
||||
IO.print(fiber.error) // expect: String does not implement 'unknown'.
|
||||
System.print(fiber.error) // expect: null
|
||||
System.print(fiber.try()) // expect: String does not implement 'unknown'.
|
||||
System.print(fiber.error) // expect: String does not implement 'unknown'.
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
var fiber = Fiber.new {
|
||||
IO.print("1")
|
||||
System.print("1")
|
||||
Fiber.yield()
|
||||
IO.print("2")
|
||||
System.print("2")
|
||||
}
|
||||
|
||||
IO.print(fiber.isDone) // expect: false
|
||||
System.print(fiber.isDone) // expect: false
|
||||
fiber.call() // expect: 1
|
||||
IO.print(fiber.isDone) // expect: false
|
||||
System.print(fiber.isDone) // expect: false
|
||||
fiber.call() // expect: 2
|
||||
IO.print(fiber.isDone) // expect: true
|
||||
System.print(fiber.isDone) // expect: true
|
||||
|
||||
@ -3,4 +3,4 @@ var fiber = Fiber.new {
|
||||
}
|
||||
|
||||
fiber.try()
|
||||
IO.print(fiber.isDone) // expect: true
|
||||
System.print(fiber.isDone) // expect: true
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
var b = Fiber.new {
|
||||
IO.print("fiber b")
|
||||
System.print("fiber b")
|
||||
}
|
||||
|
||||
var a = Fiber.new {
|
||||
IO.print("begin fiber a")
|
||||
System.print("begin fiber a")
|
||||
b.call()
|
||||
IO.print("end fiber a")
|
||||
System.print("end fiber a")
|
||||
}
|
||||
|
||||
IO.print("begin main")
|
||||
System.print("begin main")
|
||||
a.call()
|
||||
IO.print("end main")
|
||||
System.print("end main")
|
||||
|
||||
// expect: begin main
|
||||
// expect: begin fiber a
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
var a = Fiber.new {
|
||||
IO.print("a")
|
||||
System.print("a")
|
||||
}
|
||||
|
||||
var b = Fiber.new {
|
||||
IO.print("b before")
|
||||
System.print("b before")
|
||||
a.transfer()
|
||||
IO.print("b after")
|
||||
System.print("b after")
|
||||
}
|
||||
|
||||
var c = Fiber.new {
|
||||
IO.print("c before")
|
||||
System.print("c before")
|
||||
b.transfer()
|
||||
IO.print("c after")
|
||||
System.print("c after")
|
||||
}
|
||||
|
||||
IO.print("start") // expect: start
|
||||
System.print("start") // expect: start
|
||||
|
||||
c.transfer()
|
||||
// expect: c before
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
var F = Fiber.new {
|
||||
IO.print(1) // expect: 1
|
||||
IO.print(F.transfer()) // expect: null
|
||||
IO.print(2) // expect: 2
|
||||
System.print(1) // expect: 1
|
||||
System.print(F.transfer()) // expect: null
|
||||
System.print(2) // expect: 2
|
||||
}
|
||||
|
||||
F.call()
|
||||
// F remembers its original caller so transfers back to main.
|
||||
IO.print(3) // expect: 3
|
||||
System.print(3) // expect: 3
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
var A = Fiber.new {
|
||||
IO.print(2)
|
||||
System.print(2)
|
||||
B.transfer()
|
||||
IO.print("nope")
|
||||
System.print("nope")
|
||||
}
|
||||
|
||||
var B = Fiber.new {
|
||||
IO.print(1)
|
||||
System.print(1)
|
||||
A.transfer()
|
||||
IO.print(3)
|
||||
System.print(3)
|
||||
}
|
||||
|
||||
B.call()
|
||||
@ -15,4 +15,4 @@ B.call()
|
||||
// expect: 2
|
||||
// expect: 3
|
||||
// B remembers its original caller so returns to main.
|
||||
IO.print(4) // expect: 4
|
||||
System.print(4) // expect: 4
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
var main = Fiber.current
|
||||
|
||||
var fiber = Fiber.new {
|
||||
IO.print("fiber 1")
|
||||
IO.print(main.transfer())
|
||||
System.print("fiber 1")
|
||||
System.print(main.transfer())
|
||||
|
||||
// Yield to bounce back to main and clear the caller so we don't get a
|
||||
// double call() error below.
|
||||
Fiber.yield()
|
||||
|
||||
IO.print(main.transfer())
|
||||
System.print(main.transfer())
|
||||
}
|
||||
|
||||
fiber.transfer() // expect: fiber 1
|
||||
IO.print("main 1") // expect: main 1
|
||||
System.print("main 1") // expect: main 1
|
||||
fiber.call("call 1") // expect: call 1
|
||||
|
||||
IO.print("main 2") // expect: main 2
|
||||
System.print("main 2") // expect: main 2
|
||||
// Transfer back into the fiber so it has a NULL caller.
|
||||
fiber.transfer()
|
||||
|
||||
fiber.call() // expect: null
|
||||
IO.print("main 3") // expect: main 3
|
||||
System.print("main 3") // expect: main 3
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
var main = Fiber.current
|
||||
|
||||
var fiber = Fiber.new {
|
||||
IO.print("fiber")
|
||||
IO.print(main.transfer())
|
||||
System.print("fiber")
|
||||
System.print(main.transfer())
|
||||
}
|
||||
|
||||
fiber.transfer() // expect: fiber
|
||||
IO.print("main") // expect: main
|
||||
System.print("main") // expect: main
|
||||
fiber.transfer("transfer") // expect: transfer
|
||||
|
||||
// This does not get run since we exit when the transferred fiber completes.
|
||||
IO.print("nope")
|
||||
System.print("nope")
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
var a = Fiber.new {
|
||||
IO.print("run")
|
||||
System.print("run")
|
||||
}
|
||||
|
||||
a.call() // expect: run
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
var a = Fiber.new {
|
||||
Fiber.abort("Error!")
|
||||
IO.print("should not get here")
|
||||
System.print("should not get here")
|
||||
}
|
||||
|
||||
a.try()
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
var fiber = Fiber.new {
|
||||
IO.print("called")
|
||||
IO.print(Fiber.yield())
|
||||
IO.print("transferred")
|
||||
System.print("called")
|
||||
System.print(Fiber.yield())
|
||||
System.print("transferred")
|
||||
}
|
||||
|
||||
fiber.call() // expect: called
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
var a = Fiber.new {
|
||||
IO.print("a")
|
||||
System.print("a")
|
||||
}
|
||||
|
||||
var b = Fiber.new {
|
||||
IO.print("b before")
|
||||
System.print("b before")
|
||||
a.transfer("ignored")
|
||||
IO.print("b after")
|
||||
System.print("b after")
|
||||
}
|
||||
|
||||
var c = Fiber.new {
|
||||
IO.print("c before")
|
||||
System.print("c before")
|
||||
b.transfer("ignored")
|
||||
IO.print("c after")
|
||||
System.print("c after")
|
||||
}
|
||||
|
||||
IO.print("start") // expect: start
|
||||
System.print("start") // expect: start
|
||||
|
||||
c.transfer("ignored")
|
||||
// expect: c before
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
var F = Fiber.new {
|
||||
IO.print(1) // expect: 1
|
||||
IO.print(F.transfer("value")) // expect: value
|
||||
IO.print(2) // expect: 2
|
||||
System.print(1) // expect: 1
|
||||
System.print(F.transfer("value")) // expect: value
|
||||
System.print(2) // expect: 2
|
||||
}
|
||||
|
||||
F.call()
|
||||
IO.print(3) // expect: 3
|
||||
System.print(3) // expect: 3
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
var A = Fiber.new {
|
||||
IO.print(2)
|
||||
System.print(2)
|
||||
B.transfer("ignored")
|
||||
IO.print("nope")
|
||||
System.print("nope")
|
||||
}
|
||||
|
||||
var B = Fiber.new {
|
||||
IO.print(1)
|
||||
System.print(1)
|
||||
A.transfer("ignored")
|
||||
IO.print(3)
|
||||
System.print(3)
|
||||
}
|
||||
|
||||
B.call()
|
||||
// expect: 1
|
||||
// expect: 2
|
||||
// expect: 3
|
||||
IO.print(4) // expect: 4
|
||||
System.print(4) // expect: 4
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
var a = Fiber.new {
|
||||
IO.print("run")
|
||||
System.print("run")
|
||||
}
|
||||
|
||||
a.call() // expect: run
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
var a = Fiber.new {
|
||||
Fiber.abort("Error!")
|
||||
IO.print("should not get here")
|
||||
System.print("should not get here")
|
||||
}
|
||||
|
||||
a.try()
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
var fiber = Fiber.new {
|
||||
IO.print("called")
|
||||
IO.print(Fiber.yield())
|
||||
IO.print("transferred")
|
||||
System.print("called")
|
||||
System.print(Fiber.yield())
|
||||
System.print("transferred")
|
||||
}
|
||||
|
||||
fiber.call() // expect: called
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
var fiber = Fiber.new {
|
||||
IO.print("before")
|
||||
System.print("before")
|
||||
true.unknownMethod
|
||||
IO.print("after")
|
||||
System.print("after")
|
||||
}
|
||||
|
||||
IO.print(fiber.try())
|
||||
System.print(fiber.try())
|
||||
// expect: before
|
||||
// expect: Bool does not implement 'unknownMethod'.
|
||||
IO.print("after try") // expect: after try
|
||||
System.print("after try") // expect: after try
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
var fiber = Fiber.new {
|
||||
IO.print("try")
|
||||
System.print("try")
|
||||
}
|
||||
|
||||
fiber.try() // expect: try
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
var fiber = Fiber.new {
|
||||
IO.print("fiber")
|
||||
System.print("fiber")
|
||||
}
|
||||
|
||||
IO.print("before") // expect: before
|
||||
IO.print(fiber.try()) // expect: fiber
|
||||
System.print("before") // expect: before
|
||||
System.print(fiber.try()) // expect: fiber
|
||||
// expect: null
|
||||
IO.print("after") // expect: after
|
||||
System.print("after") // expect: after
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
var fiber = Fiber.new {}
|
||||
IO.print(fiber is Fiber) // expect: true
|
||||
IO.print(fiber is Object) // expect: true
|
||||
IO.print(fiber is Bool) // expect: false
|
||||
IO.print(fiber.type == Fiber) // expect: true
|
||||
System.print(fiber is Fiber) // expect: true
|
||||
System.print(fiber is Object) // expect: true
|
||||
System.print(fiber is Bool) // expect: false
|
||||
System.print(fiber.type == Fiber) // expect: true
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user