From 3fc324f48de49b54ac644eb4942ba6c96b3b906b Mon Sep 17 00:00:00 2001 From: Oliver Linnarsson Date: Wed, 19 Jun 2024 11:37:28 +0200 Subject: [PATCH] feat: Add format_runtime_error --- src/handles/error.gleam | 9 ++- src/handles/format.gleam | 27 ++++++++- src/handles/internal/ctx_utils.gleam | 79 +++++++++++++++++--------- src/handles/internal/engine.gleam | 16 +++--- src/handles/internal/parser.gleam | 34 +++++------ src/handles/internal/tokenizer.gleam | 39 +++++++------ test/unit_tests/engine_test.gleam | 32 +++++------ test/unit_tests/parser_test.gleam | 24 ++++---- test/unit_tests/tokenizer_test.gleam | 10 ++-- test/user_stories/hello_test.gleam | 7 ++- test/user_stories/knattarna_test.gleam | 14 +++-- test/user_stories/nested_block.gleam | 8 ++- 12 files changed, 181 insertions(+), 118 deletions(-) diff --git a/src/handles/error.gleam b/src/handles/error.gleam index d7fb60f..6744cf4 100644 --- a/src/handles/error.gleam +++ b/src/handles/error.gleam @@ -7,6 +7,11 @@ pub type TokenizerError { } pub type RuntimeError { - UnexpectedTypeError(path: List(String), got: String, expected: List(String)) - UnknownPropertyError(key: List(String)) + UnexpectedTypeError( + index: Int, + path: List(String), + got: String, + expected: List(String), + ) + UnknownPropertyError(index: Int, path: List(String)) } diff --git a/src/handles/format.gleam b/src/handles/format.gleam index 3876dac..2fc4e18 100644 --- a/src/handles/format.gleam +++ b/src/handles/format.gleam @@ -38,7 +38,7 @@ fn resolve_position( } } -pub fn transform_error(template: String, offset: Int, message: String) { +fn transform_error(template: String, offset: Int, message: String) { case resolve_position(template, offset, Position(0, 0, 0)) { Position(_, row, col) -> Ok( @@ -74,3 +74,28 @@ pub fn format_tokenizer_error( transform_error(template, index, "Tag is of unknown block kind") } } + +pub fn format_runtime_error( + error: error.RuntimeError, + template: String, +) -> Result(String, Nil) { + case error { + error.UnexpectedTypeError(index, path, got, expected) -> + transform_error( + template, + index, + "Unexpected type of property " + <> string.join(path, ".") + <> ", extepced " + <> string.join(expected, " or ") + <> " but found found " + <> got, + ) + error.UnknownPropertyError(index, path) -> + transform_error( + template, + index, + "Unable to resolve property " <> string.join(path, "."), + ) + } +} diff --git a/src/handles/internal/ctx_utils.gleam b/src/handles/internal/ctx_utils.gleam index 33fc08b..59f811f 100644 --- a/src/handles/internal/ctx_utils.gleam +++ b/src/handles/internal/ctx_utils.gleam @@ -16,28 +16,31 @@ pub fn drill_ctx( ctx.Dict(arr) -> { case list.find(arr, fn(it) { it.key == key }) { Ok(ctx.Prop(_, value)) -> drill_ctx(rest, value) - Error(_) -> Error(error.UnknownPropertyError([])) + Error(_) -> Error(error.UnknownPropertyError(0, [])) } } - ctx.List(_) -> Error(error.UnexpectedTypeError([], "List", ["Dict"])) - ctx.Str(_) -> Error(error.UnexpectedTypeError([], "Str", ["Dict"])) - ctx.Int(_) -> Error(error.UnexpectedTypeError([], "Int", ["Dict"])) - ctx.Float(_) -> Error(error.UnexpectedTypeError([], "Float", ["Dict"])) - ctx.Bool(_) -> Error(error.UnexpectedTypeError([], "Bool", ["Dict"])) + ctx.List(_) -> Error(error.UnexpectedTypeError(0, [], "List", ["Dict"])) + ctx.Str(_) -> Error(error.UnexpectedTypeError(0, [], "Str", ["Dict"])) + ctx.Int(_) -> Error(error.UnexpectedTypeError(0, [], "Int", ["Dict"])) + ctx.Float(_) -> + Error(error.UnexpectedTypeError(0, [], "Float", ["Dict"])) + ctx.Bool(_) -> Error(error.UnexpectedTypeError(0, [], "Bool", ["Dict"])) } } } pub fn get_property( + index: Int, path: List(String), root_ctx: ctx.Value, ) -> Result(String, error.RuntimeError) { drill_ctx(path, root_ctx) |> result.map_error(fn(err) { case err { - error.UnexpectedTypeError(_, got, expected) -> - error.UnexpectedTypeError(path, got, expected) - error.UnknownPropertyError(_) -> error.UnknownPropertyError(path) + error.UnexpectedTypeError(_, _, got, expected) -> + error.UnexpectedTypeError(index, path, got, expected) + error.UnknownPropertyError(_, _) -> + error.UnknownPropertyError(index, path) } }) |> result.try(fn(it) { @@ -46,59 +49,79 @@ pub fn get_property( ctx.Int(value) -> value |> int.to_string |> Ok ctx.Float(value) -> value |> float.to_string |> Ok ctx.List(_) -> - Error(error.UnexpectedTypeError(path, "List", ["Str", "Int", "Float"])) + Error( + error.UnexpectedTypeError(index, path, "List", ["Str", "Int", "Float"]), + ) ctx.Dict(_) -> - Error(error.UnexpectedTypeError(path, "Dict", ["Str", "Int", "Float"])) + Error( + error.UnexpectedTypeError(index, path, "Dict", ["Str", "Int", "Float"]), + ) ctx.Bool(_) -> - Error(error.UnexpectedTypeError(path, "Bool", ["Str", "Int", "Float"])) + Error( + error.UnexpectedTypeError(index, path, "Bool", ["Str", "Int", "Float"]), + ) } }) } pub fn get_list( + index: Int, path: List(String), root_ctx: ctx.Value, ) -> Result(List(ctx.Value), error.RuntimeError) { drill_ctx(path, root_ctx) |> result.map_error(fn(err) { case err { - error.UnexpectedTypeError(_, got, expected) -> - error.UnexpectedTypeError(path, got, expected) - error.UnknownPropertyError(_) -> error.UnknownPropertyError(path) + error.UnexpectedTypeError(_, _, got, expected) -> + error.UnexpectedTypeError(index, path, got, expected) + error.UnknownPropertyError(_, _) -> + error.UnknownPropertyError(index, path) } }) |> result.try(fn(it) { case it { ctx.List(value) -> value |> Ok - ctx.Bool(_) -> Error(error.UnexpectedTypeError(path, "Bool", ["List"])) - ctx.Str(_) -> Error(error.UnexpectedTypeError(path, "Str", ["List"])) - ctx.Int(_) -> Error(error.UnexpectedTypeError(path, "Int", ["List"])) - ctx.Float(_) -> Error(error.UnexpectedTypeError(path, "Float", ["List"])) - ctx.Dict(_) -> Error(error.UnexpectedTypeError(path, "Dict", ["List"])) + ctx.Bool(_) -> + Error(error.UnexpectedTypeError(index, path, "Bool", ["List"])) + ctx.Str(_) -> + Error(error.UnexpectedTypeError(index, path, "Str", ["List"])) + ctx.Int(_) -> + Error(error.UnexpectedTypeError(index, path, "Int", ["List"])) + ctx.Float(_) -> + Error(error.UnexpectedTypeError(index, path, "Float", ["List"])) + ctx.Dict(_) -> + Error(error.UnexpectedTypeError(index, path, "Dict", ["List"])) } }) } pub fn get_bool( + index: Int, path: List(String), root_ctx: ctx.Value, ) -> Result(Bool, error.RuntimeError) { drill_ctx(path, root_ctx) |> result.map_error(fn(err) { case err { - error.UnexpectedTypeError(_, got, expected) -> - error.UnexpectedTypeError(path, got, expected) - error.UnknownPropertyError(_) -> error.UnknownPropertyError(path) + error.UnexpectedTypeError(_, _, got, expected) -> + error.UnexpectedTypeError(index, path, got, expected) + error.UnknownPropertyError(_, _) -> + error.UnknownPropertyError(index, path) } }) |> result.try(fn(it) { case it { ctx.Bool(value) -> value |> Ok - ctx.List(_) -> Error(error.UnexpectedTypeError(path, "List", ["Bool"])) - ctx.Str(_) -> Error(error.UnexpectedTypeError(path, "Str", ["Bool"])) - ctx.Int(_) -> Error(error.UnexpectedTypeError(path, "Int", ["Bool"])) - ctx.Float(_) -> Error(error.UnexpectedTypeError(path, "Float", ["Bool"])) - ctx.Dict(_) -> Error(error.UnexpectedTypeError(path, "Dict", ["Bool"])) + ctx.List(_) -> + Error(error.UnexpectedTypeError(index, path, "List", ["Bool"])) + ctx.Str(_) -> + Error(error.UnexpectedTypeError(index, path, "Str", ["Bool"])) + ctx.Int(_) -> + Error(error.UnexpectedTypeError(index, path, "Int", ["Bool"])) + ctx.Float(_) -> + Error(error.UnexpectedTypeError(index, path, "Float", ["Bool"])) + ctx.Dict(_) -> + Error(error.UnexpectedTypeError(index, path, "Dict", ["Bool"])) } }) } diff --git a/src/handles/internal/engine.gleam b/src/handles/internal/engine.gleam index 6141f60..a7da311 100644 --- a/src/handles/internal/engine.gleam +++ b/src/handles/internal/engine.gleam @@ -41,17 +41,17 @@ pub fn run( [] -> builder |> string_builder.to_string |> Ok [node, ..rest] -> case node { - parser.Constant(value) -> Ok(value) - parser.Property(path) -> ctx_utils.get_property(path, ctx) - parser.IfBlock(path, children) -> - ctx_utils.get_bool(path, ctx) + parser.Constant(_, value) -> Ok(value) + parser.Property(index, path) -> ctx_utils.get_property(index, path, ctx) + parser.IfBlock(index, path, children) -> + ctx_utils.get_bool(index, path, ctx) |> result.try(run_if(_, children, ctx)) - parser.UnlessBlock(path, children) -> - ctx_utils.get_bool(path, ctx) + parser.UnlessBlock(index, path, children) -> + ctx_utils.get_bool(index, path, ctx) |> result.map(bool.negate) |> result.try(run_if(_, children, ctx)) - parser.EachBlock(path, children) -> - ctx_utils.get_list(path, ctx) + parser.EachBlock(index, path, children) -> + ctx_utils.get_list(index, path, ctx) |> result.try(run_each(_, children, string_builder.new())) } |> result.try(fn(it) { diff --git a/src/handles/internal/parser.gleam b/src/handles/internal/parser.gleam index d056203..ac22fe5 100644 --- a/src/handles/internal/parser.gleam +++ b/src/handles/internal/parser.gleam @@ -2,11 +2,11 @@ import gleam/list import handles/internal/tokenizer pub type AST { - Constant(value: String) - Property(path: List(String)) - IfBlock(path: List(String), children: List(AST)) - UnlessBlock(path: List(String), children: List(AST)) - EachBlock(path: List(String), children: List(AST)) + Constant(index: Int, value: String) + Property(index: Int, path: List(String)) + IfBlock(index: Int, path: List(String), children: List(AST)) + UnlessBlock(index: Int, path: List(String), children: List(AST)) + EachBlock(index: Int, path: List(String), children: List(AST)) } pub fn run(tokens: List(tokenizer.Token), ast: List(AST)) -> List(AST) { @@ -14,32 +14,34 @@ pub fn run(tokens: List(tokenizer.Token), ast: List(AST)) -> List(AST) { [] -> list.reverse(ast) [head, ..tail] -> { case head { - tokenizer.Constant(value) -> run(tail, [Constant(value), ..ast]) - tokenizer.Property(path) -> run(tail, [Property(path), ..ast]) - tokenizer.IfBlockStart(path) -> { + tokenizer.Constant(index, value) -> + run(tail, [Constant(index, value), ..ast]) + tokenizer.Property(index, path) -> + run(tail, [Property(index, path), ..ast]) + tokenizer.IfBlockStart(index, path) -> { let children = run(tail, []) run(list.drop(tail, list.length(children) + 1), [ - IfBlock(path, children), + IfBlock(index, path, children), ..ast ]) } - tokenizer.UnlessBlockStart(path) -> { + tokenizer.UnlessBlockStart(index, path) -> { let children = run(tail, []) run(list.drop(tail, list.length(children) + 1), [ - UnlessBlock(path, children), + UnlessBlock(index, path, children), ..ast ]) } - tokenizer.EachBlockStart(path) -> { + tokenizer.EachBlockStart(index, path) -> { let children = run(tail, []) run(list.drop(tail, list.length(children) + 1), [ - EachBlock(path, children), + EachBlock(index, path, children), ..ast ]) } - tokenizer.IfBlockEnd -> list.reverse(ast) - tokenizer.UnlessBlockEnd -> list.reverse(ast) - tokenizer.EachBlockEnd -> list.reverse(ast) + tokenizer.IfBlockEnd(_) -> list.reverse(ast) + tokenizer.UnlessBlockEnd(_) -> list.reverse(ast) + tokenizer.EachBlockEnd(_) -> list.reverse(ast) } } } diff --git a/src/handles/internal/tokenizer.gleam b/src/handles/internal/tokenizer.gleam index 1ba8d9c..bf93ac6 100644 --- a/src/handles/internal/tokenizer.gleam +++ b/src/handles/internal/tokenizer.gleam @@ -3,14 +3,14 @@ import gleam/string import handles/error pub type Token { - Constant(value: String) - Property(path: List(String)) - IfBlockStart(path: List(String)) - IfBlockEnd - UnlessBlockStart(path: List(String)) - UnlessBlockEnd - EachBlockStart(path: List(String)) - EachBlockEnd + Constant(index: Int, value: String) + Property(index: Int, path: List(String)) + IfBlockStart(index: Int, path: List(String)) + IfBlockEnd(index: Int) + UnlessBlockStart(index: Int, path: List(String)) + UnlessBlockEnd(index: Int) + EachBlockStart(index: Int, path: List(String)) + EachBlockEnd(index: Int) } pub fn run( @@ -21,7 +21,8 @@ pub fn run( case input { "{{/if" <> rest -> case rest |> string.split_once("}}") { - Ok(#("", rest)) -> run(rest, index + 7, [IfBlockEnd, ..tokens]) + Ok(#("", rest)) -> + run(rest, index + 7, [IfBlockEnd(index + 2), ..tokens]) _ -> Error(error.UnexpectedBlockArgument(index + 2)) } "{{#if" <> rest -> @@ -31,7 +32,7 @@ pub fn run( [""] -> Error(error.MissingBlockArgument(index + 2)) path -> run(rest, index + 7 + string.length(arg), [ - IfBlockStart(path), + IfBlockStart(index + 2, path), ..tokens ]) } @@ -40,7 +41,8 @@ pub fn run( "{{/unless" <> rest -> case rest |> string.split_once("}}") { - Ok(#("", rest)) -> run(rest, index + 11, [UnlessBlockEnd, ..tokens]) + Ok(#("", rest)) -> + run(rest, index + 11, [UnlessBlockEnd(index + 2), ..tokens]) _ -> Error(error.UnexpectedBlockArgument(index + 2)) } "{{#unless" <> rest -> @@ -50,7 +52,7 @@ pub fn run( [""] -> Error(error.MissingBlockArgument(index + 2)) path -> run(rest, index + 11 + string.length(arg), [ - UnlessBlockStart(path), + UnlessBlockStart(index + 2, path), ..tokens ]) } @@ -59,7 +61,8 @@ pub fn run( "{{/each" <> rest -> case rest |> string.split_once("}}") { - Ok(#("", rest)) -> run(rest, index + 9, [EachBlockEnd, ..tokens]) + Ok(#("", rest)) -> + run(rest, index + 9, [EachBlockEnd(index + 2), ..tokens]) _ -> Error(error.UnexpectedBlockArgument(index + 2)) } "{{#each" <> rest -> @@ -69,7 +72,7 @@ pub fn run( [""] -> Error(error.MissingBlockArgument(index + 2)) path -> run(rest, index + 9 + string.length(arg), [ - EachBlockStart(path), + EachBlockStart(index + 2, path), ..tokens ]) } @@ -87,12 +90,12 @@ pub fn run( [""] -> Error(error.MissingPropertyPath(index + 2)) ["", ""] -> run(rest, index + 4 + string.length(body), [ - Property([]), + Property(index + 2, []), ..tokens ]) path -> run(rest, index + 4 + string.length(body), [ - Property(path), + Property(index + 2, path), ..tokens ]) } @@ -103,13 +106,13 @@ pub fn run( case input |> string.split_once("{{") { Ok(#(str, rest)) -> run("{{" <> rest, index + string.length(str), [ - Constant(str), + Constant(index, str), ..tokens ]) _ -> case input { "" -> Ok(list.reverse(tokens)) - str -> Ok(list.reverse([Constant(str), ..tokens])) + str -> Ok(list.reverse([Constant(index, str), ..tokens])) } } } diff --git a/test/unit_tests/engine_test.gleam b/test/unit_tests/engine_test.gleam index 883499d..24ff507 100644 --- a/test/unit_tests/engine_test.gleam +++ b/test/unit_tests/engine_test.gleam @@ -5,14 +5,14 @@ import handles/internal/engine import handles/internal/parser pub fn hello_world_test() { - [parser.Constant("Hello World")] + [parser.Constant(0, "Hello World")] |> engine.run(ctx.Dict([]), string_builder.new()) |> should.be_ok |> should.equal("Hello World") } pub fn hello_name_test() { - [parser.Constant("Hello "), parser.Property(["name"])] + [parser.Constant(0, "Hello "), parser.Property(0, ["name"])] |> engine.run( ctx.Dict([ctx.Prop("name", ctx.Str("Oliver"))]), string_builder.new(), @@ -22,14 +22,14 @@ pub fn hello_name_test() { } pub fn self_tag_test() { - [parser.Property([])] + [parser.Property(0, [])] |> engine.run(ctx.Str("Hello"), string_builder.new()) |> should.be_ok |> should.equal("Hello") } pub fn nested_property_test() { - [parser.Property(["foo", "bar"])] + [parser.Property(0, ["foo", "bar"])] |> engine.run( ctx.Dict([ctx.Prop("foo", ctx.Dict([ctx.Prop("bar", ctx.Int(42))]))]), string_builder.new(), @@ -39,7 +39,7 @@ pub fn nested_property_test() { } pub fn truthy_if_test() { - [parser.IfBlock(["bool"], [parser.Property(["foo", "bar"])])] + [parser.IfBlock(0, ["bool"], [parser.Property(0, ["foo", "bar"])])] |> engine.run( ctx.Dict([ ctx.Prop("foo", ctx.Dict([ctx.Prop("bar", ctx.Int(42))])), @@ -52,7 +52,7 @@ pub fn truthy_if_test() { } pub fn falsy_if_test() { - [parser.IfBlock(["bool"], [parser.Property(["foo", "bar"])])] + [parser.IfBlock(0, ["bool"], [parser.Property(0, ["foo", "bar"])])] |> engine.run( ctx.Dict([ctx.Prop("bool", ctx.Bool(False))]), string_builder.new(), @@ -62,7 +62,7 @@ pub fn falsy_if_test() { } pub fn truthy_unless_test() { - [parser.UnlessBlock(["bool"], [parser.Property(["foo", "bar"])])] + [parser.UnlessBlock(0, ["bool"], [parser.Property(0, ["foo", "bar"])])] |> engine.run( ctx.Dict([ctx.Prop("bool", ctx.Bool(True))]), string_builder.new(), @@ -72,7 +72,7 @@ pub fn truthy_unless_test() { } pub fn falsy_unless_test() { - [parser.UnlessBlock(["bool"], [parser.Property(["foo", "bar"])])] + [parser.UnlessBlock(0, ["bool"], [parser.Property(0, ["foo", "bar"])])] |> engine.run( ctx.Dict([ ctx.Prop("foo", ctx.Dict([ctx.Prop("bar", ctx.Int(42))])), @@ -86,12 +86,12 @@ pub fn falsy_unless_test() { pub fn each_test() { [ - parser.Constant("They are "), - parser.EachBlock(["list"], [ - parser.Property(["name"]), - parser.Constant(", "), + parser.Constant(0, "They are "), + parser.EachBlock(0, ["list"], [ + parser.Property(0, ["name"]), + parser.Constant(0, ", "), ]), - parser.Constant("and Kalle"), + parser.Constant(0, "and Kalle"), ] |> engine.run( ctx.Dict([ @@ -112,9 +112,9 @@ pub fn each_test() { pub fn empty_each_test() { [ - parser.EachBlock(["list"], [ - parser.Property(["name"]), - parser.Constant(", "), + parser.EachBlock(0, ["list"], [ + parser.Property(0, ["name"]), + parser.Constant(0, ", "), ]), ] |> engine.run( diff --git a/test/unit_tests/parser_test.gleam b/test/unit_tests/parser_test.gleam index 29e3812..6722bc2 100644 --- a/test/unit_tests/parser_test.gleam +++ b/test/unit_tests/parser_test.gleam @@ -9,37 +9,37 @@ pub fn no_tokens_test() { } pub fn one_constant_test() { - [tokenizer.Constant("Hello World")] + [tokenizer.Constant(0, "Hello World")] |> parser.run([]) - |> should.equal([parser.Constant("Hello World")]) + |> should.equal([parser.Constant(0, "Hello World")]) } pub fn one_property_test() { - [tokenizer.Property(["foo", "bar"])] + [tokenizer.Property(0, ["foo", "bar"])] |> parser.run([]) - |> should.equal([parser.Property(["foo", "bar"])]) + |> should.equal([parser.Property(0, ["foo", "bar"])]) } pub fn self_tag_test() { - [tokenizer.Property([])] + [tokenizer.Property(0, [])] |> parser.run([]) - |> should.equal([parser.Property([])]) + |> should.equal([parser.Property(0, [])]) } pub fn one_ifblock_test() { - [tokenizer.IfBlockStart(["bar", "biz"]), tokenizer.IfBlockEnd] + [tokenizer.IfBlockStart(0, ["bar", "biz"]), tokenizer.IfBlockEnd(0)] |> parser.run([]) - |> should.equal([parser.IfBlock(["bar", "biz"], [])]) + |> should.equal([parser.IfBlock(0, ["bar", "biz"], [])]) } pub fn one_unlessblock_test() { - [tokenizer.UnlessBlockStart(["bar", "biz"]), tokenizer.UnlessBlockEnd] + [tokenizer.UnlessBlockStart(0, ["bar", "biz"]), tokenizer.UnlessBlockEnd(0)] |> parser.run([]) - |> should.equal([parser.UnlessBlock(["bar", "biz"], [])]) + |> should.equal([parser.UnlessBlock(0, ["bar", "biz"], [])]) } pub fn one_eachblock_test() { - [tokenizer.EachBlockStart(["bar", "biz"]), tokenizer.EachBlockEnd] + [tokenizer.EachBlockStart(0, ["bar", "biz"]), tokenizer.EachBlockEnd(0)] |> parser.run([]) - |> should.equal([parser.EachBlock(["bar", "biz"], [])]) + |> should.equal([parser.EachBlock(0, ["bar", "biz"], [])]) } diff --git a/test/unit_tests/tokenizer_test.gleam b/test/unit_tests/tokenizer_test.gleam index 5c5b60b..50c50a7 100644 --- a/test/unit_tests/tokenizer_test.gleam +++ b/test/unit_tests/tokenizer_test.gleam @@ -13,7 +13,7 @@ pub fn one_tag_test() { "{{foo}}" |> tokenizer.run(0, []) |> should.be_ok - |> should.equal([tokenizer.Property(["foo"])]) + |> should.equal([tokenizer.Property(2, ["foo"])]) } pub fn two_tags_test() { @@ -21,9 +21,9 @@ pub fn two_tags_test() { |> tokenizer.run(0, []) |> should.be_ok |> should.equal([ - tokenizer.Property(["foo"]), - tokenizer.Constant(" "), - tokenizer.Property(["bar"]), + tokenizer.Property(2, ["foo"]), + tokenizer.Constant(7, " "), + tokenizer.Property(10, ["bar"]), ]) } @@ -31,7 +31,7 @@ pub fn self_tag_test() { "{{.}}" |> tokenizer.run(0, []) |> should.be_ok - |> should.equal([tokenizer.Property([])]) + |> should.equal([tokenizer.Property(2, [])]) } pub fn unexpected_token_test() { diff --git a/test/user_stories/hello_test.gleam b/test/user_stories/hello_test.gleam index d6e3910..ac8d3fa 100644 --- a/test/user_stories/hello_test.gleam +++ b/test/user_stories/hello_test.gleam @@ -10,12 +10,13 @@ const input_template = "Hello {{name}}!" const input_context = ctx.Dict([ctx.Prop("name", ctx.Str("Oliver"))]) const expected_tokens = [ - tokenizer.Constant("Hello "), tokenizer.Property(["name"]), - tokenizer.Constant("!"), + tokenizer.Constant(0, "Hello "), tokenizer.Property(8, ["name"]), + tokenizer.Constant(14, "!"), ] const expected_ast = [ - parser.Constant("Hello "), parser.Property(["name"]), parser.Constant("!"), + parser.Constant(0, "Hello "), parser.Property(8, ["name"]), + parser.Constant(14, "!"), ] const expected_output = "Hello Oliver!" diff --git a/test/user_stories/knattarna_test.gleam b/test/user_stories/knattarna_test.gleam index 746efb2..c21c149 100644 --- a/test/user_stories/knattarna_test.gleam +++ b/test/user_stories/knattarna_test.gleam @@ -23,17 +23,19 @@ const input_context = ctx.Dict( ) const expected_tokens = [ - tokenizer.Constant("They are "), tokenizer.EachBlockStart(["knattarna"]), - tokenizer.Property(["name"]), tokenizer.Constant(", "), tokenizer.EachBlockEnd, - tokenizer.Constant("and Kalle"), + tokenizer.Constant(0, "They are "), + tokenizer.EachBlockStart(11, ["knattarna"]), tokenizer.Property(30, ["name"]), + tokenizer.Constant(36, ", "), tokenizer.EachBlockEnd(40), + tokenizer.Constant(47, "and Kalle"), ] const expected_ast = [ - parser.Constant("They are "), + parser.Constant(0, "They are "), parser.EachBlock( + 11, ["knattarna"], - [parser.Property(["name"]), parser.Constant(", ")], - ), parser.Constant("and Kalle"), + [parser.Property(30, ["name"]), parser.Constant(36, ", ")], + ), parser.Constant(47, "and Kalle"), ] const expected_output = "They are Knatte, Fnatte, Tjatte, and Kalle" diff --git a/test/user_stories/nested_block.gleam b/test/user_stories/nested_block.gleam index 19365b3..e8727d5 100644 --- a/test/user_stories/nested_block.gleam +++ b/test/user_stories/nested_block.gleam @@ -46,14 +46,16 @@ const input_context = ctx.Dict( ) const expected_tokens = [ - tokenizer.EachBlockStart(["outer"]), tokenizer.EachBlockStart(["inner"]), - tokenizer.Property(["value"]), tokenizer.EachBlockEnd, tokenizer.EachBlockEnd, + tokenizer.EachBlockStart(2, ["outer"]), + tokenizer.EachBlockStart(17, ["inner"]), tokenizer.Property(32, ["value"]), + tokenizer.EachBlockEnd(41), tokenizer.EachBlockEnd(50), ] const expected_ast = [ parser.EachBlock( + 2, ["outer"], - [parser.EachBlock(["inner"], [parser.Property(["value"])])], + [parser.EachBlock(17, ["inner"], [parser.Property(32, ["value"])])], ), ]