summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c23
-rw-r--r--decls_cgen.c2
-rw-r--r--eval.c44
-rw-r--r--test.toc55
-rw-r--r--types.c122
5 files changed, 115 insertions, 131 deletions
diff --git a/cgen.c b/cgen.c
index 94baf18..dc61f5b 100644
--- a/cgen.c
+++ b/cgen.c
@@ -121,7 +121,7 @@ static void cgen_defs_decl(CGenerator *g, Declaration *d);
break; \
case EXPR_FN: { \
FnExpr *fn = e->fn; \
- if (fn->instances.data) { \
+ if (fn_has_instances(fn)) { \
Instance **data = fn->instances.data; \
for (U64 i = 0; i < fn->instances.cap; ++i) { \
if (fn->instances.occupied[i]) { \
@@ -250,6 +250,12 @@ static bool cgen_fn_is_direct(CGenerator *g, Declaration *d) {
return (g->block == NULL || (g->block->flags & BLOCK_IS_NMS)) && (d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_FN && arr_len(d->idents) == 1;
}
+static bool fn_has_instances(FnExpr *f) {
+ if (fn_has_any_const_params(f)) return true;
+ if (!arr_len(f->params)) return false;
+ return type_is_builtin(&((Declaration *)arr_last(f->params))->type, BUILTIN_VARARGS);
+}
+
static bool cgen_uses_ptr(Type *t) {
assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
@@ -901,7 +907,7 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) {
else
cgen_write(g, "val_");
bool positive_step
- = fo->range.stepval == NULL || val_is_nonnegative(fo->range.stepval, &fo->type);
+ = fo->range.stepval == NULL || val_is_nonnegative(*fo->range.stepval, &fo->type);
cgen_write(g, " %c= to_", positive_step ? '<' : '>');
} else {
if (fo->index)
@@ -1011,11 +1017,13 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) {
cgen_expr_pre(g, e->call.fn);
size_t i = 0;
Constness *constness = e->call.fn->type.fn.constness;
+ size_t nparams = arr_len(e->call.fn->type.fn.types)-1;
arr_foreach(e->call.arg_exprs, Expression, arg) {
if (!constness || !arg_is_const(arg, constness[i])) {
cgen_arg_pre(g, arg);
}
- ++i;
+ if (i < nparams-1)
+ ++i;
}
if (e->type.kind == TYPE_TUPLE) {
Type *t = &e->type;
@@ -1198,6 +1206,7 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) {
}
static void cgen_expr(CGenerator *g, Expression *e) {
+ assert(e->flags & EXPR_FOUND_TYPE);
switch (e->kind) {
case EXPR_LITERAL_FLOAT:
cgen_write(g, "%.16Lf", (long double)e->floatl);
@@ -1611,8 +1620,8 @@ static void cgen_fn(CGenerator *g, FnExpr *f, U64 instance, Value *compile_time_
Type *type = param->type.kind == TYPE_TUPLE ? &param->type.tuple[i]
: &param->type;
Value arg = compile_time_args[carg_idx];
- if (type_is_builtin(type, BUILTIN_TYPE)) {
- /* don't need to do anything; we'll just use the type's id */
+ if (type_is_builtin(type, BUILTIN_TYPE) || type_is_builtin(type, BUILTIN_VARARGS)) {
+ /* don't need to do anything */
} else {
cgen_val_pre(g, arg, type);
cgen_type_pre(g, type);
@@ -1942,8 +1951,8 @@ static void cgen_stmt(CGenerator *g, Statement *s) {
}
static void cgen_defs_fn(CGenerator *g, FnExpr *f) {
- HashTable *instances = &f->instances;
- if (instances->data) {
+ if (fn_has_instances(f)) {
+ HashTable *instances = &f->instances;
/* generate each instance */
Instance **is = instances->data;
for (U64 i = 0; i < instances->cap; ++i) {
diff --git a/decls_cgen.c b/decls_cgen.c
index bd97756..84bab0a 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -164,7 +164,7 @@ static void cgen_fn_decl(CGenerator *g, FnExpr *f, Type *t) {
cgen_nl(g);
return;
}
- if (f->instances.data) {
+ if (fn_has_instances(f)) {
cgen_decls_fn_instances(g, f);
} else {
cgen_single_fn_decl(g, f, 0, 0);
diff --git a/eval.c b/eval.c
index d19f365..796894e 100644
--- a/eval.c
+++ b/eval.c
@@ -69,16 +69,16 @@ static bool val_truthiness(Value v, Type *t) {
-static I64 val_to_i64(Value *v, BuiltinType v_type) {
+static I64 val_to_i64(Value v, BuiltinType v_type) {
switch (v_type) {
- case BUILTIN_I8: return (I64)v->i8;
- case BUILTIN_I16: return (I64)v->i16;
- case BUILTIN_I32: return (I64)v->i32;
- case BUILTIN_I64: return (I64)v->i64;
- case BUILTIN_U8: return (I64)v->u8;
- case BUILTIN_U16: return (I64)v->u16;
- case BUILTIN_U32: return (I64)v->u32;
- case BUILTIN_U64: return (I64)v->u64;
+ case BUILTIN_I8: return (I64)v.i8;
+ case BUILTIN_I16: return (I64)v.i16;
+ case BUILTIN_I32: return (I64)v.i32;
+ case BUILTIN_I64: return (I64)v.i64;
+ case BUILTIN_U8: return (I64)v.u8;
+ case BUILTIN_U16: return (I64)v.u16;
+ case BUILTIN_U32: return (I64)v.u32;
+ case BUILTIN_U64: return (I64)v.u64;
default: break;
}
assert(0);
@@ -87,8 +87,8 @@ static I64 val_to_i64(Value *v, BuiltinType v_type) {
-static U64 val_to_u64(Value *v, BuiltinType v_type) {
- if (v_type == BUILTIN_U64) return v->u64;
+static U64 val_to_u64(Value v, BuiltinType v_type) {
+ if (v_type == BUILTIN_U64) return v.u64;
return (U64)val_to_i64(v, v_type);
}
@@ -628,7 +628,7 @@ static Status eval_expr_ptr_at_index(Evaluator *ev, Expression *e, void **ptr, T
if (rtype->builtin == BUILTIN_U64) {
i = index.u64;
} else {
- I64 signed_index = val_to_i64(&index, rtype->builtin);
+ I64 signed_index = val_to_i64(index, rtype->builtin);
if (signed_index < 0) {
err_print(e->where, "Array or slice out of bounds (index = %ld)\n", (long)signed_index);
return false;
@@ -936,7 +936,7 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value
switch (op) {
case BINARY_ADD:
if (lhs_type->kind == TYPE_PTR) {
- out->ptr = (char *)lhs.ptr + val_to_i64(&rhs, rhs_type->builtin)
+ out->ptr = (char *)lhs.ptr + val_to_i64(rhs, rhs_type->builtin)
* (I64)compiler_sizeof(lhs_type->ptr);
} else {
eval_binary_op_nums_only(+);
@@ -944,7 +944,7 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value
break;
case BINARY_SUB:
if (lhs_type->kind == TYPE_PTR) {
- out->ptr = (char *)lhs.ptr - val_to_i64(&rhs, rhs_type->builtin)
+ out->ptr = (char *)lhs.ptr - val_to_i64(rhs, rhs_type->builtin)
* (I64)compiler_sizeof(lhs_type->ptr);
} else {
eval_binary_op_nums_only(-);
@@ -987,12 +987,12 @@ static Value val_zero(Type *t) {
return val;
}
-static bool val_is_nonnegative(Value *v, Type *t) {
+static bool val_is_nonnegative(Value v, Type *t) {
switch (t->builtin) {
case BUILTIN_BOOL: assert(0); return false;
- case BUILTIN_CHAR: return v->charv >= 0;
- case BUILTIN_F32: return v->f32 >= 0;
- case BUILTIN_F64: return v->f64 >= 0;
+ case BUILTIN_CHAR: return v.charv >= 0;
+ case BUILTIN_F32: return v.f32 >= 0;
+ case BUILTIN_F64: return v.f64 >= 0;
default: break;
}
if (!type_builtin_is_signed(t->builtin))
@@ -1271,7 +1271,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
if (fo->range.stepval)
stepval = *fo->range.stepval;
Value x = from;
- bool step_is_negative = fo->range.stepval && !val_is_nonnegative(&stepval, &fo->type);
+ bool step_is_negative = fo->range.stepval && !val_is_nonnegative(stepval, &fo->type);
if (index_val) index_val->i64 = 0;
while (1) {
if (fo->range.to) {
@@ -1391,7 +1391,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
Value n;
if (!eval_expr(ev, e->new.n, &n))
return false;
- U64 n64 = val_to_u64(&n, e->new.n->type.builtin);
+ U64 n64 = val_to_u64(n, e->new.n->type.builtin);
v->slice.data = err_calloc(n64, compiler_sizeof(&e->new.type));
v->slice.n = (I64)n64;
} else {
@@ -1521,7 +1521,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
if (!eval_expr(ev, s->from, &fromv))
return false;
assert(s->from->type.kind == TYPE_BUILTIN);
- from = val_to_u64(&fromv, s->from->type.builtin);
+ from = val_to_u64(fromv, s->from->type.builtin);
} else {
from = 0;
}
@@ -1530,7 +1530,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
if (!eval_expr(ev, s->to, &tov))
return false;
assert(s->to->type.kind == TYPE_BUILTIN);
- to = val_to_u64(&tov, s->to->type.builtin);
+ to = val_to_u64(tov, s->to->type.builtin);
} else {
to = n;
}
diff --git a/test.toc b/test.toc
index a6d1b14..0004af0 100644
--- a/test.toc
+++ b/test.toc
@@ -1,54 +1,9 @@
-#include "io.toc";
+// #include "std/io.toc";
-Arr ::= struct (t :: Type) {
- data: []t;
- len, cap: int;
-};
-
-
-arr_add ::= fn(t ::=, a : &Arr(t), x : t) {
- if a.len >= a.cap {
- a.cap = a.cap * 2 + 2;
- new_data := new(t, a.cap);
- for i := 0..a.len-1 {
- new_data[i] = a.data[i];
- }
- a.data = new_data;
- }
- a.data[a.len] = x;
- a.len += 1;
-};
-
-square ::= fn(t ::=, x : t) t {
- a : Arr(t);
- for i := 1,2..2*x-1 {
- arr_add(&a, i);
- };
- sum := 0 as t;
- for i := 0..a.len-1 {
- sum += a.data[i];
- };
- sum
-};
-
-
-// ArrInt ::= Arr(int);
-
-inc ::= fn(t ::=, x : t) t {
- x + 1
+f ::= fn(x :: ..) int {
+ x[0]
};
main ::= fn() {
- arr : Arr(int);
- farr : Arr(float);
- for i := 1..100 {
- arr_add(&arr, inc(square(i)));
- arr_add(&farr, inc(square(i as float)));
- }
- for i := 0..arr.len - 1 {
- puti(arr.data[i]);
- }
- for i := 0..farr.len - 1 {
- puti(farr.data[i] as int);
- }
-};
+ f(1,2,3);
+}; \ No newline at end of file
diff --git a/types.c b/types.c
index b11f39b..423ac2a 100644
--- a/types.c
+++ b/types.c
@@ -755,14 +755,14 @@ static Status type_resolve(Typer *tr, Type *t, Location where) {
U64 size;
if (type_builtin_is_signed(n_expr->type.builtin)) {
- I64 ssize = val_to_i64(&val, n_expr->type.builtin);
+ I64 ssize = val_to_i64(val, n_expr->type.builtin);
if (ssize < 0) {
err_print(t->arr.n_expr->where, "Negative array length (" I64_FMT ")", ssize);
return false;
}
size = (U64)ssize;
} else {
- size = val_to_u64(&val, n_expr->type.builtin);
+ size = val_to_u64(val, n_expr->type.builtin);
}
t->arr.n = (U64)size;
if (!type_resolve(tr, t->arr.of, where))
@@ -1935,6 +1935,7 @@ static Status types_expr(Typer *tr, Expression *e) {
goto ret;
}
fn_decl = val.fn;
+ if (has_varargs) fn_decl->flags |= FN_EXPR_HAS_VARARGS;
}
@@ -2028,7 +2029,7 @@ static Status types_expr(Typer *tr, Expression *e) {
original_fn = fn;
fn_copy = typer_malloc(tr, sizeof *fn_copy);
Copier cop = copier_create(tr->allocr, fn->body.parent);
- copy_fn_expr(&cop, fn_copy, fn, has_varargs ? COPY_FN_EXPR_DONT_COPY_HEADER : 0);
+ copy_fn_expr(&cop, fn_copy, fn, 0);
}
if (fn_type->constness) {
@@ -2121,10 +2122,19 @@ static Status types_expr(Typer *tr, Expression *e) {
for (i = 0; i < nparams; ++i) {
bool should_be_evald = arg_is_const(&arg_exprs[i], fn_type->constness[i]);
if (i == nparams-1 && has_varargs) {
- param_decl->val.varargs = NULL;
-
- if (should_be_evald) {
- /* TODO */
+ /* set value of varargs param decl */
+ VarArg *varargs = NULL;
+ arr_set_lena(&varargs, nvarargs, tr->allocr);
+ Declaration *varargs_param = arr_last(fn_copy->params);
+ varargs_param->val.varargs = varargs;
+
+ for (int v = 0; v < (int)nvarargs; ++v) {
+ Expression *arg = &arg_exprs[v+order[nparams-1]];
+ VarArg *vararg = &varargs[v];
+
+ if (varargs_param->flags & DECL_IS_CONST)
+ vararg->val = arg->val;
+ vararg->type = &arg->type;
}
} else if (should_be_evald) {
if (!order || order[i] != -1) {
@@ -2291,25 +2301,6 @@ static Status types_expr(Typer *tr, Expression *e) {
arr_remove_lasta(&err_ctx->instance_stack, tr->allocr);
if (!success) return false;
arr_cleara(&table_index_type.tuple, tr->allocr);
-
- if (has_varargs) {
- /* set value of varargs param decl */
- VarArg *varargs = NULL;
- arr_set_lena(&varargs, nvarargs, tr->allocr);
- Declaration *varargs_param = arr_last(fn_copy->params);
- varargs_param->val.varargs = varargs;
-
- for (int i = 0; i < (int)nvarargs; ++i) {
- Expression *arg = &arg_exprs[i+order[nparams-1]];
- VarArg *vararg = &varargs[i];
-
- if (varargs_param->flags & DECL_IS_CONST)
- vararg->val = arg->val;
- vararg->type = &arg->type;
-
- }
-
- }
}
}
free(order);
@@ -2592,7 +2583,7 @@ static Status types_expr(Typer *tr, Expression *e) {
break;
}
case BINARY_AT_INDEX:
- if ((lhs_type->kind == TYPE_ARR || lhs_type->kind == TYPE_SLICE) &&
+ if ((lhs_type->kind == TYPE_ARR || lhs_type->kind == TYPE_SLICE || type_is_builtin(lhs_type, BUILTIN_VARARGS)) &&
(rhs_type->kind != TYPE_BUILTIN || !type_builtin_is_numerical(rhs_type->builtin))) {
err_print(e->where, "The index of an array must be a builtin numerical type.");
return false;
@@ -2642,34 +2633,63 @@ static Status types_expr(Typer *tr, Expression *e) {
} break;
case TYPE_BUILTIN:
if (lhs_type->builtin == BUILTIN_NMS) {
- if (!type_is_slicechar(rhs_type))
+ /* allow accessing namespace members with a string */
+ if (!type_is_slicechar(rhs_type)) {
+ char *s = type_to_str(rhs_type);
+ err_print(e->where, "Expected a string for namsepace member access with [], but got type %s.", s);
+ return false;
+ }
+
+ Value nms_val;
+ if (!eval_expr(tr->evalr, lhs, &nms_val))
+ return false;
+ Namespace *nms = nms_val.nms;
+ lhs->kind = EXPR_VAL;
+ lhs->val.nms = nms;
+
+ Value member_name;
+ if (!eval_expr(tr->evalr, rhs, &member_name)) return false;
+ e->binary.op = BINARY_DOT;
+ e->binary.rhs->kind = EXPR_IDENT;
+ e->binary.rhs->ident = ident_get_with_len(&nms->body.idents, member_name.slice.data, (size_t)member_name.slice.n);
+ if (!type_of_ident(tr, rhs->where, &e->binary.rhs->ident, t)) {
+ return false;
+ }
+ break;
+ } else if (lhs_type->builtin == BUILTIN_VARARGS) {
+ assert(lhs->kind == EXPR_IDENT);
+ assert(lhs->ident->decl_kind == IDECL_DECL);
+ Declaration *decl = lhs->ident->decl;
+ assert(decl->flags & DECL_IS_PARAM);
+ Value index_val;
+ if (!eval_expr(tr->evalr, rhs, &index_val))
+ return false;
+ /* NOTE: rhs->type was checked above */
+ I64 i = val_to_i64(index_val, rhs->type.builtin);
+ VarArg *varargs = decl->val.varargs;
+ if (i < 0 || i >= (I64)arr_len(varargs)) {
+ err_print(e->where, "Index out of bounds for varargs access (index = " I64_FMT ", length = %lu).", i, (unsigned long)arr_len(varargs));
+ return 0;
+ }
+ if (decl->flags & DECL_IS_CONST) {
+ /* replace with value */
+ VarArg *vararg = &varargs[i];
+ e->kind = EXPR_VAL;
+ e->type = *vararg->type;
+ copy_val(tr->allocr, &e->val, &vararg->val, &e->type);
+
+ } else {
+ /* TODO */
+ }
break;
}
/* fallthrough */
default: {
- /* allow accessing namespace members with a string */
- if (!type_is_slicechar(rhs_type)) {
- char *s = type_to_str(rhs_type);
- err_print(e->where, "Expected a string for namsepace member access with [], but got type %s.", s);
- return false;
- }
-
- Value nms_val;
- if (!eval_expr(tr->evalr, lhs, &nms_val))
- return false;
- Namespace *nms = nms_val.nms;
- lhs->kind = EXPR_VAL;
- lhs->val.nms = nms;
-
- Value member_name;
- if (!eval_expr(tr->evalr, rhs, &member_name)) return false;
- e->binary.op = BINARY_DOT;
- e->binary.rhs->kind = EXPR_IDENT;
- e->binary.rhs->ident = ident_get_with_len(&nms->body.idents, member_name.slice.data, (size_t)member_name.slice.n);
- if (!type_of_ident(tr, rhs->where, &e->binary.rhs->ident, t)) {
- return false;
- }
- } break;
+ char *s = type_to_str(lhs_type);
+ err_print(e->where, "Cannot subscript type %s", s);
+ free(s);
+ return false;
+ }
}
break;
case BINARY_DOT: {