miauuuw :3
This commit is contained in:
parent
d2d432c4ca
commit
0d16b96fc5
19 changed files with 966 additions and 49 deletions
4
Makefile
4
Makefile
|
@ -10,10 +10,10 @@ FLAGS=-g $(CFLAGS) $(LDFLAGS) $(LIBS)
|
|||
S=main.c
|
||||
S+=comp.c wayland.c glfw.c
|
||||
S+=vulkan.c kitty.c
|
||||
S+=gpu_allocator.c hashmap.c util.c io.c matrix.c dynarray.c image.c types.c allocator.c log.c
|
||||
S+=string.c gpu_allocator.c hashmap.c util.c io.c matrix.c dynarray.c image.c types.c allocator.c log.c
|
||||
S+=object.c register.c
|
||||
S+=Wayland/xdg-shell-protocol.c
|
||||
S+=lang/ast.c lang/vstack.c
|
||||
S+=lang/ast.c lang/vstack.c lang/parser.c lang/ast_disc.c lang/functable.c
|
||||
SO=$(addprefix build/,$(S:.c=.o))
|
||||
SC=$(addprefix src/,$(S))
|
||||
|
||||
|
|
36
main.c
36
main.c
|
@ -4,41 +4,49 @@
|
|||
#include "trig.c"
|
||||
|
||||
#include "src/lang/ast.h"
|
||||
#include "src/lang/ast_disc.h"
|
||||
#include "src/lang/parser.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
int main() {
|
||||
|
||||
struct PawAST *t = parse("./src/lang/test.paw");
|
||||
return 0;
|
||||
|
||||
struct PawAST *ast = ast_make();
|
||||
ast_insert_property(ast, "i", make_pawval_int(ast->mem, 0));
|
||||
ast_append_cfunc(ast, print);
|
||||
|
||||
enum PawCtrl *body = make_pawctrl_seq(ast->mem);
|
||||
pawseq_append(body,
|
||||
make_pawctrl_asign(
|
||||
ast->mem, PSV_P(ast_get_property(ast, "i")),
|
||||
make_pawval_expr(ast->mem, ast_get_property(ast, "i"),
|
||||
make_pawval_int(ast->mem, 1), op_add)));
|
||||
pawseq_append(body, make_pawctrl_asign(
|
||||
ast->mem, PSV_P(ast_get_property(ast, "i")),
|
||||
make_pawval_expr(ast->mem, ast_get_property(ast, "i"),
|
||||
make_pawval_int(ast->mem, 1),
|
||||
paw_get_op_index("+"))));
|
||||
|
||||
enum PawCtrl *truthy = make_pawctrl_seq(ast->mem);
|
||||
pawseq_append(truthy, make_pawctrl_spush(ast->mem, PSV_INT(0)));
|
||||
pawseq_append(truthy, make_pawctrl_asign(ast->mem, PSV_SP(0),
|
||||
ast_get_property(ast, "i")));
|
||||
pawseq_append(truthy, make_pawctrl_ccall(ast->mem, 0));
|
||||
pawseq_append(truthy,
|
||||
make_pawctrl_ccall(ast->mem, paw_get_cfunc_index("io::print")));
|
||||
pawseq_append(truthy, make_pawctrl_spop(ast->mem));
|
||||
pawseq_append(body,
|
||||
make_pawctrl_if(
|
||||
ast->mem,
|
||||
make_pawval_expr(ast->mem, ast_get_property(ast, "i"),
|
||||
make_pawval_int(ast->mem, 20), op_equals),
|
||||
truthy, make_pawctrl_seq(ast->mem)));
|
||||
pawseq_append(body, make_pawctrl_if(
|
||||
ast->mem,
|
||||
make_pawval_expr(ast->mem, ast_get_property(ast, "i"),
|
||||
make_pawval_int(ast->mem, 20),
|
||||
paw_get_op_index("==")),
|
||||
truthy, make_pawctrl_seq(ast->mem)));
|
||||
pawseq_append(
|
||||
ast->prog,
|
||||
make_pawctrl_while(ast->mem,
|
||||
make_pawval_expr(ast->mem, ast_get_property(ast, "i"),
|
||||
make_pawval_int(ast->mem, 1000000),
|
||||
op_unequals),
|
||||
make_pawval_int(ast->mem, 100),
|
||||
paw_get_op_index("!=")),
|
||||
body));
|
||||
ast_write(ast, "test");
|
||||
ast = ast_read("test");
|
||||
ast_exec(ast);
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "allocator.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
@ -21,9 +22,9 @@ struct Mem {
|
|||
};
|
||||
|
||||
struct Mem *make_mem(size_t size) {
|
||||
struct Mem *mem = malloc(sizeof(struct Mem));
|
||||
struct Mem *mem = malloc(sizeof(struct Mem) + size);
|
||||
mem->mem_size = size;
|
||||
mem->mem = malloc(mem->mem_size);
|
||||
mem->mem = mem + 1;
|
||||
memset(mem->mem, 0, mem->mem_size);
|
||||
mem->count = 0;
|
||||
memset(&mem->allocs, 0, sizeof(struct Alloc) * MAX_ALLOCS);
|
||||
|
@ -32,10 +33,7 @@ struct Mem *make_mem(size_t size) {
|
|||
mem->alloc = &mem->allocs[1];
|
||||
return mem;
|
||||
}
|
||||
void uninit_mem(struct Mem *mem) {
|
||||
free(mem->mem);
|
||||
free(mem);
|
||||
}
|
||||
void uninit_mem(struct Mem *mem) { free(mem); }
|
||||
|
||||
static struct Alloc *get_next_alloc(struct Mem *mem) {
|
||||
while (mem->allocs[mem->count].start != NULL ||
|
||||
|
@ -49,6 +47,21 @@ static struct Alloc *get_next_alloc(struct Mem *mem) {
|
|||
return &mem->allocs[mem->count];
|
||||
}
|
||||
|
||||
void *malloc_or_mem_malloc(struct Mem *mem, size_t size) {
|
||||
if (mem == NULL) {
|
||||
return malloc(size);
|
||||
} else {
|
||||
return mem_malloc(mem, size);
|
||||
}
|
||||
}
|
||||
void free_or_mem_free(struct Mem *mem, void *ptr) {
|
||||
if (mem == NULL) {
|
||||
free(ptr);
|
||||
} else {
|
||||
mem_free(mem, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void *mem_malloc(struct Mem *mem, size_t size) {
|
||||
if (size <= 0) {
|
||||
size = 1;
|
||||
|
|
|
@ -3,12 +3,26 @@
|
|||
|
||||
#include "sys/types.h"
|
||||
|
||||
struct Mem;
|
||||
#define MAX_ALLOCS 256
|
||||
struct Alloc {
|
||||
void *start;
|
||||
uint size;
|
||||
struct Alloc *next;
|
||||
};
|
||||
struct Mem {
|
||||
void *mem;
|
||||
size_t mem_size;
|
||||
uint count;
|
||||
struct Alloc *alloc;
|
||||
struct Alloc allocs[MAX_ALLOCS];
|
||||
};
|
||||
|
||||
struct Mem *make_mem(size_t size);
|
||||
void uninit_mem(struct Mem *mem);
|
||||
|
||||
void *mem_malloc(struct Mem *mem, size_t size);
|
||||
void mem_free(struct Mem *mem, void *p);
|
||||
void *malloc_or_mem_malloc(struct Mem *mem, size_t size);
|
||||
void free_or_mem_free(struct Mem *mem, void *ptr);
|
||||
|
||||
#endif // INCLUDE_WAYLANDCLIENT_ALLOCATOR_H_
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "allocator.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define dyn_array_append(array, item) \
|
||||
|
|
12
src/io.c
12
src/io.c
|
@ -28,7 +28,7 @@ char *read_text_file(char *path) {
|
|||
uint32_t *read_binary_file(char *path, int *size) {
|
||||
FILE *file = fopen(path, "r");
|
||||
if (file == NULL) {
|
||||
meow("Could not open file %s", path);
|
||||
meow("could not open file %s", path);
|
||||
return NULL;
|
||||
}
|
||||
fseek(file, 0, SEEK_END);
|
||||
|
@ -45,3 +45,13 @@ uint32_t *read_binary_file(char *path, int *size) {
|
|||
fclose(file);
|
||||
return (uint32_t *)content;
|
||||
}
|
||||
|
||||
void write_binary_file(char *path, char *data, int size) {
|
||||
FILE *file = fopen(path, "w");
|
||||
if (file == NULL) {
|
||||
meow("could not open file %s", path);
|
||||
return;
|
||||
}
|
||||
fwrite(data, size, sizeof(char), file);
|
||||
fclose(file);
|
||||
}
|
||||
|
|
1
src/io.h
1
src/io.h
|
@ -5,5 +5,6 @@
|
|||
|
||||
char *read_text_file(char *path);
|
||||
uint32_t *read_binary_file(char *path, int *size);
|
||||
void write_binary_file(char *path, char *data, int size);
|
||||
|
||||
#endif // INCLUDE_WAYLANDCLIENT_IO_H_
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
const bool log_stack = false;
|
||||
|
||||
struct PawStackVal op_equals(struct PawAST *ast, struct PawStackVal lhs,
|
||||
struct PawStackVal rhs) {
|
||||
struct PawStackVal op_equals(struct PawStackVal lhs, struct PawStackVal rhs) {
|
||||
LS("comparing %s to %s", print_valtype(lhs.type), print_valtype(rhs.type));
|
||||
switch (lhs.type) {
|
||||
case PAW_VAL_FLOAT:
|
||||
|
@ -22,6 +21,7 @@ struct PawStackVal op_equals(struct PawAST *ast, struct PawStackVal lhs,
|
|||
case PAW_VAL_FLOAT:
|
||||
return PSV_BOOL(lhs.i == rhs.f);
|
||||
case PAW_VAL_INT:
|
||||
LS("%d == %d", lhs.i, rhs.i);
|
||||
return PSV_BOOL(lhs.i == rhs.i);
|
||||
}
|
||||
case PAW_VAL_BOOL:
|
||||
|
@ -145,13 +145,34 @@ struct PawStackVal try_cast(enum PawVal target, enum PawVal *val) {
|
|||
return PSV_NULL;
|
||||
}
|
||||
|
||||
struct PawStackVal op_unequals(struct PawAST *ast, struct PawStackVal lhs,
|
||||
struct PawStackVal rhs) {
|
||||
return PSV_BOOL(!op_equals(ast, lhs, rhs).b);
|
||||
enum PawVal *ast_stack_to_heap(struct PawAST *ast, struct PawStackVal val) {
|
||||
switch (val.type) {
|
||||
case PAW_VAL_FLOAT:
|
||||
return make_pawval_float(ast->mem, val.f);
|
||||
case PAW_VAL_INT:
|
||||
return make_pawval_int(ast->mem, val.i);
|
||||
case PAW_VAL_BOOL:
|
||||
return make_pawval_bool(ast->mem, val.b);
|
||||
case PAW_VAL_CHAR:
|
||||
crash("TODO");
|
||||
// return make_pawval_char(ast->mem, val.c);
|
||||
case PAW_VAL_POINT:
|
||||
return make_pawval_point(ast->mem, val.p);
|
||||
case PAW_VAL_SPOINT:
|
||||
crash("TODO");
|
||||
// return make_pawval_spoint(ast->mem, val.sp);
|
||||
case PAW_VAL_EXPR:
|
||||
crash("sdfgjhhkjdfgd");
|
||||
}
|
||||
meow("unreachable");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct PawStackVal op_add(struct PawAST *ast, struct PawStackVal lhs,
|
||||
struct PawStackVal rhs) {
|
||||
struct PawStackVal op_unequals(struct PawStackVal lhs, struct PawStackVal rhs) {
|
||||
return PSV_BOOL(!op_equals(lhs, rhs).b);
|
||||
}
|
||||
|
||||
struct PawStackVal op_add(struct PawStackVal lhs, struct PawStackVal rhs) {
|
||||
LS("adding %s to %s", print_valtype(lhs.type), print_valtype(rhs.type));
|
||||
switch (lhs.type) {
|
||||
case PAW_VAL_FLOAT:
|
||||
|
@ -166,6 +187,7 @@ struct PawStackVal op_add(struct PawAST *ast, struct PawStackVal lhs,
|
|||
case PAW_VAL_FLOAT:
|
||||
return PSV_FLOAT(lhs.i + rhs.f);
|
||||
case PAW_VAL_INT:
|
||||
LS("%d + %d", lhs.i, rhs.i);
|
||||
return PSV_INT(lhs.i + rhs.i);
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +245,7 @@ enum PawVal *make_pawval_char(struct Mem *mem, char n) {
|
|||
}
|
||||
|
||||
enum PawVal *make_pawval_expr(struct Mem *mem, enum PawVal *lhs,
|
||||
enum PawVal *rhs, paw_p op) {
|
||||
enum PawVal *rhs, uint32_t op) {
|
||||
enum PawVal *val;
|
||||
val_make(val, struct PawExpr, PAW_VAL_EXPR);
|
||||
struct PawExpr *i = val_get_data(val);
|
||||
|
@ -323,17 +345,20 @@ void pawseq_append(enum PawCtrl *seq, enum PawCtrl *ctrl) {
|
|||
dyn_array_append(&seqval->seq, ctrl);
|
||||
}
|
||||
|
||||
void ping_func() { meow("ping"); }
|
||||
|
||||
struct PawAST *ast_make() {
|
||||
struct Mem *mem = make_mem(8192);
|
||||
// ast HAS to be the first thing allocated with mem
|
||||
struct PawAST *ast = mem_malloc(mem, sizeof(struct PawAST));
|
||||
|
||||
char *t = "meow\n";
|
||||
char *test = mem_malloc(mem, strlen(t) + 1);
|
||||
memcpy(test, t, strlen(t) + 1);
|
||||
|
||||
ast->mem = mem;
|
||||
ast->ping_func = ping_func;
|
||||
ast->prog = make_pawctrl_seq(ast->mem);
|
||||
dyn_array_create_inplace_mem(&ast->properties, ast->mem);
|
||||
dyn_array_create_inplace_mem(&ast->cfuncs, ast->mem);
|
||||
dyn_array_create_inplace_mem(&ast->funcs, ast->mem);
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
@ -343,6 +368,19 @@ void ast_append_cfunc(struct PawAST *ast,
|
|||
dyn_array_append(&ast->cfuncs, (struct CFunc){func});
|
||||
}
|
||||
|
||||
void ast_register_func(struct PawAST *ast, char *name) {
|
||||
dyn_array_append(&ast->funcs, ((struct PawFunc){.body = NULL, .name = name}));
|
||||
}
|
||||
void ast_set_func_body(struct PawAST *ast, char *name, enum PawCtrl *body) {
|
||||
for (int i = 0; i < ast->funcs.count; i++) {
|
||||
if (strcmp(name, ast->funcs.items[i].name) == 0) {
|
||||
ast->funcs.items[i].body = body;
|
||||
return;
|
||||
}
|
||||
}
|
||||
meow("function %s could not be found", name);
|
||||
}
|
||||
|
||||
enum PawVal *ast_get_property(struct PawAST *ast, char *name) {
|
||||
for (int i = 0; i < ast->properties.count; i++) {
|
||||
if (strcmp(ast->properties.items[i].name, name) == 0) {
|
||||
|
@ -457,10 +495,12 @@ struct PawStackVal ast_eval(struct PawAST *ast, enum PawVal *val) {
|
|||
return PSV_CHAR(*(char *)val_get_data(val));
|
||||
case PAW_VAL_EXPR:;
|
||||
struct PawExpr *expr = val_get_data(val);
|
||||
LS("calling op at %p", expr->op);
|
||||
LS("calling op at %d", expr->op);
|
||||
LS("lhs is %p rhs is %p", expr->lhs, expr->rhs);
|
||||
struct PawStackVal lhs = ast_eval(ast, expr->lhs);
|
||||
struct PawStackVal rhs = ast_eval(ast, expr->rhs);
|
||||
struct PawStackVal ret = expr->op(ast, lhs, rhs);
|
||||
struct PawStackVal ret = ((struct PawStackVal(*)(
|
||||
struct PawStackVal, struct PawStackVal))paw_get_op(expr->op))(lhs, rhs);
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
|
@ -487,7 +527,17 @@ void ast_exec(struct PawAST *ast) {
|
|||
int offset = 0;
|
||||
ast_stack_push(stack, ast->prog);
|
||||
meow("starting exec");
|
||||
#define NO_LIMIT_ITS
|
||||
#ifndef NO_LIMIT_ITS
|
||||
int i = 0;
|
||||
#endif
|
||||
while (stack->top < stack->right) {
|
||||
#ifndef NO_LIMIT_ITS
|
||||
i++;
|
||||
if (i > 100) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
enum PawCtrl *ctrl = stack_poke(stack);
|
||||
switch (*ctrl) {
|
||||
case PAW_CTRL_SEQ:;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#ifndef INCLUDE_LANG_AST_H_
|
||||
#define INCLUDE_LANG_AST_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
@ -44,6 +46,14 @@ enum PawVal {
|
|||
PAW_VAL_SPOINT,
|
||||
PAW_VAL_EXPR,
|
||||
};
|
||||
enum ArgType {
|
||||
PAW_ARG_FLOAT,
|
||||
PAW_ARG_INT,
|
||||
PAW_ARG_BOOL,
|
||||
PAW_ARG_CHAR,
|
||||
PAW_ARG_POINT,
|
||||
PAW_ARG_ANY,
|
||||
};
|
||||
|
||||
enum PawCtrl {
|
||||
PAW_CTRL_SEQ,
|
||||
|
@ -66,18 +76,18 @@ struct PawProperty {
|
|||
dyn_array_define(da_paw_property, struct PawProperty);
|
||||
|
||||
dyn_array_define(da_cfunc, struct CFunc);
|
||||
dyn_array_define(da_func, struct PawFunc);
|
||||
|
||||
struct PawAST {
|
||||
struct Mem *mem;
|
||||
enum PawCtrl *prog;
|
||||
void *ping_func;
|
||||
struct da_paw_property properties;
|
||||
struct da_cfunc cfuncs;
|
||||
struct da_func funcs;
|
||||
};
|
||||
|
||||
struct PawExpr {
|
||||
struct PawStackVal (*op)(struct PawAST *ast, struct PawStackVal lhs,
|
||||
struct PawStackVal rhs);
|
||||
uint32_t op;
|
||||
enum PawVal *lhs;
|
||||
enum PawVal *rhs;
|
||||
};
|
||||
|
@ -121,11 +131,16 @@ struct PawStackPush {
|
|||
struct PawStackVal v;
|
||||
};
|
||||
|
||||
struct PawFunc {
|
||||
enum PawCtrl *body;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct PawCall {
|
||||
enum PawCtrl *body;
|
||||
};
|
||||
struct PawCCall {
|
||||
int index;
|
||||
uint32_t index;
|
||||
};
|
||||
|
||||
struct VStack {
|
||||
|
@ -153,19 +168,16 @@ struct CFunc {
|
|||
void (*func)(struct VStack *stack, int offset);
|
||||
};
|
||||
|
||||
struct PawStackVal op_equals(struct PawAST *ast, struct PawStackVal lhs,
|
||||
struct PawStackVal rhs);
|
||||
struct PawStackVal op_unequals(struct PawAST *ast, struct PawStackVal lhs,
|
||||
struct PawStackVal rhs);
|
||||
struct PawStackVal op_add(struct PawAST *ast, struct PawStackVal lhs,
|
||||
struct PawStackVal rhs);
|
||||
struct PawStackVal op_equals(struct PawStackVal lhs, struct PawStackVal rhs);
|
||||
struct PawStackVal op_unequals(struct PawStackVal lhs, struct PawStackVal rhs);
|
||||
struct PawStackVal op_add(struct PawStackVal lhs, struct PawStackVal rhs);
|
||||
|
||||
enum PawVal *make_pawval_float(struct Mem *mem, float n);
|
||||
enum PawVal *make_pawval_int(struct Mem *mem, int n);
|
||||
enum PawVal *make_pawval_bool(struct Mem *mem, bool n);
|
||||
enum PawVal *make_pawval_point(struct Mem *mem, paw_p n);
|
||||
enum PawVal *make_pawval_expr(struct Mem *mem, enum PawVal *lhs,
|
||||
enum PawVal *rhs, paw_p op);
|
||||
enum PawVal *rhs, uint32_t op);
|
||||
void free_pawval(struct Mem *mem, enum PawVal *val);
|
||||
enum PawCtrl *make_pawctrl_seq(struct Mem *mem);
|
||||
enum PawCtrl *make_pawctrl_spush(struct Mem *mem, struct PawStackVal val);
|
||||
|
@ -179,7 +191,7 @@ enum PawCtrl *make_pawctrl_if(struct Mem *mem, enum PawVal *cond,
|
|||
enum PawCtrl *make_pawctrl_asign(struct Mem *mem, struct PawStackVal target,
|
||||
enum PawVal *val);
|
||||
void pawseq_append(enum PawCtrl *seq, enum PawCtrl *ctrl);
|
||||
void ping_func();
|
||||
enum PawVal *ast_stack_to_heap(struct PawAST *ast, struct PawStackVal val);
|
||||
struct PawAST *ast_make();
|
||||
void ast_insert_property(struct PawAST *ast, char *name, enum PawVal *val);
|
||||
void ast_append_cfunc(struct PawAST *ast,
|
||||
|
@ -200,3 +212,12 @@ void ast_exec(struct PawAST *ast);
|
|||
$ret = mem_malloc(mem, sizeof(enum PawCtrl) + sizeof($type)); \
|
||||
*$ret = $TYPE_ENUM; \
|
||||
} while (0)
|
||||
|
||||
uint32_t paw_get_ops_size();
|
||||
const char *paw_get_op_sym(uint32_t index);
|
||||
uint32_t paw_get_op_index(char *sym);
|
||||
void *paw_get_op(uint32_t);
|
||||
uint32_t paw_get_cfunc_index(char *name);
|
||||
void *paw_get_cfunc(uint32_t);
|
||||
|
||||
#endif // INCLUDE_LANG_AST_H_
|
||||
|
|
227
src/lang/ast_disc.c
Normal file
227
src/lang/ast_disc.c
Normal file
|
@ -0,0 +1,227 @@
|
|||
#include "ast_disc.h"
|
||||
|
||||
#include "../io.h"
|
||||
#include "../log.h"
|
||||
#include "ast.h"
|
||||
|
||||
#define AO1($p) \
|
||||
if (apply_before && \
|
||||
((void *)($p) >= region_start && (void *)($p) <= region_end)) { \
|
||||
$p = (void *)((void *)$p + offset); \
|
||||
}
|
||||
#define AO2($p) \
|
||||
if (!apply_before && \
|
||||
((void *)$p >= region_start && (void *)$p <= region_end)) { \
|
||||
$p = (void *)((void *)$p + offset); \
|
||||
}
|
||||
|
||||
long offset = 0;
|
||||
|
||||
void *region_start = NULL;
|
||||
void *region_end = NULL;
|
||||
bool apply_before = false;
|
||||
|
||||
// for nyow ast and ast->mem will be garbled afterwards
|
||||
void ast_write(struct PawAST *ast, char *path) {
|
||||
int size = ast->mem->mem_size + sizeof(struct Mem);
|
||||
char *data = (char *)ast->mem;
|
||||
meow("size is %d data %p", size, data);
|
||||
region_start = ast->mem;
|
||||
region_end = ast->mem + ast->mem->mem_size + sizeof(struct Mem);
|
||||
offset = -(long)region_start;
|
||||
apply_before = false;
|
||||
AO2(ast->mem->alloc);
|
||||
AO2(ast->mem->mem);
|
||||
for (int i = 0; i < MAX_ALLOCS; i++) {
|
||||
if (ast->mem->allocs[i].start == NULL && ast->mem->allocs[i].size == 0 &&
|
||||
ast->mem->allocs[i].next == NULL) {
|
||||
continue;
|
||||
} else {
|
||||
AO2(ast->mem->allocs[i].start);
|
||||
AO2(ast->mem->allocs[i].next);
|
||||
}
|
||||
}
|
||||
AO2(ast->mem);
|
||||
apply_offset_ctrl(ast->prog);
|
||||
AO2(ast->prog);
|
||||
for (int i = 0; i < ast->properties.count; i++) {
|
||||
AO2(ast->properties.items[i].name);
|
||||
apply_offset_val(ast->properties.items[i].val);
|
||||
AO2(ast->properties.items[i].val);
|
||||
meow("a property is now at %p", ast->properties.items[i].val);
|
||||
}
|
||||
AO2(ast->properties.items);
|
||||
AO2(ast->properties.mem);
|
||||
|
||||
AO2(ast->cfuncs.items);
|
||||
AO2(ast->cfuncs.mem);
|
||||
|
||||
for (int i = 0; i < ast->funcs.count; i++) {
|
||||
AO2(ast->funcs.items[i].name);
|
||||
apply_offset_ctrl(ast->funcs.items[i].body);
|
||||
AO2(ast->funcs.items[i].body);
|
||||
}
|
||||
AO2(ast->funcs.items);
|
||||
AO2(ast->funcs.mem);
|
||||
|
||||
write_binary_file(path, data, size);
|
||||
}
|
||||
|
||||
// assumes all PawStackVals existent at compile time of type PAW_VAL_POINT point
|
||||
// to a valid PawVal
|
||||
struct PawAST *ast_read(char *path) {
|
||||
region_start = 0x0;
|
||||
int size;
|
||||
char *data = (char *)read_binary_file(path, &size);
|
||||
meow("size is %d data %p", size, data);
|
||||
offset = (long)data;
|
||||
region_end = (void *)(long)size;
|
||||
struct Mem *mem = (struct Mem *)data;
|
||||
|
||||
meow("offset is %ld", offset);
|
||||
|
||||
apply_before = true;
|
||||
for (int i = 0; i < MAX_ALLOCS; i++) {
|
||||
if (mem->allocs[i].start == NULL && mem->allocs[i].size == 0 &&
|
||||
mem->allocs[i].next == NULL) {
|
||||
continue;
|
||||
} else {
|
||||
AO1(mem->allocs[i].start);
|
||||
AO1(mem->allocs[i].next);
|
||||
}
|
||||
}
|
||||
meow("mem before %p", mem->mem);
|
||||
AO1(mem->mem);
|
||||
meow("mem after %p", mem->mem);
|
||||
AO1(mem->alloc);
|
||||
struct PawAST *ast = mem->allocs[2].start;
|
||||
AO1(ast->mem);
|
||||
AO1(ast->prog);
|
||||
apply_offset_ctrl(ast->prog);
|
||||
meow("ao1 %p", ast->prog);
|
||||
AO1(ast->properties.items);
|
||||
AO1(ast->properties.mem);
|
||||
for (int i = 0; i < ast->properties.count; i++) {
|
||||
meow("a property was at %p", ast->properties.items[i].val);
|
||||
AO1(ast->properties.items[i].name);
|
||||
AO1(ast->properties.items[i].val);
|
||||
apply_offset_val(ast->properties.items[i].val);
|
||||
meow("a property is now at %p", ast->properties.items[i].val);
|
||||
}
|
||||
|
||||
AO1(ast->cfuncs.items);
|
||||
AO1(ast->cfuncs.mem);
|
||||
|
||||
AO1(ast->funcs.items);
|
||||
AO1(ast->funcs.mem);
|
||||
for (int i = 0; i < ast->funcs.count; i++) {
|
||||
AO1(ast->funcs.items[i].name);
|
||||
AO1(ast->funcs.items[i].body);
|
||||
apply_offset_ctrl(ast->funcs.items[i].body);
|
||||
}
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
void apply_offset_ctrl(enum PawCtrl *ctrl) {
|
||||
switch (*ctrl) {
|
||||
case PAW_CTRL_SEQ:;
|
||||
struct PawSeq *seq = ctrl_get_data(ctrl);
|
||||
AO1(seq->seq.mem);
|
||||
AO1(seq->seq.items);
|
||||
for (int i = 0; i < seq->seq.count; i++) {
|
||||
AO1(seq->seq.items[i]);
|
||||
apply_offset_ctrl(seq->seq.items[i]);
|
||||
AO2(seq->seq.items[i]);
|
||||
}
|
||||
AO2(seq->seq.items);
|
||||
AO2(seq->seq.mem);
|
||||
break;
|
||||
case PAW_CTRL_WHILE:;
|
||||
struct PawWhile *_while = ctrl_get_data(ctrl);
|
||||
AO1(_while->body);
|
||||
apply_offset_ctrl(_while->body);
|
||||
AO2(_while->body);
|
||||
AO1(_while->cond);
|
||||
apply_offset_val(_while->cond);
|
||||
AO2(_while->cond);
|
||||
break;
|
||||
case PAW_CTRL_IF:;
|
||||
struct PawIf *_if = ctrl_get_data(ctrl);
|
||||
AO1(_if->truthy);
|
||||
AO1(_if->falsy);
|
||||
apply_offset_ctrl(_if->truthy);
|
||||
apply_offset_ctrl(_if->falsy);
|
||||
AO2(_if->truthy);
|
||||
AO2(_if->falsy);
|
||||
AO1(_if->cond);
|
||||
apply_offset_val(_if->cond);
|
||||
AO2(_if->cond);
|
||||
break;
|
||||
case PAW_CTRL_ASIGN:;
|
||||
struct PawAsign *asign = ctrl_get_data(ctrl);
|
||||
AO1(asign->rhs);
|
||||
apply_offset_val(asign->rhs);
|
||||
AO2(asign->rhs);
|
||||
asign->lhs = apply_offset_stackval(asign->lhs);
|
||||
break;
|
||||
case PAW_CTRL_SPUSH:
|
||||
break;
|
||||
case PAW_CTRL_SPOP:
|
||||
break;
|
||||
case PAW_CTRL_CALL:;
|
||||
struct PawCall *call = ctrl_get_data(ctrl);
|
||||
AO1(call->body);
|
||||
apply_offset_ctrl(call->body);
|
||||
AO2(call->body);
|
||||
break;
|
||||
case PAW_CTRL_CCALL:
|
||||
break;
|
||||
}
|
||||
}
|
||||
struct PawStackVal apply_offset_stackval(struct PawStackVal val) {
|
||||
switch (val.type) {
|
||||
case PAW_VAL_FLOAT:
|
||||
case PAW_VAL_INT:
|
||||
case PAW_VAL_BOOL:
|
||||
case PAW_VAL_CHAR:
|
||||
case PAW_VAL_SPOINT:
|
||||
return val;
|
||||
case PAW_VAL_EXPR:
|
||||
meow("AGHJKGHJKASZGHJKASGHJKGHJK");
|
||||
return (struct PawStackVal){.type = PAW_VAL_POINT, .p = NULL};
|
||||
case PAW_VAL_POINT:
|
||||
AO1(val.p);
|
||||
apply_offset_val(val.p);
|
||||
AO2(val.p);
|
||||
return val;
|
||||
}
|
||||
}
|
||||
void apply_offset_val(enum PawVal *val) {
|
||||
switch (*val) {
|
||||
case PAW_VAL_FLOAT:
|
||||
break;
|
||||
case PAW_VAL_INT:
|
||||
break;
|
||||
case PAW_VAL_BOOL:
|
||||
break;
|
||||
case PAW_VAL_CHAR:
|
||||
break;
|
||||
case PAW_VAL_POINT:
|
||||
meow("uuuh this should not happen i thinky?");
|
||||
apply_offset_val(*(enum PawVal **)val_get_data(val));
|
||||
break;
|
||||
case PAW_VAL_SPOINT:
|
||||
break;
|
||||
case PAW_VAL_EXPR:;
|
||||
struct PawExpr *expr = val_get_data(val);
|
||||
AO1(expr->lhs);
|
||||
AO1(expr->rhs);
|
||||
apply_offset_val(expr->lhs);
|
||||
apply_offset_val(expr->rhs);
|
||||
AO2(expr->lhs);
|
||||
AO2(expr->rhs);
|
||||
meow("applying offset to an expr");
|
||||
break;
|
||||
}
|
||||
}
|
12
src/lang/ast_disc.h
Normal file
12
src/lang/ast_disc.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef INCLUDE_LANG_AST_DISC_H_
|
||||
#define INCLUDE_LANG_AST_DISC_H_
|
||||
|
||||
#include "ast.h"
|
||||
|
||||
void ast_write(struct PawAST *ast, char *path);
|
||||
struct PawAST *ast_read(char *path);
|
||||
void apply_offset_ctrl(enum PawCtrl *ctrl);
|
||||
void apply_offset_val(enum PawVal *val);
|
||||
struct PawStackVal apply_offset_stackval(struct PawStackVal val);
|
||||
|
||||
#endif // INCLUDE_LANG_AST_DISC_H_
|
49
src/lang/functable.c
Normal file
49
src/lang/functable.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
#include "../log.h"
|
||||
#include "../util.h"
|
||||
#include "ast.h"
|
||||
|
||||
struct FuncDef {
|
||||
void (*func)(struct VStack *, int);
|
||||
const char *name;
|
||||
// enum ArgType *args;
|
||||
};
|
||||
struct OpDef {
|
||||
struct PawStackVal (*op)(struct PawStackVal, struct PawStackVal);
|
||||
const char *sym;
|
||||
// enum ArgType *args;
|
||||
};
|
||||
|
||||
struct FuncDef PAW_CFUNCS[] = {
|
||||
{print, "io::print"},
|
||||
};
|
||||
|
||||
// important to unimportant!!!
|
||||
struct OpDef PAW_OPS[] = {
|
||||
{op_equals, "=="}, {op_unequals, "!="}, {NULL, "*"},
|
||||
{NULL, "/"}, {op_add, "+"}, {NULL, "-"},
|
||||
};
|
||||
|
||||
uint32_t paw_get_ops_size() { return sizeof(PAW_OPS); }
|
||||
const char *paw_get_op_sym(uint32_t index) { return PAW_OPS[index].sym; }
|
||||
|
||||
uint32_t paw_get_op_index(char *sym) {
|
||||
for (int i = 0; i < sizeof(PAW_OPS) / sizeof(PAW_OPS[0]); i++) {
|
||||
if (strcmp(sym, PAW_OPS[i].sym) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
meow("could not find op %s, returning %d", sym, UINT32_NULL);
|
||||
return UINT32_NULL;
|
||||
}
|
||||
void *paw_get_op(uint32_t index) { return PAW_OPS[index].op; }
|
||||
|
||||
uint32_t paw_get_cfunc_index(char *name) {
|
||||
for (int i = 0; i < sizeof(PAW_CFUNCS) / sizeof(PAW_CFUNCS[0]); i++) {
|
||||
if (strcmp(name, PAW_CFUNCS[i].name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
meow("could not find cfunc %s, returning %d", name, UINT32_NULL);
|
||||
return UINT32_NULL;
|
||||
}
|
||||
void *paw_get_cfunc(uint32_t index) { return PAW_CFUNCS[index].func; }
|
167
src/lang/parser.c
Normal file
167
src/lang/parser.c
Normal file
|
@ -0,0 +1,167 @@
|
|||
#include "../allocator.h"
|
||||
#include "../io.h"
|
||||
#include "../log.h"
|
||||
#include "../string.h"
|
||||
#include "../util.h"
|
||||
#include "ast.h"
|
||||
#include <limits.h>
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
struct PawStackVal parse_stack_val(char *start) {
|
||||
start = trim_start(start);
|
||||
if (start_matches(start, "true")) {
|
||||
return PSV_BOOL(true);
|
||||
}
|
||||
if (start_matches(start, "false")) {
|
||||
return PSV_BOOL(false);
|
||||
}
|
||||
if (start_matches(start, "null")) {
|
||||
return PSV_NULL;
|
||||
}
|
||||
char *end = start;
|
||||
|
||||
while (is_digid(*end) || *end == '.') {
|
||||
end++;
|
||||
}
|
||||
|
||||
if (includes_between(start, end, '.')) {
|
||||
return PSV_FLOAT(strtof(start, NULL));
|
||||
} else {
|
||||
return PSV_INT(strtol(start, NULL, 10));
|
||||
}
|
||||
}
|
||||
|
||||
enum PawVal *parse_val(int stack_offset, struct StringTable *vars,
|
||||
struct Mem *tmp, struct Mem *pem, char *start,
|
||||
char *end) {
|
||||
start = trim_start(start);
|
||||
end = trim_end(end);
|
||||
|
||||
// figure out the most important op
|
||||
char *opstart = start;
|
||||
int op_rating = INT_MAX;
|
||||
char *op = NULL;
|
||||
|
||||
// as * before + in functable it will choose to split on + first, meaning
|
||||
// a+b*c => (a)+(b*c)
|
||||
while (opstart < end) {
|
||||
if (*opstart == '(') {
|
||||
opstart = skip_brackets(opstart, '(', ')');
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < paw_get_ops_size(); i++) {
|
||||
if (start_matches(opstart, (char *)paw_get_op_sym(i))) {
|
||||
if (i >= op_rating) {
|
||||
continue;
|
||||
}
|
||||
op_rating = i;
|
||||
op = opstart;
|
||||
}
|
||||
}
|
||||
opstart++;
|
||||
}
|
||||
|
||||
if (op == 0) {
|
||||
}
|
||||
|
||||
enum PawVal *lhs;
|
||||
// expected: var, brackets or function
|
||||
if (start_matches(start, "(")) {
|
||||
char *in_end = skip_brackets(start, '(', ')');
|
||||
lhs = parse_val(stack_offset, vars, tmp, pem, start + 1, in_end);
|
||||
start = in_end;
|
||||
} else {
|
||||
char *tmp = start;
|
||||
while (is_char(*tmp)) {
|
||||
tmp++;
|
||||
}
|
||||
tmp = trim_start(tmp);
|
||||
if (*tmp == '(') {
|
||||
// TODO, call
|
||||
} else {
|
||||
// TODO, var
|
||||
}
|
||||
}
|
||||
start = trim_start(start);
|
||||
if (start == end) {
|
||||
return lhs;
|
||||
}
|
||||
}
|
||||
|
||||
enum PawCtrl *parse_block(struct Mem *tmp, struct Mem *pem,
|
||||
struct StringTable *vars, char *start) {
|
||||
enum PawCtrl *body = make_pawctrl_seq(pem);
|
||||
start = trim_start(start);
|
||||
while (!start_matches(start, "}")) {
|
||||
if (start_matches(start, "while")) {
|
||||
start = skip_after_char(start, ' ');
|
||||
char *end = skip_to_char(start, '{') - 1;
|
||||
enum PawVal *cond = parse_val(0, vars, tmp, pem, start, end);
|
||||
enum PawCtrl *wbody =
|
||||
parse_block(tmp, pem, vars, skip_after_char(start, '{'));
|
||||
enum PawCtrl *w = make_pawctrl_while(pem, cond, wbody);
|
||||
pawseq_append(body, w);
|
||||
start = skip_brackets(start, '{', '}');
|
||||
start = trim_start(start);
|
||||
continue;
|
||||
}
|
||||
if (start_matches(start, "if")) {
|
||||
start = skip_after_char(start, ' ');
|
||||
char *end = skip_to_char(start, '{') - 1;
|
||||
enum PawVal *cond = parse_val(0, vars, tmp, pem, start, end);
|
||||
enum PawCtrl *truthy =
|
||||
parse_block(tmp, pem, vars, skip_after_char(start, '{'));
|
||||
enum PawCtrl *falsy = NULL;
|
||||
start = skip_brackets(start, '{', '}');
|
||||
if (start_matches(start, "else")) {
|
||||
start = skip_after_char(start, '{');
|
||||
falsy = parse_block(tmp, pem, vars, start);
|
||||
start = skip_brackets(start, '{', '}');
|
||||
}
|
||||
enum PawCtrl *i = make_pawctrl_if(pem, cond, truthy, falsy);
|
||||
pawseq_append(body, i);
|
||||
start = trim_start(start);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// start has to start with func asdjlasd(dfssdf)->jsd
|
||||
enum PawCtrl *parse_func(char *start) { skip_to_char(start, ' '); }
|
||||
|
||||
struct PawAST *parse(char *path) {
|
||||
char *contents = read_text_file(path);
|
||||
struct PawAST *ast = ast_make();
|
||||
|
||||
struct Mem *tmp = make_mem(4096); // temporary memory
|
||||
struct Mem *pem =
|
||||
ast->mem; // permanent memory, will be present once ast is evaled
|
||||
|
||||
struct StringTable *methods = st_make(tmp);
|
||||
struct StringTable *props = st_make(tmp);
|
||||
|
||||
for (int i = 0; i < strlen(contents); i++) {
|
||||
if (start_matches(&contents[i], "func ")) {
|
||||
char *name = extract_inbetween_chars(tmp, &contents[i], ' ', '(');
|
||||
meow("got a method named '%s'", name);
|
||||
st_insert(methods, name, &contents[i]);
|
||||
i = skip_brackets(&contents[i], '{', '}') - contents;
|
||||
} else if (start_matches(&contents[i], "let")) {
|
||||
char *name = extract_inbetween_chars(tmp, &contents[i], ' ', ':');
|
||||
meow("got a property named '%s'", name);
|
||||
st_insert(props, name, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < st_get_size(props); i++) {
|
||||
ast_insert_property(
|
||||
ast, mem_strdup(st_get_nth_key(props, i), pem),
|
||||
ast_stack_to_heap(
|
||||
ast, parse_stack_val(st_get(props, st_get_nth_key(props, i)))));
|
||||
}
|
||||
|
||||
uninit_mem(tmp);
|
||||
|
||||
return ast;
|
||||
}
|
8
src/lang/parser.h
Normal file
8
src/lang/parser.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef INCLUDE_LANG_PARSER_H_
|
||||
#define INCLUDE_LANG_PARSER_H_
|
||||
|
||||
#include "ast.h"
|
||||
|
||||
struct PawAST *parse(char *path);
|
||||
|
||||
#endif // INCLUDE_LANG_PARSER_H_
|
17
src/lang/test.paw
Normal file
17
src/lang/test.paw
Normal file
|
@ -0,0 +1,17 @@
|
|||
let count: int = 0;
|
||||
|
||||
func make() -> void {
|
||||
let b: int = 5;
|
||||
while i != self.count {
|
||||
if i == b {
|
||||
io::print(i);
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
func tick() -> void {
|
||||
}
|
||||
|
||||
func free() -> void {
|
||||
}
|
183
src/string.c
Normal file
183
src/string.c
Normal file
|
@ -0,0 +1,183 @@
|
|||
#include "string.h"
|
||||
#include "allocator.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
struct da_string split(struct Mem *mem, char *string, char needle, int *count) {
|
||||
struct da_string items;
|
||||
dyn_array_create_inplace_mem(&items, mem);
|
||||
|
||||
int last = 0;
|
||||
for (int i = 0; i < strlen(string); i++) {
|
||||
|
||||
if (string[i] == needle) {
|
||||
char *tmp = mem_malloc(mem, i - last + 1);
|
||||
memcpy(tmp, &string[last], i - last);
|
||||
tmp[last - i + 1] = 0x0;
|
||||
dyn_array_append(&items, tmp);
|
||||
last = i;
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
bool start_matches(char *string, char *match) {
|
||||
return memcmp(string, match, strlen(match)) == 0;
|
||||
}
|
||||
|
||||
char *extract_brackets(struct Mem *mem, char *start, char open, char close) {
|
||||
char *end = skip_brackets(start, open, close);
|
||||
// { ... }
|
||||
// ^ end
|
||||
end -= 2;
|
||||
// { ... }
|
||||
// ^ end
|
||||
while (*start != open) {
|
||||
start++;
|
||||
}
|
||||
// { ... }
|
||||
// start ^ ^ end
|
||||
start++;
|
||||
char *res = mem_malloc(mem, end - start + 1);
|
||||
memcpy(res, start, end - start);
|
||||
res[end - start] = 0x0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
char *skip_brackets(char *start, char open, char close) {
|
||||
char *end = start;
|
||||
while (end[0] != open) {
|
||||
end++;
|
||||
}
|
||||
end++;
|
||||
|
||||
int count = 1;
|
||||
while (count > 0) {
|
||||
if (end[0] == close) {
|
||||
count--;
|
||||
} else if (end[0] == open) {
|
||||
count++;
|
||||
}
|
||||
end++;
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
int index_of_char(char *string, char key) {
|
||||
int i = 0;
|
||||
while (i < strlen(string) && string[i] != key) {
|
||||
i++;
|
||||
}
|
||||
if (i == strlen(string)) {
|
||||
return -1;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
char *extract(struct Mem *mem, char *string, int start, int size) {
|
||||
char *new = mem_malloc(mem, size + 1);
|
||||
memcpy(new, string + start, size);
|
||||
new[size + 1] = 0x0;
|
||||
return new;
|
||||
}
|
||||
|
||||
char *extract_inbetween_chars(struct Mem *mem, char *string, char one,
|
||||
char two) {
|
||||
int start = index_of_char(string, one) + 1;
|
||||
int end = index_of_char(string, two);
|
||||
if (end < start) {
|
||||
SWAP(start, end);
|
||||
}
|
||||
|
||||
return extract(mem, string, start, end - start);
|
||||
}
|
||||
|
||||
char *tmp_format(struct Mem *mem, char *format, ...) {
|
||||
char *res = malloc(1024);
|
||||
va_list ap;
|
||||
va_start(ap, NULL);
|
||||
vsprintf(res, format, ap);
|
||||
|
||||
char *new = mem_malloc(mem, (strlen(res) + 1) * sizeof(char));
|
||||
memcpy(new, res, (strlen(res) + 1) * sizeof(char));
|
||||
|
||||
free(res);
|
||||
return new;
|
||||
}
|
||||
|
||||
char *trim_start(char *string) {
|
||||
while (*string == ' ' || *string == '\n') {
|
||||
string++;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
char *trim_end(char *string) {
|
||||
while (*string == ' ' || *string == '\n') {
|
||||
string--;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
// dont judge :(
|
||||
bool is_digid(char n) {
|
||||
if (n == '0' || n == '1' || n == '2' || n == '3' || n == '4' || n == '5' ||
|
||||
n == '6' || n == '7' || n == '8' || n == '9') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool is_char(char n) {
|
||||
// 65 A, 90 Z, 97 a, 122 z
|
||||
if (n >= 65 && n <= 90 || n >= 97 && n <= 122) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool includes_between(char *start, char *end, char n) {
|
||||
while (*start != n && start <= end) {
|
||||
start++;
|
||||
}
|
||||
if (*start == n) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
char *mem_strdup(char *string, struct Mem *mem) {
|
||||
char *new = mem_malloc(mem, (strlen(string) + 1) * sizeof(char));
|
||||
memcpy(new, string, (strlen(string) + 1) * sizeof(char));
|
||||
return new;
|
||||
}
|
||||
|
||||
char *mem_strdup_reg(char *start, char *end, struct Mem *mem) {
|
||||
char *new = mem_malloc(mem, end - start + 1);
|
||||
memcpy(new, start, end - start);
|
||||
new[end - start + 1] = 0x0;
|
||||
return new;
|
||||
}
|
||||
|
||||
char *skip_to_char(char *string, char n) {
|
||||
while (*string != n) {
|
||||
string++;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
char *skip_after_char(char *string, char n) {
|
||||
while (*string != n) {
|
||||
string++;
|
||||
}
|
||||
return string + 1;
|
||||
}
|
28
src/string.h
Normal file
28
src/string.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef INCLUDE_SRC_STRING_H_
|
||||
#define INCLUDE_SRC_STRING_H_
|
||||
|
||||
#include "allocator.h"
|
||||
#include "dynarray.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct da_string split(struct Mem *mem, char *string, char needle, int *count);
|
||||
bool start_matches(char *string, char *match);
|
||||
char *extract_brackets(struct Mem *mem, char *start, char open, char close);
|
||||
char *skip_brackets(char *start, char open, char close);
|
||||
int index_of_char(char *string, char key);
|
||||
char *extract(struct Mem *mem, char *string, int start, int size);
|
||||
char *extract_inbetween_chars(struct Mem *mem, char *string, char one,
|
||||
char two);
|
||||
char *tmp_format(struct Mem *mem, char *format, ...);
|
||||
char *trim_start(char *string);
|
||||
char *trim_end(char *string);
|
||||
bool is_digid(char n);
|
||||
bool is_char(char n);
|
||||
bool includes_between(char *start, char *end, char n);
|
||||
char *mem_strdup(char *string, struct Mem *mem);
|
||||
char *mem_strdup_reg(char *start, char *end, struct Mem *mem);
|
||||
char *skip_to_char(char *string, char n);
|
||||
char *skip_after_char(char *string, char n);
|
||||
|
||||
#endif // INCLUDE_SRC_STRING_H_
|
86
src/util.c
86
src/util.c
|
@ -1,3 +1,89 @@
|
|||
#include "allocator.h"
|
||||
#include "dynarray.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
float randf() { return (float)rand() / (float)RAND_MAX; }
|
||||
|
||||
struct ST_key {
|
||||
char *key;
|
||||
void *value;
|
||||
};
|
||||
|
||||
dyn_array_define(da_ST_key, struct ST_key);
|
||||
|
||||
struct StringTable {
|
||||
struct da_ST_key keys;
|
||||
};
|
||||
|
||||
struct StringTable *st_make(struct Mem *mem) {
|
||||
struct StringTable *st =
|
||||
malloc_or_mem_malloc(mem, sizeof(struct StringTable));
|
||||
if (mem == NULL) {
|
||||
dyn_array_create_inplace(&st->keys);
|
||||
} else {
|
||||
dyn_array_create_inplace_mem(&st->keys, mem);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
struct StringTable *st_dup(struct StringTable *st) {
|
||||
struct StringTable *new =
|
||||
malloc_or_mem_malloc(st->keys.mem, sizeof(struct StringTable));
|
||||
new->keys.mem = st->keys.mem;
|
||||
new->keys.count = st->keys.count;
|
||||
new->keys.capacity = st->keys.capacity;
|
||||
new->keys.items = malloc_or_mem_malloc(new->keys.mem, sizeof(struct ST_key) *
|
||||
new->keys.capacity);
|
||||
memcpy(new->keys.items, st->keys.items,
|
||||
st->keys.capacity * sizeof(struct ST_key));
|
||||
|
||||
return new;
|
||||
}
|
||||
void st_insert(struct StringTable *st, char *key, void *value) {
|
||||
dyn_array_append(&st->keys, ((struct ST_key){.key = key, .value = value}));
|
||||
}
|
||||
bool st_has_key(struct StringTable *st, char *key) {
|
||||
for (int i = 0; i < st->keys.count; i++) {
|
||||
if (strcmp(st->keys.items[i].key, key) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool st_has_value(struct StringTable *st, void *value) {
|
||||
for (int i = 0; i < st->keys.count; i++) {
|
||||
if (st->keys.items[i].value == value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void *st_get(struct StringTable *st, char *key) {
|
||||
for (int i = 0; i < st->keys.count; i++) {
|
||||
if (strcmp(st->keys.items[i].key, key) == 0) {
|
||||
return st->keys.items[i].value;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void st_remove(struct StringTable *st, char *key) {
|
||||
for (int i = 0; i < st->keys.count; i++) {
|
||||
if (strcmp(st->keys.items[i].key, key) == 0) {
|
||||
dyn_array_remove(&st->keys, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
void st_unmake(struct StringTable *st) {
|
||||
if (st->keys.mem == NULL) {
|
||||
dyn_array_destroy(&st->keys);
|
||||
free(st);
|
||||
} else {
|
||||
dyn_array_destroy(&st->keys);
|
||||
mem_free(st->keys.mem, st);
|
||||
}
|
||||
}
|
||||
int st_get_size(struct StringTable *st) { return st->keys.count; }
|
||||
char *st_get_nth_key(struct StringTable *st, int index) {
|
||||
return st->keys.items[index].key;
|
||||
}
|
||||
|
|
22
src/util.h
22
src/util.h
|
@ -1,6 +1,28 @@
|
|||
#ifndef INCLUDE_ENGINE_UTIL_H_
|
||||
#define INCLUDE_ENGINE_UTIL_H_
|
||||
|
||||
#define UINT32_NULL 42424242
|
||||
|
||||
float randf();
|
||||
|
||||
#define SWAP($a, $b) \
|
||||
do { \
|
||||
void *tmp = alloca(sizeof($a)); \
|
||||
memcpy(tmp, &$a, sizeof($a)); \
|
||||
$a = $b; \
|
||||
memcpy(&$b, tmp, sizeof($b)); \
|
||||
} while (0)
|
||||
|
||||
struct StringTable;
|
||||
struct StringTable *st_make(struct Mem *mem);
|
||||
struct StringTable *st_dup(struct StringTable *st);
|
||||
void st_insert(struct StringTable *st, char *key, void *value);
|
||||
bool st_has_key(struct StringTable *st, char *key);
|
||||
void *st_get(struct StringTable *st, char *key);
|
||||
bool st_has_value(struct StringTable *st, void *value);
|
||||
void st_remove(struct StringTable *st, char *key);
|
||||
void st_unmake(struct StringTable *st);
|
||||
int st_get_size(struct StringTable *st);
|
||||
char *st_get_nth_key(struct StringTable *st, int index);
|
||||
|
||||
#endif // INCLUDE_ENGINE_UTIL_H_
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue