From 2e5a6d69d38e4bcebfe8efcef41c7c816b061f0b Mon Sep 17 00:00:00 2001 From: Oliver Linnarsson Date: Tue, 18 Jun 2024 14:01:39 +0200 Subject: [PATCH] feat: Test are passing for v2.0 --- src/handles/internal/ctx_utils.gleam | 104 ++++++++++++++++ src/handles/internal/engine.gleam | 180 +++++---------------------- src/handles/internal/parser.gleam | 6 +- 3 files changed, 136 insertions(+), 154 deletions(-) create mode 100644 src/handles/internal/ctx_utils.gleam diff --git a/src/handles/internal/ctx_utils.gleam b/src/handles/internal/ctx_utils.gleam new file mode 100644 index 0000000..33fc08b --- /dev/null +++ b/src/handles/internal/ctx_utils.gleam @@ -0,0 +1,104 @@ +import gleam/float +import gleam/int +import gleam/list +import gleam/result +import handles/ctx +import handles/error + +pub fn drill_ctx( + path: List(String), + ctx: ctx.Value, +) -> Result(ctx.Value, error.RuntimeError) { + case path { + [] -> Ok(ctx) + [key, ..rest] -> + case 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([])) + } + } + 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"])) + } + } +} + +pub fn get_property( + 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) + } + }) + |> result.try(fn(it) { + case it { + ctx.Str(value) -> value |> Ok + 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"])) + ctx.Dict(_) -> + Error(error.UnexpectedTypeError(path, "Dict", ["Str", "Int", "Float"])) + ctx.Bool(_) -> + Error(error.UnexpectedTypeError(path, "Bool", ["Str", "Int", "Float"])) + } + }) +} + +pub fn get_list( + 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) + } + }) + |> 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"])) + } + }) +} + +pub fn get_bool( + 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) + } + }) + |> 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"])) + } + }) +} diff --git a/src/handles/internal/engine.gleam b/src/handles/internal/engine.gleam index 989483a..6141f60 100644 --- a/src/handles/internal/engine.gleam +++ b/src/handles/internal/engine.gleam @@ -1,110 +1,11 @@ -import gleam/float -import gleam/int -import gleam/list +import gleam/bool import gleam/result import gleam/string_builder import handles/ctx import handles/error +import handles/internal/ctx_utils import handles/internal/parser -fn drill_ctx( - path: List(String), - ctx: ctx.Value, -) -> Result(ctx.Value, error.RuntimeError) { - case path { - [] -> Ok(ctx) - [key, ..rest] -> - case 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([])) - } - } - 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"])) - } - } -} - -fn get_property( - 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) - } - }) - |> result.try(fn(it) { - case it { - ctx.Str(value) -> value |> Ok - 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"])) - ctx.Dict(_) -> - Error(error.UnexpectedTypeError(path, "Dict", ["Str", "Int", "Float"])) - ctx.Bool(_) -> - Error(error.UnexpectedTypeError(path, "Bool", ["Str", "Int", "Float"])) - } - }) -} - -fn get_list( - 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) - } - }) - |> 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"])) - } - }) -} - -fn get_bool( - 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) - } - }) - |> 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"])) - } - }) -} - fn run_each( ctxs: List(ctx.Value), ast: List(parser.AST), @@ -120,6 +21,17 @@ fn run_each( } } +fn run_if( + bool: Bool, + children: List(parser.AST), + ctx: ctx.Value, +) -> Result(String, error.RuntimeError) { + case bool { + False -> Ok("") + True -> run(children, ctx, string_builder.new()) + } +} + pub fn run( ast: List(parser.AST), ctx: ctx.Value, @@ -129,60 +41,26 @@ pub fn run( [] -> builder |> string_builder.to_string |> Ok [node, ..rest] -> case node { - parser.Constant(value) -> - run( - rest, - ctx, - builder - |> string_builder.append(value), - ) - parser.Property(path) -> - get_property(path, ctx) - |> result.try(fn(it) { - run( - rest, - ctx, - builder - |> string_builder.append(it), - ) - }) + parser.Constant(value) -> Ok(value) + parser.Property(path) -> ctx_utils.get_property(path, ctx) parser.IfBlock(path, children) -> - get_bool(path, ctx) - |> result.try(fn(it) { - case it { - False -> run(rest, ctx, builder) - True -> - run(children, ctx, string_builder.new()) - |> result.try(fn(it) { - run( - rest, - ctx, - builder - |> string_builder.append(it), - ) - }) - } - }) + ctx_utils.get_bool(path, ctx) + |> result.try(run_if(_, children, ctx)) parser.UnlessBlock(path, children) -> - get_bool(path, ctx) - |> result.try(fn(it) { - case it { - True -> run(rest, ctx, builder) - False -> - run(children, ctx, string_builder.new()) - |> result.try(fn(it) { - run( - rest, - ctx, - builder - |> string_builder.append(it), - ) - }) - } - }) + ctx_utils.get_bool(path, ctx) + |> result.map(bool.negate) + |> result.try(run_if(_, children, ctx)) parser.EachBlock(path, children) -> - get_list(path, ctx) + ctx_utils.get_list(path, ctx) |> result.try(run_each(_, children, string_builder.new())) } + |> result.try(fn(it) { + run( + rest, + ctx, + builder + |> string_builder.append(it), + ) + }) } } diff --git a/src/handles/internal/parser.gleam b/src/handles/internal/parser.gleam index 70c1221..d056203 100644 --- a/src/handles/internal/parser.gleam +++ b/src/handles/internal/parser.gleam @@ -18,21 +18,21 @@ pub fn run(tokens: List(tokenizer.Token), ast: List(AST)) -> List(AST) { tokenizer.Property(path) -> run(tail, [Property(path), ..ast]) tokenizer.IfBlockStart(path) -> { let children = run(tail, []) - run(list.drop(tail, list.length(children)), [ + run(list.drop(tail, list.length(children) + 1), [ IfBlock(path, children), ..ast ]) } tokenizer.UnlessBlockStart(path) -> { let children = run(tail, []) - run(list.drop(tail, list.length(children)), [ + run(list.drop(tail, list.length(children) + 1), [ UnlessBlock(path, children), ..ast ]) } tokenizer.EachBlockStart(path) -> { let children = run(tail, []) - run(list.drop(tail, list.length(children)), [ + run(list.drop(tail, list.length(children) + 1), [ EachBlock(path, children), ..ast ])