add generic arrays
This commit is contained in:
parent
6f91a71306
commit
f6b74f8f97
20
ir.c
20
ir.c
@ -21,6 +21,7 @@ const char *irinstr_str[IRInstrEnumSize] = {
|
||||
[IRJnz] = "jnz",
|
||||
[IRCallInternal] = "calli",
|
||||
[IRAddrOf] = "addrof",
|
||||
[IRArrMake] = "mkarr",
|
||||
};
|
||||
|
||||
#define IRLIST_INIT_CAP_LONG 4096
|
||||
@ -86,13 +87,16 @@ void irlist_term(IRList *v) {
|
||||
case IRJnz:
|
||||
free_irparam(&i->tok.CJmp.condition, true);
|
||||
break;
|
||||
case IRCallInternal: {
|
||||
size_t n_args = i->tok.CallI.n_args;
|
||||
for (size_t j = 0; j < n_args; j++)
|
||||
case IRCallInternal:
|
||||
for (size_t j = 0; j < i->tok.CallI.n_args; j++)
|
||||
free_irparam(&i->tok.CallI.args[j], true);
|
||||
free(i->tok.CallI.args);
|
||||
break;
|
||||
}
|
||||
case IRArrMake:
|
||||
for (size_t j = 0; j < i->tok.ArrMake.len; j++)
|
||||
free_irparam(&i->tok.ArrMake.vals[j], true);
|
||||
free(i->tok.ArrMake.vals);
|
||||
break;
|
||||
default:
|
||||
ASSERT_UNREACHED();
|
||||
}
|
||||
@ -198,6 +202,14 @@ void print_ir(IRList *v, const BuiltinFunc *builtin_funcs) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IRArrMake: {
|
||||
printf(" %%%zx", i->tok.ArrMake.arr_addr);
|
||||
for (size_t j = 0; j < i->tok.ArrMake.len; j++) {
|
||||
printf(" ");
|
||||
print_irparam(&i->tok.ArrMake.vals[j]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: ASSERT_UNREACHED();
|
||||
}
|
||||
printf(" ; %zu:%zu", i->tok.ln, i->tok.col);
|
||||
|
7
ir.h
7
ir.h
@ -51,6 +51,7 @@ enum IRInstr {
|
||||
IRJnz,
|
||||
IRCallInternal,
|
||||
IRAddrOf,
|
||||
IRArrMake,
|
||||
IRInstrEnumSize,
|
||||
};
|
||||
typedef enum IRInstr IRInstr;
|
||||
@ -106,6 +107,12 @@ typedef struct IRTok {
|
||||
size_t n_args;
|
||||
IRParam *args;
|
||||
} CallI;
|
||||
|
||||
struct {
|
||||
size_t arr_addr;
|
||||
size_t len, cap;
|
||||
IRParam *vals;
|
||||
} ArrMake;
|
||||
};
|
||||
} IRTok;
|
||||
|
||||
|
2
lex.c
2
lex.c
@ -247,6 +247,8 @@ TokList lex(const char *s) {
|
||||
case '}':
|
||||
case '(':
|
||||
case ')':
|
||||
case '[':
|
||||
case ']':
|
||||
case ',':
|
||||
case '+':
|
||||
case '-':
|
||||
|
98
parse.c
98
parse.c
@ -66,6 +66,9 @@ static void set_irtok_dest_addr(IRTok *t, size_t addr) {
|
||||
case IRCallInternal:
|
||||
t->CallI.ret_addr = addr;
|
||||
break;
|
||||
case IRArrMake:
|
||||
t->ArrMake.arr_addr = addr;
|
||||
break;
|
||||
default:
|
||||
ASSERT_UNREACHED();
|
||||
}
|
||||
@ -313,7 +316,7 @@ static ExprRet expr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc,
|
||||
eval_func_in_place = false;
|
||||
if (t->next->tok.kind == TokOp) {
|
||||
if (t->next->tok.Op == OpComma) {
|
||||
toklist_del(toks, t->next, t->next); /* delete right parenthesis */
|
||||
toklist_del(toks, t->next, t->next); /* delete comma */
|
||||
continue;
|
||||
} else if (t->next->tok.Op == OpRParen) {
|
||||
toklist_del(toks, t->next, t->next); /* delete right parenthesis */
|
||||
@ -394,6 +397,99 @@ static ExprRet expr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc,
|
||||
}
|
||||
}
|
||||
|
||||
/* Collapse array. */
|
||||
else if (t->tok.kind == TokOp && t->tok.Op == OpLBrack) {
|
||||
TokListItem *lbrack = t;
|
||||
bool eval_immediately = true;
|
||||
size_t elems_len = 0;
|
||||
size_t elems_cap = 0;
|
||||
IRParam *elems = NULL;
|
||||
|
||||
if (t->next->tok.kind == TokOp && t->next->tok.Op == OpRBrack) {
|
||||
/* empty array */
|
||||
toklist_del(toks, t->next, t->next); /* delete right bracket */
|
||||
} else {
|
||||
elems_cap = 16;
|
||||
elems = xmalloc(sizeof(IRParam) * elems_cap);
|
||||
for (;;) {
|
||||
if (elems_len+1 > elems_cap)
|
||||
elems = xrealloc(elems, (elems_cap *= 2));
|
||||
IRParam e;
|
||||
TRY_RET_ELSE(e = expr_into_irparam(out_ir, toks, funcs, &sc, t->next), (ExprRet){0}, free(elems));
|
||||
if (e.kind != IRParamLiteral)
|
||||
eval_immediately = false;
|
||||
elems[elems_len++] = e;
|
||||
if (t->next->tok.kind == TokOp) {
|
||||
if (t->next->tok.Op == OpComma) {
|
||||
toklist_del(toks, t->next, t->next); /* delete comma */
|
||||
continue;
|
||||
} else if (t->next->tok.Op == OpRBrack) {
|
||||
toklist_del(toks, t->next, t->next); /* delete right bracket */
|
||||
break;
|
||||
}
|
||||
}
|
||||
mark_err(&t->next->tok);
|
||||
set_err("Expected ',' or ']' after array element");
|
||||
free(elems);
|
||||
return (ExprRet){0};
|
||||
}
|
||||
}
|
||||
|
||||
if (eval_immediately) {
|
||||
/* turn array into value */
|
||||
Value arr = {
|
||||
.type = TypeArr,
|
||||
.Arr = {
|
||||
.type = TypeVoid,
|
||||
.is_string = false,
|
||||
.dynamically_allocated = false,
|
||||
.vals = NULL,
|
||||
.len = elems_len,
|
||||
.cap = elems_len ? elems_cap : 0,
|
||||
},
|
||||
};
|
||||
if (elems_len) {
|
||||
Type arr_ty = elems[0].Literal.type;
|
||||
void *arr_vals = xmalloc(type_size[arr_ty] * elems_cap);
|
||||
for (size_t i = 0; i < elems_len; i++) {
|
||||
Value *v = &elems[i].Literal;
|
||||
if (v->type != arr_ty) {
|
||||
free(arr_vals);
|
||||
free(elems);
|
||||
set_err("Type of array item %zu (%s) differs from array type (%s)", i, type_str[v->type], type_str[arr_ty]);
|
||||
return (ExprRet){0};
|
||||
}
|
||||
memcpy((uint8_t*)arr_vals + type_size[arr_ty] * i, &v->Void, type_size[arr_ty]);
|
||||
}
|
||||
arr.Arr.type = arr_ty;
|
||||
arr.Arr.vals = arr_vals;
|
||||
}
|
||||
/* set lbracket to collapsed array value */
|
||||
lbrack->tok.kind = TokVal;
|
||||
lbrack->tok.Val = arr;
|
||||
/* free the now no longer needed element IRParam values */
|
||||
free(elems);
|
||||
} else {
|
||||
/* array initialization IR instruction */
|
||||
IRTok ir_tok = {
|
||||
.ln = lbrack->tok.ln,
|
||||
.col = lbrack->tok.col,
|
||||
.instr = IRArrMake,
|
||||
.ArrMake = {
|
||||
.arr_addr = 0,
|
||||
.len = elems_len,
|
||||
.cap = elems_cap,
|
||||
.vals = elems,
|
||||
},
|
||||
};
|
||||
|
||||
/* return if we've just evaluated the last instruction */
|
||||
ExprRet ret;
|
||||
if (expr_flush_ir_and_maybe_return(out_ir, toks, ir_tok, start, &sc, lbrack, &ret))
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Collapse unary operation. */
|
||||
if (perform_unary) {
|
||||
Tok *v = &t->tok; /* what we want to perform the operation on */
|
||||
|
3
tok.c
3
tok.c
@ -117,6 +117,7 @@ int8_t op_prec[OperatorEnumSize] = {
|
||||
[OpNewLn] = PREC_DELIM,
|
||||
[OpLCurl] = PREC_DELIM,
|
||||
[OpRParen] = PREC_DELIM,
|
||||
[OpRBrack] = PREC_DELIM,
|
||||
[OpComma] = PREC_DELIM,
|
||||
[OpAnd] = 0,
|
||||
[OpOr] = 0,
|
||||
@ -137,6 +138,8 @@ const char *op_str[OperatorEnumSize] = {
|
||||
[OpRCurl] = "}",
|
||||
[OpLParen] = "(",
|
||||
[OpRParen] = ")",
|
||||
[OpLBrack] = "[",
|
||||
[OpRBrack] = "]",
|
||||
[OpComma] = ",",
|
||||
[OpAdd] = "+",
|
||||
[OpSub] = "-",
|
||||
|
2
tok.h
2
tok.h
@ -51,6 +51,8 @@ enum Operator {
|
||||
OpRCurl = '}',
|
||||
OpLParen = '(',
|
||||
OpRParen = ')',
|
||||
OpLBrack = '[',
|
||||
OpRBrack = ']',
|
||||
OpComma = ',',
|
||||
OpAdd = '+',
|
||||
OpSub = '-',
|
||||
|
35
vm.c
35
vm.c
@ -92,6 +92,8 @@ void run(IRList *ir, const BuiltinFunc *builtin_funcs) {
|
||||
}
|
||||
case IRAddrOf: {
|
||||
if (instr->Unary.val.kind != IRParamAddr) {
|
||||
free(fn_args);
|
||||
stack_term(&s);
|
||||
set_err("Unable to take the address of a literal");
|
||||
return;
|
||||
}
|
||||
@ -174,6 +176,39 @@ void run(IRList *ir, const BuiltinFunc *builtin_funcs) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IRArrMake: {
|
||||
size_t arr_len = instr->ArrMake.len, arr_cap = instr->ArrMake.cap;
|
||||
Value arr = {
|
||||
.type = TypeArr,
|
||||
.Arr = {
|
||||
.type = TypeVoid,
|
||||
.is_string = false,
|
||||
.dynamically_allocated = true,
|
||||
.vals = NULL,
|
||||
.len = arr_len,
|
||||
.cap = arr_len ? arr_cap : 0,
|
||||
},
|
||||
};
|
||||
if (arr_len) {
|
||||
Type arr_ty = irparam_to_val(&s, &instr->ArrMake.vals[0])->type;
|
||||
void *arr_vals = xmalloc(type_size[arr_ty] * arr_cap);
|
||||
for (size_t j = 0; j < arr_len; j++) {
|
||||
Value *v = irparam_to_val(&s, &instr->ArrMake.vals[j]);
|
||||
if (v->type != arr_ty) {
|
||||
free(arr_vals);
|
||||
free(fn_args);
|
||||
stack_term(&s);
|
||||
set_err("Type of array item %zu (%s) differs from array type (%s)", j, type_str[v->type], type_str[arr_ty]);
|
||||
return;
|
||||
}
|
||||
memcpy((uint8_t*)arr_vals + type_size[arr_ty] * j, &v->Void, type_size[arr_ty]);
|
||||
}
|
||||
arr.Arr.type = arr_ty;
|
||||
arr.Arr.vals = arr_vals;
|
||||
}
|
||||
stack_assign(&s, instr->ArrMake.arr_addr, &arr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT_UNREACHED();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user