aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-04-09 12:59:07 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-04-09 12:59:07 +0300
commit451111dc51df69580d04c9965f70531f50e3d509 (patch)
tree379a7123f2588f149021c896118ce0ded4f5a9cc /src
parentf86cb1e9ec6cb562d1d0ebf4b0fd7119296ff10d (diff)
downloadek-451111dc51df69580d04c9965f70531f50e3d509.tar.gz
ek-451111dc51df69580d04c9965f70531f50e3d509.zip
add initial ufcs checks
Diffstat (limited to 'src')
-rw-r--r--src/actualize.c106
-rw-r--r--src/ast.c81
-rw-r--r--src/compiler.c4
-rw-r--r--src/debug.c4
-rw-r--r--src/parser.y2
5 files changed, 86 insertions, 111 deletions
diff --git a/src/actualize.c b/src/actualize.c
index dc9fe1d..7d30a0f 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -347,6 +347,8 @@ static void set_type(struct ast *node, struct type *type)
node->t = clone_type_list(type);
}
+/* important to keep in mind that this does not maintain list state, must be
+ * done elsewhere */
static void replace_type(struct type *t, struct type *r)
{
/* free strings before they get overwritten */
@@ -836,11 +838,52 @@ static int actualize_macro_expand(struct act_state *state,
}
free(macro_expand_id(macro_expand));
- *macro_expand = *body;
+ replace_ast(macro_expand, body);
/* actualize the new content */
return actualize(state, scope, macro_expand);
}
+static int simplify_refderef(struct act_state *state, struct scope *scope, struct ast *n)
+{
+ if (!is_unop(n))
+ return 0;
+
+ struct ast *e = unop_expr(n);
+ if (n->k == AST_REF && e->k == AST_DEREF) {
+ replace_ast(n, unop_expr(e));
+ return simplify_refderef(state, scope, n);
+ }
+
+ if (n->k == AST_DEREF && e->k == AST_REF) {
+ replace_ast(n, unop_expr(e));
+ return simplify_refderef(state, scope, n);
+ }
+
+ return 0;
+}
+
+static int maybe_ufcs(struct act_state *state, struct scope *scope, struct ast *call)
+{
+ assert(call->k == AST_CALL);
+ struct ast *dot = call_expr(call);
+ if (dot->k != AST_DOT)
+ return 0;
+
+ struct ast *expr = dot_expr(dot);
+ call_expr(call) = gen_fetch(dot_id(dot), clone_type(expr->t), dot->loc);
+
+ /* hard core type */
+ struct ast *ref = gen_unop(AST_REF, expr, dot->loc);
+ ref->t = tgen_ptr(clone_type(expr->t), dot->loc);
+ ref->scope = scope;
+
+ if (simplify_refderef(state, scope, ref))
+ return -1;
+
+ ast_prepend(call_args(call), ref);
+ return 0;
+}
+
static int actualize_call(struct act_state *state,
struct scope *scope, struct ast *call)
{
@@ -861,6 +904,9 @@ static int actualize_call(struct act_state *state,
return -1;
}
+ if (maybe_ufcs(state, scope, call))
+ return -1;
+
struct type *callable = expr->t;
struct type *ptypes = callable_ptypes(callable);
struct ast *arg = call_args(call);
@@ -935,13 +981,16 @@ static int actualize_proc(struct act_state *state,
/* actualize body */
new_state.cur_proc = proc;
- if (actualize(&new_state, proc->scope, proc_body(proc)))
+ if (actualize(&new_state, proc->scope, proc_body(proc))) {
+ destroy_act_state(&new_state);
return -1;
+ }
if (!act_flags(&new_state, ACT_HAS_RETURN)) {
if (!is_void(proc_rtype(proc))) {
semantic_error(scope->fctx, proc,
"no return with non-void return type");
+ destroy_act_state(&new_state);
return -1;
}
@@ -955,12 +1004,15 @@ static int actualize_proc(struct act_state *state,
/* TODO: something more sophisticated than this */
semantic_warn(scope->fctx, proc,
"unable to determine explicit return for all branches");
+ destroy_act_state(&new_state);
return -1;
}
warn_unused_labels(&new_state, scope);
- if (undefined_gotos(&new_state, scope))
+ if (undefined_gotos(&new_state, scope)) {
+ destroy_act_state(&new_state);
return -1;
+ }
/* if we're main, don't mangle the entry point */
char *id = proc_id(proc);
@@ -968,6 +1020,7 @@ static int actualize_proc(struct act_state *state,
ast_set_flags(proc, AST_FLAG_NOMANGLE);
/* we have successfully actualized the procedure */
+ destroy_act_state(&new_state);
return 0;
}
@@ -1142,8 +1195,6 @@ static int actualize_tid(struct act_state *state, struct scope *scope, struct ty
return 0;
}
- struct src_loc l = t->loc;
-
struct ast *def = file_scope_find_type(scope, t->id);
if (!def) {
type_error(scope->fctx, t, "no such type");
@@ -1200,6 +1251,7 @@ static int actualize_callable(struct act_state *state, struct scope *scope, stru
static int actualize_i27(struct act_state *state, struct scope *scope, struct type *t)
{
+ UNUSED(state);
/* not much to do */
if (t->d)
return 0;
@@ -1207,7 +1259,7 @@ static int actualize_i27(struct act_state *state, struct scope *scope, struct ty
struct ast *def = file_scope_find_type(scope, "i27");
if (!def) {
error("missing definition of type 'i27'");
- return NULL;
+ return -1;
}
t->d = def;
@@ -1216,6 +1268,7 @@ static int actualize_i27(struct act_state *state, struct scope *scope, struct ty
static int actualize_i9(struct act_state *state, struct scope *scope, struct type *t)
{
+ UNUSED(state);
/* not much to do */
if (t->d)
return 0;
@@ -1223,7 +1276,7 @@ static int actualize_i9(struct act_state *state, struct scope *scope, struct typ
struct ast *def = file_scope_find_type(scope, "i9");
if (!def) {
error("missing definition of type 'i9'");
- return NULL;
+ return -1;
}
t->d = def;
@@ -1232,6 +1285,7 @@ static int actualize_i9(struct act_state *state, struct scope *scope, struct typ
static int actualize_bool(struct act_state *state, struct scope *scope, struct type *t)
{
+ UNUSED(state);
/* not much to do */
if (t->d)
return 0;
@@ -1239,7 +1293,7 @@ static int actualize_bool(struct act_state *state, struct scope *scope, struct t
struct ast *def = file_scope_find_type(scope, "bool");
if (!def) {
error("missing definition of type 'bool'");
- return NULL;
+ return -1;
}
t->d = def;
@@ -1693,6 +1747,7 @@ static void actualize_goto_defer(struct ast *got, struct ast *label)
static int actualize_goto(struct act_state *state, struct scope *scope,
struct ast *node)
{
+ UNUSED(scope);
assert(node->k == AST_GOTO);
push_goto(state, node);
@@ -1726,6 +1781,7 @@ static void actualize_goto_defers(struct act_state *state,
static int actualize_label(struct act_state *state, struct scope *scope,
struct ast *node)
{
+ UNUSED(scope);
assert(node->k == AST_LABEL);
struct ast *prev = find_label(state, label_id(node));
if (prev) {
@@ -1769,12 +1825,18 @@ static int actualize_unop(struct act_state *state,
set_type(node, ptr_base(type));
assert(node->t);
+ if (simplify_refderef(state, scope, node))
+ return -1;
+
break;
}
case AST_REF: {
/** @todo array pointer decay? */
node->t = tgen_ptr(clone_type(expr->t), node->loc);
+ if (simplify_refderef(state, scope, node))
+ return -1;
+
break;
}
@@ -1881,6 +1943,7 @@ static int replace_type_id(struct ast *nodes, char *id,
static int actualize_trait(struct act_state *state, struct scope *scope,
struct ast *node)
{
+ UNUSED(scope);
assert(node->k == AST_TRAIT_DEF);
foreach_node(n, trait_body(node)) {
/* there's really only prodcedure body actualization left I
@@ -1903,6 +1966,7 @@ static int actualize_trait(struct act_state *state, struct scope *scope,
static int actualize_struct(struct act_state *state,
struct scope *scope, struct ast *node)
{
+ UNUSED(scope);
assert(node->k == AST_STRUCT_DEF);
foreach_node(n, struct_body(node)) {
/* there's really only prodcedure body actualization left I
@@ -1922,35 +1986,9 @@ static int actualize_struct(struct act_state *state,
return 0;
}
-/* could maybe be renamed, but essentially dot in copper works as either
- * -> or . in C, so allow structures or traits and single level pointers to
- * structures or traits. */
-static int has_members(struct type *type)
-{
- /* most likely */
- if (type->k == TYPE_STRUCT)
- return 1;
-
- if (type->k == TYPE_TRAIT)
- return 1;
-
- if (type->k == TYPE_CONSTRUCT)
- return 1;
-
- return 0;
-}
-
static int actualize_dot(struct act_state *state,
struct scope *scope, struct ast *node)
{
- /* TODO: handle enums as well, idea is something like
- * enum whatever {A_FLAG}
- * ...
- * whatever.A_FLAG
- *
- * possibly also if the expr is of type whatever then .A_FLAG just gets
- * the corresponding constant?
- **/
assert(node->k == AST_DOT);
struct ast *expr = dot_expr(node);
if (actualize(state, scope, expr))
diff --git a/src/ast.c b/src/ast.c
index 49010c6..6677513 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -161,6 +161,12 @@ void ast_append(struct ast *list, struct ast *elem)
cur->n = elem;
}
+struct ast *ast_prepend(struct ast *list, struct ast *elem)
+{
+ elem->n = list;
+ return elem;
+}
+
void type_append(struct type *list, struct type *elem)
{
struct type *cur = list;
@@ -170,48 +176,10 @@ void type_append(struct type *list, struct type *elem)
cur->n = elem;
}
-static const char *binop_symbol(enum ast_kind op)
+struct type *type_prepend(struct type *list, struct type *elem)
{
- switch (op) {
- case AST_ADD: return "+";
- case AST_SUB: return "-";
- case AST_MUL: return "*";
- case AST_DIV: return "/";
- case AST_REM: return "%";
- case AST_LOR: return "||";
- case AST_LAND: return "&&";
- case AST_LSHIFT: return "<<";
- case AST_RSHIFT: return ">>";
- case AST_ASSIGN_ADD: return "+=";
- case AST_ASSIGN_SUB: return "-=";
- case AST_ASSIGN_MUL: return "*=";
- case AST_ASSIGN_DIV: return "/=";
- case AST_ASSIGN_REM: return "%=";
- case AST_ASSIGN_LSHIFT: return "<<=";
- case AST_ASSIGN_RSHIFT: return ">>=";
- case AST_LT: return "<";
- case AST_GT: return ">";
- case AST_LE: return "<=";
- case AST_GE: return ">=";
- case AST_NE: return "!=";
- case AST_EQ: return "==";
- default:
- }
-
- return "UNKNOWN";
-}
-
-static const char *unop_symbol(enum ast_kind op)
-{
- switch (op) {
- case AST_NEG: return "-";
- case AST_LNOT: return "!";
- case AST_REF: return "&";
- case AST_DEREF: return "*";
- default:
- }
-
- return "UNKNOWN";
+ elem->n = list;
+ return elem;
}
static void dump(int depth, const char *fmt, ...)
@@ -227,37 +195,6 @@ static void dump(int depth, const char *fmt, ...)
va_end(args);
}
-static void dump_flags(struct ast *node)
-{
- if (node->scope)
- printf(" %zu:", node->scope->number);
-
- enum ast_flags flags = node->f;
- if (flags & AST_FLAG_MUTABLE)
- printf(" MUT");
-
- if (flags & AST_FLAG_CONST)
- printf(" CONST");
-
- if (flags & AST_FLAG_EXTERN)
- printf(" EXTERN");
-
- if (flags & AST_FLAG_VARIADIC)
- printf(" VARIADIC");
-
- if (flags & AST_FLAG_DELAYED)
- printf(" DELAYED");
-
- if (flags & AST_FLAG_PUBLIC)
- printf(" PUB");
-
- if (flags & AST_FLAG_UNTYPED)
- printf(" UNTYPED");
-
- if (flags & AST_FLAG_FALLTHROUGH)
- printf(" FALLTHROUGH");
-}
-
const char *primitive_str(struct type *type)
{
switch (type->k) {
diff --git a/src/compiler.c b/src/compiler.c
index 5aa6787..14a838a 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -47,11 +47,11 @@ static char *read_file(const char *file, FILE *f)
fseek(f, 0, SEEK_SET);
- char *buf = malloc(s + 1);
+ char *buf = malloc((size_t)(s + 1));
if (!buf)
return NULL;
- fread(buf, s + 1, 1, f);
+ fread(buf, (size_t)(s + 1), 1, f);
/* remember terminating null */
buf[s] = 0;
return buf;
diff --git a/src/debug.c b/src/debug.c
index f4b481d..d16aab2 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -73,12 +73,12 @@ static void _issue(struct src_issue issue, const char *fmt, va_list args)
{
/* get start and end of current line in buffer */
const char *line_start = find_lineno(issue.fctx.fbuf,
- issue.loc.first_line);
+ (size_t)issue.loc.first_line);
const char *line_end = strchr(line_start, '\n');
if (!line_end)
line_end = strchr(line_start, 0);
- const int line_len = line_end - line_start;
+ const int line_len = (int)(line_end - line_start);
fprintf(stderr, "%s:%i:%i: %s: ", issue.fctx.fname,
issue.loc.first_line,
diff --git a/src/parser.y b/src/parser.y
index 51d950c..fb137b1 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -283,7 +283,7 @@ binop
unop
: "-" expr { $$ = gen_unop(AST_NEG, $2, src_loc(@$)); }
| "!" expr { $$ = gen_unop(AST_LNOT, $2, src_loc(@$)); }
- | "&" expr { $$ = gen_unop(AST_REF, $2, src_loc(@$)); }
+ | expr "&" { $$ = gen_unop(AST_REF, $1, src_loc(@$)); }
| expr "*" { $$ = gen_unop(AST_DEREF, $1, src_loc(@$)); }
arr_init