#include #include #include #include typedef enum BinaryOperation { Add, Sub, Mul, Div, Less, More, } BinaryOperation; typedef struct EvDistr EvDistr; typedef struct HashMap_String__Evaluation HashMap_String__Evaluation; typedef struct String String; typedef struct Vec_NPPair Vec_NPPair; typedef enum Evaluation_Tag { Number, MeanDev, } Evaluation_Tag; typedef struct Evaluation { Evaluation_Tag tag; union { struct { double number; }; struct { double mean; double dev; Vec_NPPair* list; } mean_dev; }; } Evaluation; typedef enum MathResult_Evaluation_Tag { /** * Ok(T) is the Ok variation. Analagous to * std::result::Result::Ok. */ Ok_Evaluation, /** * One of the referenced variables in an expression has not been * assigned yet. */ VariableNotFound_Evaluation, /** * This is no an error per-se, but rather the result of return with * no expression to return. This is early-returned to simulate the * fact that any expression involving null would also return null. */ Void_Evaluation, /** * The denominator of a division was 0. */ ZeroDivision_Evaluation, /** * Bad type for operands */ TypeError_Evaluation, /** * a probability was not in the range [0, 1] */ OutOfRange_Evaluation, /** * probabilities don't sum to 1 */ InsufficientSum_Evaluation, /** * operation not supported */ NotImplemented_Evaluation, } MathResult_Evaluation_Tag; typedef struct MathResult_Evaluation { MathResult_Evaluation_Tag tag; union { struct { struct Evaluation ok; }; }; } MathResult_Evaluation; /** * This is all the things a bst node can be. * a lot of them have 2 levels of heap indirection, * because for ffi reasons, anything on the heap * has to be representable as a single pointer. * only box can do that, and only when given a * Sized type, so `Box`, not `Box` or * just `String`. */ typedef enum BST_Tag { Literal, Variable, Negate, Root, Binary, ListDistr, TwoVar, } BST_Tag; typedef struct Negate_Body { struct BST *operand; } Negate_Body; typedef struct Binary_Body { enum BinaryOperation op; struct BST *left; struct BST *right; } Binary_Body; typedef struct TwoVar_Body { struct BST *_0; struct BST *_1; } TwoVar_Body; typedef struct BST { BST_Tag tag; union { struct { double literal; }; struct { struct String *variable; }; Negate_Body negate; struct { struct BST *root; }; Binary_Body binary; struct { struct Vec_NPPair *list_distr; }; TwoVar_Body two_var; }; } BST; typedef struct Variables { struct HashMap_String__Evaluation *_0; } Variables; struct MathResult_Evaluation bst_eval(struct BST root, const struct Variables *variables); struct BST add(struct BST left, struct BST right); struct BST sub(struct BST left, struct BST right); struct BST mul(struct BST left, struct BST right); struct BST divide(struct BST left, struct BST right); struct BST less(struct BST left, struct BST right); struct BST more(struct BST left, struct BST right); struct BST neg(struct BST operand); struct BST sqrt(struct BST operand); void print(struct MathResult_Evaluation p); /** * # Safety * you must be able to form a slice from `name` and `len` */ struct BST number(const uint8_t *name, uintptr_t len); /** * # Safety * you must be able to form a slice from `name` and `len` */ struct BST variable(const uint8_t *name, uintptr_t len); struct BST two_var_distr(struct BST mu, struct BST sig); struct BST empty_list(void); struct BST np_pair(struct BST left, struct BST right); struct BST np_pair_push(struct BST list, struct BST left, struct BST right); struct Variables new_variables(void); void insert_variable(struct Variables *vars, struct BST name, struct MathResult_Evaluation value); void drop_variables(struct Variables v); void debug(const struct MathResult_Evaluation *v);