From 5e3e238b5ea972d2cfc37fc09aba8e0cb7d6e771 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Tue, 29 Oct 2024 00:44:26 -0500 Subject: [PATCH] renderable error type --- squared_away/src/squared_away.gleam | 51 ++++--------------- squared_away_lang/src/renderable_error.gleam | 14 +++++ .../src/squared_away_lang/error.gleam | 15 +++--- .../typechecker/type_error.gleam | 12 +++++ 4 files changed, 42 insertions(+), 50 deletions(-) create mode 100644 squared_away_lang/src/renderable_error.gleam diff --git a/squared_away/src/squared_away.gleam b/squared_away/src/squared_away.gleam index a65cd8c..44b1a5e 100644 --- a/squared_away/src/squared_away.gleam +++ b/squared_away/src/squared_away.gleam @@ -1,3 +1,4 @@ +import renderable_error import gleam/dict import gleam/int import gleam/list @@ -130,7 +131,7 @@ fn view(model: Model) -> element.Element(Msg) { list.find_map(model.errors_to_display, fn(e) { case Some(e.0) == model.active_cell { False -> Error(Nil) - True -> Ok(error_view(e.1)) + True -> Ok(error_view(e.1 |> error.to_renderable_error)) } }) |> result.unwrap(or: html.div([], [])) @@ -221,47 +222,15 @@ fn view(model: Model) -> element.Element(Msg) { ]) } -fn error_view(e: error.CompileError) { - case e { - error.TypeError(te) -> { - case te { - type_error.IncorrectTypesForBinaryOp(lhs, rhs, bo) -> - html.div([], [ - html.h4( - [], - t( - "Type Error: Incorrect types for binary operation " - <> type_error.describe_binary_op_kind_for_err(bo), - ), - ), - html.p( - [], - t( - "The `&&` operator is specifically for booleans values (TRUE/FALSE). ", - ), - ), - html.p( - [], - t( - "You provided a " - <> typ.to_string(lhs) - <> " on the left and a " - <> typ.to_string(rhs) - <> " on the right", - ), - ), - html.p( - [], - t( - "Hint: If you're trying to verify both values have been provided, use the global `notempty` function like so: notempty(myvar) && notempty(myothervar).", - ), - ), - ]) - type_error.TypeError(txt) -> html.div([], t(txt)) - } +fn error_view(re: renderable_error.RenderableError) { + html.div([], [ + html.h4([], t(re.title)), + html.p([], t(re.info)), + .. case re.hint { + None -> [] + Some(hint) -> [html.p([], t(hint))] } - _ -> html.p([], t(error.to_string(e))) - } + ]) } fn t(input: String) { diff --git a/squared_away_lang/src/renderable_error.gleam b/squared_away_lang/src/renderable_error.gleam new file mode 100644 index 0000000..fae39a9 --- /dev/null +++ b/squared_away_lang/src/renderable_error.gleam @@ -0,0 +1,14 @@ +import gleam/option.{type Option} + +/// This type represents an error we want to render. The idea is that the +/// various error types implement converstion functions to this, rather than +/// individual to_string, to_html, etc. functions, which cuts down on work for +/// me as just one person. +/// It will hopefully also help to keep error's looking consistent in the UI. +pub type RenderableError { + RenderableError( + title: String, + info: String, + hint: Option(String) + ) +} \ No newline at end of file diff --git a/squared_away_lang/src/squared_away_lang/error.gleam b/squared_away_lang/src/squared_away_lang/error.gleam index e1ca693..4ec57db 100644 --- a/squared_away_lang/src/squared_away_lang/error.gleam +++ b/squared_away_lang/src/squared_away_lang/error.gleam @@ -1,7 +1,9 @@ +import renderable_error import squared_away_lang/interpreter/runtime_error import squared_away_lang/parser/parse_error import squared_away_lang/scanner/scan_error import squared_away_lang/typechecker/type_error +import gleam/option.{None} pub type CompileError { ScanError(scan_error.ScanError) @@ -10,15 +12,10 @@ pub type CompileError { RuntimeError(runtime_error.RuntimeError) } -pub fn to_string(e: CompileError) -> String { - case e { - ParseError(parse_error.ParseError(txt)) -> - error_type_string(e) <> ": " <> txt - RuntimeError(runtime_error.RuntimeError(txt)) -> - error_type_string(e) <> ": " <> txt - ScanError(scan_error.ScanError) -> - error_type_string(e) <> ": Unrecognized token" - TypeError(te) -> type_error.to_string(te) +pub fn to_renderable_error(ce: CompileError) -> renderable_error.RenderableError { + case ce { + TypeError(te) -> type_error.to_renderable_error(te) + _ -> renderable_error.RenderableError(title: "Compiler error", info: "Todo: implement this error description", hint: None) } } diff --git a/squared_away_lang/src/squared_away_lang/typechecker/type_error.gleam b/squared_away_lang/src/squared_away_lang/typechecker/type_error.gleam index 50bd6ed..d4bf706 100644 --- a/squared_away_lang/src/squared_away_lang/typechecker/type_error.gleam +++ b/squared_away_lang/src/squared_away_lang/typechecker/type_error.gleam @@ -1,5 +1,7 @@ +import renderable_error import squared_away_lang/parser/expr import squared_away_lang/typechecker/typ +import gleam/option.{None} pub type TypeError { TypeError(context: String) @@ -10,6 +12,16 @@ pub type TypeError { ) } +pub fn to_renderable_error(te: TypeError) -> renderable_error.RenderableError { + case te { + IncorrectTypesForBinaryOp(lhs, rhs, op) -> renderable_error.RenderableError( + title: "Unexpected arguments to binary operation `&&`", + info: "Expected booleans. Got " <> typ.to_string(lhs) <> " on the left and " <> typ.to_string(rhs) <> " on the right", + hint: None) + TypeError(_) -> renderable_error.RenderableError(title: "Type Error", info: "Todo: Fill in this error", hint: None) + } +} + pub fn to_string(te: TypeError) -> String { case te { IncorrectTypesForBinaryOp(lhs:, rhs:, binary_op:) -> "Type Error:\n