Skip to content

Commit

Permalink
initial support for multiple types
Browse files Browse the repository at this point in the history
  • Loading branch information
ap29600 committed Sep 20, 2022
1 parent e0ef996 commit 7b83a06
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 110 deletions.
57 changes: 34 additions & 23 deletions src/array/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,58 @@

#include "array.h"

Array* make_array(const double* data, u64 shape) {
Array *result = malloc(sizeof(Array) + sizeof(double) * shape);
result->data = (double*)(((u8*)result) + sizeof(Array));
result->owner = NULL;
result->ref_count = 1;
result->shape = shape;

if (data) memcpy(result->data, data, shape * sizeof(double));
else memset(result->data, 0, shape * sizeof(double));
const static u64 sizes[] = {
[Type_Float] = sizeof(f64),
[Type_Char] = sizeof(char),
[Type_Int] = sizeof(i64),
[Type_UInt] = sizeof(u64),
[Type_Bool] = sizeof(bool),
};

Array* make_array(const void* data, u64 shape, Element_Type type) {
Array *result = malloc(sizeof(Array) + sizes[type] * shape);

*result = (Array){
.data = ((u8*)result) + sizeof(Array),
.ref_count = 1,
.type = type,
.shape = shape,
};

if (data) memcpy(result->data, data, shape * sizes[type]);
else memset(result->data, 0, shape * sizes[type]);

return result;
}

Array *borrow_array(Array *array) {
assert(array);
array->ref_count += 1;
return array;
}

void release_array(Array *array) {
assert(array);
if (array->ref_count == 1) {
if (array->owner) release_array(array->owner);
free(array);
} else {
array->ref_count -= 1;
}
}

Array *clone_array(Array *array) {
return make_array(array->data, array->shape);
assert(array);
return make_array(array->data, array->shape, array->type);
}

Array* array_append_elem(Array *array, double elem) {
if (array->ref_count == 1) {
array = realloc(array, sizeof(Array) + sizeof(double) * (array->shape + 1));
array->data = (double*)((uintptr_t)array + sizeof(Array));
array->data[array->shape++] = elem;
return array;
} else {
Array *copy = make_array(NULL, array->shape + 1);
memcpy(copy->data, array->data, array->shape * sizeof(double));
copy->data[copy->shape-1] = elem;
return copy;
}
Array* array_append_elem(const void *elem, Array *array, Element_Type type) {
assert(array);
assert(array->type == type && "type mismatch");
assert(array->ref_count == 1 && "permission to modify");
assert((u8*)array->data == ((u8*)array + sizeof(Array)) && "single allocation");

array = realloc(array, sizeof(Array) + (array->shape+1) * sizes[type]);
array->data = ((u8*)array) + sizeof(Array);
memcpy(((u8*)array->data) + array->shape * sizes[type], elem, sizes[type]);
return array;
}
20 changes: 14 additions & 6 deletions src/array/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@

#include "lib/builtin.h"

typedef enum {
Type_Float,
Type_Char,
Type_Int,
Type_UInt,
Type_Bool,
} Element_Type;

typedef struct Array {
double *data;
u64 shape;
u64 ref_count;
struct Array *owner;
void *data;
u64 shape;
Element_Type type;
u64 ref_count;
} Array;

Array* make_array(const double* data, u64 shape);
Array* make_array(const void* data, u64 shape, Element_Type type);
Array* clone_array(Array *array);
Array* borrow_array(Array *array);
void release_array(Array *array);
Array* array_append_elem(Array *array, double elem);
Array* array_append_elem(const void *elem, Array *array, Element_Type type);

#endif // ARRAY_H
52 changes: 0 additions & 52 deletions src/eval/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,6 @@
#include "eval.h"
#include "src/funcs/funcs.h"

i64 fmt_expression(Byte_Slice dest, Ast_Node src, Fmt_Info info) {
const Ast_Node *ctx = info.user_ptr;
const char *begin = dest.begin;
switch (src.type) {
case Node_None:
dest.begin += fmt_cstr(dest, "<No_Expression>", info);
break;

case Node_Monad:
dest.begin += fmt_rune(dest, '(', info);
dest.begin += fmt_expression(dest, ctx[src.as.args.callee], info);
dest.begin += fmt_rune(dest, ' ', info);
dest.begin += fmt_expression(dest, ctx[src.as.args.right], info);
dest.begin += fmt_rune(dest, ')', info);
break;

case Node_Dyad:
dest.begin += fmt_rune(dest, '(', info);
dest.begin += fmt_expression(dest, ctx[src.as.args.left], info);
dest.begin += fmt_rune(dest, ' ', info);
dest.begin += fmt_expression(dest, ctx[src.as.args.callee], info);
dest.begin += fmt_rune(dest, ' ', info);
dest.begin += fmt_expression(dest, ctx[src.as.args.right], info);
dest.begin += fmt_rune(dest, ')', info);
break;

case Node_Function:
assert(false);

case Node_Identifier:
dest.begin += fmt_cstr(dest, src.as.identifier, info);
break;

case Node_Array:
for (u64 i = 0; i < src.as.array->shape; ++i) {
if (i > 0) {
dest.begin += fmt_rune(dest, ',', info);
}
dest.begin += fmt_i64(dest, (i64)src.as.array->data[i], info);
}
break;
case Node_Assign:
dest.begin += fmt_rune(dest, '(', info);
dest.begin += fmt_expression(dest, ctx[src.as.args.left], info);
dest.begin += fmt_cstr(dest, ":", info);
dest.begin += fmt_expression(dest, ctx[src.as.args.callee], info);
dest.begin += fmt_rune(dest, ')', info);
}

return dest.begin - begin;
}

i64 fmt_expression_va(Byte_Slice dest, va_list va, Fmt_Info info) {
Ast_Node src = va_arg(va, Ast_Node);
return fmt_expression(dest, src, info);
Expand Down
128 changes: 125 additions & 3 deletions src/formats/formats.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,45 @@ i64 fmt_eval_node (Byte_Slice dest, Eval_Node src, Fmt_Info info) {
break;

case Node_Array:
for (u64 i = 0; i < src.as.array->shape; ++i) {
if (i > 0) dest.begin += fmt_rune(dest, ',', info);
dest.begin += fmt_f64(dest, src.as.array->data[i], info);
switch(src.as.array->type) {
case Type_Float: {
f64 *data = src.as.array->data;
for (u64 i = 0; i < src.as.array->shape; ++i) {
if (i > 0) dest.begin += fmt_rune(dest, ',', info);
dest.begin += fmt_f64(dest, data[i], info);
}
} break;

case Type_Int: {
i64 *data = src.as.array->data;
for (u64 i = 0; i < src.as.array->shape; ++i) {
if (i > 0) dest.begin += fmt_rune(dest, ',', info);
dest.begin += fmt_i64(dest, data[i], info);
}
} break;

case Type_UInt: {
u64 *data = src.as.array->data;
for (u64 i = 0; i < src.as.array->shape; ++i) {
if (i > 0) dest.begin += fmt_rune(dest, ',', info);
dest.begin += fmt_u64(dest, data[i], info);
}
} break;

case Type_Char: {
String data = {.begin = src.as.array->data, .end = (char*)src.as.array->data + src.as.array->shape};
dest.begin += fmt_rune(dest, '"', info);
dest.begin += fmt_str(dest, data, info);
dest.begin += fmt_rune(dest, '"', info);
} break;

case Type_Bool: {
bool *data = src.as.array->data;
for (u64 i = 0; i < src.as.array->shape; ++i) {
if (i > 0) dest.begin += fmt_rune(dest, ',', info);
dest.begin += fmt_rune(dest, "01"[data[i]], info);
}
} break;
}
break;

Expand Down Expand Up @@ -134,6 +170,92 @@ i64 fmt_token_va(Byte_Slice dest, va_list va, Fmt_Info info) {
return fmt_token(dest, tok, info);
}

i64 fmt_expression(Byte_Slice dest, Ast_Node src, Fmt_Info info) {
const Ast_Node *ctx = info.user_ptr;
const char *begin = dest.begin;
switch (src.type) {
case Node_None:
dest.begin += fmt_cstr(dest, "<No_Expression>", info);
break;

case Node_Monad:
dest.begin += fmt_rune(dest, '(', info);
dest.begin += fmt_expression(dest, ctx[src.as.args.callee], info);
dest.begin += fmt_rune(dest, ' ', info);
dest.begin += fmt_expression(dest, ctx[src.as.args.right], info);
dest.begin += fmt_rune(dest, ')', info);
break;

case Node_Dyad:
dest.begin += fmt_rune(dest, '(', info);
dest.begin += fmt_expression(dest, ctx[src.as.args.left], info);
dest.begin += fmt_rune(dest, ' ', info);
dest.begin += fmt_expression(dest, ctx[src.as.args.callee], info);
dest.begin += fmt_rune(dest, ' ', info);
dest.begin += fmt_expression(dest, ctx[src.as.args.right], info);
dest.begin += fmt_rune(dest, ')', info);
break;

case Node_Function:
assert(false);

case Node_Identifier:
dest.begin += fmt_cstr(dest, src.as.identifier, info);
break;

case Node_Array:
switch(src.as.array->type) {
case Type_Float: {
f64 *data = src.as.array->data;
for (u64 i = 0; i < src.as.array->shape; ++i) {
if (i > 0) dest.begin += fmt_rune(dest, ',', info);
dest.begin += fmt_f64(dest, data[i], info);
}
} break;

case Type_Int: {
i64 *data = src.as.array->data;
for (u64 i = 0; i < src.as.array->shape; ++i) {
if (i > 0) dest.begin += fmt_rune(dest, ',', info);
dest.begin += fmt_i64(dest, data[i], info);
}
} break;

case Type_UInt: {
u64 *data = src.as.array->data;
for (u64 i = 0; i < src.as.array->shape; ++i) {
if (i > 0) dest.begin += fmt_rune(dest, ',', info);
dest.begin += fmt_u64(dest, data[i], info);
}
} break;

case Type_Char: {
String data = {.begin = src.as.array->data, .end = (char*)src.as.array->data + src.as.array->shape};
dest.begin += fmt_rune(dest, '"', info);
dest.begin += fmt_str(dest, data, info);
dest.begin += fmt_rune(dest, '"', info);
} break;

case Type_Bool: {
bool *data = src.as.array->data;
for (u64 i = 0; i < src.as.array->shape; ++i) {
if (i > 0) dest.begin += fmt_rune(dest, ',', info);
dest.begin += fmt_rune(dest, "01"[data[i]], info);
}
} break;
}
break;
case Node_Assign:
dest.begin += fmt_rune(dest, '(', info);
dest.begin += fmt_expression(dest, ctx[src.as.args.left], info);
dest.begin += fmt_cstr(dest, ":", info);
dest.begin += fmt_expression(dest, ctx[src.as.args.callee], info);
dest.begin += fmt_rune(dest, ')', info);
}

return dest.begin - begin;
}

void init_formats(void) {
register_format_directive((Fmt_Directive){"expr", fmt_expression_va});
register_format_directive((Fmt_Directive){"node", fmt_eval_node_va});
Expand Down
67 changes: 43 additions & 24 deletions src/funcs/funcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,51 @@
#include <stdlib.h>
#include <math.h>

#define BINARY_OP(name, op) \
static Eval_Node name(Eval_Context *ctx, Node_Handle left, Node_Handle right) { \
assert(ctx->nodes[left].type == Node_Array); \
assert(ctx->nodes[right].type == Node_Array); \
Array *left_arr = borrow_array(ctx->nodes[left].as.array); \
Array *right_arr = borrow_array(ctx->nodes[right].as.array); \
assert(left_arr->shape == right_arr->shape); \
\
Array *result = clone_array(left_arr); \
for(i64 i = 0; i < left_arr->shape; i++) { \
result->data[i] = result->data[i] op right_arr->data[i]; \
} \
release_array(left_arr); \
release_array(right_arr); \
return (Eval_Node){.type = Node_Array, .as.array = result}; \
#define BINARY_OP_ONCE(a, b, i, op, ty) ((ty *)a)[i] = ((ty *)a)[i] op ((ty *)b)[i]

#define BINARY_OP(name, op) \
static Eval_Node name(Eval_Context *ctx, Node_Handle left, Node_Handle right) { \
assert(ctx->nodes[left].type == Node_Array); \
assert(ctx->nodes[right].type == Node_Array); \
Array *left_arr = borrow_array(ctx->nodes[left].as.array); \
Array *right_arr = borrow_array(ctx->nodes[right].as.array); \
assert(left_arr->shape == right_arr->shape); \
assert(left_arr->type == right_arr->type); \
Array *const result = clone_array(left_arr); \
const u64 n = result->shape; \
void *const a = result->data; \
const void *const b = right_arr->data; \
switch (left_arr->type) { \
case Type_Float: for(i64 i = 0; i < n; i++) BINARY_OP_ONCE(a, b, i, op, f64); break; \
case Type_Int: for(i64 i = 0; i < n; i++) BINARY_OP_ONCE(a, b, i, op, i64); break; \
case Type_UInt: for(i64 i = 0; i < n; i++) BINARY_OP_ONCE(a, b, i, op, u64); break; \
case Type_Char: for(i64 i = 0; i < n; i++) BINARY_OP_ONCE(a, b, i, op, char); break; \
case Type_Bool: for(i64 i = 0; i < n; i++) BINARY_OP_ONCE(a, b, i, op, bool); break; \
default: assert(false); \
} \
release_array(left_arr); \
release_array(right_arr); \
return (Eval_Node){.type = Node_Array, .as.array = result}; \
}

#define UNARY_OP(name, op) \
static Eval_Node name (Eval_Context *ctx, Node_Handle left, Node_Handle right) { \
assert(ctx->nodes[right].type == Node_Array); \
Array *result = clone_array(ctx->nodes[right].as.array); \
for(i64 i = 0; i < result->shape; i++) { \
result->data[i] = op (result->data[i]); \
} \
return (Eval_Node){.type = Node_Array, .as.array = result}; \
} \
#define UNARY_OP_ONCE(a, i, op, ty) ((ty *)a)[i] = op (((ty *)a)[i])

#define UNARY_OP(name, op) \
static Eval_Node name (Eval_Context *ctx, Node_Handle left, Node_Handle right) { \
assert(ctx->nodes[right].type == Node_Array); \
Array *result = clone_array(ctx->nodes[right].as.array); \
const u64 n = result->shape; \
void *const a = result->data; \
switch (result->type) { \
case Type_Float: for(i64 i = 0; i < n; i++) UNARY_OP_ONCE(a, i, op, f64); break; \
case Type_Int: for(i64 i = 0; i < n; i++) UNARY_OP_ONCE(a, i, op, i64); break; \
case Type_UInt: for(i64 i = 0; i < n; i++) UNARY_OP_ONCE(a, i, op, u64); break; \
case Type_Char: for(i64 i = 0; i < n; i++) UNARY_OP_ONCE(a, i, op, char); break; \
case Type_Bool: for(i64 i = 0; i < n; i++) UNARY_OP_ONCE(a, i, op, bool); break; \
default: assert(false); \
} \
return (Eval_Node){.type = Node_Array, .as.array = result}; \
} \


static Eval_Node func_right_identity(Eval_Context *ctx, Node_Handle left, Node_Handle right) {
Expand Down
Loading

0 comments on commit 7b83a06

Please sign in to comment.