196 lines
7.1 KiB
Nix
196 lines
7.1 KiB
Nix
{
|
|
lib,
|
|
pkgs,
|
|
}:
|
|
with lib;
|
|
let
|
|
indent =
|
|
indent: text:
|
|
pkgs.lib.strings.concatMapLines (line: indent + line + "\n") (
|
|
if builtins.isList text then text else pkgs.lib.strings.splitString "\n" text
|
|
);
|
|
pyBool = val: if val then "True" else "False";
|
|
pyStr = val: "\"${builtins.replaceStrings ["\\" "\"" "\n"] ["\\\\" "\\\"" "\\n"] val}\"";
|
|
in
|
|
mkModule (self: {
|
|
pythonRuntime = mkRuntime (self: {
|
|
nativeFunctionTypes = [ self.func ];
|
|
nativeDataFormats = with self.formats; [
|
|
jsonObject
|
|
blobStream
|
|
blobString
|
|
];
|
|
python = pkgs.python3;
|
|
builder =
|
|
bindings:
|
|
let
|
|
initialState = {
|
|
repositories = [ ];
|
|
bindings = [ ];
|
|
functions = [ ];
|
|
classes = [ ];
|
|
};
|
|
stateAppend =
|
|
state: kind: obj:
|
|
state // { ${kind} = state.${kind} ++ [ obj ]; };
|
|
findOrAssign =
|
|
lst: obj:
|
|
let
|
|
newIndex = builtins.length lst;
|
|
index = pkgs.lib.lists.findFirstIndex (obj2: obj == obj2) newIndex lst;
|
|
new = index == newIndex;
|
|
newLst = lst ++ (if new then [ obj ] else [ ]);
|
|
in
|
|
{
|
|
inherit index new;
|
|
lst = newLst;
|
|
};
|
|
|
|
typeToAttr = {
|
|
Function = "functions";
|
|
Repo = "repositories";
|
|
Class = "classes";
|
|
Binding = "bindings";
|
|
};
|
|
|
|
visit = visitors: obj: visitors.${typeToAttr.${obj.__artinixType}} obj;
|
|
childrenOf = obj: visit childVisitors obj;
|
|
childVisitors = {
|
|
repositories =
|
|
repository:
|
|
initialState
|
|
// {
|
|
classes = [ repository.class ];
|
|
};
|
|
classes = class: initialState;
|
|
functions = func: initialState;
|
|
bindings =
|
|
binding:
|
|
initialState
|
|
// {
|
|
classes = [ binding.class ];
|
|
repositories =
|
|
(mapAttrsToList (_: r: r) bindings.inputs) ++ (mapAttrsToList (_: r: r) bindings.outputs);
|
|
functions = [ binding.function ];
|
|
};
|
|
};
|
|
|
|
explode' = state: obj: let
|
|
lst = state.${typeToAttr.${obj.__artinixType}};
|
|
found = findOrAssign lst obj;
|
|
in (if found.new then (let
|
|
state1 = stateAppend state typeToAttr.${obj.__artinixType} obj;
|
|
children = childrenOf obj;
|
|
state3 = foldlAttrs (state2: _: childrenList: builtins.foldl' explode' state2 childrenList) state1 children;
|
|
in state3) else state);
|
|
explodeList = builtins.foldl' explode' initialState;
|
|
|
|
indexOf = item: lst: findFirstIndex (obj: obj == item) (throw "Option was not found in the options list") lst;
|
|
reloop = exploded: let
|
|
numberVisitors = {
|
|
repositories = repo: repo // { class = indexOf repo.class exploded.classes; };
|
|
classes = class: class;
|
|
functions = func: func;
|
|
bindings = binding: binding // {
|
|
class = indexOf binding.class exploded.classes;
|
|
function = indexOf binding.function exploded.functions;
|
|
inputs = builtins.mapAttrs (k: v: indexOf v exploded.repositories) binding.inputs;
|
|
outputs = builtins.mapAttrs (k: v: indexOf v exploded.repositories) binding.outputs;
|
|
};
|
|
};
|
|
numbered = builtins.mapAttrs (k: v: builtins.map numberVisitors.${k} v) exploded;
|
|
result = pkgs.lib.converge (final: let
|
|
reloopVisitors = {
|
|
repositories = repo: repo // { class = builtins.elemAt final.classes repo.class; };
|
|
classes = class: class;
|
|
functions = func: func;
|
|
bindings = binding: binding // {
|
|
class = builtins.elemAt final.classes binding.class;
|
|
function = builtins.elemAt final.functions binding.function;
|
|
inputs = builtins.mapAttrs (k: v: builtins.elemAt final.repositories v) binding.inputs;
|
|
outputs = builtins.mapAttrs (k: v: builtins.elemAt final.repositories v) binding.outputs;
|
|
};
|
|
};
|
|
in
|
|
builtins.mapAttrs (k: v: pkgs.lib.imap0 (i: v': (reloopVisitors.${k} v') // { __index = i; }) v) final
|
|
) numbered;
|
|
in result;
|
|
|
|
#index' = exploded: obj: let
|
|
# options = exploded.${typeToAttr.${obj.__artinixType}};
|
|
# index = indexOf obj options;
|
|
# relooped = reloop exploded;
|
|
# options' = relooped.${typeToAttr.${obj.__artinixType}};
|
|
#in builtins.elemAt options' index;
|
|
#indexList = lst: let exploded = explodeList lst; in builtins.map (index' exploded) lst;
|
|
#index = obj: index' (explode obj) obj;
|
|
#bindings = indexList bindings;
|
|
|
|
finalState = reloop (explodeList bindings);
|
|
|
|
inherit (pkgs.lib.attrsets) mapAttrsToList foldlAttrs;
|
|
inherit (pkgs.lib.lists) findFirstIndex;
|
|
|
|
allPyDeps = pkgs.lib.lists.concatMap (func: func.pythonDeps) attrs.nativeFunctions;
|
|
pyEnv = self.python.withPackages (
|
|
pythonPackages:
|
|
builtins.map (dep: if builtins.isString dep then pythonPackages.${dep} else dep) allPyDeps
|
|
);
|
|
in
|
|
pkgs.substituteAll {
|
|
name = "driver.py";
|
|
src = ./src/driver.py.template;
|
|
interpreter = pyEnv.mainProgram;
|
|
allowDefault = pyBool TODO;
|
|
allowManual = pyBool TODO;
|
|
entityClassSetup = indent "" (
|
|
pkgs.lib.flip builtins.map finalState.bindings (
|
|
binding: "entity_classes.append(ArtinixEntityClass(${pyStr binding.name}))"
|
|
)
|
|
);
|
|
repositorySetup = indent "" (
|
|
pkgs.lib.flip builtins.map finalState.repositories (
|
|
repo: "repositories.append(ArtinixRepository(entity_classes[${repo.class.__index}], ${pyStr repo.name}, ${pystr "dtype?"}))"
|
|
)
|
|
);
|
|
|
|
functionSetup = indent "" (
|
|
pkgs.lib.flip builtins.map finalState.functions (
|
|
func: "functions.append(ArtinixPythonFunction(${pyStr func.module_path}, ${pyStr func.func_name}))"
|
|
)
|
|
);
|
|
datastoreSetup = "";
|
|
};
|
|
});
|
|
# TODO integrate the typechecker right here I think?
|
|
func = mkFuncType (
|
|
{ module, function }:
|
|
{
|
|
linker = self.pythonLinker;
|
|
inherit module function;
|
|
}
|
|
);
|
|
pythonTypeChecker = (
|
|
{
|
|
module,
|
|
function,
|
|
inputs,
|
|
outputs,
|
|
}:
|
|
pkgs.runCommand "typecheck-python-${builtins.baseNameOf module}-${function}" { } ''
|
|
# tee hee
|
|
touch $out
|
|
''
|
|
);
|
|
formats = mkModule (self': {
|
|
jsonObject = mkFormat { pythonConstructor = "ArtinixJsonObjectFormat()"; };
|
|
blobStream = mkFormat { pythonConstructor = "ArtinixBlobStreamFormat()"; };
|
|
blobString = mkFormat { pythonConstructor = "ArtinixBlobStringFormat()"; };
|
|
pythonObject = ty: mkFormat { inherit ty; pythonConstructor = "ArtinixPythonObjectFormat(${pyStr ty})"; };
|
|
generatorOf = subfmt: mkFormat { inherit subfmt; pythonConstructor = "ArtinixGeneratorOfFormat(${subfmt.pythonConstructor})"; };
|
|
});
|
|
dtypes = mkModule (self': {
|
|
pythonClass = name: mkRepoType { inherit name; };
|
|
});
|
|
})
|