Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions argparse/error.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,32 @@ impl Show for ArgError with output(self : ArgError, logger) {
}
}

///|
impl @debug.Debug for ArgError with to_repr(self) {
match self {
Message(msg) => @debug.Repr::literal(msg)
}
}

///|
test "ArgError debug keeps display text" {
let err : Error = ArgError::Message(
(
$|error: unexpected argument '--bad' found
$|
$|Usage: demo [options]
),
)
inspect(
err.to_string(),
content=(
#|error: unexpected argument '--bad' found
#|
#|Usage: demo [options]
),
)
}

///|
/// Internal parse error variants used while parsing.
priv suberror ArgParseError {
Expand Down
4 changes: 2 additions & 2 deletions builtin/autoloc.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ pub(all) type SourceLoc
fn SourceLoc::repr(self : Self) -> String = "%loc_to_string"

///|
pub impl Show for SourceLoc with output(self, logger) {
logger.write_string(self.repr())
pub impl Show for SourceLoc with to_string(self) {
self.repr()
}

///|
Expand Down
4 changes: 2 additions & 2 deletions builtin/double.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,8 @@ pub fn Double::to_string(self : Double) -> String {
// }

///|
pub impl Show for Double with output(self, logger) {
logger.write_string(self.to_string())
pub impl Show for Double with to_string(self) {
Double::to_string(self)
}

///|
Expand Down
2 changes: 1 addition & 1 deletion builtin/feature_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
struct RangeImpl[T] {
lo : T
hi : T
} derive(Show, ToJson)
} derive(ToJson)

// pub
// priv
Expand Down
2 changes: 1 addition & 1 deletion builtin/guard_feature_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ enum Expr {
Div(Expr, Expr)
Lit(Int)
Var(String)
} derive(Show, ToJson, Eq)
} derive(ToJson, Eq)

///|
fn simplify(e : Expr) -> Expr {
Expand Down
3 changes: 2 additions & 1 deletion builtin/pkg.generated.mbti
Original file line number Diff line number Diff line change
Expand Up @@ -1305,8 +1305,9 @@ pub impl Shl for UInt
pub impl Shl for UInt16
pub impl Shl for UInt64

#must_implement_one(output, to_string)
pub(open) trait Show {
output(Self, &Logger) -> Unit
output(Self, &Logger) -> Unit = _
to_string(Self) -> String = _
}
pub impl Show for Unit
Expand Down
34 changes: 17 additions & 17 deletions builtin/show.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,47 @@
// limitations under the License.

///|
pub impl Show for Unit with output(_self, logger) {
logger.write_string("()")
pub impl Show for Unit with to_string(_self) {
"()"
}

///|
pub impl Show for Bool with output(self, logger) {
pub impl Show for Bool with to_string(self) {
if self {
logger.write_string("true")
"true"
} else {
logger.write_string("false")
"false"
}
}

///|
pub impl Show for Int with output(self, logger) {
logger.write_string(self.to_string())
pub impl Show for Int with to_string(self) {
Int::to_string(self)
}

///|
pub impl Show for Int64 with output(self, logger) {
logger.write_string(self.to_string())
pub impl Show for Int64 with to_string(self) {
Int64::to_string(self)
}

///|
pub impl Show for UInt with output(self, logger) {
logger.write_string(self.to_string())
pub impl Show for UInt with to_string(self) {
UInt::to_string(self)
}

///|
pub impl Show for UInt64 with output(self, logger) {
logger.write_string(self.to_string())
pub impl Show for UInt64 with to_string(self) {
UInt64::to_string(self)
}

///|
pub impl Show for Byte with output(self, logger) {
logger.write_string(self.to_string())
pub impl Show for Byte with to_string(self) {
Byte::to_string(self)
}

///|
pub impl Show for UInt16 with output(self, logger) {
logger.write_string(self.to_string())
pub impl Show for UInt16 with to_string(self) {
UInt16::to_string(self)
}

///|
Expand Down
16 changes: 13 additions & 3 deletions builtin/traits.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -123,22 +123,32 @@ impl Logger with write_char(self, value) {

///|
/// Trait for types that can be converted to `String`
#must_implement_one(output, to_string)
pub(open) trait Show {
// `output` is used for composition of aggregate structure.
// `output` writes a string representation of `self` to a logger.
// `output` should produce a valid MoonBit-syntax representation if possible.
// For example, `Show::output` for `String` should be quoted
output(Self, &Logger) -> Unit
// By default `output` is implemented using `to_string`,
// but some types, such as `String` and `Char`, may override `output`,
// for different (escaped) behavior when composed into larger structures.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is no longer the case? we have two purely for efficiency?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It depends on how we are going to phase out the transition.

output(Self, &Logger) -> Unit = _
// `to_string` should be used by end users of `Show`,
// for printing, interpolation, etc. only, and should not be used for composition.
// By default `to_string` is implemented using `output` and a buffer,
// but some types, such as `String`, may override `to_string`,
// for different (unescaped) behavior when interpolated/printed directly
// for different (unescaped) behavior when interpolated/printed directly.
to_string(Self) -> String = _
}

///|
/// Default implementation for `Show::to_string`, uses a `StringBuilder`
/// Default implementation for `Show::output`, uses `Show::to_string`.
impl Show with output(self, logger) {
logger.write_string(self.to_string())
}

///|
/// Default implementation for `Show::to_string`, uses a `StringBuilder`.
impl Show with to_string(self) {
let logger = StringBuilder::new()
self.output(logger)
Expand Down
4 changes: 3 additions & 1 deletion error/error.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
// limitations under the License.

///|
fn Error::to_string(self : Error) -> String = "%error.to_string"
fn Error::to_string(self : Error) -> String {
@debug.to_string(self)
}
Comment on lines +16 to +18
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are using debug.to_string to display. But this can cause major breakage for errors that have display, such as the errors in the argparse. Users might find that the program no longer prints the errors well. Though no one should depend on the error message's content.


///|
/// Implements `Show` trait for `Error` type by converting the error into a
Expand Down
7 changes: 6 additions & 1 deletion error/error_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ test "show error" {
inspect(try! f(true), content="ok")
inspect(
try? f(false),
content="Err(moonbitlang/core/error_blackbox_test.IntError.IntError)",
content="Err(<moonbitlang/core/error_blackbox_test.IntError.IntError: ...>)",
)
inspect(
(IntError(42) : Error).to_string() ==
@debug.to_string((IntError(42) : Error)),
content="true",
)
}

Expand Down
8 changes: 4 additions & 4 deletions json/derive_json_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ struct Hello[A, B] {
fieldA : A
fieldB : B
data : Map[String, A]
} derive(ToJson, FromJson, Show, Eq)
} derive(ToJson, FromJson, Debug, Eq)

///|
test {
let v = Hello::{ fieldA: 3, fieldB: 2, data: { "a": 3 } }
let vj = v.to_json()
let v0 : Hello[Int, Int] = @json.from_json(vj)
inspect(
v0,
v0.to_json(),
content=(
#|{fieldA: 3, fieldB: 2, data: {"a": 3}}
#|Object({"fieldA": Number(3), "fieldB": Number(2), "data": Object({"a": Number(3)})})
),
)
assert_eq(v0, v)
assert_true(v0 == v)
}

// struct Hello2 [A, B] {
Expand Down
8 changes: 4 additions & 4 deletions json/from_to_json_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ enum Expr {
Mul(Expr, Expr)
Div(Expr, Expr)
Val(String)
} derive(ToJson, FromJson, Show, Eq)
} derive(ToJson, FromJson, Debug, Eq)

///|
test {
Expand All @@ -33,10 +33,10 @@ test {
)
let e0 : Expr = @json.from_json(ej)
inspect(
e0,
e0.to_json().stringify(),
content=(
#|Add(Val("x"), Val("y"))
#|["Add",["Val","x"],["Val","y"]]
),
)
assert_eq(e0, e)
assert_true(e0 == e)
}
8 changes: 4 additions & 4 deletions json/json_encode_decode_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub(all) struct AllThree {
ints : Array[Int]
floats : Array[Double]
strings : Array[String]
} derive(Eq, Show)
} derive(Eq, Debug)

///|
fn[T] array_to_json(arr : Array[T], f~ : (T) -> Json) -> Json {
Expand All @@ -38,7 +38,7 @@ fn AllThree::to_json(self : AllThree) -> Json {
///|
suberror DecodeError {
DecodeError(String)
} derive(Eq, Show)
} derive(Eq, Debug)

///|
fn of_json(jv : Json) -> AllThree raise DecodeError {
Expand Down Expand Up @@ -85,9 +85,9 @@ test {
}
let json = all_three.to_json()
inspect(
try? of_json(json),
(try! of_json(json)).to_json(),
content=(
#|Ok({ints: [1, 2, 3], floats: [1, 2, 3], strings: ["a", "b", "c"]})
#|Object({"ints": Array([Number(1), Number(2), Number(3)]), "floats": Array([Number(1), Number(2), Number(3)]), "strings": Array([String("a"), String("b"), String("c")])})
),
)
// FIXME:
Expand Down
8 changes: 4 additions & 4 deletions json/to_json_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ test "Map::to_json" {
struct Opt {
x : Int?
t : Int??
} derive(ToJson, FromJson, Eq, Show)
} derive(ToJson, FromJson, Eq, Debug)

///|
test "Option::to_json" {
Expand Down Expand Up @@ -231,11 +231,11 @@ test "optional field" {
///|
test "optional field round trip" {
let opt = { x: Some(42), t: Some(Some(42)) }
assert_eq(@json.from_json(opt.to_json()), opt)
assert_true(@json.from_json(opt.to_json()) == opt)
let opt = { x: None, t: None }
assert_eq(@json.from_json(opt.to_json()), opt)
assert_true(@json.from_json(opt.to_json()) == opt)
let opt = { x: None, t: Some(None) }
assert_eq(@json.from_json(opt.to_json()), opt)
assert_true(@json.from_json(opt.to_json()) == opt)
}

///|
Expand Down
Loading