Tag return types where Dynamic is not needed

This way the standard library relies less on dynamic return types, using
them only where the return type is truly dynamic.
parent 6c4ec92a
Pipeline #100139399 passed with stages
in 14 minutes and 45 seconds
......@@ -76,7 +76,7 @@ impl Inspect for Array!(T) {
}
# Formats this `Array` into a human-readable representation.
def format_for_inspect(formatter: Formatter) where T: Inspect {
def format_for_inspect(formatter: Formatter) -> Nil where T: Inspect {
let last = length - 1
formatter.push('Array')
......@@ -98,5 +98,7 @@ impl Inspect for Array!(T) {
}
formatter.push(' }')
Nil
}
}
......@@ -42,8 +42,9 @@ impl ToString for Boolean {
}
impl Hash for Boolean {
def hash(hasher: Hasher) {
def hash(hasher: Hasher) -> Nil {
hasher.write_boolean(self)
Nil
}
}
......
......@@ -3,19 +3,22 @@
import std::format::(self, Formatter, Inspect)
impl Inspect for Boolean {
def format_for_inspect(formatter: Formatter) {
def format_for_inspect(formatter: Formatter) -> Nil {
formatter.push('Boolean')
Nil
}
}
impl Inspect for True {
def format_for_inspect(formatter: Formatter) {
def format_for_inspect(formatter: Formatter) -> Nil {
formatter.push('True')
Nil
}
}
impl Inspect for False {
def format_for_inspect(formatter: Formatter) {
def format_for_inspect(formatter: Formatter) -> Nil {
formatter.push('False')
Nil
}
}
......@@ -390,10 +390,12 @@ impl Length for ByteArray {
impl Inspect for ByteArray {
# Formats this `ByteArray` into a human-readable representation.
def format_for_inspect(formatter: Formatter) {
def format_for_inspect(formatter: Formatter) -> Nil {
formatter.push('ByteArray { ')
formatter.push(length.to_string)
formatter.push(' bytes }')
Nil
}
}
......
......@@ -790,15 +790,19 @@ object Lexer {
consume_whitespace
}
def advance_line {
def advance_line -> Nil {
@position += 1
@column = 1
@line += 1
Nil
}
def advance_one_byte {
def advance_one_byte -> Nil {
@position += 1
@column += 1
Nil
}
def slice_string(start: Integer, stop: Integer) -> String {
......
......@@ -1197,7 +1197,7 @@ object Parser {
True
}
def require_token_type(token: Token, expected: String) !! ParseError {
def require_token_type(token: Token, expected: String) !! ParseError -> Nil {
(token.type == expected).if_true {
return
}
......@@ -1331,7 +1331,7 @@ object Parser {
Nil
}
def list_separator_or_terminal(type: String) !! ParseError {
def list_separator_or_terminal(type: String) !! ParseError -> Nil {
let peeked = peek_token
(peeked.type == 'comma').if_true {
......
......@@ -425,9 +425,11 @@ object LayoutBuilder {
}
# Disables the padding of members.
def disable_padding {
def disable_padding -> Nil {
@padding = False
@alignment = 1
Nil
}
# Creates a new `Layout` based on the current state of this builder.
......
......@@ -347,8 +347,9 @@ impl ToString for Float {
}
impl Hash for Float {
def hash(hasher: Hasher) {
def hash(hasher: Hasher) -> Nil {
hasher.write_float(self)
Nil
}
}
......
......@@ -3,7 +3,8 @@
import std::format::(Formatter, Inspect)
impl Inspect for Float {
def format_for_inspect(formatter: Formatter) {
def format_for_inspect(formatter: Formatter) -> Nil {
formatter.push(to_string)
Nil
}
}
......@@ -11,15 +11,16 @@ let MAX_DEPTH = 31
# A Formatter can be used to format an object for debugging purposes.
trait Formatter: ToString {
# Pushes the given `String` into the underlying buffer.
def push(string: String)
def push(string: String) -> String
# Descends into a child object, running the supplied block if the object
# should be formatted.
#
# This method can be used to produce a placeholder when formatting an object
# that is too deeply nested.
def descend(block: do) {
def descend(block: do) -> Nil {
block.call
Nil
}
}
......@@ -46,7 +47,7 @@ impl ToString for DefaultFormatter {
impl Formatter for DefaultFormatter {
# Pushes a new `String` into the underlying buffer.
def push(string: String) {
def push(string: String) -> String {
@buffer.push(string)
}
......@@ -55,19 +56,19 @@ impl Formatter for DefaultFormatter {
#
# If nesting _is_ too great, a placeholder value is added to the buffer, and
# the supplied block is not executed.
def descend(block: do) {
(@nesting >= MAX_DEPTH).if(
true: {
push(PLACEHOLDER)
},
false: {
@nesting += 1
block.call
@nesting -= 1
}
)
def descend(block: do) -> Nil {
(@nesting >= MAX_DEPTH).if_true {
push(PLACEHOLDER)
return
}
@nesting += 1
block.call
@nesting -= 1
Nil
}
}
......@@ -82,7 +83,7 @@ trait Inspect {
#
# Objects implementing this method should push their values into the given
# `Formatter`, instead of immediately returning a `String`.
def format_for_inspect(formatter: Formatter)
def format_for_inspect(formatter: Formatter) -> Nil
}
# Returns a human-readable representation of the object.
......
......@@ -33,5 +33,5 @@ trait Hasher {
# A value that can be hashed.
trait Hash: Equal {
# Writes the hash for `self` into the given `Hasher`.
def hash(hasher: Hasher)
def hash(hasher: Hasher) -> Nil
}
......@@ -146,8 +146,9 @@ impl Numeric for Integer {
}
impl Hash for Integer {
def hash(hasher: Hasher) {
def hash(hasher: Hasher) -> Nil {
hasher.write_integer(self)
Nil
}
}
......
......@@ -104,7 +104,8 @@ impl ToRange!(Integer) for Integer {
}
impl Inspect for Integer {
def format_for_inspect(formatter: Formatter) {
def format_for_inspect(formatter: Formatter) -> Nil {
formatter.push(to_string)
Nil
}
}
......@@ -385,7 +385,7 @@ object Map!(K: Hash + Equal, V) {
}
# Resizes and rehashes `self`.
def rehash {
def rehash -> Nil {
let old_buckets = @buckets
@capacity = @capacity * 2
......@@ -399,6 +399,8 @@ object Map!(K: Hash + Equal, V) {
rehash_pair(pair!)
}
}
Nil
}
# Hashes the supplied key using the internal hasher of this `Map`.
......@@ -414,7 +416,7 @@ object Map!(K: Hash + Equal, V) {
#
# The `Pair` to insert must be pre-hashed using the `Hasher` used internally
# by this `Map`, otherwise it might not be retrieved later.
def insert_pair(mut pair: Pair!(K, V)) {
def insert_pair(mut pair: Pair!(K, V)) -> Nil {
let mut index = desired_bucket(pair.hash)
{
......@@ -444,7 +446,7 @@ object Map!(K: Hash + Equal, V) {
}
# Rehashes an existing pair into the list of buckets.
def rehash_pair(mut pair: Pair!(K, V)) {
def rehash_pair(mut pair: Pair!(K, V)) -> Nil {
let mut index = desired_bucket(pair.hash)
{
......@@ -507,7 +509,7 @@ object Map!(K: Hash + Equal, V) {
}
# Shifts all pairs to the left starting at the given bucket index.
def backwards_shift(mut index: Integer) {
def backwards_shift(mut index: Integer) -> Nil {
let mut pair = @buckets[index]
{ pair.and { pair!.distance.positive? } }.while_true {
......@@ -519,6 +521,8 @@ object Map!(K: Hash + Equal, V) {
index += 1
pair = @buckets[index]
}
Nil
}
}
......@@ -638,7 +642,9 @@ impl Inspect for Map!(K, V) {
}
# Formats this `Map` into a human-readable representation.
def format_for_inspect(formatter: Formatter) where K: Inspect, V: Inspect {
def format_for_inspect(
formatter: Formatter
) -> Nil where K: Inspect, V: Inspect {
let last = length - 1
let mut index = 0
......@@ -669,5 +675,7 @@ impl Inspect for Map!(K, V) {
}
formatter.push(' }')
Nil
}
}
......@@ -110,7 +110,8 @@ impl UnknownMessage for Nil {
impl Optional for Nil {}
impl Hash for Nil {
def hash(hasher: Hasher) {
def hash(hasher: Hasher) -> Nil {
_INKOC.hasher_write(hasher, self)
Nil
}
}
......@@ -3,7 +3,8 @@
import std::format::(Formatter, Inspect)
impl Inspect for Nil {
def format_for_inspect(formatter: Formatter) {
def format_for_inspect(formatter: Formatter) -> Nil {
formatter.push('Nil')
Nil
}
}
......@@ -32,7 +32,7 @@ impl Inspect for Object {
}
# Formats a human-readable representation of this object.
def format_for_inspect(formatter: Formatter) {
def format_for_inspect(formatter: Formatter) -> Nil {
let self_mirror = mirror.reflect_object(self)
let attributes = self_mirror.instance_attributes
let last_index = attributes.length - 1
......@@ -62,5 +62,7 @@ impl Inspect for Object {
}
formatter.push(' }')
Nil
}
}
......@@ -52,7 +52,9 @@ object Pair!(A, B) {
}
impl Inspect for Pair!(A, B) {
def format_for_inspect(formatter: Formatter) where A: Inspect, B: Inspect {
def format_for_inspect(
formatter: Formatter
) -> Nil where A: Inspect, B: Inspect {
formatter.push('Pair { ')
formatter.descend {
......@@ -66,6 +68,8 @@ impl Inspect for Pair!(A, B) {
}
formatter.push(' }')
Nil
}
}
......@@ -76,9 +80,11 @@ impl Equal for Pair!(A, B) {
}
impl Hash for Pair!(A, B) {
def hash(hasher: Hasher) where A: Hash, B: Hash {
def hash(hasher: Hasher) -> Nil where A: Hash, B: Hash {
@first.hash(hasher)
@second.hash(hasher)
Nil
}
}
......@@ -149,7 +155,7 @@ object Triple!(A, B, C) {
impl Inspect for Triple!(A, B, C) {
def format_for_inspect(
formatter: Formatter
) where A: Inspect, B: Inspect, C: Inspect {
) -> Nil where A: Inspect, B: Inspect, C: Inspect {
formatter.push('Triple { ')
formatter.descend {
......@@ -169,6 +175,8 @@ impl Inspect for Triple!(A, B, C) {
}
formatter.push(' }')
Nil
}
}
......@@ -181,10 +189,12 @@ impl Equal for Triple!(A, B, C) {
}
impl Hash for Triple!(A, B, C) {
def hash(hasher: Hasher) where A: Hash, B: Hash, C: Hash {
def hash(hasher: Hasher) -> Nil where A: Hash, B: Hash, C: Hash {
@first.hash(hasher)
@second.hash(hasher)
@third.hash(hasher)
Nil
}
}
......@@ -197,7 +197,7 @@ impl Inspect for Set!(V) {
}
# Formats this `Set` into a human-readable representation.
def format_for_inspect(formatter: Formatter) where V: Inspect {
def format_for_inspect(formatter: Formatter) -> Nil where V: Inspect {
let last = length - 1
let mut index = 0
......@@ -222,5 +222,7 @@ impl Inspect for Set!(V) {
}
formatter.push(' }')
Nil
}
}
......@@ -231,7 +231,8 @@ impl Add!(String) for String {
}
impl Hash for String {
def hash(hasher: Hasher) {
def hash(hasher: Hasher) -> Nil {
hasher.write_string(self)
Nil
}
}
......@@ -30,8 +30,9 @@ impl Inspect for String {
#
# # This would print "hello" (including quotes) to STDOUT.
# stdout.print(fmt.to_string)
def format_for_inspect(formatter: Formatter) {
def format_for_inspect(formatter: Formatter) -> Nil {
formatter.push(_INKOC.string_format_debug(self))
Nil
}
}
......
......@@ -101,18 +101,20 @@ import std::test::test_group::TestGroup
let DEFAULT_CLIENT = runner.start
# Defines a new test group and sends it to the default test runner.
def group(name: String, body: do (TestGroup)) {
def group(name: String, body: do (TestGroup)) -> TestGroup {
let group = TestGroup.new(name: name, client: DEFAULT_CLIENT)
body.call(group)
group
}
# Sets a configuration option of the default `Client` to the given value.
def configure(option: String, value: Dynamic) {
def configure!(T)(option: String, value: T) -> T {
DEFAULT_CLIENT.configure(option, value)
}
# Runs all the tests registered with the default `Client`.
def run {
def run -> Nil {
DEFAULT_CLIENT.run
}
......@@ -48,7 +48,7 @@ object PanicTest {
@block = block
}
def run {
def run -> Nil {
process.panicking do (error) {
notify_owner(PanicResult.new(panicked: True, error: error))
}
......@@ -56,15 +56,17 @@ object PanicTest {
@block.call
notify_owner(PanicResult.new(panicked: False))
Nil
}
def notify_owner(result: PanicResult) {
def notify_owner(result: PanicResult) -> Nil {
@owner.send(result)
Nil
}
}
# Asserts that the given arguments are equal to each other.
def equal!(T: Inspect + Equal)(given: T, expected: T) {
def equal!(T: Inspect + Equal)(given: T, expected: T) -> Nil {
(given == expected).if_true {
return
}
......@@ -80,7 +82,7 @@ def equal!(T: Inspect + Equal)(given: T, expected: T) {
}
# Asserts that the given arguments are not equal to each other.
def not_equal!(T: Inspect + Equal)(given: T, expected: T) {
def not_equal!(T: Inspect + Equal)(given: T, expected: T) -> Nil {
(given == expected).if_false {
return
}
......@@ -96,7 +98,7 @@ def not_equal!(T: Inspect + Equal)(given: T, expected: T) {
}
# Asserts that the first argument is greater than the second argument.
def greater!(T: Inspect + Greater)(given: T, minimum: T) {
def greater!(T: Inspect + Greater)(given: T, minimum: T) -> Nil {
(given > minimum).if_true {
return
}
......@@ -112,7 +114,7 @@ def greater!(T: Inspect + Greater)(given: T, minimum: T) {
}
# Asserts that the given lambda panics.
def panic(block: lambda) {
def panic(block: lambda) -> Nil {
let proc = process.spawn {
let test = process.receive as PanicTest
......@@ -131,7 +133,7 @@ def panic(block: lambda) {
}
# Asserts that the given lambda does not panic.
def no_panic(block: lambda) {
def no_panic(block: lambda) -> Nil {
let proc = process.spawn {
let test = process.receive as PanicTest
......@@ -153,7 +155,7 @@ def no_panic(block: lambda) {
#
# Something is considered to be truthy when its implementation of `if_true`
# calls the supplied block.
def true!(T: Inspect + Conditional)(value: T) {
def true!(T: Inspect + Conditional)(value: T) -> Nil {
value.if_true {
return
}
......@@ -167,7 +169,7 @@ def true!(T: Inspect + Conditional)(value: T) {
#
# Something is considered to be falsy when its implementation of `if_false`
# calls the supplied block.
def false!(T: Inspect + Conditional)(value: T) {
def false!(T: Inspect + Conditional)(value: T) -> Nil {
value.if_false {
return
}
......
......@@ -8,25 +8,25 @@ import std::time::Duration
# A type for formatting the results of tests.
trait Formatter {
# Displays the result of a single test.
def test(test: Test) {
def test(test: Test) -> Nil {
test.passed?.if(true: { passed(test) }, false: { failed(test) })
}
# Displays the result of a passed test.
def passed(test: Test)
def passed(test: Test) -> Nil
# Displays the result of a failed test.
def failed(test: Test)
def failed(test: Test) -> Nil
# Displays all of the failed tests after the test suite has finished.
#
# The `tests` argument will be passed an `Array` of `Test` objects that
# did not pass.
def failures(tests: Array!(Test))
def failures(tests: Array!(Test)) -> Nil
# Displays a summary of all the tests that have been executed.
#
# The `tests` argument will be passed an `Array` of all `Test` objects
# (including failed tests) that were executed.
def summary(tests: Array!(Test), duration: Duration)
def summary(tests: Array!(Test), duration: Duration) -> Nil
}
......@@ -99,18 +99,20 @@ object ProgressFormatter {
}
impl Formatter for ProgressFormatter {
def passed(test: Test) {
def passed(test: Test) -> Nil {
stdout.write_string(green('.'))
Nil
}
def failed(test: Test) {
def failed(test: Test) -> Nil {
@failed += 1
stdout.write_string(red('F'))
Nil
}
# Displays a list of all the failed tests.
def failures(tests: Array!(Test)) {
def failures(tests: Array!(Test)) -> Nil {
stdout.write_string("\n\nFailures:")
tests.each_with_index do (test, index) {
......@@ -136,10 +138,12 @@ impl Formatter for ProgressFormatter {
stdout.write_string(buffer)
}
Nil
}
# Displays a summary of the test suite, once the suite has finished running.
def summary(tests: Array!(Test), duration: Duration) {
def summary(tests: Array!(Test), duration: Duration) -> Nil {
let buffer = StringBuffer.new(
"\n\nFinished running in ",
test_suite_duration_time(duration).to_string,
......@@ -150,5 +154,6 @@ impl Formatter for ProgressFormatter {
)