230 lines
4.7 KiB
C
230 lines
4.7 KiB
C
|
/* date = July 8th 2020 7:11 am */
|
||
|
|
||
|
#ifndef COMPUTE_H
|
||
|
#define COMPUTE_H
|
||
|
|
||
|
typedef enum{
|
||
|
C_TokenKind_NULL,
|
||
|
C_TokenKind_Space,
|
||
|
C_TokenKind_Newline,
|
||
|
C_TokenKind_Comment,
|
||
|
#define C_TokenKind_FIRST_HARD C_TokenKind_OpenParen
|
||
|
C_TokenKind_OpenParen,
|
||
|
C_TokenKind_CloseParen,
|
||
|
C_TokenKind_Quote,
|
||
|
C_TokenKind_Label,
|
||
|
#define C_TokenKind_LAST_HARD C_TokenKind_Label
|
||
|
C_TokenKind_COUNT,
|
||
|
} C_TokenKind;
|
||
|
|
||
|
typedef struct C_Token C_Token;
|
||
|
struct C_Token{
|
||
|
C_TokenKind kind;
|
||
|
STR_Index string;
|
||
|
};
|
||
|
|
||
|
typedef struct C_TokenArray C_TokenArray;
|
||
|
struct C_TokenArray{
|
||
|
C_Token *vals;
|
||
|
u64 count;
|
||
|
};
|
||
|
|
||
|
////////////////////////////////
|
||
|
|
||
|
typedef u64 C_Id;
|
||
|
|
||
|
typedef struct C_Deferred C_Deferred;
|
||
|
struct C_Deferred{
|
||
|
void *user_ptr;
|
||
|
struct C_Cell *env;
|
||
|
struct C_Cell *cell;
|
||
|
b32 doing_eval;
|
||
|
b32 finished_eval;
|
||
|
};
|
||
|
|
||
|
#define C_BUILT_IN_SIG(name) struct C_Cell* name(struct C_EvalCtx *ctx, struct C_Cell *cell, struct C_Cell **env)
|
||
|
typedef C_BUILT_IN_SIG(C_BuiltInFunctionType);
|
||
|
|
||
|
typedef enum{
|
||
|
C_CellKind_Nil,
|
||
|
C_CellKind_Constructed,
|
||
|
C_CellKind_F64,
|
||
|
C_CellKind_Id,
|
||
|
C_CellKind_Identifier,
|
||
|
|
||
|
// NOTE(allen): Used in eval but not emitted by parser
|
||
|
C_CellKind_BuiltIn,
|
||
|
C_CellKind_Environment,
|
||
|
C_CellKind_Function,
|
||
|
C_CellKind_Macro,
|
||
|
C_CellKind_FunctionV,
|
||
|
C_CellKind_MacroV,
|
||
|
C_CellKind_Register,
|
||
|
C_CellKind_Deferred,
|
||
|
C_CellKind_Space,
|
||
|
|
||
|
// NOTE(allen): Used in memory allocation strategy,
|
||
|
// a correctly functioning lisp eval should not encounter this.
|
||
|
// If it does it will be treated as Nil.
|
||
|
C_CellKind_BlockHeader,
|
||
|
} C_CellKind;
|
||
|
|
||
|
// NOTE(allen): Forming verbs (functions, macros, variadics):
|
||
|
// first_child -> constructed list of parameters
|
||
|
// -> identifier for variadics
|
||
|
// next -> expression forming body of function
|
||
|
// env -> environment inherited from enclosing scope
|
||
|
|
||
|
typedef struct C_Cell C_Cell;
|
||
|
struct C_Cell{
|
||
|
C_CellKind kind;
|
||
|
C_Cell *next;
|
||
|
union{
|
||
|
C_Cell *first_child;
|
||
|
C_BuiltInFunctionType *built_in;
|
||
|
};
|
||
|
union{
|
||
|
u64 x;
|
||
|
struct C_CellBucket *bucket;
|
||
|
void *space;
|
||
|
f64 f;
|
||
|
STR_Index identifier;
|
||
|
C_Cell *env;
|
||
|
C_Deferred *deferred;
|
||
|
C_Id id;
|
||
|
u64 depth_counter;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
// NOTE(allen): We want fast divides on whatever size we pick here.
|
||
|
#define C_BLOCK_CAP 256
|
||
|
|
||
|
typedef struct C_CellMemory C_CellMemory;
|
||
|
struct C_CellMemory{
|
||
|
M_Arena arena;
|
||
|
C_Cell *cells;
|
||
|
C_Cell *free_block;
|
||
|
};
|
||
|
|
||
|
typedef struct C_CellBucket C_CellBucket;
|
||
|
struct C_CellBucket{
|
||
|
C_CellMemory *memory;
|
||
|
C_Cell *first_block;
|
||
|
C_Cell *last_block;
|
||
|
u64 cursor;
|
||
|
};
|
||
|
|
||
|
typedef struct C_ListBuilder C_ListBuilder;
|
||
|
struct C_ListBuilder{
|
||
|
C_Cell *f;
|
||
|
C_Cell **u;
|
||
|
u64 c;
|
||
|
};
|
||
|
|
||
|
////////////////////////////////
|
||
|
|
||
|
typedef struct C_ParseError C_ParseError;
|
||
|
struct C_ParseError{
|
||
|
String8 message;
|
||
|
C_Token *token;
|
||
|
};
|
||
|
|
||
|
typedef struct C_ParseCtx C_ParseCtx;
|
||
|
struct C_ParseCtx{
|
||
|
struct C_Statics *statics;
|
||
|
C_CellBucket *bucket;
|
||
|
C_Token *token;
|
||
|
C_Token *opl;
|
||
|
u64 error_count;
|
||
|
u64 error_max;
|
||
|
C_ParseError *errors;
|
||
|
};
|
||
|
|
||
|
////////////////////////////////
|
||
|
|
||
|
#define C_BuiltInXList(X) \
|
||
|
X("define", Define) \
|
||
|
X("function", Function) \
|
||
|
X("function...", FunctionV) \
|
||
|
X("macro", Macro) \
|
||
|
X("macro...", MacroV) \
|
||
|
X("write-reg", WriteRegister) \
|
||
|
X("read-reg", ReadRegister) \
|
||
|
X("get-thread-local-reg", GetUniqueRegister) \
|
||
|
X("block", Block) \
|
||
|
X("first", First) \
|
||
|
X("next", Next) \
|
||
|
X("push", Push) \
|
||
|
X("list", List) \
|
||
|
X("list-count", ListCount) \
|
||
|
X("id", Id) \
|
||
|
X("all-ids", AllIds) \
|
||
|
X("quote", Quote) \
|
||
|
X("eval", Eval) \
|
||
|
X("apply", Apply) \
|
||
|
X("far-eval", FarEval) \
|
||
|
X("kind", Kind) \
|
||
|
X("if", If) \
|
||
|
X("switch", Switch) \
|
||
|
X("loop", Loop) \
|
||
|
X("+1", Increment) \
|
||
|
X("-1", Decrement) \
|
||
|
X("+", Add) \
|
||
|
X("-", Sub) \
|
||
|
X("*", Mul) \
|
||
|
X("/", Div) \
|
||
|
X("%", Mod) \
|
||
|
X("^", Pow) \
|
||
|
X("<", Ls) \
|
||
|
X(">", Gr) \
|
||
|
X("<=", LsEq) \
|
||
|
X(">=", GrEq) \
|
||
|
X("==", Eq) \
|
||
|
X("!=", NotEq) \
|
||
|
X("not", Not) \
|
||
|
X("and", And) \
|
||
|
X("or", Or) \
|
||
|
X("ceil", Ceil) \
|
||
|
X("floor", Floor) \
|
||
|
X("round", Round)
|
||
|
|
||
|
typedef enum{
|
||
|
C_BuiltInIndex_Nil,
|
||
|
|
||
|
#define EnumMember(N,F) C_BuiltInIndex_##F,
|
||
|
C_BuiltInXList(EnumMember)
|
||
|
#undef EnumMember
|
||
|
|
||
|
C_BuiltInIndex_COUNT,
|
||
|
} C_BuiltInIndex;
|
||
|
|
||
|
typedef struct C_Statics C_Statics;
|
||
|
struct C_Statics{
|
||
|
union{
|
||
|
struct{
|
||
|
C_Cell *Nil;
|
||
|
#define StaticMember(N,F) C_Cell *F;
|
||
|
C_BuiltInXList(StaticMember)
|
||
|
#undef StaticMember
|
||
|
};
|
||
|
C_Cell *built_in[C_BuiltInIndex_COUNT];
|
||
|
};
|
||
|
C_Cell *env;
|
||
|
};
|
||
|
|
||
|
////////////////////////////////
|
||
|
|
||
|
typedef struct C_EvalCtx C_EvalCtx;
|
||
|
struct C_EvalCtx{
|
||
|
C_Statics *statics;
|
||
|
C_CellBucket *bucket;
|
||
|
C_Cell *id_env;
|
||
|
C_Cell *regs;
|
||
|
u64 max_depth;
|
||
|
u64 depth;
|
||
|
u64 loop_lim;
|
||
|
C_Id reg_id_counter;
|
||
|
};
|
||
|
|
||
|
#endif //COMPUTE_H
|