adding compilation of if-else statements
This commit is contained in:
@@ -1 +1,2 @@
|
|||||||
build
|
build
|
||||||
|
temp
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
if 1 1;
|
||||||
+22
-4
@@ -48,12 +48,15 @@ static const InstrInfo instr_table[] = {
|
|||||||
[OPCODE_MUL] = {"MUL", 2, 0, NULL},
|
[OPCODE_MUL] = {"MUL", 2, 0, NULL},
|
||||||
[OPCODE_DIV] = {"DIV", 2, 0, NULL},
|
[OPCODE_DIV] = {"DIV", 2, 0, NULL},
|
||||||
|
|
||||||
[OPCODE_PUSHI] = {"PUSHI", 2, 1, (OperandType[]) {OPTP_INT}},
|
[OPCODE_PUSHI] = {"PUSHI", 1, 1, (OperandType[]) {OPTP_INT}},
|
||||||
[OPCODE_PUSHF] = {"PUSHF", 2, 1, (OperandType[]) {OPTP_FLOAT}},
|
[OPCODE_PUSHF] = {"PUSHF", 1, 1, (OperandType[]) {OPTP_FLOAT}},
|
||||||
[OPCODE_PUSHS] = {"PUSHS", 2, 1, (OperandType[]) {OPTP_STRING}},
|
[OPCODE_PUSHS] = {"PUSHS", 1, 1, (OperandType[]) {OPTP_STRING}},
|
||||||
[OPCODE_PUSHV] = {"PUSHV", 2, 1, (OperandType[]) {OPTP_STRING}},
|
[OPCODE_PUSHV] = {"PUSHV", 1, 1, (OperandType[]) {OPTP_STRING}},
|
||||||
|
|
||||||
[OPCODE_RETURN] = {"RETURN", 0, 0, NULL},
|
[OPCODE_RETURN] = {"RETURN", 0, 0, NULL},
|
||||||
|
|
||||||
|
[OPCODE_JUMPIFNOTANDPOP] = {"JUMPIFNOTANDPOP", 1, 1, (OperandType[]) {OPTP_INT}},
|
||||||
|
[OPCODE_JUMP] = {"JUMP", 0, 1, (OperandType[]) {OPTP_INT}},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *operand_type_names[] = {
|
static const char *operand_type_names[] = {
|
||||||
@@ -363,3 +366,18 @@ _Bool ExeBuilder_Append(ExeBuilder *exeb, Error *error, Opcode opcode, Operand *
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BPAlloc *ExeBuilder_GetAlloc(ExeBuilder *exeb)
|
||||||
|
{
|
||||||
|
return BucketList_GetAlloc(exeb->code);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ExeBuilder_InstrCount(ExeBuilder *exeb)
|
||||||
|
{
|
||||||
|
int raw_size = BucketList_Size(exeb->code);
|
||||||
|
|
||||||
|
assert(raw_size % sizeof(Instruction) == 0);
|
||||||
|
|
||||||
|
return raw_size / sizeof(Instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ typedef enum {
|
|||||||
OPCODE_PUSHS,
|
OPCODE_PUSHS,
|
||||||
OPCODE_PUSHV,
|
OPCODE_PUSHV,
|
||||||
OPCODE_RETURN,
|
OPCODE_RETURN,
|
||||||
|
OPCODE_JUMPIFNOTANDPOP,
|
||||||
|
OPCODE_JUMP,
|
||||||
} Opcode;
|
} Opcode;
|
||||||
|
|
||||||
typedef struct xExecutable Executable;
|
typedef struct xExecutable Executable;
|
||||||
@@ -47,4 +49,6 @@ Source *Executable_GetSource(Executable *exe);
|
|||||||
ExeBuilder *ExeBuilder_New(BPAlloc *alloc);
|
ExeBuilder *ExeBuilder_New(BPAlloc *alloc);
|
||||||
_Bool ExeBuilder_Append(ExeBuilder *exeb, Error *error, Opcode opcode, Operand *opv, int opc, int off, int len);
|
_Bool ExeBuilder_Append(ExeBuilder *exeb, Error *error, Opcode opcode, Operand *opv, int opc, int off, int len);
|
||||||
Executable *ExeBuilder_Finalize(ExeBuilder *exeb, Error *error);
|
Executable *ExeBuilder_Finalize(ExeBuilder *exeb, Error *error);
|
||||||
|
BPAlloc *ExeBuilder_GetAlloc(ExeBuilder *exeb);
|
||||||
|
int ExeBuilder_InstrCount(ExeBuilder *exeb);
|
||||||
#endif
|
#endif
|
||||||
+71
-2
@@ -42,7 +42,8 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error)
|
|||||||
OperExprNode *oper = (OperExprNode*) expr;
|
OperExprNode *oper = (OperExprNode*) expr;
|
||||||
|
|
||||||
for(Node *operand = oper->head; operand; operand = operand->next)
|
for(Node *operand = oper->head; operand; operand = operand->next)
|
||||||
emit_instr_for_node(exeb, operand, error);
|
if(!emit_instr_for_node(exeb, operand, error))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return ExeBuilder_Append(exeb, error,
|
return ExeBuilder_Append(exeb, error,
|
||||||
exprkind_to_opcode(expr->kind),
|
exprkind_to_opcode(expr->kind),
|
||||||
@@ -84,10 +85,78 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case NODE_IFELSE:
|
||||||
|
{
|
||||||
|
IfElseNode *ifelse = (IfElseNode*) node;
|
||||||
|
|
||||||
|
if(!emit_instr_for_node(exeb, ifelse->condition, error))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(ifelse->false_branch)
|
||||||
|
{
|
||||||
|
Promise *else_offset = Promise_New(ExeBuilder_GetAlloc(exeb), sizeof(long long int));
|
||||||
|
Promise *done_offset = Promise_New(ExeBuilder_GetAlloc(exeb), sizeof(long long int));
|
||||||
|
|
||||||
|
if(else_offset == NULL || done_offset == NULL)
|
||||||
|
{
|
||||||
|
Error_Report(error, 1, "No memory");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand op = { .type = OPTP_PROMISE, .as_promise = else_offset };
|
||||||
|
if(!ExeBuilder_Append(exeb, error, OPCODE_JUMPIFNOTANDPOP, &op, 1, node->offset, node->length))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(!emit_instr_for_node(exeb, ifelse->true_branch, error))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
op = (Operand) { .type = OPTP_PROMISE, .as_promise = done_offset };
|
||||||
|
if(!ExeBuilder_Append(exeb, error, OPCODE_JUMP, &op, 1, node->offset, node->length))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
long long int temp = ExeBuilder_InstrCount(exeb);
|
||||||
|
Promise_Resolve(else_offset, &temp, sizeof(temp));
|
||||||
|
|
||||||
|
if(!emit_instr_for_node(exeb, ifelse->false_branch, error))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
temp = ExeBuilder_InstrCount(exeb);
|
||||||
|
Promise_Resolve(done_offset, &temp, sizeof(temp));
|
||||||
|
|
||||||
|
Promise_Free(else_offset);
|
||||||
|
Promise_Free(done_offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Promise *done_offset = Promise_New(ExeBuilder_GetAlloc(exeb), sizeof(long long int));
|
||||||
|
|
||||||
|
if(done_offset == NULL)
|
||||||
|
{
|
||||||
|
Error_Report(error, 1, "No memory");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ExeBuilder_Append(exeb, error, OPCODE_JUMPIFNOTANDPOP, &(Operand) { .type = OPTP_PROMISE, .as_promise = done_offset }, 1, node->offset, node->length))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(!emit_instr_for_node(exeb, ifelse->true_branch, error))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
long long int temp = ExeBuilder_InstrCount(exeb);
|
||||||
|
Promise_Resolve(done_offset, &temp, sizeof(temp));
|
||||||
|
|
||||||
|
Promise_Free(done_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
UNREACHABLE;
|
UNREACHABLE;
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
|
UNREACHABLE;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Executable *compile(AST *ast, BPAlloc *alloc, Error *error)
|
Executable *compile(AST *ast, BPAlloc *alloc, Error *error)
|
||||||
|
|||||||
+30
-14
@@ -369,7 +369,7 @@ static Node *parse_string_primary_expression(Context *ctx)
|
|||||||
assert(ctx != NULL);
|
assert(ctx != NULL);
|
||||||
assert(ctx->token->kind == TSTRING);
|
assert(ctx->token->kind == TSTRING);
|
||||||
|
|
||||||
if(current(ctx) == TDONE)
|
if(done(ctx))
|
||||||
{
|
{
|
||||||
Error_Report(ctx->error, 0, "Source ended where a string literal was expected");
|
Error_Report(ctx->error, 0, "Source ended where a string literal was expected");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -493,6 +493,12 @@ static Node *parse_primary_expresion(Context *ctx)
|
|||||||
{
|
{
|
||||||
assert(ctx != NULL);
|
assert(ctx != NULL);
|
||||||
|
|
||||||
|
if(done(ctx))
|
||||||
|
{
|
||||||
|
Error_Report(ctx->error, 0, "Source ended where a primary expression was expected");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
switch(current(ctx))
|
switch(current(ctx))
|
||||||
{
|
{
|
||||||
case '+':
|
case '+':
|
||||||
@@ -532,7 +538,7 @@ static Node *parse_primary_expresion(Context *ctx)
|
|||||||
if(node == NULL)
|
if(node == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if(current(ctx) == TDONE)
|
if(done(ctx))
|
||||||
{
|
{
|
||||||
Error_Report(ctx->error, 0, "Source ended before \")\", after sub-expression");
|
Error_Report(ctx->error, 0, "Source ended before \")\", after sub-expression");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -823,34 +829,44 @@ static Node *parse_ifelse_statement(Context *ctx)
|
|||||||
{
|
{
|
||||||
assert(ctx != NULL);
|
assert(ctx != NULL);
|
||||||
assert(ctx->token != NULL);
|
assert(ctx->token != NULL);
|
||||||
assert(ctx->token->kind == TKWIF);
|
|
||||||
|
|
||||||
ctx->token = ctx->token->next;
|
if(done(ctx))
|
||||||
|
|
||||||
if(ctx->token->kind == TDONE)
|
|
||||||
{
|
{
|
||||||
// ERROR: Source ended after if keyword.
|
Error_Report(ctx->error, 0, "Source ended where an if-else statement was expected");
|
||||||
// An expression was expected.
|
return NULL;
|
||||||
Error_Report(ctx->error, 0, "Source ended after if keyword. An expression was expected");
|
}
|
||||||
|
|
||||||
|
if(current(ctx) != TKWIF)
|
||||||
|
{
|
||||||
|
Error_Report(ctx->error, 0, "Got unexpected token \"%.*s\" where an if-else statement was expected", ctx->token->length, ctx->src + ctx->token->offset);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token *if_token = current_token(ctx);
|
Token *if_token = current_token(ctx);
|
||||||
|
assert(if_token != NULL);
|
||||||
|
|
||||||
|
next(ctx); // Consume the "if" keyword.
|
||||||
|
|
||||||
Node *condition = parse_expression(ctx);
|
Node *condition = parse_expression(ctx);
|
||||||
if(condition == NULL) return NULL;
|
|
||||||
|
if(condition == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
Node *true_branch = parse_statement(ctx);
|
Node *true_branch = parse_statement(ctx);
|
||||||
if(condition == NULL) return NULL;
|
|
||||||
|
if(condition == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
Node *false_branch = NULL;
|
Node *false_branch = NULL;
|
||||||
|
|
||||||
if(ctx->token->kind == TKWELSE)
|
if(ctx->token->kind == TKWELSE)
|
||||||
{
|
{
|
||||||
// Consume the "else" token.
|
next(ctx); // Consume the "else" token.
|
||||||
ctx->token = ctx->token->next;
|
|
||||||
|
|
||||||
false_branch = parse_statement(ctx);
|
false_branch = parse_statement(ctx);
|
||||||
if(false_branch == NULL) return NULL;
|
|
||||||
|
if(false_branch == NULL)
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
IfElseNode *ifelse;
|
IfElseNode *ifelse;
|
||||||
|
|||||||
@@ -126,6 +126,27 @@ static xj_value *convert_node(Node *node, xj_error *error, xj_alloc **alloc)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NODE_IFELSE:
|
||||||
|
{
|
||||||
|
IfElseNode *ifelse = (IfElseNode*) node;
|
||||||
|
|
||||||
|
xj_value *condition = convert_node(ifelse->condition, error, alloc);
|
||||||
|
if(condition == NULL) return NULL;
|
||||||
|
|
||||||
|
xj_value *true_branch = convert_node(ifelse->true_branch, error, alloc);
|
||||||
|
if(true_branch == NULL) return NULL;
|
||||||
|
|
||||||
|
xj_value *false_branch = convert_node(ifelse->false_branch, error, alloc);
|
||||||
|
if(false_branch == NULL) return NULL;
|
||||||
|
|
||||||
|
return xj_decodef(error, alloc,
|
||||||
|
"{"
|
||||||
|
"\t\"node-kind\": \"if-else\", \n"
|
||||||
|
"\t\"condition\": %v, \n"
|
||||||
|
"\t\"true-branch\": %v, \n"
|
||||||
|
"\t\"false-branch\": %v\n"
|
||||||
|
"}", condition, true_branch, false_branch);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
UNREACHABLE;
|
UNREACHABLE;
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "objects.h"
|
||||||
|
|
||||||
|
static _Bool to_bool(Object *obj, Error *err);
|
||||||
|
|
||||||
|
static const Type t_int = {
|
||||||
|
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
|
||||||
|
.name = "int",
|
||||||
|
.size = sizeof (Object),
|
||||||
|
.atomic = ATMTP_BOOL,
|
||||||
|
.to_bool = to_bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
static Object the_true_object = {
|
||||||
|
.type = t_bool,
|
||||||
|
.flags = Object_STATIC,
|
||||||
|
}
|
||||||
|
|
||||||
|
static Object the_false_object = {
|
||||||
|
.type = t_bool,
|
||||||
|
.flags = Object_STATIC,
|
||||||
|
}
|
||||||
|
|
||||||
|
static _Bool to_bool(Object *obj, Error *err)
|
||||||
|
{
|
||||||
|
assert(obj);
|
||||||
|
assert(err);
|
||||||
|
assert(Object_GetType(obj) == &t_bool);
|
||||||
|
return obj == &the_true_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *Object_FromBool(_Bool val, Heap *heap, Error *error)
|
||||||
|
{
|
||||||
|
(void) heap;
|
||||||
|
(void) error;
|
||||||
|
return val ? &the_true_object : &the_false_object;
|
||||||
|
}
|
||||||
@@ -218,6 +218,13 @@ _Bool Object_IsInt(Object *obj)
|
|||||||
return obj->type->atomic == ATMTP_INT;
|
return obj->type->atomic == ATMTP_INT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_Bool Object_IsBool(Object *obj)
|
||||||
|
{
|
||||||
|
assert(obj != NULL);
|
||||||
|
assert(obj->type != NULL);
|
||||||
|
return obj->type->atomic == ATMTP_BOOL;
|
||||||
|
}
|
||||||
|
|
||||||
_Bool Object_IsFloat(Object *obj)
|
_Bool Object_IsFloat(Object *obj)
|
||||||
{
|
{
|
||||||
assert(obj != NULL);
|
assert(obj != NULL);
|
||||||
@@ -248,6 +255,29 @@ long long int Object_ToInt(Object *obj, Error *err)
|
|||||||
return type->to_int(obj, err);
|
return type->to_int(obj, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_Bool Object_ToBool(Object *obj, Error *err)
|
||||||
|
{
|
||||||
|
assert(err);
|
||||||
|
assert(obj);
|
||||||
|
|
||||||
|
if(!Object_IsBool(obj))
|
||||||
|
{
|
||||||
|
Error_Report(err, 0, "Object is not a boolean");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type *type = Object_GetType(obj);
|
||||||
|
assert(type);
|
||||||
|
|
||||||
|
if(type->to_bool == NULL)
|
||||||
|
{
|
||||||
|
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return type->to_bool(obj, err);
|
||||||
|
}
|
||||||
|
|
||||||
double Object_ToFloat(Object *obj, Error *err)
|
double Object_ToFloat(Object *obj, Error *err)
|
||||||
{
|
{
|
||||||
assert(err);
|
assert(err);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ struct Object {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
ATMTP_NOTATOMIC = 0,
|
ATMTP_NOTATOMIC = 0,
|
||||||
ATMTP_INT,
|
ATMTP_INT,
|
||||||
|
ATMTP_BOOL,
|
||||||
ATMTP_FLOAT,
|
ATMTP_FLOAT,
|
||||||
} AtomicType;
|
} AtomicType;
|
||||||
|
|
||||||
@@ -47,6 +48,7 @@ struct Type {
|
|||||||
// Some.
|
// Some.
|
||||||
union {
|
union {
|
||||||
long long int (*to_int)(Object *self, Error *err);
|
long long int (*to_int)(Object *self, Error *err);
|
||||||
|
_Bool (*to_bool)(Object *self, Error *err);
|
||||||
double (*to_float)(Object *self, Error *err);
|
double (*to_float)(Object *self, Error *err);
|
||||||
char *(*to_string)(Object *self, int *size, Heap *heap, Error *err);
|
char *(*to_string)(Object *self, int *size, Heap *heap, Error *err);
|
||||||
};
|
};
|
||||||
@@ -81,13 +83,16 @@ Object* Object_NewMap(int num, Heap *heap, Error *error);
|
|||||||
Object* Object_NewNone(Heap *heap, Error *error);
|
Object* Object_NewNone(Heap *heap, Error *error);
|
||||||
|
|
||||||
Object* Object_FromInt (long long int val, Heap *heap, Error *error);
|
Object* Object_FromInt (long long int val, Heap *heap, Error *error);
|
||||||
|
Object* Object_FromBool (_Bool val, Heap *heap, Error *error);
|
||||||
Object* Object_FromFloat (double val, Heap *heap, Error *error);
|
Object* Object_FromFloat (double val, Heap *heap, Error *error);
|
||||||
Object* Object_FromString(const char *str, int len, Heap *heap, Error *error);
|
Object* Object_FromString(const char *str, int len, Heap *heap, Error *error);
|
||||||
|
|
||||||
_Bool Object_IsInt (Object *obj);
|
_Bool Object_IsInt (Object *obj);
|
||||||
|
_Bool Object_IsBool (Object *obj);
|
||||||
_Bool Object_IsFloat(Object *obj);
|
_Bool Object_IsFloat(Object *obj);
|
||||||
|
|
||||||
long long int Object_ToInt (Object *obj, Error *err);
|
long long int Object_ToInt (Object *obj, Error *err);
|
||||||
|
_Bool Object_ToBool (Object *obj, Error *err);
|
||||||
double Object_ToFloat(Object *obj, Error *err);
|
double Object_ToFloat(Object *obj, Error *err);
|
||||||
|
|
||||||
_Bool Object_Compare(Object *obj1, Object *obj2, Error *error);
|
_Bool Object_Compare(Object *obj1, Object *obj2, Error *error);
|
||||||
|
|||||||
@@ -433,6 +433,40 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
case OPCODE_RETURN:
|
case OPCODE_RETURN:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case OPCODE_JUMP:
|
||||||
|
assert(opc == 1);
|
||||||
|
assert(ops[0].type == OPTP_INT);
|
||||||
|
runtime->frame->index = ops[0].as_int;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case OPCODE_JUMPIFNOTANDPOP:
|
||||||
|
{
|
||||||
|
assert(opc == 1);
|
||||||
|
assert(ops[0].type == OPTP_INT);
|
||||||
|
|
||||||
|
long long int target = ops[0].as_int;
|
||||||
|
|
||||||
|
if(runtime->frame->used == 0)
|
||||||
|
{
|
||||||
|
Error_Report(error, 1, "Frame doesn't have enough items on the stack to execute JUMPIFNOTANDPOP");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *top = Stack_Top(runtime->stack, 0);
|
||||||
|
assert(top != NULL);
|
||||||
|
|
||||||
|
if(!Object_IsBool(top))
|
||||||
|
{
|
||||||
|
Error_Report(error, 1, "JUMPIFNOTANDPOP expected a boolean on the stack");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Object_ToBool(top, error)) // This can't fail because we know it's a bool.
|
||||||
|
runtime->frame->index = target;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
UNREACHABLE;
|
UNREACHABLE;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -175,3 +175,8 @@ void BucketList_Copy(BucketList *blist, void *dest, int len)
|
|||||||
bucket = bucket->next;
|
bucket = bucket->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BPAlloc *BucketList_GetAlloc(BucketList *blist)
|
||||||
|
{
|
||||||
|
return blist->alloc;
|
||||||
|
}
|
||||||
@@ -7,4 +7,5 @@ int BucketList_Size(BucketList *blist);
|
|||||||
void BucketList_Copy(BucketList *blist, void *dest, int len);
|
void BucketList_Copy(BucketList *blist, void *dest, int len);
|
||||||
_Bool BucketList_Append (BucketList *blist, const void *data, int size);
|
_Bool BucketList_Append (BucketList *blist, const void *data, int size);
|
||||||
void *BucketList_Append2(BucketList *blist, const void *data, int size);
|
void *BucketList_Append2(BucketList *blist, const void *data, int size);
|
||||||
|
BPAlloc *BucketList_GetAlloc(BucketList *blist);
|
||||||
#endif
|
#endif
|
||||||
+1
-1
@@ -41,7 +41,7 @@ unsigned int Promise_Size(Promise *promise)
|
|||||||
return promise->size;
|
return promise->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Promise_Delete(Promise *promise)
|
void Promise_Free(Promise *promise)
|
||||||
{
|
{
|
||||||
assert(promise->set == 1);
|
assert(promise->set == 1);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
typedef struct xPromise Promise;
|
typedef struct xPromise Promise;
|
||||||
Promise *Promise_New(BPAlloc *alloc, int size);
|
Promise *Promise_New(BPAlloc *alloc, int size);
|
||||||
unsigned int Promise_Size(Promise *promise);
|
unsigned int Promise_Size(Promise *promise);
|
||||||
void Promise_Delete(Promise *promise);
|
void Promise_Free(Promise *promise);
|
||||||
void Promise_Resolve(Promise *promise, const void *data, int size);
|
void Promise_Resolve(Promise *promise, const void *data, int size);
|
||||||
_Bool Promise_Subscribe(Promise *promise, void *dest);
|
_Bool Promise_Subscribe(Promise *promise, void *dest);
|
||||||
_Bool Promise_Subscribe2(Promise *promise, void *dest, void *userp, void (*callback)(void*));
|
_Bool Promise_Subscribe2(Promise *promise, void *dest, void *userp, void (*callback)(void*));
|
||||||
|
|||||||
+1
-1
@@ -80,7 +80,7 @@ Source *Source_FromFile(const char *file, Error *error)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fseek(fp, 0, SEEK_END))
|
if(fseek(fp, 0, SEEK_SET))
|
||||||
{
|
{
|
||||||
Error_Report(error, 1, "Call to fseek failed (%s, errno = %d)", strerror(errno), errno);
|
Error_Report(error, 1, "Call to fseek failed (%s, errno = %d)", strerror(errno), errno);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|||||||
Reference in New Issue
Block a user