From ce62a78f5ac9d7693cea23c5db7d44eed2f80d9a Mon Sep 17 00:00:00 2001 From: Dmitriy Pleshevskiy Date: Sat, 20 Apr 2024 19:11:24 +0300 Subject: [PATCH] improve call and conditions api --- lib.nix | 68 ++++++++++++++------------- lib.test.nix | 128 ++++++++++++++++----------------------------------- 2 files changed, 76 insertions(+), 120 deletions(-) diff --git a/lib.nix b/lib.nix index fc0886d..72e0baf 100644 --- a/lib.nix +++ b/lib.nix @@ -26,6 +26,9 @@ let ################################################################################ error = message: throw "[nix2lua] ${message}"; + validationError = expr: message: + let val = if builtins.isFunction expr then "Function" else "Value '${toString expr}'"; in + error "${val} ${message}"; warn = msg: builtins.trace "[nix2lua] warning: ${msg}"; deprecated = before: now: warn "`${before}` is deprecated. Use `${now}` instead"; @@ -34,11 +37,11 @@ let validString = expr: if isRaw expr then validString expr.raw else if isString expr || isPath expr then toString expr - else error "Value '${toString expr}' is not a valid string"; + else validationError expr "is not a valid string"; validFuncName = fnName: if isString fnName && builtins.stringLength fnName > 0 then raw fnName - else error "Value '${toString fnName}' is not a valid function name"; + else validationError fnName "is not a valid function name"; ################################################################################ # Low-Level @@ -46,25 +49,16 @@ let isRaw = expr: getType expr == "raw"; raw = expr: - if isRaw expr then - { _type = "raw"; raw = expr.raw; } - else if isString expr then - { _type = "raw"; raw = expr; } - else - error "Value '${toString expr}' is not supported for a raw type"; + if isRaw expr then { _type = "raw"; raw = expr.raw; } + else if isString expr then { _type = "raw"; raw = expr; } + else validationError expr "is not supported for a raw type"; isJoin = expr: getType expr == "_join"; join = sep: expr: if isList expr then { _type = "_join"; sep = validString sep; parts = expr; } - else error "Value '${toString expr}' is not supported for a join type"; + else validationError expr "is not supported for a join type"; concat = join ""; - concatLines = lines: - join "\n" ( - lines - # add an empty line at the end - ++ [ (raw "") ] - ); pipe = join "."; pipe1 = lft: rgt: pipe [ lft rgt ]; spaceBetween = join " "; @@ -74,10 +68,17 @@ let wrapParen = wrap "(" ")"; call = fnName: args: - concat [ (validFuncName fnName) (wrapParen (join ", " args)) ]; + concat [ + (validFuncName fnName) + (wrapParen ( + if isList args then join ", " args + else if builtins.isFunction args then validationError args "is not supported to call args" + else args + )) + ]; call0 = fnName: call fnName [ ]; call1 = fnName: arg: call fnName [ arg ]; - require = name: call1 "require" name; + require = name: call "require" name; kw_and = raw "and"; kw_or = raw "or"; @@ -117,36 +118,38 @@ let or = op kw_or; not = expr: spaceBetween [ kw_not expr ]; + # Type: validBlockBody :: a -> [b] + validBlockBody = body: + if isList body then body + else if isAttrs body then [ body ] + else validationError body "is not valid block body"; + local = expr: spaceBetween [ kw_local expr ]; set = variable: value: join " = " [ (raw variable) value ]; func = fnName: params: body: - let - f = - if isList body then concatLines - else if isAttrs body then spaceBetween - else error "Value ${toString body} is not a valid function body"; - in - (f + (spaceBetween ([ (concat [ (spaceBetween [ kw_function (validFuncName fnName) ]) (wrapParen (join ", " (map raw params))) ]) ] - ++ (if isList body then body else if isAttrs body then [ body ] else [ ]) + ++ (validBlockBody body) ++ [ kw_end ]) ); + func0 = fnName: func fnName [ ]; lambda = func ""; lambda0 = lambda [ ]; return = expr: spaceBetween ([ kw_return expr ]); - return_void = return null; + return_void = return + null; ifelse = condition: trueBody: falseBody: - (concatLines - ([ (spaceBetween [ kw_if condition kw_then ]) ] - ++ trueBody - ++ (if falseBody != [ ] then [ kw_else ] ++ falseBody else [ ]) + (spaceBetween + ([ kw_if condition kw_then ] + ++ (validBlockBody trueBody) + ++ (if falseBody != [ ] then [ kw_else ] ++ (validBlockBody falseBody) else [ ]) ++ [ kw_end ]) ); if' = condition: trueBody: ifelse condition trueBody [ ]; @@ -198,17 +201,18 @@ in mkLuaRaw = deprecated "mkLuaRaw" "raw" raw; mkCall = deprecated "mkCall" "call" call; mkNamedField = deprecated "mkNamedField" "namedField" namedField; + concatLines = deprecated "concatLines" "spaceBetween" spaceBetween; inherit toLua; inherit LuaNil; - inherit raw join concat concatLines; + inherit raw join concat spaceBetween; inherit pipe pipe1; inherit namedField require local set ifelse if'; inherit call call0 call1; - inherit func lambda lambda0; + inherit func func0 lambda lambda0; inherit op; inherit eq ne gt lt gte lte; diff --git a/lib.test.nix b/lib.test.nix index 57b95de..8731185 100644 --- a/lib.test.nix +++ b/lib.test.nix @@ -33,11 +33,11 @@ with nix2lua; pkgs.lib.runTests { }; "test returns a lua string" = { expr = toLua "hello world"; - expected = "\"hello world\""; + expected = ''"hello world"''; }; "test returns a path as a lua string" = { expr = toLua /hello/world; - expected = "\"/hello/world\""; + expected = ''"/hello/world"''; }; "test returns an integer number" = { expr = toLua 10; @@ -61,11 +61,11 @@ with nix2lua; pkgs.lib.runTests { }; "test returns table with all primitive types" = { expr = toLua [ "hello" 10 10.1 true ]; - expected = "{ \"hello\", 10, 10.100000, true }"; + expected = ''{ "hello", 10, 10.100000, true }''; }; "test returns table without null values" = { expr = toLua [ null "hello" null 10 null 10.1 null true null ]; - expected = "{ \"hello\", 10, 10.100000, true }"; + expected = ''{ "hello", 10, 10.100000, true }''; }; "test returns named table" = { expr = toLua { @@ -75,11 +75,11 @@ with nix2lua; pkgs.lib.runTests { success = true; fail = false; }; - expected = "{ [\"fail\"] = false, [\"float\"] = 10.100000, [\"foo\"] = \"hello\", [\"int\"] = 10, [\"success\"] = true }"; + expected = ''{ ["fail"] = false, ["float"] = 10.100000, ["foo"] = "hello", ["int"] = 10, ["success"] = true }''; }; "test returns named table without nullable items" = { expr = toLua { foo = "hello"; bar = null; }; - expected = "{ [\"foo\"] = \"hello\" }"; + expected = ''{ ["foo"] = "hello" }''; }; "test returns recursive named table" = { expr = toLua { @@ -89,11 +89,11 @@ with nix2lua; pkgs.lib.runTests { }; }; }; - expected = "{ [\"first\"] = { [\"second\"] = { [\"last\"] = \"hello\" } } }"; + expected = ''{ ["first"] = { ["second"] = { ["last"] = "hello" } } }''; }; "test return recursive table" = { expr = toLua [ [ [ "foo" ] "bar" ] ]; - expected = "{ { { \"foo\" }, \"bar\" } }"; + expected = ''{ { { "foo" }, "bar" } }''; }; "test returns table with one named field" = { expr = toLua [ @@ -101,7 +101,7 @@ with nix2lua; pkgs.lib.runTests { (namedField "foo" "hello") 10 ]; - expected = "{ \"foo\", [\"foo\"] = \"hello\", 10 }"; + expected = ''{ "foo", ["foo"] = "hello", 10 }''; }; "test returns raw string" = { expr = toLua (raw "hello"); @@ -113,7 +113,7 @@ with nix2lua; pkgs.lib.runTests { }; "test returns path as string" = { expr = toLua /foo/bar; - expected = "\"/foo/bar\""; + expected = ''"/foo/bar"''; }; "test throws an error when you try to use named field withoun table" = { expr = tryEval (toLua (namedField "foo" "bar")); @@ -121,17 +121,14 @@ with nix2lua; pkgs.lib.runTests { }; "test returns call function with arguments" = { expr = toLua (call "root_pattern" [ "deno.json" "deno.jsonc" ]); - expected = "root_pattern(\"deno.json\", \"deno.jsonc\")"; + expected = ''root_pattern("deno.json", "deno.jsonc")''; }; - "test returns concated lines" = { - expr = toLua (concatLines [ + "test returns concated expressions" = { + expr = toLua (spaceBetween [ (call "foo" [ 1 2 ]) (call "bar" [ "baz" "biz" ]) ]); - expected = '' - foo(1, 2) - bar("baz", "biz") - ''; + expected = ''foo(1, 2) bar("baz", "biz")''; }; "test returns a pipe with many function call" = { expr = toLua (pipe [ @@ -149,18 +146,13 @@ with nix2lua; pkgs.lib.runTests { expected = "local parser_config.d2 = { }"; }; "test returns all operations" = { - expr = toLua (concatLines [ - (eq (mul (add 1 2) (sub 2 1)) 3) - (not (eq (mul (add 1 2) (sub 2 1)) 3)) - (not 10) - (gt 10 5) + expr = toLua (spaceBetween [ + (set "a" (eq (mul (add 1 2) (sub 2 1)) 3)) + (set "b" (not (eq (mul (add 1 2) (sub 2 1)) 3))) + (set "c" (not 10)) + (set "d" (gt 10 5)) ]); - expected = '' - (((1 + 2) * (2 - 1)) == 3) - not (((1 + 2) * (2 - 1)) == 3) - not 10 - (10 > 5) - ''; + expected = ''a = (((1 + 2) * (2 - 1)) == 3) b = not (((1 + 2) * (2 - 1)) == 3) c = not 10 d = (10 > 5)''; }; "test returns rendered condition" = { expr = toLua (set "name" @@ -168,82 +160,42 @@ with nix2lua; pkgs.lib.runTests { ); expected = "name = ((a >= 1) and (a <= 10))"; }; - "test returns defined multiline function" = { + "test returns defined function" = { expr = toLua (func "hello" [ "a" "b" ] [ - (eq (mul (add (var "a") 2) (sub 2 1)) 3) - (not (eq (mul (add (var "b") 2) (sub 2 1)) 3)) - (not 10) - (gt 10 5) + (set "a" (eq (mul (add 1 2) (sub 2 1)) 3)) + (set "b" (not (eq (mul (add 1 2) (sub 2 1)) 3))) + (set "c" (not 10)) + (set "d" (gt 10 5)) ]); - expected = '' - function hello(a, b) - (((a + 2) * (2 - 1)) == 3) - not (((b + 2) * (2 - 1)) == 3) - not 10 - (10 > 5) - end - ''; + expected = ''function hello(a, b) a = (((1 + 2) * (2 - 1)) == 3) b = not (((1 + 2) * (2 - 1)) == 3) c = not 10 d = (10 > 5) end''; }; "test returns defined singleline function" = { expr = toLua (func "hello" [ "a" ] (call1 "h.world" (var "a"))); expected = "function hello(a) h.world(a) end"; }; "test returns if statement" = { - expr = toLua (if' (eq 10 10) [ - (call "print" [ 10 ]) - ]); - expected = '' - if (10 == 10) then - print(10) - end - ''; + expr = toLua (if' (eq 10 10) (call "print" [ 10 ])); + expected = ''if (10 == 10) then print(10) end''; }; "test returns if else statement" = { expr = toLua (ifelse (eq 10 10) [ - (call "print" [ "10 == 10" ]) + (call "print" "10 == 10") + (call "print" "10 == 10") ] [ - (call "print" [ "10 != 10" ]) + (call "print" "10 != 10") + (call "print" "10 != 10") ]); - expected = '' - if (10 == 10) then - print("10 == 10") - else - print("10 != 10") - end - ''; + expected = ''if (10 == 10) then print("10 == 10") print("10 == 10") else print("10 != 10") print("10 != 10") end''; }; "test returns a deep if else statement" = { - expr = toLua (ifelse (eq 10 10) [ - (if' true [ (call "print" [ "yes" ]) ]) - ] [ - (if' true [ (call "print" [ "no" ]) ]) - ]); - expected = '' - if (10 == 10) then - if true then - print("yes") - end - - else - if true then - print("no") - end - - end - ''; + expr = toLua (ifelse (eq 10 10) + (if' true (call "print" "yes")) + (if' true (call "print" "no")) + ); + expected = ''if (10 == 10) then if true then print("yes") end else if true then print("no") end end''; }; "test returns a returns keyword" = { - expr = toLua (ifelse (eq 10 10) [ - return_void - ] [ - (return 10) - ]); - expected = '' - if (10 == 10) then - return - else - return 10 - end - ''; + expr = toLua (ifelse (eq 10 10) return_void (return 10)); + expected = ''if (10 == 10) then return else return 10 end''; }; }