Compare commits

...

3 Commits

Author SHA1 Message Date
Dmitriy Pleshevskiy f1f7668117
add vars alias 2024-04-17 17:22:56 +03:00
Dmitriy Pleshevskiy 94ea63f90c
add if, ifelse, return 2024-04-17 17:05:36 +03:00
Dmitriy Pleshevskiy e80b4f0b88
add keywords 2024-04-17 15:45:30 +03:00
2 changed files with 127 additions and 37 deletions

106
lib.nix
View File

@ -18,6 +18,9 @@ let
inherit (builtins) isString isFloat isInt isBool isList isAttrs isNull isPath;
inherit (builtins) concatStringsSep filter mapAttrs attrValues;
isNotNull = v: !(isNull v);
excludeNull = expr: filter isNotNull expr;
################################################################################
# Utils
################################################################################
@ -32,10 +35,23 @@ let
if isString expr || isPath expr then toString expr
else error "Value '${toString 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";
################################################################################
# Low-Level
################################################################################
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";
isJoin = expr: getType expr == "_join";
join = sep: expr:
if isList expr then { _type = "_join"; sep = validString sep; parts = expr; }
@ -51,7 +67,33 @@ let
pipe = join ".";
spaceBetween = join " ";
op = operation: left: right: concat [ (raw "(") (join " ${operation} " [ left right ]) (raw ")") ];
wrap = start: end: expr:
concat [ (raw start) expr (raw end) ];
wrapParen = wrap "(" ")";
call = fnName: args:
concat [ (validFuncName fnName) (wrapParen (join ", " args)) ];
require = name: call "require" [ name ];
kw_and = raw "and";
kw_or = raw "or";
kw_not = raw "not";
kw_function = raw "function";
kw_end = raw "end";
kw_break = raw "break";
kw_return = raw "return";
kw_if = raw "if";
kw_in = raw "in";
kw_then = raw "then";
kw_else = raw "else";
kw_local = raw "local";
kw_for = raw "for";
kw_do = raw "do";
kw_until = raw "until";
kw_while = raw "while";
kw_repeat = raw "repeat";
op = operation: left: right: wrapParen (join " ${operation} " [ left right ]);
add = op "+";
sub = op "-";
@ -67,48 +109,36 @@ let
gte = op ">=";
lte = op "<=";
and = op "and";
or = op "or";
not = expr: spaceBetween [ (raw "not") expr ];
and = op kw_and;
or = op kw_or;
not = expr: spaceBetween [ kw_not expr ];
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";
call = fnName: args:
let
luaFn =
if isString fnName && builtins.stringLength fnName > 0 then raw fnName
else error "Value '${toString fnName}' is not a valid function name";
in
concat (
[ luaFn (raw "(") ]
++ [ (join ", " args) ]
++ [ (raw ")") ]
);
require = name: call "require" [ name ];
local = expr: spaceBetween [ (raw "local") expr ];
local = expr: spaceBetween [ kw_local expr ];
set = variable: value: join " = " [ (raw variable) value ];
func = name: params: body:
func = fnName: params: body:
(concatLines
([
(concat [
(spaceBetween (map raw [ "function" name ]))
(raw "(")
(join ", " (map raw params))
(raw ")")
(spaceBetween [ kw_function (validFuncName fnName) ])
(wrapParen (join ", " (map raw params)))
])
]
++ body
++ [ (raw "end") ])
++ [ kw_end ])
);
return = expr: spaceBetween ([ kw_return expr ]);
return_void = return null;
ifelse = condition: trueBody: falseBody:
(concatLines
([ (spaceBetween [ kw_if condition kw_then ]) ]
++ trueBody
++ (if falseBody != [ ] then [ kw_else ] ++ falseBody else [ ])
++ [ kw_end ])
);
if' = condition: trueBody: ifelse condition trueBody [ ];
isLuaNil = expr: getType expr == "nil";
LuaNil = { _type = "nil"; };
@ -125,7 +155,6 @@ let
toLuaList = onValue: expr:
let
wrapObj = expr: "{ ${concatStringsSep ", " expr} }";
excludeNull = expr: filter (v: !(isNull v)) expr;
in
wrapObj (excludeNull (map onValue expr));
toLuaNamedField = name: expr:
@ -135,7 +164,7 @@ let
toLuaInternal = depth: expr:
let nextDepth = depth + 1; in
if isJoin expr then concatStringsSep expr.sep (map (toLuaInternal depth) expr.parts)
if isJoin expr then concatStringsSep expr.sep (map (toLuaInternal depth) (excludeNull expr.parts))
else if isLuaNil expr then "nil"
else if isRaw expr then expr.raw
else if isNamedField expr then
@ -162,13 +191,16 @@ in
inherit LuaNil;
inherit raw join concat concatLines pipe;
inherit namedField call require local set func;
inherit namedField call require local set func ifelse if';
inherit op;
inherit eq ne gt lt gte lte;
inherit add sub mul div mod exp;
inherit and or not;
# useful alias
inherit return return_void;
# useful aliases
var = raw;
vars = map raw;
}

View File

@ -178,4 +178,62 @@ with nix2lua; pkgs.lib.runTests {
end
'';
};
"test returns if statement" = {
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" ])
]);
expected = ''
if (10 == 10) then
print("10 == 10")
else
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
'';
};
"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
'';
};
}