133 lines
3.2 KiB
Nix
133 lines
3.2 KiB
Nix
{pkgs, ...}: let
|
|
inherit
|
|
(builtins)
|
|
attrNames
|
|
concatStringsSep
|
|
filter
|
|
isAttrs
|
|
isBool
|
|
isFloat
|
|
isInt
|
|
isList
|
|
isPath
|
|
isNull
|
|
isString
|
|
match
|
|
toJSON
|
|
typeOf
|
|
;
|
|
inherit
|
|
(pkgs.lib)
|
|
assertMsg
|
|
concatStrings
|
|
fix
|
|
imap0
|
|
isDerivation
|
|
mapAttrsToList
|
|
optionalString
|
|
splitString
|
|
toPretty
|
|
;
|
|
|
|
commaJoin = concatStringsSep ", ";
|
|
|
|
renderLua = {
|
|
multiline ? true,
|
|
indent ? "",
|
|
asBindings ? false,
|
|
} @ args: v: let
|
|
innerIndent = "${indent} ";
|
|
introSpace =
|
|
if multiline
|
|
then "\n${innerIndent}"
|
|
else " ";
|
|
outroSpace =
|
|
if multiline
|
|
then "\n${indent}"
|
|
else " ";
|
|
innerArgs =
|
|
args
|
|
// {
|
|
indent =
|
|
if asBindings
|
|
then indent
|
|
else innerIndent;
|
|
asBindings = false;
|
|
};
|
|
|
|
ast = {
|
|
render = args: data: let
|
|
astType = data.__ast;
|
|
in
|
|
if ast ? ${astType}
|
|
then ast.${astType} args data
|
|
else abort ''Unknown ast type ${astType}'';
|
|
raw = args: {
|
|
data,
|
|
__no_indent ? false,
|
|
...
|
|
}: let
|
|
content =
|
|
if __no_indent
|
|
then data
|
|
else concatStringsSep "\n" (imap0 (idx: line: "${optionalString (idx != 0) args.indent}${line}") (splitString "\n" data));
|
|
in
|
|
content;
|
|
return = args: {data, ...}: "return ${renderLua args data}";
|
|
fn = args: {
|
|
data,
|
|
name,
|
|
args,
|
|
...
|
|
}: "function ${name}(${commaJoin args})${introSpace}${renderLua innerArgs data}${outroSpace}end";
|
|
};
|
|
|
|
generatedBindings = assert assertMsg (badBindingNames == []) "Bad Lua var names: ${toPretty {} badBindingNames}";
|
|
concatStrings (mapAttrsToList (key: value: "${indent}${key} = ${renderLua innerArgs value}\n") v);
|
|
|
|
concatItems = concatStringsSep ",${introSpace}";
|
|
varNameRe = "[[:alpha:]_][[:alnum:]_]*";
|
|
matchBindingName = match "${varNameRe}(\\.${varNameRe})*";
|
|
badBindingNames = filter (name: matchBindingName name == null) (attrNames v);
|
|
|
|
luaKey = key:
|
|
if match varNameRe key == null
|
|
then "[${toJSON key}]"
|
|
else key;
|
|
|
|
withSpaces = val: optionalString (val != "") "${introSpace}${val}${outroSpace}";
|
|
|
|
mkKV = key: value: "${luaKey key} = ${renderLua innerArgs value}";
|
|
in
|
|
if asBindings
|
|
then generatedBindings
|
|
else if isNull v
|
|
then "nil"
|
|
else if isInt v || isFloat v || isString v || isBool v
|
|
then toJSON v
|
|
else if isPath v || isDerivation v
|
|
then toJSON "${v}"
|
|
else if isList v
|
|
then "{${withSpaces (concatItems (map (renderLua innerArgs) v))}}"
|
|
else if v ? __ast
|
|
then ast.render args v
|
|
else if isAttrs v
|
|
then "{${withSpaces (concatItems (mapAttrsToList mkKV v))}}"
|
|
else abort "generators.renderLua: type ${typeOf v} is unsupported";
|
|
|
|
newAst = type: set: set // {__ast = type;};
|
|
in
|
|
fix (lua: {
|
|
inherit renderLua;
|
|
|
|
writeLua = name: value: pkgs.writeText name (lua.renderLua {} value);
|
|
|
|
raw = data: newAst "raw" {inherit data;};
|
|
|
|
function = name: args: data: newAst "fn" {inherit name data args;};
|
|
|
|
lambda = lua.function "";
|
|
|
|
return = data: newAst "return" {inherit data;};
|
|
})
|