0
Fork 0
data-structures-lesson1/aritynode.h

93 lines
3.0 KiB
C

#ifndef ARITYNODE_H
#define ARITYNODE_H
////////////////////////////////
// Type: Arity Node
typedef enum DS_ArityKind{
DS_ArityKind_Empty = 0,
DS_ArityKind_Singleton = 1,
DS_ArityKind_Arrow = 2,
DS_ArityKind_Tuple = 3,
} DS_ArityKind;
typedef struct DS_ArityNode{
DS_ArityKind kind;
U32 coefficient;
union{
struct{
struct DS_ArityNode *domain;
struct DS_ArityNode *codomain;
} arrow;
struct{
struct DS_ArityNode **parts;
U64 part_count;
} tuple;
};
} DS_ArityNode;
////////////////////////////////
// Functions: Arity Node
// construction
/* NOTE:
** Construction functions that take in arity node(s) require
** that the arena that allocated the input arity node(s)
** is the same arena that is used in the current call, and
** that the arena has not popped the nodes.
**
** Example of misuse:
**
** GIVEN Arena *a1; Arena *a2;
** WITH (a1 != a2):
** DS_ArityNode *n1 = ds_aritynode_singleton(a1);
** DS_ArityNode *n2 = ds_aritynode_arrow(a2, n1); @bad - changing arenas
**
** Why this matters:
**
** We don't want to have to deep copy every node we ever see as input,
** so construction functions just keep pointers to their inputs, or
** sometimes make shallow copies but still keep the original versions
** of the deeper nodes. Because of the way arenas work, if these
** all exist on one arena, later nodes always point towards earlier
** nodes, and so if a node is still on the arena, so are all of the nodes
** that it depends on. However, if we start crossing arenas, we would
** have to be much more careful not to start generating use-after-free
** issues.
**
** If you think it through and you *know what you're doing* you can
** break this rule, but as a rule of thumb, it usually works best if you
** can put all the nodes that work together into the same arena.
*/
MR4TH_SYMBOL DS_ArityNode* ds_aritynode_empty(Arena *arena);
MR4TH_SYMBOL DS_ArityNode* ds_aritynode_singleton(Arena *arena);
MR4TH_SYMBOL DS_ArityNode* ds_aritynode_arrow(Arena *arena, DS_ArityNode *domain, DS_ArityNode *codomain);
MR4TH_SYMBOL DS_ArityNode* ds_aritynode_paste(Arena *arena, DS_ArityNode *a, DS_ArityNode *b);
/* NOTE:
** ds_aritynode_sum takes the variadic layout:
** (coeff_1:U32, arity_1:DS_ArityNode*, ..., coeff_k:U32, arity_k:DS_ArityNode*, 0)
*/
MR4TH_SYMBOL DS_ArityNode* ds_aritynode_sum(Arena *arena, ...);
MR4TH_SYMBOL DS_ArityNode* ds_aritynode_ktuple(Arena *arena, U32 coefficient);
// operations
/* NOTE:
** ds_aritynode_copy is not a "construction function"
** it can deep copy an arity node from one arena to another.
*/
MR4TH_SYMBOL DS_ArityNode* ds_aritynode_copy(Arena *arena, DS_ArityNode *arity);
MR4TH_SYMBOL B32 ds_aritynode_equal(DS_ArityNode *a, DS_ArityNode *b);
// helpers
MR4TH_SYMBOL DS_ArityNode* ds_aritynode__part_copy(Arena *arena, DS_ArityNode *node);
MR4TH_SYMBOL DS_ArityNode* ds_aritynode__part_find_match(DS_ArityNode **parts_first, DS_ArityNode **parts_opl, DS_ArityNode *key);
#endif //ARITYNODE_H