Global declarations. Starting work on struct initializers, lots of arithmetics now checked correctly. Support 2cc 4cc 8cc

This commit is contained in:
Christoffer Lerno
2019-09-08 21:32:08 +02:00
parent 3b2051ea80
commit 000d1fea4a
7 changed files with 578 additions and 116 deletions

View File

@@ -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:

View File

@@ -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:

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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

View File

@@ -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;
}