Skip to content

Commit

Permalink
Merge Format and DefaultFormatter into Formatter
Browse files Browse the repository at this point in the history
The original idea behind this split was to allow different formatters.
This however ended up not making much sense. For example, the
Format.write method doesn't require/provide nearly enough information to
meaningfully format objects differently, as all it does is take a String
and store it somewhere.

Instead, Formatter is now a class instead of a trait. To make formatting
easier, we'll introduce helper types (similar to Rust) in a similar
commit. In a future commit we can then hook into those types to make
it easier to present the formatted data in different ways (e.g. with and
without indentation).

Changelog: changed
  • Loading branch information
yorickpeterse committed Aug 9, 2023
1 parent 85b213e commit b0bbc43
Show file tree
Hide file tree
Showing 28 changed files with 59 additions and 79 deletions.
44 changes: 14 additions & 30 deletions std/src/std/fmt.inko
@@ -1,4 +1,4 @@
# Types for formatting objects in a human-readable manner.
# Formatting of Inko values for debugging purposes.
import std.string.(IntoString, StringBuffer)

# The value to use for objects if the nesting is too great.
Expand All @@ -17,44 +17,23 @@ let MAX_DEPTH = 16
# fmt('hello') # => "hello"
# fmt([10, 20]) # => '[10, 20]'
fn pub fmt[T: Format](value: ref T) -> String {
let formatter: Formatter = DefaultFormatter.new
let formatter = Formatter.new

value.fmt(formatter)
formatter.into_string
}

# A Formatter can be used to format an object for debugging purposes.
trait pub Formatter: IntoString {
# Writes the given `String` into the underlying buffer.
fn pub mut write(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.
fn pub mut descend(block: fn)
}

# The default formatter to use when formatting an object.
class pub DefaultFormatter {
class pub Formatter {
let @buffer: StringBuffer
let @nesting: Int

fn pub static new -> DefaultFormatter {
DefaultFormatter { @buffer = StringBuffer.new, @nesting = 0 }
# Returns a new `Formatter` with its default settings.
fn pub static new -> Formatter {
Formatter { @buffer = StringBuffer.new, @nesting = 0 }
}
}

impl IntoString for DefaultFormatter {
# Returns a `String` containing the data pushed into this buffer so far.
fn pub move into_string -> String {
@buffer.into_string
}
}

impl Formatter for DefaultFormatter {
# Pushes a new `String` into the underlying buffer.
# Writes the given `String` into the underlying buffer.
fn pub mut write(string: String) {
@buffer.push(string)
}
Expand All @@ -71,13 +50,18 @@ impl Formatter for DefaultFormatter {
}

@nesting += 1

block.call

@nesting -= 1
}
}

impl IntoString for Formatter {
# Moves `self` into a `String`, containing the formatted data.
fn pub move into_string -> String {
@buffer.into_string
}
}

# A type that can be formatted into a human-readable format for debugging
# purposes.
trait pub Format {
Expand Down
15 changes: 4 additions & 11 deletions std/src/std/test.inko
Expand Up @@ -60,7 +60,7 @@
import std.cmp.(Compare, Equal)
import std.debug
import std.env
import std.fmt.(DefaultFormatter, Format, Formatter)
import std.fmt.(Format, Formatter, fmt)
import std.fs.path.Path
import std.int.(Format as IntFormat)
import std.io.Write
Expand All @@ -73,13 +73,6 @@ import std.time.(Duration, Instant)
let CHILD_VAR = 'INKO_TEST_CHILD'
let TEST_PREFIX = 'test_'

fn format(value: ref Format) -> String {
let formatter: Formatter = DefaultFormatter.new

value.fmt(formatter)
formatter.into_string
}

# A single unit test.
class pub Test {
# The unique ID of this test.
Expand Down Expand Up @@ -126,21 +119,21 @@ class pub Test {
fn pub mut equal[T: Equal[T] + Format](got: ref T, expected: ref T) {
if got == expected { return }

@failures.push(Failure.new(format(got), format(expected)))
@failures.push(Failure.new(fmt(got), fmt(expected)))
}

# Asserts that the given arguments are not equal to each other.
fn pub mut not_equal[T: Equal[T] + Format](got: ref T, expected: ref T) {
if got != expected { return }

@failures.push(Failure.new(format(got), format(expected)))
@failures.push(Failure.new(fmt(got), fmt(expected)))
}

# Asserts that `got` is greater than `minimum`.
fn pub mut greater[T: Compare[T] + Format](got: ref T, minimum: ref T) {
if got > minimum { return }

@failures.push(Failure.new(format(got), "> {format(minimum)}"))
@failures.push(Failure.new(fmt(got), "> {fmt(minimum)}"))
}

# Asserts that the given value is `true`.
Expand Down
9 changes: 1 addition & 8 deletions std/test/helpers.inko
@@ -1,6 +1,6 @@
import std.drop.(drop)
import std.env
import std.fmt.(DefaultFormatter, Format, Formatter)
import std.fmt.(Format, Formatter)
import std.fs.path.Path
import std.hash.(Hash, Hasher)
import std.hash.siphash.SipHasher13
Expand All @@ -12,13 +12,6 @@ fn pub hash(value: ref Hash) -> Int {
hasher.finish
}

fn pub fmt(value: ref Format) -> String {
let fmt: Formatter = DefaultFormatter.new

value.fmt(fmt)
fmt.into_string
}

fn pub compiler_path -> Path {
let base = match env.working_directory {
case Ok(path) -> path
Expand Down
2 changes: 1 addition & 1 deletion std/test/std/crypto/test_hash.inko
@@ -1,7 +1,7 @@
import helpers.(fmt)
import std.crypto.hash.(Block, Hash)
import std.endian.big
import std.endian.little
import std.fmt.(fmt)
import std.test.Tests

fn pub tests(t: mut Tests) {
Expand Down
2 changes: 1 addition & 1 deletion std/test/std/fs/test_path.inko
@@ -1,5 +1,5 @@
import helpers.(fmt)
import std.env
import std.fmt.(fmt)
import std.fs.(DirectoryEntry, FileType)
import std.fs.file.(self, ReadOnlyFile, WriteOnlyFile)
import std.fs.path.(self, Path)
Expand Down
2 changes: 1 addition & 1 deletion std/test/std/net/test_ip.inko
@@ -1,4 +1,4 @@
import helpers.(fmt)
import std.fmt.(fmt)
import std.net.ip.(self, IpAddress, Ipv4Address, Ipv6Address)
import std.test.Tests

Expand Down
2 changes: 1 addition & 1 deletion std/test/std/net/test_socket.inko
@@ -1,6 +1,6 @@
import helpers.(fmt)
import std.drop.Drop
import std.env
import std.fmt.(fmt)
import std.fs.file
import std.fs.path.Path
import std.io.Error
Expand Down
3 changes: 2 additions & 1 deletion std/test/std/test_array.inko
@@ -1,6 +1,7 @@
import helpers.(fmt, hash)
import helpers.(hash)
import std.cmp.(Compare, Ordering)
import std.drop.(drop, Drop)
import std.fmt.(fmt)
import std.rand.Random
import std.test.Tests

Expand Down
3 changes: 2 additions & 1 deletion std/test/std/test_bool.inko
@@ -1,4 +1,5 @@
import helpers.(fmt, hash)
import helpers.(hash)
import std.fmt.(fmt)
import std.cmp.Ordering
import std.test.Tests

Expand Down
3 changes: 2 additions & 1 deletion std/test/std/test_byte_array.inko
@@ -1,4 +1,5 @@
import helpers.(fmt, hash)
import helpers.(hash)
import std.fmt.(fmt)
import std.iter.EOF
import std.test.Tests

Expand Down
2 changes: 1 addition & 1 deletion std/test/std/test_cmp.inko
@@ -1,5 +1,5 @@
import helpers.(fmt)
import std.cmp.(Compare, Equal, Ordering, max, min)
import std.fmt.(fmt)
import std.test.Tests

class enum Letter {
Expand Down
3 changes: 2 additions & 1 deletion std/test/std/test_float.inko
@@ -1,5 +1,6 @@
import helpers.(fmt, hash)
import helpers.(hash)
import std.cmp.Ordering
import std.fmt.(fmt)
import std.hash.Hasher
import std.int.(MAX as INT_MAX)
import std.test.Tests
Expand Down
12 changes: 6 additions & 6 deletions std/test/std/test_fmt.inko
@@ -1,10 +1,10 @@
import std.fmt.(DefaultFormatter, fmt)
import std.fmt.(Formatter, fmt)
import std.test.Tests

fn pub tests(t: mut Tests) {
t.test('DefaultFormatter.descend') fn (t) {
let fmt1 = DefaultFormatter.new
let fmt2 = DefaultFormatter.new
t.test('Formatter.descend') fn (t) {
let fmt1 = Formatter.new
let fmt2 = Formatter.new

fmt1.descend fn {
fmt1.descend fn {
Expand Down Expand Up @@ -48,8 +48,8 @@ fn pub tests(t: mut Tests) {
t.equal(fmt2.into_string, 'test')
}

t.test('DefaultFormatter.write') fn (t) {
let fmt = DefaultFormatter.new
t.test('Formatter.write') fn (t) {
let fmt = Formatter.new

fmt.write('test')

Expand Down
2 changes: 1 addition & 1 deletion std/test/std/test_fs.inko
@@ -1,4 +1,4 @@
import helpers.(fmt)
import std.fmt.(fmt)
import std.fs.(DirectoryEntry, FileType)
import std.test.Tests

Expand Down
3 changes: 2 additions & 1 deletion std/test/std/test_int.inko
@@ -1,5 +1,6 @@
import helpers.(fmt, hash)
import helpers.(hash)
import std.cmp.Ordering
import std.fmt.(fmt)
import std.int.(Format, MAX, MIN)
import std.test.Tests

Expand Down
2 changes: 1 addition & 1 deletion std/test/std/test_io.inko
@@ -1,4 +1,4 @@
import helpers.(fmt)
import std.fmt.(fmt)
import std.io.(DEFAULT_BUFFER_SIZE, Buffer, BufferedReader, Error, Read, Write)
import std.libc.bsd.errors if bsd
import std.libc.linux.errors if linux
Expand Down
2 changes: 1 addition & 1 deletion std/test/std/test_json.inko
@@ -1,4 +1,4 @@
import helpers.(fmt)
import std.fmt.(fmt)
import std.json.(Error, Json, Parser)
import std.test.Tests

Expand Down
3 changes: 2 additions & 1 deletion std/test/std/test_map.inko
@@ -1,4 +1,5 @@
import helpers.(fmt, hash)
import helpers.(hash)
import std.fmt.(fmt)
import std.hash.Hasher
import std.test.Tests

Expand Down
2 changes: 1 addition & 1 deletion std/test/std/test_nil.inko
@@ -1,5 +1,5 @@
import std.fmt.(fmt)
import std.test.Tests
import helpers.(fmt)

fn pub tests(t: mut Tests) {
t.test('Nil.==') fn (t) {
Expand Down
2 changes: 1 addition & 1 deletion std/test/std/test_option.inko
@@ -1,4 +1,4 @@
import helpers.(fmt)
import std.fmt.(fmt)
import std.test.Tests

fn pub tests(t: mut Tests) {
Expand Down
3 changes: 2 additions & 1 deletion std/test/std/test_rand.inko
@@ -1,4 +1,5 @@
import helpers.(fmt, hash)
import helpers.(hash)
import std.fmt.(fmt)
import std.rand.(Random, Shuffle)
import std.test.Tests

Expand Down
3 changes: 2 additions & 1 deletion std/test/std/test_range.inko
@@ -1,4 +1,5 @@
import helpers.(fmt, hash)
import helpers.(hash)
import std.fmt.(fmt)
import std.range.(ExclusiveRange, InclusiveRange)
import std.test.Tests

Expand Down
2 changes: 1 addition & 1 deletion std/test/std/test_result.inko
@@ -1,4 +1,4 @@
import helpers.(fmt)
import std.fmt.(fmt)
import std.iter.Iter
import std.test.Tests

Expand Down
2 changes: 1 addition & 1 deletion std/test/std/test_set.inko
@@ -1,4 +1,4 @@
import helpers.(fmt)
import std.fmt.(fmt)
import std.set.Set
import std.test.Tests

Expand Down
3 changes: 2 additions & 1 deletion std/test/std/test_string.inko
@@ -1,4 +1,5 @@
import helpers.(fmt, hash)
import helpers.(hash)
import std.fmt.(fmt)
import std.fs.path.Path
import std.iter.EOF
import std.test.Tests
Expand Down
2 changes: 1 addition & 1 deletion std/test/std/test_test.inko
@@ -1,5 +1,5 @@
import helpers.(fmt)
import std.env
import std.fmt.(fmt)
import std.fs.path.Path
import std.io.Write
import std.sys
Expand Down
2 changes: 1 addition & 1 deletion std/test/std/test_time.inko
@@ -1,5 +1,5 @@
import helpers.(fmt)
import std.cmp.Ordering
import std.fmt.(fmt)
import std.process.(sleep)
import std.test.Tests
import std.time.(DateTime, Duration, Instant)
Expand Down
3 changes: 2 additions & 1 deletion std/test/std/test_tuple.inko
@@ -1,4 +1,5 @@
import helpers.(fmt, hash)
import helpers.(hash)
import std.fmt.(fmt)
import std.test.Tests

fn pub tests(t: mut Tests) {
Expand Down

0 comments on commit b0bbc43

Please sign in to comment.