mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Global declarations. Starting work on struct initializers, lots of arithmetics now checked correctly. Support 2cc 4cc 8cc
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
module foo;
|
||||
|
||||
int oefk = 1;
|
||||
int bob = 'HELO';
|
||||
|
||||
struct Foo
|
||||
{
|
||||
int i;
|
||||
@@ -10,8 +13,19 @@ struct Bar
|
||||
{
|
||||
Foo foo;
|
||||
Foo* fooPtr;
|
||||
struct bar
|
||||
{
|
||||
int a;
|
||||
}
|
||||
}
|
||||
|
||||
union Xyz
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
}
|
||||
|
||||
|
||||
$if (1)
|
||||
{
|
||||
struct Ogg
|
||||
@@ -29,13 +43,31 @@ $if (1)
|
||||
|
||||
}
|
||||
|
||||
|
||||
func int boo()
|
||||
{
|
||||
Zed zfe;
|
||||
//zfe = { 1, 2 };
|
||||
//Zed zfed = { 1 };
|
||||
int eok = 0;
|
||||
{
|
||||
eok = 2;
|
||||
}
|
||||
eok = eok * 2 + 1 * 2;
|
||||
eok = eok / 2 + 32 / 2;
|
||||
eok = eok % 2 - 32 % 45;
|
||||
|
||||
int de = eok;
|
||||
de++;
|
||||
de = de << 1;
|
||||
de = de >> 1;
|
||||
de = de ^ cast(byte, 1);
|
||||
de = de & 1;
|
||||
de = de | 1;
|
||||
if (de > 100 || de < 10 || de <= 1000 || de >= 1921 || de == 100 || de != 2)
|
||||
{
|
||||
return boo();
|
||||
}
|
||||
switch (eok)
|
||||
{
|
||||
case 1:
|
||||
|
||||
@@ -140,12 +140,10 @@ static inline int codegen_emit_identifier_expr(Context *context, Expr *expr, int
|
||||
return context->unique_index;
|
||||
}
|
||||
|
||||
|
||||
static inline int codegen_emit_const_expr(Context *context, Expr *expr, int indent)
|
||||
static inline void codegen_emit_const_expr_raw(Context *context, Expr *expr)
|
||||
{
|
||||
assert(expr->expr_kind == EXPR_CONST);
|
||||
Type *canonical = expr->type->canonical;
|
||||
INDENT();
|
||||
switch (canonical->type_kind)
|
||||
{
|
||||
case TYPE_POISONED:
|
||||
@@ -155,50 +153,44 @@ static inline int codegen_emit_const_expr(Context *context, Expr *expr, int inde
|
||||
break;
|
||||
case TYPE_BOOL:
|
||||
assert(expr->const_expr.type == CONST_BOOL);
|
||||
PRINTTYPE(expr->type);
|
||||
PRINTF(" _%d = %s;\n", ++context->unique_index, expr->const_expr.b ? "true" : "false");
|
||||
return context->unique_index;
|
||||
PRINTF(expr->const_expr.b ? "true" : "false");
|
||||
return;
|
||||
case TYPE_I8:
|
||||
case TYPE_I16:
|
||||
case TYPE_I32:
|
||||
case TYPE_I64:
|
||||
case TYPE_IXX:
|
||||
assert(expr->const_expr.type == CONST_INT);
|
||||
PRINTTYPE(expr->type);
|
||||
PRINTF(" _%d = (", ++context->unique_index);
|
||||
PRINTF("(");
|
||||
PRINTTYPE(canonical);
|
||||
PRINTF(")");
|
||||
PRINTF("%lld;\n", (long long)expr->const_expr.i);
|
||||
return context->unique_index;
|
||||
PRINTF("%lld", (long long)expr->const_expr.i);
|
||||
return;
|
||||
case TYPE_U8:
|
||||
case TYPE_U16:
|
||||
case TYPE_U32:
|
||||
case TYPE_U64:
|
||||
case TYPE_UXX:
|
||||
assert(expr->const_expr.type == CONST_INT);
|
||||
PRINTTYPE(expr->type);
|
||||
PRINTF(" _%d = (", ++context->unique_index);
|
||||
PRINTF("(");
|
||||
PRINTTYPE(canonical);
|
||||
PRINTF(")");
|
||||
PRINTF("%llu;\n", expr->const_expr.i);
|
||||
return context->unique_index;
|
||||
PRINTF("%llu", (long long)expr->const_expr.i);
|
||||
return;
|
||||
case TYPE_F32:
|
||||
case TYPE_F64:
|
||||
case TYPE_FXX:
|
||||
assert(expr->const_expr.type == CONST_FLOAT);
|
||||
PRINTTYPE(expr->type);
|
||||
PRINTF(" _%d = (", ++context->unique_index);
|
||||
assert(expr->const_expr.type == CONST_INT);
|
||||
PRINTF("(");
|
||||
PRINTTYPE(canonical);
|
||||
PRINTF(")");
|
||||
PRINTF("%Lf;\n", expr->const_expr.f);
|
||||
return context->unique_index;
|
||||
PRINTF("%Lf", expr->const_expr.f);
|
||||
return;
|
||||
case TYPE_POINTER:
|
||||
assert(expr->const_expr.type == CONST_NIL);
|
||||
PRINTTYPE(expr->type);
|
||||
PRINTF(" _%d = ((", ++context->unique_index);
|
||||
PRINTF("((");
|
||||
PRINTTYPE(canonical);
|
||||
PRINTF("0);\n");
|
||||
return context->unique_index;
|
||||
PRINTF("0)");
|
||||
return;
|
||||
case TYPE_STRING:
|
||||
TODO
|
||||
case TYPE_ARRAY:
|
||||
@@ -209,6 +201,17 @@ static inline int codegen_emit_const_expr(Context *context, Expr *expr, int inde
|
||||
}
|
||||
}
|
||||
|
||||
static inline int codegen_emit_const_expr(Context *context, Expr *expr, int indent)
|
||||
{
|
||||
assert(expr->expr_kind == EXPR_CONST);
|
||||
INDENT();
|
||||
PRINTTYPE(expr->type);
|
||||
PRINTF(" _%d = ", ++context->unique_index);
|
||||
codegen_emit_const_expr_raw(context, expr);
|
||||
PRINTF(";\n");
|
||||
return context->unique_index;
|
||||
}
|
||||
|
||||
static inline int codegen_emit_cast_expr(Context *context, Expr *expr, int indent)
|
||||
{
|
||||
int index = codegen_emit_expr(context, expr->expr_cast.expr, indent);
|
||||
@@ -263,14 +266,15 @@ static int codegen_emit_binary_expr(Context *context, Expr *expr, int indent)
|
||||
case TOKEN_NOT_EQUAL:
|
||||
case TOKEN_MOD:
|
||||
case TOKEN_DIV:
|
||||
case TOKEN_AND:
|
||||
case TOKEN_OR:
|
||||
case TOKEN_STAR:
|
||||
return codegen_emit_simple_binary_expr(context, expr, indent);
|
||||
case TOKEN_BIT_OR:
|
||||
case TOKEN_AMP:
|
||||
case TOKEN_BIT_XOR:
|
||||
case TOKEN_SHL:
|
||||
case TOKEN_SHR:
|
||||
TODO
|
||||
return codegen_emit_simple_binary_expr(context, expr, indent);
|
||||
case TOKEN_MULT_ASSIGN:
|
||||
case TOKEN_DIV_ASSIGN:
|
||||
case TOKEN_MINUS_ASSIGN:
|
||||
@@ -830,7 +834,16 @@ static inline void codegen_top_level_decl_header(Context *context, Decl *decl)
|
||||
codegen_top_level_func(context, decl);
|
||||
return;
|
||||
case DECL_VAR:
|
||||
break;
|
||||
if (decl->visibility != VISIBLE_PUBLIC) PRINTF("static ");
|
||||
PRINTTYPE(decl->var.type);
|
||||
PRINTF(" %s", decl->name.string);
|
||||
if (decl->var.init_expr)
|
||||
{
|
||||
PRINTF(" = ");
|
||||
codegen_emit_const_expr_raw(context, decl->var.init_expr);
|
||||
}
|
||||
PRINTF(";\n");
|
||||
return;
|
||||
case DECL_TYPEDEF:
|
||||
TODO
|
||||
case DECL_STRUCT:
|
||||
@@ -873,7 +886,7 @@ static inline void codegen_top_level_decl(Context *context, Decl *decl)
|
||||
codegen_func(context, decl);
|
||||
return;
|
||||
case DECL_VAR:
|
||||
break;
|
||||
return;
|
||||
case DECL_ENUM_CONSTANT:
|
||||
break;
|
||||
case DECL_TYPEDEF:
|
||||
|
||||
@@ -55,6 +55,7 @@ void compiler_compile()
|
||||
diag_reset();
|
||||
parse_file(file);
|
||||
sema_analysis(current_context);
|
||||
if (diagnostics.errors > 0) exit(EXIT_FAILURE);
|
||||
FILE *f = fopen("test.c","w");
|
||||
fprintf(f, "#include <stdbool.h>\n#include <stdint.h>\n");
|
||||
current_context->codegen_output = f;
|
||||
|
||||
@@ -600,6 +600,7 @@ typedef struct _Context
|
||||
Decl **vars;
|
||||
Decl **ct_ifs;
|
||||
Decl *active_function_for_analysis;
|
||||
Type *left_type_in_assignment;
|
||||
FILE *codegen_output;
|
||||
Decl **last_local;
|
||||
Ast **labels;
|
||||
@@ -620,6 +621,7 @@ extern Decl poisoned_decl;
|
||||
extern Expr poisoned_expr;
|
||||
extern Type poisoned_type;
|
||||
extern Module poisoned_module;
|
||||
extern Diagnostics diagnostics;
|
||||
|
||||
extern Token next_tok;
|
||||
extern Token tok;
|
||||
@@ -726,7 +728,8 @@ Decl *decl_new(DeclKind decl_kind, Token name, Visibility visibility);
|
||||
Decl *decl_new_user_defined_type(Token name, DeclKind decl_type, Visibility visibility);
|
||||
Decl *decl_new_var(Token name, Type *type, VarDeclKind kind, Visibility visibility);
|
||||
static inline bool decl_ok(Decl *decl) { return decl->decl_kind != DECL_POISONED; }
|
||||
static inline Decl *decl_poison(Decl *decl) { decl->decl_kind = DECL_POISONED; decl->resolve_status = RESOLVE_DONE; return decl; }
|
||||
static inline bool decl_poison(Decl *decl) { decl->decl_kind = DECL_POISONED; decl->resolve_status = RESOLVE_DONE; return false; }
|
||||
static inline bool decl_is_struct_type(Decl *decl) { return decl->decl_kind == DECL_UNION || decl->decl_kind == DECL_STRUCT; }
|
||||
static inline DeclKind decl_from_token(TokenType type)
|
||||
{
|
||||
if (type == TOKEN_STRUCT) return DECL_STRUCT;
|
||||
|
||||
@@ -144,17 +144,37 @@ static inline bool sema_expr_analyse_method_ref(Context *context, Expr *expr)
|
||||
TODO
|
||||
}
|
||||
|
||||
|
||||
static inline bool sema_expr_analyse_initializer_list(Context *context, Expr *expr)
|
||||
static inline bool sema_expr_analyse_struct_initializer_list(Context *context, Expr *expr)
|
||||
{
|
||||
TODO
|
||||
}
|
||||
static inline bool sema_expr_analyse_initializer_list(Context *context, Expr *expr)
|
||||
{
|
||||
assert(context->left_type_in_assignment);
|
||||
Type *assigned = context->left_type_in_assignment->canonical;
|
||||
assert(assigned);
|
||||
switch (assigned->type_kind)
|
||||
{
|
||||
case TYPE_USER_DEFINED:
|
||||
if (decl_is_struct_type(assigned->decl)) return sema_expr_analyse_struct_initializer_list(context, expr);
|
||||
break;
|
||||
case TYPE_ARRAY:
|
||||
TODO
|
||||
case TYPE_VARARRAY:
|
||||
TODO
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SEMA_ERROR(expr->loc, "Cannot assign expression to '%s'.", type_to_error_string(context->left_type_in_assignment));
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_sizeof(Context *context, Expr *expr)
|
||||
{
|
||||
TODO
|
||||
}
|
||||
|
||||
|
||||
static inline bool sema_expr_analyse_cast(Context *context, Expr *expr)
|
||||
{
|
||||
Expr *inner = expr->expr_cast.expr;
|
||||
@@ -174,8 +194,25 @@ static inline bool sema_expr_analyse_cast(Context *context, Expr *expr)
|
||||
|
||||
static bool sema_expr_analyse_assign(Context *context, Expr *expr, Expr *left, Expr *right)
|
||||
{
|
||||
if (!sema_analyse_expr(context, left)) return false;
|
||||
|
||||
if (!expr_is_ltype(left))
|
||||
{
|
||||
SEMA_ERROR(left->loc, "Expression is not assignable.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Type *prev_type = context->left_type_in_assignment;
|
||||
context->left_type_in_assignment = left->type;
|
||||
|
||||
bool success = sema_analyse_expr(context, right);
|
||||
|
||||
context->left_type_in_assignment = prev_type;
|
||||
|
||||
if (!success) return false;
|
||||
|
||||
if (!cast(right, left->type, CAST_TYPE_IMPLICIT_ASSIGN)) return false;
|
||||
// Check assignable
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -184,6 +221,14 @@ static inline bool both_const(Expr *left, Expr *right)
|
||||
return left->expr_kind == EXPR_CONST && right->expr_kind == EXPR_CONST;
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_bit_and_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_bit_or_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_bit_xor_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_div_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_add_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_sub_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_mult_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
|
||||
static bool sema_expr_analyse_add(Context *context, Expr *expr, Expr *left, Expr *right)
|
||||
{
|
||||
Type *left_type = left->type->canonical;
|
||||
@@ -228,14 +273,115 @@ static bool sema_expr_analyse_add(Context *context, Expr *expr, Expr *left, Expr
|
||||
expr->type = left->type;
|
||||
return true;
|
||||
}
|
||||
static bool sema_expr_analyse_add_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_sub(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_sub_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
|
||||
static bool sema_expr_analyse_mult(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_mult_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_sub(Context *context, Expr *expr, Expr *left, Expr *right)
|
||||
{
|
||||
Type *left_type = left->type->canonical;
|
||||
Type *right_type = right->type->canonical;
|
||||
if (left_type->type_kind == TYPE_POINTER)
|
||||
{
|
||||
if (right_type->type_kind == TYPE_POINTER)
|
||||
{
|
||||
if (!cast(right, left_type, CAST_TYPE_IMPLICIT)) return false;
|
||||
expr->type = type_isize;
|
||||
return true;
|
||||
}
|
||||
if (!cast_arithmetic(right, left, "-")) return false;
|
||||
expr->type = left->type;
|
||||
return true;
|
||||
}
|
||||
if (!cast_arithmetic(left, right, "-")) return false;
|
||||
if (!cast_arithmetic(right, left, "-")) return false;
|
||||
|
||||
Type *canonical = left->type->canonical;
|
||||
if (!type_is_number(canonical))
|
||||
{
|
||||
SEMA_ERROR(expr->loc, "- is not allowed");
|
||||
return false;
|
||||
}
|
||||
if (both_const(left, right))
|
||||
{
|
||||
switch (left->const_expr.type)
|
||||
{
|
||||
case CONST_INT:
|
||||
expr->const_expr.i = left->const_expr.i - right->const_expr.i;
|
||||
break;
|
||||
case CONST_FLOAT:
|
||||
expr->const_expr.f = left->const_expr.f - right->const_expr.f;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.type = left->const_expr.type;
|
||||
}
|
||||
expr->type = left->type;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_mult(Context *context, Expr *expr, Expr *left, Expr *right)
|
||||
{
|
||||
if (!cast_arithmetic(left, right, "*")) return false;
|
||||
if (!cast_arithmetic(right, left, "*")) return false;
|
||||
|
||||
Type *canonical = left->type->canonical;
|
||||
if (!type_is_number(canonical))
|
||||
{
|
||||
SEMA_ERROR(expr->loc, "* is not allowed");
|
||||
return false;
|
||||
}
|
||||
if (both_const(left, right))
|
||||
{
|
||||
switch (left->const_expr.type)
|
||||
{
|
||||
case CONST_INT:
|
||||
expr->const_expr.i = left->const_expr.i * right->const_expr.i;
|
||||
break;
|
||||
case CONST_FLOAT:
|
||||
expr->const_expr.f = left->const_expr.f * right->const_expr.f;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.type = left->const_expr.type;
|
||||
}
|
||||
expr->type = left->type;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_div(Context *context, Expr *expr, Expr *left, Expr *right)
|
||||
{
|
||||
if (!cast_arithmetic(left, right, "/")) return false;
|
||||
if (!cast_arithmetic(right, left, "/")) return false;
|
||||
|
||||
Type *canonical = left->type->canonical;
|
||||
if (!type_is_number(canonical))
|
||||
{
|
||||
SEMA_ERROR(expr->loc, "/ is not allowed");
|
||||
return false;
|
||||
}
|
||||
if (both_const(left, right))
|
||||
{
|
||||
switch (left->const_expr.type)
|
||||
{
|
||||
case CONST_INT:
|
||||
expr->const_expr.i = left->const_expr.i / right->const_expr.i;
|
||||
break;
|
||||
case CONST_FLOAT:
|
||||
expr->const_expr.f = left->const_expr.f / right->const_expr.f;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.type = left->const_expr.type;
|
||||
}
|
||||
expr->type = left->type;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
switch (left->type)
|
||||
{
|
||||
@@ -261,51 +407,136 @@ static bool sema_expr_analyse_div(Context *context, Expr *expr, Expr *left, Expr
|
||||
expr->const_expr.type = CONST_FLOAT;
|
||||
break;
|
||||
}*/
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_div_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_mod(Context *context, Expr *expr, Expr *left, Expr *right)
|
||||
{
|
||||
if (!cast_arithmetic(left, right, "%")) return false;
|
||||
if (!cast_arithmetic(left, right, "%") || !cast_arithmetic(right, left, "%")) return false;
|
||||
if (!type_is_integer(right->type->canonical) || !type_is_integer(left->type->canonical)) return sema_type_error_on_binop("%", expr);
|
||||
|
||||
if (right->expr_kind == EXPR_CONST)
|
||||
if (right->expr_kind == EXPR_CONST && right->const_expr.i == 0)
|
||||
{
|
||||
if (right->const_expr.i == 0)
|
||||
{
|
||||
SEMA_ERROR(expr->binary_expr.right->loc, "Cannot perform mod by zero.");
|
||||
return false;
|
||||
}
|
||||
if (left->expr_kind == EXPR_CONST)
|
||||
{
|
||||
// TODO negative
|
||||
expr->const_expr.i = left->const_expr.i / right->const_expr.i;
|
||||
expr->type = right->type;
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.type = CONST_INT;
|
||||
}
|
||||
SEMA_ERROR(expr->binary_expr.right->loc, "Cannot perform mod by zero.");
|
||||
return false;
|
||||
}
|
||||
if (left->expr_kind == EXPR_CONST && right->expr_kind == EXPR_CONST)
|
||||
{
|
||||
// TODO negative
|
||||
expr_replace(expr, left);
|
||||
expr->const_expr.i %= right->const_expr.i;
|
||||
return true;
|
||||
}
|
||||
|
||||
expr->type = left->type;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_mod_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
|
||||
static bool sema_expr_analyse_bit_and(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_bit_and_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_bit_or(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_bit_or_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_bit_xor(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_bit_xor_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
#define SEMA_ANALYSE_BIT(op) \
|
||||
{ if (!cast_arithmetic(left, right, #op) || !cast_arithmetic(right, left, #op)) return false; \
|
||||
if (left->type->canonical->type_kind != TYPE_BOOL && !type_is_integer(left->type)) sema_type_error_on_binop(#op, expr); \
|
||||
if (left->expr_kind == EXPR_CONST && right->expr_kind == EXPR_CONST)\
|
||||
{ expr_replace(expr, left); \
|
||||
if (left->const_expr.type == CONST_BOOL) \
|
||||
{ expr->const_expr.b |= right->const_expr.b; } \
|
||||
else { expr->const_expr.i |= expr->const_expr.i; } \
|
||||
return true; } \
|
||||
expr->type = left->type; \
|
||||
return true; }
|
||||
|
||||
static bool sema_expr_analyse_bit_or(Context *context, Expr *expr, Expr *left, Expr *right) SEMA_ANALYSE_BIT(|)
|
||||
static bool sema_expr_analyse_bit_xor(Context *context, Expr *expr, Expr *left, Expr *right) SEMA_ANALYSE_BIT(^)
|
||||
static bool sema_expr_analyse_bit_and(Context *context, Expr *expr, Expr *left, Expr *right) SEMA_ANALYSE_BIT(&)
|
||||
|
||||
static bool sema_expr_analyse_shr(Context *context, Expr *expr, Expr *left, Expr *right)
|
||||
{ TODO }
|
||||
{
|
||||
// Todo: proper handling of signed / unsigned. Proper reduction of constants.
|
||||
if (!type_is_integer(left->type) || !type_is_integer(right->type)) return sema_type_error_on_binop(">>", expr);
|
||||
if (type_is_signed(right->type->canonical))
|
||||
{
|
||||
cast(right, type_long, CAST_TYPE_IMPLICIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
cast(left, type_ulong, CAST_TYPE_IMPLICIT);
|
||||
}
|
||||
if (right->expr_kind == EXPR_CONST)
|
||||
{
|
||||
if (right->const_expr.i > left->type->canonical->builtin.bitsize)
|
||||
{
|
||||
SEMA_ERROR(right->loc, "Rightshift exceeds bitsize of '%s'", type_to_error_string(left->type));
|
||||
return false;
|
||||
}
|
||||
if (left->expr_kind == EXPR_CONST)
|
||||
{
|
||||
expr_replace(expr, left);
|
||||
expr->const_expr.i >>= right->const_expr.i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
expr->type = left->type;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_shl(Context *context, Expr *expr, Expr *left, Expr *right)
|
||||
{
|
||||
// Todo: proper handling of signed / unsigned. Proper reduction of constants.
|
||||
if (!type_is_integer(left->type) || !type_is_integer(right->type)) return sema_type_error_on_binop("<<", expr);
|
||||
if (type_is_signed(right->type->canonical))
|
||||
{
|
||||
cast(right, type_long, CAST_TYPE_IMPLICIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
cast(left, type_ulong, CAST_TYPE_IMPLICIT);
|
||||
}
|
||||
if (right->expr_kind == EXPR_CONST)
|
||||
{
|
||||
if (right->const_expr.i > left->type->canonical->builtin.bitsize)
|
||||
{
|
||||
SEMA_ERROR(right->loc, "Leftshift exceeds bitsize of '%s'", type_to_error_string(left->type));
|
||||
return false;
|
||||
}
|
||||
if (left->expr_kind == EXPR_CONST)
|
||||
{
|
||||
expr_replace(expr, left);
|
||||
expr->const_expr.i <<= right->const_expr.i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
expr->type = left->type;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_shr_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_shl(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_shl_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
|
||||
static bool sema_expr_analyse_and(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_and(Context *context, Expr *expr, Expr *left, Expr *right)
|
||||
{
|
||||
if (!cast(left, type_bool, CAST_TYPE_IMPLICIT)) return false;
|
||||
if (!cast(right, type_bool, CAST_TYPE_IMPLICIT)) return false;
|
||||
if (both_const(left, right))
|
||||
{
|
||||
expr_replace(expr, left);
|
||||
expr->const_expr.b &= right->const_expr.b;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_or(Context *context, Expr *expr, Expr *left, Expr *right)
|
||||
{
|
||||
if (!cast(left, type_bool, CAST_TYPE_IMPLICIT)) return false;
|
||||
if (!cast(right, type_bool, CAST_TYPE_IMPLICIT)) return false;
|
||||
if (both_const(left, right))
|
||||
{
|
||||
expr_replace(expr, left);
|
||||
expr->const_expr.b |= right->const_expr.b;
|
||||
}
|
||||
expr->type = type_bool;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_and_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_or(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
static bool sema_expr_analyse_or_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
|
||||
|
||||
#define SEMA_ANALYSE_CMP(op) { \
|
||||
@@ -516,9 +747,17 @@ static inline bool sema_expr_analyse_binary(Context *context, Expr *expr)
|
||||
Expr *left = expr->binary_expr.left;
|
||||
Expr *right = expr->binary_expr.right;
|
||||
|
||||
// Special handling due to initalizer lists
|
||||
if (expr->binary_expr.operator == TOKEN_EQ)
|
||||
{
|
||||
return sema_expr_analyse_assign(context, expr, left, right);
|
||||
}
|
||||
|
||||
if (!sema_analyse_expr(context, left)) return false;
|
||||
if (!sema_analyse_expr(context, right)) return false;
|
||||
|
||||
assert(left->type);
|
||||
assert(right->type);
|
||||
return BINOP_ANALYSIS[expr->binary_expr.operator](context, expr, left, right);
|
||||
}
|
||||
|
||||
@@ -565,7 +804,7 @@ static inline bool sema_expr_analyse_type(Context *context, Expr *expr)
|
||||
|
||||
|
||||
static ExprBinopAnalysis BINOP_ANALYSIS[TOKEN_EOF] = {
|
||||
[TOKEN_EQ] = &sema_expr_analyse_assign,
|
||||
[TOKEN_EQ] = NULL, // Explicitly dispatched
|
||||
[TOKEN_STAR] = &sema_expr_analyse_mult,
|
||||
[TOKEN_MULT_ASSIGN] = &sema_expr_analyse_mult_assign,
|
||||
[TOKEN_PLUS] = &sema_expr_analyse_add,
|
||||
@@ -578,7 +817,7 @@ static ExprBinopAnalysis BINOP_ANALYSIS[TOKEN_EOF] = {
|
||||
[TOKEN_MOD_ASSIGN] = &sema_expr_analyse_mod_assign,
|
||||
[TOKEN_AND] = &sema_expr_analyse_and,
|
||||
[TOKEN_AND_ASSIGN] = &sema_expr_analyse_and_assign,
|
||||
[TOKEN_OR] = &sema_expr_analyse_bit_or,
|
||||
[TOKEN_OR] = &sema_expr_analyse_or,
|
||||
[TOKEN_OR_ASSIGN] = &sema_expr_analyse_or_assign,
|
||||
[TOKEN_AMP] = &sema_expr_analyse_bit_and,
|
||||
[TOKEN_BIT_AND_ASSIGN] = &sema_expr_analyse_bit_and_assign,
|
||||
|
||||
@@ -12,6 +12,7 @@ static Expr *parse_expr(void);
|
||||
static Expr *parse_paren_expr(void);
|
||||
static Expr *parse_precedence(Precedence precedence);
|
||||
static Expr *parse_initializer_list(void);
|
||||
static Expr *parse_initializer(void);
|
||||
static bool parse_type_or_expr(Expr **exprPtr, Type **typePtr);
|
||||
static Decl *parse_top_level(void);
|
||||
|
||||
@@ -245,7 +246,7 @@ static inline Type *parse_base_type(void)
|
||||
CONSUME_OR(TOKEN_LPAREN, &poisoned_type);
|
||||
{
|
||||
type = type_new(TYPE_EXPRESSION);
|
||||
type->unresolved_type_expr = TRY_EXPR_OR(parse_expr(), &poisoned_type);
|
||||
type->unresolved_type_expr = TRY_EXPR_OR(parse_initializer(), &poisoned_type);
|
||||
}
|
||||
EXPECT_OR(TOKEN_RPAREN, &poisoned_type);
|
||||
break;
|
||||
@@ -461,7 +462,7 @@ static inline Decl *parse_decl_after_type(bool local, Type *type)
|
||||
return &poisoned_decl;
|
||||
}
|
||||
advance_and_verify(TOKEN_EQ);
|
||||
decl->var.init_expr = TRY_EXPR_OR(parse_expr(), &poisoned_decl);
|
||||
decl->var.init_expr = TRY_EXPR_OR(parse_initializer(), &poisoned_decl);
|
||||
decl = NULL;
|
||||
if (try_consume(TOKEN_COMMA)) continue;
|
||||
return main_decl;
|
||||
@@ -949,7 +950,6 @@ static inline Ast* parse_ct_if_stmt(void)
|
||||
|
||||
static inline Ast* parse_ct_each_stmt(void)
|
||||
{
|
||||
LOG_FUNC
|
||||
|
||||
TODO
|
||||
}
|
||||
@@ -1620,7 +1620,7 @@ static inline Decl *parse_const_declaration(Visibility visibility)
|
||||
|
||||
CONSUME_OR(TOKEN_EQ, &poisoned_decl);
|
||||
|
||||
decl->var.init_expr = TRY_EXPR_OR(parse_expr(), &poisoned_decl);
|
||||
decl->var.init_expr = TRY_EXPR_OR(parse_initializer(), &poisoned_decl);
|
||||
|
||||
CONSUME_OR(TOKEN_EOS, &poisoned_decl);
|
||||
return decl;
|
||||
@@ -1637,7 +1637,6 @@ static inline Decl *parse_const_declaration(Visibility visibility)
|
||||
*/
|
||||
static inline Decl *parse_global_declaration(Visibility visibility)
|
||||
{
|
||||
|
||||
Type *type = TRY_TYPE_OR(parse_type_expression(), &poisoned_decl);
|
||||
|
||||
Decl *decl = decl_new_var(tok, type, VARDECL_GLOBAL, visibility);
|
||||
@@ -1646,8 +1645,9 @@ static inline Decl *parse_global_declaration(Visibility visibility)
|
||||
|
||||
if (try_consume(TOKEN_EQ))
|
||||
{
|
||||
decl->var.init_expr = TRY_EXPR_OR(parse_expr(), &poisoned_decl);
|
||||
decl->var.init_expr = TRY_EXPR_OR(parse_initializer(), &poisoned_decl);
|
||||
}
|
||||
TRY_CONSUME_EOS_OR(&poisoned_decl);
|
||||
return decl;
|
||||
}
|
||||
|
||||
@@ -1859,7 +1859,6 @@ static inline Ast *parse_generics_statements(void)
|
||||
*/
|
||||
static inline Decl *parse_generics_declaration(Visibility visibility)
|
||||
{
|
||||
LOG_FUNC
|
||||
advance_and_verify(TOKEN_GENERIC);
|
||||
Type *rtype = NULL;
|
||||
if (tok.type != TOKEN_IDENT)
|
||||
@@ -1933,8 +1932,6 @@ static inline Decl *parse_generics_declaration(Visibility visibility)
|
||||
*/
|
||||
static inline bool parse_param_decl(Decl *parent, Decl*** parameters, bool type_only)
|
||||
{
|
||||
LOG_FUNC
|
||||
|
||||
Type *type = TRY_TYPE_OR(parse_type_expression(), false);
|
||||
Decl *param = decl_new_var(tok, type, VARDECL_PARAM, parent->visibility);
|
||||
|
||||
@@ -1952,7 +1949,7 @@ static inline bool parse_param_decl(Decl *parent, Decl*** parameters, bool type_
|
||||
}
|
||||
if (name && try_consume(TOKEN_EQ))
|
||||
{
|
||||
param->var.init_expr = TRY_EXPR_OR(parse_expr(), false);
|
||||
param->var.init_expr = TRY_EXPR_OR(parse_initializer(), false);
|
||||
}
|
||||
if (param->name.string)
|
||||
{
|
||||
@@ -2073,7 +2070,6 @@ static inline bool parse_opt_parameter_type_list(Decl *decl, FunctionSignature *
|
||||
*/
|
||||
static inline bool parse_func_typedef(Decl *decl, Visibility visibility)
|
||||
{
|
||||
LOG_FUNC
|
||||
decl->typedef_decl.is_func = true;
|
||||
advance_and_verify(TOKEN_FUNC);
|
||||
Type *type = TRY_TYPE_OR(parse_type_expression(), false);
|
||||
@@ -2088,7 +2084,6 @@ static inline bool parse_func_typedef(Decl *decl, Visibility visibility)
|
||||
|
||||
static inline Decl *parse_typedef_declaration(Visibility visibility)
|
||||
{
|
||||
LOG_FUNC
|
||||
Decl *decl = decl_new(DECL_TYPEDEF, tok, visibility);
|
||||
advance_and_verify(TOKEN_TYPEDEF);
|
||||
if (tok.type == TOKEN_FUNC)
|
||||
@@ -2109,8 +2104,6 @@ static inline Decl *parse_typedef_declaration(Visibility visibility)
|
||||
|
||||
static inline Decl *parse_macro_declaration(Visibility visibility)
|
||||
{
|
||||
LOG_FUNC
|
||||
|
||||
advance_and_verify(TOKEN_MACRO);
|
||||
|
||||
Type *rtype = NULL;
|
||||
@@ -2180,8 +2173,6 @@ static inline Decl *parse_macro_declaration(Visibility visibility)
|
||||
*/
|
||||
static inline Decl *parse_func_definition(Visibility visibility, bool is_interface)
|
||||
{
|
||||
LOG_FUNC
|
||||
|
||||
advance_and_verify(TOKEN_FUNC);
|
||||
|
||||
Type *return_type = TRY_TYPE_OR(parse_type_expression(), false);
|
||||
@@ -2355,6 +2346,7 @@ static inline bool parse_conditional_top_level(Decl ***decls)
|
||||
while (tok.type != TOKEN_RBRACE && tok.type != TOKEN_EOF)
|
||||
{
|
||||
Decl *decl = parse_top_level();
|
||||
if (decl == NULL) continue;
|
||||
if (decl_ok(decl))
|
||||
{
|
||||
vec_add(*decls, decl);
|
||||
@@ -2396,6 +2388,30 @@ static inline Decl *parse_ct_if_top_level(void)
|
||||
return ct;
|
||||
}
|
||||
|
||||
static inline Decl *parse_incremental_array(void)
|
||||
{
|
||||
Token name = tok;
|
||||
advance_and_verify(TOKEN_IDENT);
|
||||
|
||||
CONSUME_OR(TOKEN_PLUS_ASSIGN, &poisoned_decl);
|
||||
TODO
|
||||
}
|
||||
|
||||
static inline bool check_no_visibility_before(Visibility visibility)
|
||||
{
|
||||
switch (visibility)
|
||||
{
|
||||
case VISIBLE_PUBLIC:
|
||||
SEMA_ERROR(tok, "Unexpected 'public' before '%.*s'.", tok.span.length, tok.start);
|
||||
return false;
|
||||
case VISIBLE_LOCAL:
|
||||
SEMA_ERROR(tok, "Unexpected 'local' before '%.*s'.", tok.span.length, tok.start);
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* top_level
|
||||
@@ -2438,10 +2454,7 @@ static inline Decl *parse_top_level(void)
|
||||
case TOKEN_FUNC:
|
||||
return parse_func_definition(visibility, false);
|
||||
case TOKEN_CT_IF:
|
||||
if (visibility != VISIBLE_MODULE)
|
||||
{
|
||||
SEMA_ERROR(tok, "Unexpected '%.*s' before '$if'.", TOK2VARSTR(tok));
|
||||
}
|
||||
if (!check_no_visibility_before(visibility)) return false;
|
||||
return parse_ct_if_top_level();
|
||||
case TOKEN_CONST:
|
||||
return parse_const_declaration(visibility);
|
||||
@@ -2458,18 +2471,20 @@ static inline Decl *parse_top_level(void)
|
||||
return parse_error_declaration(visibility);
|
||||
case TOKEN_TYPEDEF:
|
||||
return parse_typedef_declaration(visibility);
|
||||
case TOKEN_IDENT:
|
||||
case TOKEN_TYPE:
|
||||
case TOKEN_TYPE_IDENT:
|
||||
// All of these start type
|
||||
return parse_global_declaration(visibility);
|
||||
case TOKEN_IDENT:
|
||||
if (!check_no_visibility_before(visibility)) return false;
|
||||
return parse_incremental_array();
|
||||
case TOKEN_EOF:
|
||||
assert(visibility != VISIBLE_MODULE);
|
||||
sema_error_at(next_tok.span.loc - 1, "Expected a top level declaration after '%.*s'.", TOK2VARSTR(tok));
|
||||
sema_error_at(tok.span.loc - 1, "Expected a top level declaration'.");
|
||||
return &poisoned_decl;
|
||||
default:
|
||||
// We could have included all fundamental types above, but do it here instead.
|
||||
if (token_is_type(next_tok.type))
|
||||
if (token_is_type(tok.type))
|
||||
{
|
||||
return parse_global_declaration(visibility);
|
||||
}
|
||||
@@ -2687,6 +2702,68 @@ static Expr *parse_integer(Expr *left)
|
||||
const char *string = tok.start;
|
||||
const char *end = string + tok.span.length;
|
||||
uint64_t i = 0;
|
||||
if (string[0] == '\'')
|
||||
{
|
||||
union
|
||||
{
|
||||
uint8_t u8;
|
||||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
uint8_t b[8];
|
||||
} bytes;
|
||||
int pos = 0;
|
||||
while (++string < end - 1)
|
||||
{
|
||||
if (*string == '\\')
|
||||
{
|
||||
if (*(++string) == 'x')
|
||||
{
|
||||
int hex = 0;
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
hex <<= 4;
|
||||
char c = *(++string);
|
||||
if (c < 'A')
|
||||
{
|
||||
hex += c - '0';
|
||||
}
|
||||
else if (c < 'a')
|
||||
{
|
||||
hex += c - 'A' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
hex += c - 'a' + 10;
|
||||
}
|
||||
}
|
||||
bytes.b[pos++] = hex;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
bytes.b[pos++] = (unsigned)*string;
|
||||
}
|
||||
switch (pos)
|
||||
{
|
||||
case 1:
|
||||
expr_int->const_expr.i = bytes.u8;
|
||||
break;
|
||||
case 2:
|
||||
expr_int->const_expr.i = bytes.u16;
|
||||
break;
|
||||
case 4:
|
||||
expr_int->const_expr.i = bytes.u32;
|
||||
break;
|
||||
case 8:
|
||||
expr_int->const_expr.i = bytes.u64;
|
||||
break;
|
||||
}
|
||||
expr_int->const_expr.type = CONST_INT;
|
||||
expr_int->type = i > INT64_MAX ? type_compuint : type_compint;
|
||||
expr_int->resolve_status = RESOLVE_DONE;
|
||||
advance();
|
||||
return expr_int;
|
||||
}
|
||||
switch (tok.span.length > 2 ? string[1] : '0')
|
||||
{
|
||||
case 'x':
|
||||
@@ -2813,7 +2890,6 @@ static Expr *parse_nil(Expr *left)
|
||||
}
|
||||
|
||||
|
||||
static Expr *parse_initializer(void);
|
||||
|
||||
/**
|
||||
* initializer_list
|
||||
|
||||
@@ -10,11 +10,9 @@ bool sema_analyse_stmt_list(Context *context, Ast *statement);
|
||||
|
||||
void sema_init(File *file)
|
||||
{
|
||||
LOG_FUNC
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sema_shadow_error(Decl *decl, Decl *old)
|
||||
{
|
||||
sema_error_range(decl->name.span, "The '%s' would shadow a previous declaration.", decl->name.string);
|
||||
@@ -101,6 +99,30 @@ static bool sema_resolve_array_type(Context *context, Type *type)
|
||||
}
|
||||
static inline bool sema_analyse_struct_member(Context *context, Decl *decl)
|
||||
{
|
||||
if (decl->decl_kind == DECL_STRUCT || decl->decl_kind == DECL_UNION)
|
||||
{
|
||||
DEBUG_LOG("Beginning analysis of inner struct/union");
|
||||
VECEACH(decl->strukt.members, i)
|
||||
{
|
||||
Decl *member = decl->strukt.members[i];
|
||||
if (!decl_ok(member))
|
||||
{
|
||||
decl_poison(decl);
|
||||
continue;
|
||||
}
|
||||
if (!sema_analyse_struct_member(context, decl->strukt.members[i]))
|
||||
{
|
||||
if (decl_ok(decl))
|
||||
{
|
||||
decl_poison(decl);
|
||||
continue;
|
||||
}
|
||||
decl_poison(decl);
|
||||
}
|
||||
}
|
||||
DEBUG_LOG("Analysis complete.");
|
||||
return decl_ok(decl);
|
||||
}
|
||||
assert(decl->decl_kind == DECL_VAR);
|
||||
assert(decl->var.kind == VARDECL_MEMBER);
|
||||
assert(!decl->var.init_expr);
|
||||
@@ -112,10 +134,11 @@ static inline bool sema_analyse_struct_member(Context *context, Decl *decl)
|
||||
assert(decl->var.type->canonical);
|
||||
return true;
|
||||
}
|
||||
static inline bool sema_analyse_struct(Context *context, Decl *decl)
|
||||
|
||||
static inline bool sema_analyse_struct_union(Context *context, Decl *decl)
|
||||
{
|
||||
DEBUG_LOG("Beginning analysis of %s.", decl->name.string);
|
||||
assert(decl->decl_kind == DECL_STRUCT);
|
||||
assert(decl->decl_kind == DECL_STRUCT || decl->decl_kind == DECL_UNION);
|
||||
VECEACH(decl->strukt.members, i)
|
||||
{
|
||||
Decl *member = decl->strukt.members[i];
|
||||
@@ -135,6 +158,7 @@ static inline bool sema_analyse_struct(Context *context, Decl *decl)
|
||||
}
|
||||
}
|
||||
DEBUG_LOG("Analysis complete.");
|
||||
// Todo, resolve alignment, size etc.
|
||||
return decl_ok(decl);
|
||||
}
|
||||
|
||||
@@ -268,8 +292,11 @@ static inline bool sema_analyse_var_decl(Context *context, Decl *decl)
|
||||
*vars = VECADD(*vars, decl);
|
||||
if (decl->var.init_expr)
|
||||
{
|
||||
if (!sema_analyse_expr(context, decl->var.init_expr) ||
|
||||
!cast(decl->var.init_expr, decl->var.type, CAST_TYPE_IMPLICIT_ASSIGN))
|
||||
Type *prev_type = context->left_type_in_assignment;
|
||||
context->left_type_in_assignment = decl->var.type;
|
||||
bool success = sema_analyse_expr(context, decl->var.init_expr) && cast(decl->var.init_expr, decl->var.type, CAST_TYPE_IMPLICIT_ASSIGN);
|
||||
context->left_type_in_assignment = prev_type;
|
||||
if (!success)
|
||||
{
|
||||
decl_poison(decl);
|
||||
return false;
|
||||
@@ -621,10 +648,6 @@ static bool sema_analyse_asm_stmt(Context *context, Ast *statement)
|
||||
TODO
|
||||
}
|
||||
|
||||
static bool sema_analyse_attribute(Context *context, Ast *statement)
|
||||
{
|
||||
TODO
|
||||
}
|
||||
|
||||
static bool sema_analyse_break_stmt(Context *context, Ast *statement)
|
||||
{
|
||||
@@ -837,7 +860,7 @@ static bool sema_analyse_compound_stmt(Context *context, Ast *statement)
|
||||
static AstAnalysis AST_ANALYSIS[AST_WHILE_STMT + 1] =
|
||||
{
|
||||
[AST_ASM_STMT] = &sema_analyse_asm_stmt,
|
||||
[AST_ATTRIBUTE] = &sema_analyse_attribute,
|
||||
[AST_ATTRIBUTE] = NULL,
|
||||
[AST_BREAK_STMT] = &sema_analyse_break_stmt,
|
||||
[AST_CASE_STMT] = &sema_analyse_case_stmt,
|
||||
[AST_CATCH_STMT] = &sema_analyse_catch_stmt,
|
||||
@@ -920,6 +943,58 @@ static inline bool sema_analyse_macro(Context *context, Decl *decl)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_global(Context *context, Decl *decl)
|
||||
{
|
||||
if (!sema_resolve_type(context, decl->var.type)) return false;
|
||||
if (decl->var.init_expr)
|
||||
{
|
||||
if (!sema_analyse_expr(context, decl->var.init_expr)) return false;
|
||||
if (!cast(decl->var.init_expr, decl->var.type, CAST_TYPE_IMPLICIT_ASSIGN)) return false;
|
||||
if (decl->var.init_expr->expr_kind != EXPR_CONST)
|
||||
{
|
||||
SEMA_ERROR(decl->var.init_expr->loc, "The expression must be a constant value.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch (decl->var.kind)
|
||||
{
|
||||
case VARDECL_CONST:
|
||||
assert(decl->var.init_expr);
|
||||
return true;
|
||||
case VARDECL_GLOBAL:
|
||||
return true;
|
||||
default:
|
||||
UNREACHABLE
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_typedef(Context *context, Decl *decl)
|
||||
{
|
||||
if (!sema_resolve_type(context, decl->typedef_decl.type)) return false;
|
||||
// Do we need anything else?
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_generic(Context *context, Decl *decl)
|
||||
{
|
||||
TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_enum(Context *context, Decl *decl)
|
||||
{
|
||||
if (!sema_resolve_type(context, decl->typedef_decl.type)) return false;
|
||||
// TODO assign numbers to constants
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_error(Context *context, Decl *decl)
|
||||
{
|
||||
// TODO assign numbers to constants
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_decl(Context *context, Decl *decl)
|
||||
{
|
||||
if (decl->resolve_status == RESOLVE_DONE) return decl_ok(decl);
|
||||
@@ -933,28 +1008,51 @@ static inline bool sema_analyse_decl(Context *context, Decl *decl)
|
||||
}
|
||||
|
||||
decl->resolve_status = RESOLVE_RUNNING;
|
||||
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_IMPORT:
|
||||
TODO
|
||||
case DECL_STRUCT:
|
||||
if (!sema_analyse_struct(context, decl)) return false;
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
case DECL_UNION:
|
||||
if (!sema_analyse_struct_union(context, decl)) return decl_poison(decl);
|
||||
context_add_header_decl(context, decl);
|
||||
return true;
|
||||
break;
|
||||
case DECL_FUNC:
|
||||
if (!sema_analyse_func(context, decl)) return false;
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
if (!sema_analyse_func(context, decl)) return decl_poison(decl);
|
||||
context_add_header_decl(context, decl);
|
||||
return true;
|
||||
break;
|
||||
case DECL_MACRO:
|
||||
if (!sema_analyse_macro(context, decl)) return false;
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
default:
|
||||
TODO
|
||||
if (!sema_analyse_macro(context, decl)) return decl_poison(decl);
|
||||
break;
|
||||
case DECL_VAR:
|
||||
if (!sema_analyse_global(context, decl)) return decl_poison(decl);
|
||||
context_add_header_decl(context, decl);
|
||||
break;
|
||||
case DECL_TYPEDEF:
|
||||
if (!sema_analyse_typedef(context, decl)) return decl_poison(decl);
|
||||
break;
|
||||
case DECL_ENUM:
|
||||
if (!sema_analyse_enum(context, decl)) return decl_poison(decl);
|
||||
break;
|
||||
case DECL_ERROR:
|
||||
if (!sema_analyse_error(context, decl)) return decl_poison(decl);
|
||||
break;
|
||||
case DECL_GENERIC:
|
||||
if (!sema_analyse_generic(context, decl)) return decl_poison(decl);
|
||||
break;
|
||||
case DECL_POISONED:
|
||||
case DECL_IMPORT:
|
||||
case DECL_ENUM_CONSTANT:
|
||||
case DECL_ERROR_CONSTANT:
|
||||
case DECL_ARRAY_VALUE:
|
||||
case DECL_MULTI_DECL:
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
UNREACHABLE
|
||||
case DECL_CT_IF:
|
||||
// Handled elsewhere
|
||||
UNREACHABLE
|
||||
}
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user