1
0
forked from Mirror/wren

Style example output and errors in the docs.

This commit is contained in:
Bob Nystrom
2015-10-18 15:56:52 -07:00
parent 2174ff31e7
commit 545a4cbf7e
24 changed files with 203 additions and 166 deletions

View File

@ -83,7 +83,7 @@ Many methods on a class exist to expose or compute some property of the object.
For example: For example:
:::wren :::wren
System.print("string".count) // "6". System.print("string".count) //> 6
These *getters* are just another kind of method—one without a parameter These *getters* are just another kind of method—one without a parameter
list. You can define them like so: list. You can define them like so:
@ -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`: Just like instance fields, static fields are initially `null`:
:::wren :::wren
System.print(Foo.bar) // null. System.print(Foo.bar) //> null
They can be used from static methods: They can be used from static methods:
:::wren :::wren
Foo.set("foo") Foo.set("foo")
System.print(Foo.bar) // foo. System.print(Foo.bar) //> foo
And also instance methods. When you do so, there is still only one static field And also instance methods. When you do so, there is still only one static field
shared among all instances of the class: shared among all instances of the class:
@ -342,7 +342,7 @@ shared among all instances of the class:
var foo2 = Foo.new() var foo2 = Foo.new()
foo1.setFromInstance("updated") foo1.setFromInstance("updated")
System.print(foo2.baz) // updated. System.print(foo2.baz) //> updated
## Inheritance ## Inheritance
@ -374,20 +374,20 @@ are not inherited.
class Pegasus is Unicorn {} class Pegasus is Unicorn {}
Pegasus.canFly // ERROR: Static methods are not inherited. Pegasus.canFly //! Static methods are not inherited.
This also means constructors are not inherited: This also means constructors are not inherited:
:::wren :::wren
class Unicorn { class Unicorn {
this new(name) { construct new(name) {
System.print("My name is " + name + ".") System.print("My name is " + name + ".")
} }
} }
class Pegasus is Unicorn {} class Pegasus is Unicorn {}
Pegasus.new("Fred") // Error! Pegasus.new("Fred") //! Pegasus does not define new().
Each class gets to control how it may be constructed independently of its base Each class gets to control how it may be constructed independently of its base
classes. However, constructor *initializers* are inherited since those are classes. However, constructor *initializers* are inherited since those are
@ -397,15 +397,15 @@ This means you can do `super` calls inside a constructor:
:::wren :::wren
class Unicorn { class Unicorn {
this new(name) { construct new(name) {
System.print("My name is " + name + ".") System.print("My name is " + name + ".")
} }
} }
class Pegasus is Unicorn { class Pegasus is Unicorn {
this new(name) { construct new(name) {
super(name) super(name)
} }
} }
Pegasus.new("Fred") // Prints "My name is Fred.". Pegasus.new("Fred") //> My name is Fred

View File

@ -10,8 +10,8 @@ Boolean values. There are two instances, `true` and `false`.
Returns the logical complement of the value. Returns the logical complement of the value.
:::wren :::wren
System.print(!true) // "false". System.print(!true) //> false
System.print(!false) // "true". System.print(!false) //> true
### toString ### toString

View File

@ -15,14 +15,14 @@ The superclass of this class.
class Crustacean {} class Crustacean {}
class Crab is Crustacean {} class Crab is Crustacean {}
System.print(Crab.supertype) // "Crustacean". System.print(Crab.supertype) //> Crustacean
A class with no explicit superclass implicitly inherits Object: A class with no explicit superclass implicitly inherits Object:
:::wren :::wren
System.print(Crustacean.supertype) // "Object". System.print(Crustacean.supertype) //> Object
Object forms the root of the class hierarchy and has no supertype: Object forms the root of the class hierarchy and has no supertype:
:::wren :::wren
System.print(Object.supertype) // "null". System.print(Object.supertype) //> null

View File

@ -39,9 +39,9 @@ here means the last fiber that was started using `call` and not `run`.
System.print("After yield") System.print("After yield")
} }
fiber.call() // "Before yield" fiber.call() //> Before yield
System.print("After call") // "After call" System.print("After call") //> After call
fiber.call() // "After yield" fiber.call() //> After yield
When resumed, the parent fiber's `call()` method returns `null`. 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,
:::wren :::wren
var fiber = Fiber.new { var fiber = Fiber.new {
System.print(Fiber.yield()) // "value" System.print(Fiber.yield()) //> value
} }
fiber.call() // Run until the first yield. fiber.call() // Run until the first yield.
@ -77,7 +77,7 @@ Similar to `Fiber.yield` but provides a value to return to the parent fiber's
Fiber.yield("value") Fiber.yield("value")
} }
System.print(fiber.call()) // "value" System.print(fiber.call()) //> value
## Methods ## Methods
@ -107,7 +107,7 @@ If the called fiber is resuming from a yield, the `yield()` method returns
} }
fiber.call() fiber.call()
fiber.call() // Prints "null". fiber.call() //> null
### **call**(value) ### **call**(value)
@ -120,7 +120,7 @@ Invokes the fiber or resumes the fiber if it is in a paused state and sets
} }
fiber.call() fiber.call()
fiber.call("value") // Prints "value". fiber.call("value") //> value
### **isDone** ### **isDone**

View File

@ -25,8 +25,8 @@ It is a runtime error if `function` is not a function.
The number of arguments the function requires. The number of arguments the function requires.
:::wren :::wren
System.print(Fn.new {}.arity) // 0. System.print(Fn.new {}.arity) //> 0
System.print(Fn.new {|a, b, c| a }.arity) // 3. System.print(Fn.new {|a, b, c| a }.arity) //> 3
### **call**(args...) ### **call**(args...)
@ -34,10 +34,10 @@ Invokes the function with the given arguments.
:::wren :::wren
var fn = Fn.new { |arg| var fn = Fn.new { |arg|
System.print(arg) System.print(arg) //> Hello world
} }
fn.call("Hello world") // Prints "Hello world". fn.call("Hello world")
It is a runtime error if the number of arguments given is less than the arity It is a runtime error if the number of arguments given is less than the arity
of the function. If more arguments are given than the function's arity they are of the function. If more arguments are given than the function's arity they are

View File

@ -26,14 +26,14 @@ Inserts the `item` at `index` in the list.
:::wren :::wren
var list = ["a", "b", "c", "d"] var list = ["a", "b", "c", "d"]
list.insert(1, "e") list.insert(1, "e")
System.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. The `index` may be one past the last index in the list to append an element.
:::wren :::wren
var list = ["a", "b", "c"] var list = ["a", "b", "c"]
list.insert(3, "d") list.insert(3, "d")
System.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. 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"] var list = ["a", "b"]
list.insert(-1, "d") list.insert(-1, "d")
list.insert(-2, "c") list.insert(-2, "c")
System.print(list) // "[a, b, c, d]". System.print(list) //> [a, b, c, d]
Returns the inserted item. Returns the inserted item.
:::wren :::wren
System.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. 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.
:::wren :::wren
var list = ["a", "b", "c", "d"] var list = ["a", "b", "c", "d"]
list.removeAt(1) list.removeAt(1)
System.print(list) // "[a, c, d]". System.print(list) //> [a, c, d]
Returns the removed item. Returns the removed item.
System.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. 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.
:::wren :::wren
var list = ["a", "b", "c"] var list = ["a", "b", "c"]
System.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. 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.
:::wren :::wren
var list = ["a", "b", "c"] var list = ["a", "b", "c"]
list[1] = "new" list[1] = "new"
System.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. It is a runtime error if the index is not an integer or is out of bounds.

View File

@ -50,8 +50,8 @@ map, returns `null`.
:::wren :::wren
var map = {"george": "harrison", "ringo": "starr"} var map = {"george": "harrison", "ringo": "starr"}
System.print(map["ringo"]) // "starr". System.print(map["ringo"]) //> starr
System.print(map["pete"]) // "null". System.print(map["pete"]) //> null
### **[**key**]=**(value) operator ### **[**key**]=**(value) operator

View File

@ -8,4 +8,4 @@
Returns `true`, since `null` is considered [false](../control-flow.html#truth). Returns `true`, since `null` is considered [false](../control-flow.html#truth).
:::wren :::wren
System.print(!null) // "true". System.print(!null) //> true

View File

@ -12,7 +12,7 @@ It is a runtime error if `value` is not a string.
### Num.**pi** ### Num.**pi**
The value of π. The value of π.
## Methods ## Methods
@ -21,7 +21,7 @@ The value of π.
The absolute value of the number. The absolute value of the number.
:::wren :::wren
-123.abs // 123 System.print(-123.abs) //> 123
### **acos** ### **acos**
@ -45,8 +45,8 @@ numbers to determine the quadrant of the result.
Rounds the number up to the nearest integer. Rounds the number up to the nearest integer.
:::wren :::wren
1.5.ceil // 2 System.print(1.5.ceil) //> 2
(-3.2).ceil // -3 System.print((-3.2).ceil) //> -3
### **cos** ### **cos**
@ -57,24 +57,24 @@ The cosine of the number.
Rounds the number down to the nearest integer. Rounds the number down to the nearest integer.
:::wren :::wren
1.5.floor // 1 System.print(1.5.floor) //> 1
(-3.2).floor // -4 System.print((-3.2).floor) //> -4
### **isInfinity** ### **isInfinity**
Whether the number is positive or negative infinity or not. Whether the number is positive or negative infinity or not.
:::wren :::wren
99999.isInfinity // false System.print(99999.isInfinity) //> false
(1/0).isInfinity // true System.print((1/0).isInfinity) //> true
### **isInteger** ### **isInteger**
Whether the number is an integer or has some fractional component. Whether the number is an integer or has some fractional component.
:::wren :::wren
2.isInteger // true System.print(2.isInteger) //> true
2.3.isInteger // false System.print(2.3.isInteger) //> false
### **isNan** ### **isNan**
@ -100,7 +100,7 @@ Negates the number.
:::wren :::wren
var a = 123 var a = 123
-a // -123 System.print(-a) //> -123
### **-**(other), **+**(other), **/**(other), **\***(other) operators ### **-**(other), **+**(other), **/**(other), **\***(other) operators
@ -148,9 +148,9 @@ from the beginning number to the ending number.
:::wren :::wren
var range = 1.2..3.4 var range = 1.2..3.4
System.print(range.min) // 1.2 System.print(range.min) //> 1.2
System.print(range.max) // 3.4 System.print(range.max) //> 3.4
System.print(range.isInclusive) // true System.print(range.isInclusive) //> true
### **...**(other) operator ### **...**(other) operator
@ -159,6 +159,6 @@ from the beginning number to the ending number not including the ending number.
:::wren :::wren
var range = 1.2...3.4 var range = 1.2...3.4
System.print(range.min) // 1.2 System.print(range.min) //> 1.2
System.print(range.max) // 3.4 System.print(range.max) //> 3.4
System.print(range.isInclusive) // false System.print(range.isInclusive) //> false

View File

@ -14,8 +14,8 @@ The starting point of the range. A range may be backwards, so this can be
greater than [to]. greater than [to].
:::wren :::wren
(3..5).min // 3. System.print((3..5).min) //> 3
(4..2).min // 4. System.print((4..2).min) //> 4
### **to** ### **to**
@ -23,8 +23,8 @@ The endpoint of the range. If the range is inclusive, this value is included,
otherwise it is not. otherwise it is not.
:::wren :::wren
(3..5).min // 5. System.print((3..5).min) //> 5
(4..2).min // 2. System.print((4..2).min) //> 2
### **min** ### **min**
@ -32,8 +32,8 @@ The minimum bound of the range. Returns either `from`, or `to`, whichever is
lower. lower.
:::wren :::wren
(3..5).min // 3. System.print((3..5).min) //> 3
(4..2).min // 2. System.print((4..2).min) //> 2
### **max** ### **max**
@ -41,16 +41,16 @@ The maximum bound of the range. Returns either `from`, or `to`, whichever is
greater. greater.
:::wren :::wren
(3..5).min // 5. System.print((3..5).min) //> 5
(4..2).min // 4. System.print((4..2).min) //> 4
### **isInclusive** ### **isInclusive**
Whether or not the range includes `to`. (`from` is always included.) Whether or not the range includes `to`. (`from` is always included.)
:::wren :::wren
(3..5).isInclusive // true. System.print((3..5).isInclusive) //> true
(3...5).isInclusive // false. System.print((3...5).isInclusive) //> false
### **iterate**(iterator), **iteratorValue**(iterator) ### **iterate**(iterator), **iteratorValue**(iterator)

View File

@ -17,8 +17,8 @@ If it returns something [false](../control-flow.html#truth), stops iterating
and returns the value. Otherwise, returns `true`. and returns the value. Otherwise, returns `true`.
:::wren :::wren
[1, 2, 3].all {|n| n > 2} // False. System.print([1, 2, 3].all {|n| n > 2}) //> false
[1, 2, 3].all {|n| n < 4} // True. System.print([1, 2, 3].all {|n| n < 4}) //> true
### **any**(predicate) ### **any**(predicate)
@ -29,8 +29,8 @@ If it returns something [true](../control-flow.html#truth), stops iterating and
returns that value. Otherwise, returns `false`. returns that value. Otherwise, returns `false`.
:::wren :::wren
[1, 2, 3].any {|n| n < 1} // False. System.print([1, 2, 3].any {|n| n < 1}) //> false
[1, 2, 3].any {|n| n > 2} // True. System.print([1, 2, 3].any {|n| n > 2}) //> true
### **contains**(element) ### **contains**(element)
@ -51,8 +51,8 @@ Iterates over the sequence, passing each element to the function `predicate`
and counting the number of times the returned value evaluates to `true`. and counting the number of times the returned value evaluates to `true`.
:::wren :::wren
[1, 2, 3].count {|n| n > 2} // 1. System.print([1, 2, 3].count {|n| n > 2}) //> 1
[1, 2, 3].count {|n| n < 4} // 3. System.print([1, 2, 3].count {|n| n < 4}) //> 3
### **each**(function) ### **each**(function)
@ -88,7 +88,9 @@ original sequence while it is iterated.
:::wren :::wren
var doubles = [1, 2, 3].map {|n| n * 2 } var doubles = [1, 2, 3].map {|n| n * 2 }
for (n in doubles) { for (n in doubles) {
System.print(n) // "2", "4", "6". System.print(n) //> 2
//> 4
//> 6
} }
The returned sequence is *lazy*. It only applies the mapping when you iterate The returned sequence is *lazy*. It only applies the mapping when you iterate
@ -105,7 +107,7 @@ To force eager evaluation, just call `.toList` on the result.
var numbers = [1, 2, 3] var numbers = [1, 2, 3]
var doubles = numbers.map {|n| n * 2 }.toList var doubles = numbers.map {|n| n * 2 }.toList
numbers.add(4) numbers.add(4)
System.print(doubles) // [2, 4, 6]. System.print(doubles) //> [2, 4, 6]
### **reduce**(function) ### **reduce**(function)
@ -127,7 +129,7 @@ the sequence is empty, returns `seed`.
Creates a [list](list.html) containing all the elements in the sequence. Creates a [list](list.html) containing all the elements in the sequence.
:::wren :::wren
(1..3).toList // [1, 2, 3]. System.print((1..3).toList) //> [1, 2, 3]
If the sequence is already a list, this creates a copy of it. If the sequence is already a list, this creates a copy of it.
@ -140,9 +142,11 @@ During iteration, each element in the original sequence is passed to the
function `predicate`. If it returns `false`, the element is skipped. function `predicate`. If it returns `false`, the element is skipped.
:::wren :::wren
var odds = (1..10).where {|n| n % 2 == 1 } var odds = (1..6).where {|n| n % 2 == 1 }
for (n in odds) { for (n in odds) {
System.print(n) // "1", "3", "5", "7", "9". System.print(n) //> 1
//> 3
//> 5
} }
The returned sequence is *lazy*. It only applies the filtering when you iterate The returned sequence is *lazy*. It only applies the filtering when you iterate
@ -160,4 +164,4 @@ To force eager evaluation, just call `.toList` on the result.
var numbers = [1, 2, 3, 4, 5, 6] var numbers = [1, 2, 3, 4, 5, 6]
var odds = numbers.where {|n| n % 2 == 1 }.toList var odds = numbers.where {|n| n % 2 == 1 }.toList
numbers.add(7) numbers.add(7)
System.print(odds) // [1, 3, 5]. System.print(odds) //> [1, 3, 5]

View File

@ -37,7 +37,7 @@ on strings *return* byte indexes too. So, for example, this does what you want:
:::wren :::wren
var metalBand = "Fäcëhämmër" var metalBand = "Fäcëhämmër"
var hPosition = metalBand.indexOf("h") var hPosition = metalBand.indexOf("h")
System.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 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 `codePoints` getter. It returns a [Sequence](sequence.html) that decodes UTF-8
@ -53,7 +53,7 @@ ignores any UTF-8 encoding and works directly at the byte level.
Creates a new string containing the UTF-8 encoding of `codePoint`. Creates a new string containing the UTF-8 encoding of `codePoint`.
:::wren :::wren
String.fromCodePoint(8225) // "‡" String.fromCodePoint(8225) //> ‡
It is a runtime error if `codePoint` is not an integer between `0` and It is a runtime error if `codePoint` is not an integer between `0` and
`0x10ffff`, inclusive. `0x10ffff`, inclusive.
@ -68,7 +68,7 @@ methods, the returned object also has a subscript operator that can be used to
directly index bytes. directly index bytes.
:::wren :::wren
System.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 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 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.
:::wren :::wren
var string = "(ᵔᴥᵔ)" var string = "(ᵔᴥᵔ)"
System.print(string.codePoints[0]) // 40, for "(". System.print(string.codePoints[0]) //> 40 (for "(")
System.print(string.codePoints[4]) // 7461, 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 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`. string is reached before the sequence is complete, returns `-1`.
:::wren :::wren
var string = "(ᵔᴥᵔ)" var string = "(ᵔᴥᵔ)"
System.print(string.codePoints[2]) // -1, in the middle of "ᵔ". System.print(string.codePoints[2]) //> -1 (in the middle of "ᵔ")
### **contains**(other) ### **contains**(other)
@ -132,7 +132,7 @@ for iterating over the *code points* in the string:
codePoints.add(c) codePoints.add(c)
} }
System.print(codePoints) // ["(", "ᵔ", "ᴥ", "ᵔ", ")"]. System.print(codePoints) //> [(, ᵔ, ᴥ, ᵔ, )]
If the string contains any bytes that are not valid UTF-8, this iterates over If the string contains any bytes that are not valid UTF-8, this iterates over
those too, one byte at a time. 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`. Returns a string containing the code point starting at byte `index`.
:::wren :::wren
System.print("ʕ•ᴥ•ʔ"[5]) // "ᴥ". System.print("ʕ•ᴥ•ʔ"[5]) //> ᴥ
Since `ʕ` is two bytes in UTF-8 and `•` is three, the fifth byte points to the Since `ʕ` is two bytes in UTF-8 and `•` is three, the fifth byte points to the
bear's nose. 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: UTF-8, this returns a one-byte string containing the byte at that index:
:::wren :::wren
System.print("I ♥ NY"[3]) // One-byte string whose value is 153. System.print("I ♥ NY"[3]) //> (one-byte string [153])
It is a runtime error if `index` is greater than the number of bytes in the It is a runtime error if `index` is greater than the number of bytes in the
string. string.

View File

@ -16,7 +16,7 @@ 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. the object is converted to a string by calling `toString` on it.
:::wren :::wren
System.print("I like bananas") // Prints "I like bananas". System.print("I like bananas") //> I like bananas
### System.**printAll**(sequence) ### System.**printAll**(sequence)
@ -24,7 +24,7 @@ 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. at the end. Each element is converted to a string by calling `toString` on it.
:::wren :::wren
System.printAll([1, [2, 3], 4]) // Prints "1[2, 3]4". System.printAll([1, [2, 3], 4]) //> 1[2, 3]4
### System.**write**(object) ### System.**write**(object)
@ -32,7 +32,7 @@ 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. afterwards. Converts the value to a string by calling `toString` on it.
:::wren :::wren
System.write(4 + 5) // Prints "9". System.write(4 + 5) //> 9
In the above example, the result of `4 + 5` is printed, and then the prompt is 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. printed on the same line because no newline character was printed afterwards.

View File

@ -11,11 +11,11 @@ simple bugs where your code doesn't follow the language's grammar, like:
:::wren :::wren
1 + * 2 1 + * 2
Wren will detect these errors as soon as it tries to read your code. When it Wren detects these errors as soon as it tries to read your code. When it hits
hits one, you'll get a friendly error message, like: one, you get a friendly error message, like:
:::text :::text
[script.wren line 1] Error on '*': Unexpected token for expression. [main line 1] Error on '*': Unexpected token for expression.
Some slightly more "semantic" errors fall into this bucket too. Things like Some slightly more "semantic" errors fall into this bucket too. Things like
using a variable that hasn't been defined, or declaring two variables with the using a variable that hasn't been defined, or declaring two variables with the
@ -28,7 +28,7 @@ same name in the same scope. So if you do:
Wren tells you: Wren tells you:
:::text :::text
[script.wren line 2] Error on 'a': Top-level variable is already defined. [main line 2] Error on 'a': Top-level variable is already defined.
Note that it does this before it executes *any* code. Unlike some other Note that it does this before it executes *any* code. Unlike some other
scripting languages, Wren tries to help you find your errors as soon as scripting languages, Wren tries to help you find your errors as soon as
@ -78,7 +78,7 @@ This exits with:
:::text :::text
Subscript must be a number or a range. Subscript must be a number or a range.
[script.wren line 2] in (script) [main line 2] in (script)
These are the most two common kinds of runtime errors, but there are others. These are the most two common kinds of runtime errors, but there are others.
Stuff like out of bounds errors on lists, calling a function with the wrong Stuff like out of bounds errors on lists, calling a function with the wrong

View File

@ -97,14 +97,14 @@ call:
:::wren :::wren
class Base { class Base {
method { method() {
System.print("base method") System.print("base method")
} }
} }
class Derived is Base { class Derived is Base {
method { method() {
super.method // Prints "base method". super.method() //> base method
} }
} }
@ -113,19 +113,17 @@ base class constructor:
:::wren :::wren
class Base { class Base {
this new(arg) { construct new(arg) {
System.print("base constructor got " + arg) System.print("base got " + arg)
} }
} }
class Derived is Base { class Derived is Base {
this new() { construct new() {
super("value") // Prints "base constructor got value". super("value") //> base got value
} }
} }
**TODO: constructors**
## Operators ## Operators
Wren has most of the same operators you know and love with the same precedence Wren has most of the same operators you know and love with the same precedence
@ -213,21 +211,20 @@ value of the left-hand side, the right-hand operand expression may or may not
be evaluated. Because of this, they cannot be overloaded and their behavior is be evaluated. Because of this, they cannot be overloaded and their behavior is
fixed. fixed.
A `&&` ("logical and") expression evaluates the left-hand argument. If it's A `&&` ("logical and") expression evaluates the left-hand argument. If
[false](control-flow.html#truth), it returns that value. Otherwise it evaluates it's [false](control-flow.html#truth), it returns that value. Otherwise it evaluates and returns the right-hand argument.
and returns the right-hand argument.
:::wren :::wren
System.print(false && 1) // false System.print(false && 1) //> false
System.print(1 && 2) // 2 System.print(1 && 2) //> 2
An `||` ("logical or") expression is reversed. If the left-hand argument is An `||` ("logical or") expression is reversed. If the left-hand argument is
[true](control-flow.html#truth), it's returned, otherwise the right-hand [true](control-flow.html#truth), it's returned, otherwise the right-hand
argument is evaluated and returned: argument is evaluated and returned:
:::wren :::wren
System.print(false || 1) // 1 System.print(false || 1) //> 1
System.print(1 || 2) // 1 System.print(1 || 2) //> 1
## The conditional operator `?:` ## The conditional operator `?:`
@ -251,11 +248,11 @@ operand is a class. It evaluates to `true` if the object is an instance of the
class (or one of its subclasses). class (or one of its subclasses).
:::wren :::wren
123 is Num // true System.print(123 is Num) //> true
"s" is Num // false System.print("s" is Num) //> false
null is String // false System.print(null is String) //> false
[] is List // true System.print([] is List) //> true
[] is Sequence // true System.print([] is Sequence) //> true
## Precedence ## Precedence

View File

@ -32,8 +32,8 @@ using the `Fiber` class's constructor:
} }
Creating a fiber does not immediately run it. It's just a first class bundle of Creating a fiber does not immediately run it. It's just a first class bundle of
code sitting there waiting to be activated, a bit like a code sitting there waiting to be activated, a bit like
[function](functions.html). a [function](functions.html).
## Invoking fibers ## Invoking fibers
@ -49,9 +49,9 @@ it's considered *done*:
:::wren :::wren
var fiber = Fiber.new { System.print("Hi") } var fiber = Fiber.new { System.print("Hi") }
fiber.isDone // false System.print(fiber.isDone) //> false
fiber.call() fiber.call()
fiber.isDone // true System.print(fiber.isDone) //> true
When it finishes, it automatically resumes the fiber that called it. It's a When it finishes, it automatically resumes the fiber that called it. It's a
runtime error to try to call a fiber that is already done. runtime error to try to call a fiber that is already done.
@ -91,9 +91,10 @@ This program prints:
fiber 2 fiber 2
main 3 main 3
Note that even though this program has *concurrency*, it's still Note that even though this program has *concurrency*, it's
*deterministic*. You can reason precisely about what it's doing and aren't at still *deterministic*. You can reason precisely about what it's doing and
the mercy of a thread scheduler playing Russian roulette with your code. aren't at the mercy of a thread scheduler playing Russian roulette with your
code.
## Passing values ## Passing values
@ -116,7 +117,7 @@ ignored. That's because the fiber isn't waiting on a `yield()` call, so there's
nowhere 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 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 `yield()`, that will become the return value of the `call()` that was used to
invoke the fiber: invoke the fiber:
:::wren :::wren
@ -135,8 +136,8 @@ Python and C# that have *generators*. Those let you define a function call that
you can suspend and resume. When using the function, it appears like a sequence you can suspend and resume. When using the function, it appears like a sequence
you can iterate over. you can iterate over.
Wren's fibers can do that, but they can do much more. Like Lua, they are full Wren's fibers can do that, but they can do much more. Like Lua, they are
*coroutines*&mdash;they can suspend from anywhere in the callstack. For full *coroutines*&mdash;they can suspend from anywhere in the callstack. For
example: example:
:::wren :::wren

View File

@ -26,8 +26,9 @@ a method. At its simplest, it looks like this:
} }
Here we're invoking the `callMe` method on `blondie`. We're passing one Here we're invoking the `callMe` method on `blondie`. We're passing one
argument, a function whose body is the following argument, a function whose body is the
[block](syntax.html#blocks)&mdash;everything between that pair of curly braces. following [block](syntax.html#blocks)&mdash;everything between that pair of
curly braces.
Methods that take a block argument receive it as a normal parameter. `callMe` Methods that take a block argument receive it as a normal parameter. `callMe`
could be defined like so: could be defined like so:
@ -144,7 +145,7 @@ leaving the scope where the function is defined:
:::wren :::wren
class Counter { class Counter {
static create { static create() {
var i = 0 var i = 0
return Fn.new { i = i + 1 } return Fn.new { i = i + 1 }
} }
@ -156,7 +157,7 @@ the function is returned from `create`, it is still able to read and assign
to`i`: to`i`:
:::wren :::wren
var counter = Counter.create var counter = Counter.create()
System.print(counter.call()) // Prints "1". System.print(counter.call()) //> 1
System.print(counter.call()) // Prints "2". System.print(counter.call()) //> 2
System.print(counter.call()) // Prints "3". System.print(counter.call()) //> 3

View File

@ -19,20 +19,20 @@ element you want. Like most languages, indexes start at zero:
:::wren :::wren
var hirsute = ["sideburns", "porkchops", "'stache", "goatee"] var hirsute = ["sideburns", "porkchops", "'stache", "goatee"]
hirsute[0] // "sideburns". hirsute[0] //> sideburns
hirsute[1] // "porkchops". hirsute[1] //> porkchops
Negative indices counts backwards from the end: Negative indices counts backwards from the end:
:::wren :::wren
hirsute[-1] // "goatee". hirsute[-1] //> goatee
hirsute[-2] // "'stache". hirsute[-2] //> 'stache
It's a runtime error to pass an index outside of the bounds of the list. If you It's a runtime error to pass an index outside of the bounds of the list. If you
don't know what those bounds are, you can find out using count: don't know what those bounds are, you can find out using count:
:::wren :::wren
hirsute.count // 4. hirsute.count //> 4
## Slices and ranges ## Slices and ranges
@ -40,7 +40,7 @@ Sometimes you want to copy a chunk of elements from a list. You can do that by
passing a [range](values.html#ranges) to the subscript operator, like so: passing a [range](values.html#ranges) to the subscript operator, like so:
:::wren :::wren
hirsute[1..2] // ["porkchops", "'stache"]. hirsute[1..2] //> [porkchops, 'stache]
This returns a new list containing the elements of the original list whose This returns a new list containing the elements of the original list whose
indices are within the given range. Both inclusive and exclusive ranges work indices are within the given range. Both inclusive and exclusive ranges work
@ -59,14 +59,14 @@ existing element in the list using the subscript setter:
:::wren :::wren
hirsute[1] = "muttonchops" hirsute[1] = "muttonchops"
System.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 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: use `add` to append a single item to the end:
:::wren :::wren
hirsute.add("goatee") hirsute.add("goatee")
System.print(hirsute.count) // 4. System.print(hirsute.count) //> 4
You can insert a new element at a specific position using `insert`: 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:
:::wren :::wren
var letters = ["a", "b", "c"] var letters = ["a", "b", "c"]
letters.insert(3, "d") // OK: inserts at end. letters.insert(3, "d") // OK: inserts at end.
System.print(letters) // ["a", "b", "c", "d"] System.print(letters) //> [a, b, c, d]
letters.insert(-2, "e") // Counts back from size after insert. letters.insert(-2, "e") // Counts back from size after insert.
System.print(letters) // ["a", "b", "c", "e", "d"] System.print(letters) //> [a, b, c, e, d]
## Removing elements ## Removing elements
@ -97,15 +97,15 @@ gap:
:::wren :::wren
var letters = ["a", "b", "c", "d"] var letters = ["a", "b", "c", "d"]
letters.removeAt(1) letters.removeAt(1)
System.print(letters) // ["a", "c", "d"] System.print(letters) //> [a, c, d]
The `removeAt` method returns the removed item: The `removeAt` method returns the removed item:
:::wren :::wren
System.print(letters.removeAt(1)) // "c" System.print(letters.removeAt(1)) //> c
If you want to remove everything from the list, you can clear it: If you want to remove everything from the list, you can clear it:
:::wren :::wren
hirsute.clear() hirsute.clear()
System.print(hirsute) // [] System.print(hirsute) //> []

View File

@ -58,7 +58,7 @@ To find the value associated with some key, again you use your friend the
subscript operator: subscript operator:
:::wren :::wren
System.print(capitals["Idaho"]) // "Boise". System.print(capitals["Idaho"]) //> Boise
If the key is present, this returns its value. Otherwise, it returns `null`. Of 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 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()`:
:::wren :::wren
var belief = {"nihilism": null} var belief = {"nihilism": null}
System.print(belief["nihilism"]) // "null" though key exists. System.print(belief["nihilism"]) //> null (though key exists)
System.print(belief["solipsism"]) // Also "null". System.print(belief["solipsism"]) //> null
System.print(belief.containsKey("nihilism")) // "true". System.print(belief.containsKey("nihilism")) //> true
System.print(belief.containsKey("solipsism")) // "false". System.print(belief.containsKey("solipsism")) //> false
You can see how many entries a map contains using `count`: You can see how many entries a map contains using `count`:
:::wren :::wren
System.print(capitals.count) // "3". System.print(capitals.count) //> 3
## Removing entries ## Removing entries
@ -86,12 +86,12 @@ entry you want to delete:
:::wren :::wren
capitals.remove("Maine") capitals.remove("Maine")
System.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: If the key was found, this returns the value that was associated with it:
:::wren :::wren
System.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`. If the key wasn't in the map to begin with, `remove()` just returns `null`.
@ -100,7 +100,7 @@ can just call `clear()`:
:::wren :::wren
capitals.clear() capitals.clear()
System.print(capitals.count) // "0". System.print(capitals.count) //> 0
[lists]: lists.html [lists]: lists.html

View File

@ -138,6 +138,13 @@ h2 {
font: 500 24px $header; font: 500 24px $header;
margin: 24px 0 0 0; margin: 24px 0 0 0;
color: $link; color: $link;
code {
border: none;
background: inherit;
color: inherit;
font-size: 24px;
}
} }
h3 { h3 {
@ -245,7 +252,7 @@ footer {
span.vc { color: hsl(130, 60%, 40%); } span.vc { color: hsl(130, 60%, 40%); }
// Numbers. // Numbers.
span.m, span.mi, span.mf { color: hsl(30, 80%, 45%); }// hsl(90, 80%, 35%) span.m, span.mi, span.mf { color: hsl(30, 80%, 45%); }
// Strings. // Strings.
span.s, span.s2 { color: hsl(40, 80%, 45%); } span.s, span.s2 { color: hsl(40, 80%, 45%); }
@ -257,6 +264,29 @@ footer {
// Preprocessor directives. // Preprocessor directives.
span.cp { color: hsl(270, 40%, 60%); } span.cp { color: hsl(270, 40%, 60%); }
span.output {
float: right;
color: hsl(150, 50%, 45%);
&::before, &::after {
color: hsl(150, 50%, 80%);
}
// Tall angle brackets.
&::before { content: "\276c "; }
&::after { content: ' \276d'; }
}
span.error {
float: right;
color: hsl(350, 50%, 60%);
&::before {
color: hsl(350, 50%, 75%);
content: "Error: ";
}
}
} }
// Have a different primary color for the core library docs. // Have a different primary color for the core library docs.

View File

@ -91,7 +91,7 @@ statement for the else:
:::wren :::wren
if (happy && knowIt) { if (happy && knowIt) {
hands.clap hands.clap()
} else System.print("sad") } else System.print("sad")
Blocks have two similar but not identical forms. Typically, blocks contain a Blocks have two similar but not identical forms. Typically, blocks contain a

View File

@ -57,12 +57,12 @@ A handful of escape characters are supported:
A `\u` followed by four hex digits can be used to specify a Unicode code point: A `\u` followed by four hex digits can be used to specify a Unicode code point:
:::wren :::wren
System.print("\u0041\u0b83\u00DE") // "AஃÞ" System.print("\u0041\u0b83\u00DE") //> AஃÞ
A `\x` followed by two hex digits specifies a single unencoded byte: A `\x` followed by two hex digits specifies a single unencoded byte:
:::wren :::wren
System.print("\x48\x69\x2e") // "Hi." System.print("\x48\x69\x2e") //> Hi.
Strings are instances of class [String](core/string.html). Strings are instances of class [String](core/string.html).
@ -91,7 +91,7 @@ example:
:::wren :::wren
var list = ["a", "b", "c", "d", "e"] var list = ["a", "b", "c", "d", "e"]
var slice = list[1..3] var slice = list[1..3]
System.print(slice) // ["b", "c", "d"] System.print(slice) //> [b, c, d]
Their class is [Range](core/range.html). Their class is [Range](core/range.html).

View File

@ -13,7 +13,7 @@ defined, it can be accessed by name as you would expect.
:::wren :::wren
var animal = "Slow Loris" var animal = "Slow Loris"
System.print(animal) // Prints "Slow Loris". System.print(animal) //> Slow Loris
## Scope ## Scope
@ -22,11 +22,11 @@ until the end of the [block](syntax.html#blocks) where that definition appears.
:::wren :::wren
{ {
System.print(a) // ERROR! a doesn't exist yet. System.print(a) //! "a" doesn't exist yet.
var a = 123 var a = 123
System.print(a) // "123" System.print(a) //> 123
} }
System.print(a) // ERROR! a doesn't exist anymore. System.print(a) //! "a" doesn't exist anymore.
Variables defined at the top level of a script are *top-level* and are visible 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*. to the [module](modules.html) system. All other variables are *local*.
@ -38,15 +38,15 @@ intend to do much).
var a = "outer" var a = "outer"
{ {
var a = "inner" var a = "inner"
System.print(a) // Prints "inner". System.print(a) //> inner
} }
System.print(a) // Prints "outer". System.print(a) //> outer
Declaring a variable with the same name in the *same* scope *is* an error. Declaring a variable with the same name in the *same* scope *is* an error.
:::wren :::wren
var a = "hi" var a = "hi"
var a = "again" // ERROR! var a = "again" //! "a" is already declared.
## Assignment ## Assignment
@ -65,6 +65,6 @@ assigned value.
:::wren :::wren
var a = "before" var a = "before"
System.print(a = "after") // Prints "after". System.print(a = "after") //> after
**TODO: Top-level names.** **TODO: Top-level names.**

View File

@ -93,6 +93,10 @@ def format_file(path, skip_up_to_date):
html = markdown.markdown(contents, ['def_list', 'codehilite', 'smarty']) html = markdown.markdown(contents, ['def_list', 'codehilite', 'smarty'])
# Use special formatting for example output and errors.
html = html.replace('<span class="c1">//&gt; ', '<span class="output">')
html = html.replace('<span class="c1">//! ', '<span class="error">')
modified = datetime.fromtimestamp(os.path.getmtime(in_path)) modified = datetime.fromtimestamp(os.path.getmtime(in_path))
mod_str = modified.strftime('%B %d, %Y') mod_str = modified.strftime('%B %d, %Y')