mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Some limited calls now working correctly.
This commit is contained in:
@@ -3,6 +3,8 @@ module foo;
|
|||||||
int oefk = 1;
|
int oefk = 1;
|
||||||
int bob = 'HELO';
|
int bob = 'HELO';
|
||||||
|
|
||||||
|
typedef Foo* as Bob;
|
||||||
|
|
||||||
struct Foo
|
struct Foo
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -13,6 +15,7 @@ struct Bar
|
|||||||
{
|
{
|
||||||
Foo foo;
|
Foo foo;
|
||||||
Foo* fooPtr;
|
Foo* fooPtr;
|
||||||
|
Bob helo;
|
||||||
struct bar
|
struct bar
|
||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
@@ -44,10 +47,17 @@ $if (1)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Simple
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
double j;
|
||||||
|
}
|
||||||
func int boo()
|
func int boo()
|
||||||
{
|
{
|
||||||
Zed zfe;
|
Zed zfe;
|
||||||
//zfe = { 1, 2 };
|
Simple s = { 1 };
|
||||||
|
s = { 2 };
|
||||||
|
//Simple x = { j = 1 };
|
||||||
//Zed zfed = { 1 };
|
//Zed zfed = { 1 };
|
||||||
int eok = 0;
|
int eok = 0;
|
||||||
{
|
{
|
||||||
@@ -123,6 +133,10 @@ func int boo()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func int helo(int i)
|
||||||
|
{
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
func void while_test()
|
func void while_test()
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -156,5 +170,6 @@ func void test()
|
|||||||
|
|
||||||
func void main()
|
func void main()
|
||||||
{
|
{
|
||||||
|
helo(2);
|
||||||
|
printf("Helo\n");
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ bool ptpt(Expr* left, Type *canonical, Type *type, CastType cast_type)
|
|||||||
|
|
||||||
if (cast_type != CAST_TYPE_EXPLICIT && !may_implicitly_cast_ptr_to_ptr(to_cast_type, canonical))
|
if (cast_type != CAST_TYPE_EXPLICIT && !may_implicitly_cast_ptr_to_ptr(to_cast_type, canonical))
|
||||||
{
|
{
|
||||||
sema_type_mismatch(left, type, cast_type);
|
return sema_type_mismatch(left, type, cast_type);
|
||||||
}
|
}
|
||||||
if (left->expr_kind == EXPR_CONST)
|
if (left->expr_kind == EXPR_CONST)
|
||||||
{
|
{
|
||||||
@@ -109,21 +109,17 @@ bool ptpt(Expr* left, Type *canonical, Type *type, CastType cast_type)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ptst(Expr* left, Type *canonical, Type *type, CastType cast_type)
|
bool stpt(Expr* left, Type *canonical, Type *type, CastType cast_type)
|
||||||
{
|
{
|
||||||
TODO
|
if (canonical->base != type_char && canonical->base != type_byte)
|
||||||
if (left->expr_kind == EXPR_CONST)
|
|
||||||
{
|
{
|
||||||
assert(left->const_expr.type == CONST_INT && type_is_unsigned(left->type->canonical));
|
return sema_type_mismatch(left, type, cast_type);
|
||||||
assert(canonical->type_kind >= TYPE_F32 && canonical->type_kind <= TYPE_F64);
|
|
||||||
left->const_expr.f = left->const_expr.i;
|
|
||||||
left->type = type;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
insert_cast(left, CAST_UIFP, canonical);
|
left->type = canonical;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool boxi(Expr* left, Type *canonical, Type *type, CastType cast_type)
|
bool boxi(Expr* left, Type *canonical, Type *type, CastType cast_type)
|
||||||
{
|
{
|
||||||
if (cast_type >= CAST_TYPE_IMPLICIT_ASSIGN) EXIT_T_MISMATCH();
|
if (cast_type >= CAST_TYPE_IMPLICIT_ASSIGN) EXIT_T_MISMATCH();
|
||||||
@@ -479,7 +475,7 @@ bool usbo(Expr* left, Type *canonical, Type *type, CastType cast_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CastFunc BUILTIN_CONVERSION[19][19] = {
|
CastFunc BUILTIN_CONVERSION[19][19] = {
|
||||||
//to bool, char, short, int, long, ctint, byte, ushort, int, ulong,ctuint, float,double,ctreal, user, ptr, str, arr, varr // from:
|
//to bool, char, short, int, long, ctint, byte, ushort, uint, ulong,ctuint, float,double,ctreal, user, ptr, str, arr, varr // from:
|
||||||
{ &erro, &boxi, &boxi, &boxi, &boxi, &erro, &boxi, &boxi, &boxi, &boxi, &erro, &bofp, &bofp, &erro, &erro, &erro, &erro, &erro, &erro }, // bool
|
{ &erro, &boxi, &boxi, &boxi, &boxi, &erro, &boxi, &boxi, &boxi, &boxi, &erro, &bofp, &bofp, &erro, &erro, &erro, &erro, &erro, &erro }, // bool
|
||||||
{ &xibo, &erro, &sisi, &sisi, &sisi, &erro, &siui, &siui, &siui, &siui, &erro, &sifp, &sifp, &erro, &sius, &erro, &erro, &erro, &erro }, // char
|
{ &xibo, &erro, &sisi, &sisi, &sisi, &erro, &siui, &siui, &siui, &siui, &erro, &sifp, &sifp, &erro, &sius, &erro, &erro, &erro, &erro }, // char
|
||||||
{ &xibo, &sisi, &erro, &sisi, &sisi, &erro, &siui, &siui, &siui, &siui, &erro, &sifp, &sifp, &erro, &sius, &erro, &erro, &erro, &erro }, // short
|
{ &xibo, &sisi, &erro, &sisi, &sisi, &erro, &siui, &siui, &siui, &siui, &erro, &sifp, &sifp, &erro, &sius, &erro, &erro, &erro, &erro }, // short
|
||||||
@@ -495,8 +491,8 @@ CastFunc BUILTIN_CONVERSION[19][19] = {
|
|||||||
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro, &erro }, // double
|
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro, &erro }, // double
|
||||||
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro }, // fxx
|
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro }, // fxx
|
||||||
{ &usbo, &ussi, &ussi, &ussi, &ussi, &erro, &usui, &usui, &usui, &usui, &erro, &erro, &erro, &erro, &usus, &erro, &erro, &erro, &erro }, // user
|
{ &usbo, &ussi, &ussi, &ussi, &ussi, &erro, &usui, &usui, &usui, &usui, &erro, &erro, &erro, &erro, &usus, &erro, &erro, &erro, &erro }, // user
|
||||||
{ &ptbo, &ptxi, &ptxi, &ptxi, &ptxi, &erro, &ptxi, &ptxi, &ptxi, &ptxi, &erro, &erro, &erro, &erro, &erro, &ptpt, &ptst, &erro, &ptva }, // ptr
|
{ &ptbo, &ptxi, &ptxi, &ptxi, &ptxi, &erro, &ptxi, &ptxi, &ptxi, &ptxi, &erro, &erro, &erro, &erro, &erro, &ptpt, &erro, &erro, &ptva }, // ptr
|
||||||
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro, &erro }, // str
|
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &erro, &erro, &erro, &stpt, &erro, &erro, &erro }, // str
|
||||||
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro }, // arr
|
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro }, // arr
|
||||||
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro, &erro }, // varr
|
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro, &erro }, // varr
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -123,10 +123,38 @@ static inline void codegen_compound_stmt(Context *context, Ast *ast, int indent)
|
|||||||
static inline int codegen_emit_call_expr(Context *context, Expr *expr, int indent)
|
static inline int codegen_emit_call_expr(Context *context, Expr *expr, int indent)
|
||||||
{
|
{
|
||||||
// TODO properly
|
// TODO properly
|
||||||
|
int *params = NULL;
|
||||||
|
VECEACH(expr->call_expr.arguments, i)
|
||||||
|
{
|
||||||
|
vec_add(params, codegen_emit_expr(context, expr->call_expr.arguments[i], indent));
|
||||||
|
}
|
||||||
INDENT();
|
INDENT();
|
||||||
PRINTTYPE(expr->type);
|
bool has_return = expr->type->type_kind != TYPE_VOID;
|
||||||
Decl *func = expr->call_expr.function->identifier_expr.decl;
|
if (has_return) PRINTTYPE(expr->type);
|
||||||
PRINTF(" _%d = %s__%s();\n", ++context->unique_index, func->module->name, func->name.string);
|
if (expr->call_expr.function->expr_kind == EXPR_IDENTIFIER)
|
||||||
|
{
|
||||||
|
Decl *func = expr->call_expr.function->identifier_expr.decl;
|
||||||
|
if (has_return) PRINTF(" _%d = ", ++context->unique_index);
|
||||||
|
if (strcmp(func->name.string, "printf") == 0)
|
||||||
|
{
|
||||||
|
PRINTF("%s", func->name.string);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PRINTF("%s__%s", func->module->name, func->name.string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TODO
|
||||||
|
}
|
||||||
|
PRINTF("(");
|
||||||
|
VECEACH(params, i)
|
||||||
|
{
|
||||||
|
if (i != 0) PRINTF(", ");
|
||||||
|
PRINTF("_%d", params[i]);
|
||||||
|
}
|
||||||
|
PRINTF(");\n");
|
||||||
return context->unique_index;
|
return context->unique_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,16 +208,27 @@ static inline void codegen_emit_const_expr_raw(Context *context, Expr *expr)
|
|||||||
case TYPE_F32:
|
case TYPE_F32:
|
||||||
case TYPE_F64:
|
case TYPE_F64:
|
||||||
case TYPE_FXX:
|
case TYPE_FXX:
|
||||||
assert(expr->const_expr.type == CONST_INT);
|
assert(expr->const_expr.type == CONST_FLOAT);
|
||||||
PRINTF("(");
|
PRINTF("(");
|
||||||
PRINTTYPE(canonical);
|
PRINTTYPE(canonical);
|
||||||
PRINTF(")");
|
PRINTF(")");
|
||||||
PRINTF("%Lf", expr->const_expr.f);
|
PRINTF("%Lf", expr->const_expr.f);
|
||||||
return;
|
return;
|
||||||
case TYPE_POINTER:
|
case TYPE_POINTER:
|
||||||
PRINTF("((");
|
if (expr->const_expr.type == CONST_NIL)
|
||||||
PRINTTYPE(canonical);
|
{
|
||||||
PRINTF("0)");
|
PRINTF("((");
|
||||||
|
PRINTTYPE(canonical);
|
||||||
|
PRINTF(")0)");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(expr->const_expr.type == CONST_STRING);
|
||||||
|
PRINTF("((");
|
||||||
|
PRINTTYPE(canonical);
|
||||||
|
|
||||||
|
PRINTF(")%.*s)", expr->const_expr.string.len, expr->const_expr.string.chars);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
case TYPE_STRING:
|
case TYPE_STRING:
|
||||||
TODO
|
TODO
|
||||||
@@ -323,10 +362,23 @@ static int codegen_emit_post_unary_expr(Context *context, Expr *expr, int indent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void codegen_print_ltype(Context *context, Expr *expr, int indent)
|
static int codegen_emit_initializer_list(Context *context, Expr *expr, int indent)
|
||||||
{
|
{
|
||||||
|
int index = ++context->unique_index;
|
||||||
|
INDENT();
|
||||||
|
PRINTTYPE(expr->type);
|
||||||
|
PRINTF(" _%d;\n", index);
|
||||||
|
Decl *decl = expr->type->canonical->decl;
|
||||||
|
// Todo, fully clear.
|
||||||
|
VECEACH(expr->initializer_expr, i)
|
||||||
|
{
|
||||||
|
int index2 = codegen_emit_expr(context, expr->initializer_expr[i], indent);
|
||||||
|
INDENT();
|
||||||
|
PRINTF("_%d.%s = _%d;\n", index, decl->strukt.members[i]->name.string, index2);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int codegen_emit_unary_expr(Context *context, Expr *expr, int indent)
|
static int codegen_emit_unary_expr(Context *context, Expr *expr, int indent)
|
||||||
{
|
{
|
||||||
int index = ++context->unique_index;
|
int index = ++context->unique_index;
|
||||||
@@ -398,6 +450,8 @@ static int codegen_emit_expr(Context *context, Expr *expr, int indent)
|
|||||||
return codegen_emit_post_unary_expr(context, expr, indent);
|
return codegen_emit_post_unary_expr(context, expr, indent);
|
||||||
case EXPR_UNARY:
|
case EXPR_UNARY:
|
||||||
return codegen_emit_unary_expr(context, expr, indent);
|
return codegen_emit_unary_expr(context, expr, indent);
|
||||||
|
case EXPR_INITIALIZER_LIST:
|
||||||
|
return codegen_emit_initializer_list(context, expr, indent);
|
||||||
default:
|
default:
|
||||||
TODO
|
TODO
|
||||||
}
|
}
|
||||||
@@ -730,12 +784,21 @@ static inline void codegen_func_decl(Context *context, Decl *decl)
|
|||||||
print_typename(context->codegen_output, decl->func.function_signature.rtype);
|
print_typename(context->codegen_output, decl->func.function_signature.rtype);
|
||||||
if (strcmp("main", decl->name.string) == 0)
|
if (strcmp("main", decl->name.string) == 0)
|
||||||
{
|
{
|
||||||
PRINTF(" %s()", decl->name.string);
|
PRINTF(" %s(", decl->name.string);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PRINTF(" %s__%s()", decl->module->name, decl->name.string);
|
PRINTF(" %s__%s(", decl->module->name, decl->name.string);
|
||||||
}
|
}
|
||||||
|
Decl **params = decl->func.function_signature.params;
|
||||||
|
VECEACH(params, i)
|
||||||
|
{
|
||||||
|
if (i != 0) PRINTF(", ");
|
||||||
|
Decl *param = params[i];
|
||||||
|
PRINTTYPE(param->var.type);
|
||||||
|
PRINTF(" _%d_%s", param->var.id, param->name.string);
|
||||||
|
}
|
||||||
|
PRINTF(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void codegen_func(Context *context, Decl *decl)
|
static inline void codegen_func(Context *context, Decl *decl)
|
||||||
@@ -750,6 +813,7 @@ static inline void codegen_func(Context *context, Decl *decl)
|
|||||||
{
|
{
|
||||||
Decl *var = vars[i];
|
Decl *var = vars[i];
|
||||||
assert(var->decl_kind == DECL_VAR);
|
assert(var->decl_kind == DECL_VAR);
|
||||||
|
if (var->var.kind == VARDECL_PARAM) continue;
|
||||||
Type *current = var->var.type->canonical;
|
Type *current = var->var.type->canonical;
|
||||||
if (type == current)
|
if (type == current)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -723,6 +723,7 @@ bool context_set_module(Context *context, Token module_name, Token *generic_para
|
|||||||
void context_print_ast(Context *context, FILE *file);
|
void context_print_ast(Context *context, FILE *file);
|
||||||
Decl *context_find_ident(Context *context, const char *symbol);
|
Decl *context_find_ident(Context *context, const char *symbol);
|
||||||
void context_add_header_decl(Context *context, Decl *decl);
|
void context_add_header_decl(Context *context, Decl *decl);
|
||||||
|
bool context_add_local(Context *context, Decl *decl);
|
||||||
|
|
||||||
Decl *decl_new(DeclKind decl_kind, Token name, Visibility visibility);
|
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_user_defined_type(Token name, DeclKind decl_type, Visibility visibility);
|
||||||
|
|||||||
@@ -26,6 +26,30 @@ void context_add_header_decl(Context *context, Decl *decl)
|
|||||||
vec_add(context->header_declarations, decl);
|
vec_add(context->header_declarations, decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool context_add_local(Context *context, Decl *decl)
|
||||||
|
{
|
||||||
|
Decl *other = context_find_ident(context, decl->name.string);
|
||||||
|
if (other)
|
||||||
|
{
|
||||||
|
sema_shadow_error(decl, other);
|
||||||
|
decl_poison(decl);
|
||||||
|
decl_poison(other);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Decl *** vars = &context->active_function_for_analysis->func.annotations->vars;
|
||||||
|
unsigned num_vars = vec_size(*vars);
|
||||||
|
if (num_vars == MAX_LOCALS - 1 || context->last_local == &context->locals[MAX_LOCALS - 1])
|
||||||
|
{
|
||||||
|
SEMA_ERROR(decl->name, "Reached the maximum number of locals.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
decl->var.id = num_vars;
|
||||||
|
*vars = VECADD(*vars, decl);
|
||||||
|
context->last_local[0] = decl;
|
||||||
|
context->last_local++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool create_module_or_check_name(Context *context, Token module_name)
|
static inline bool create_module_or_check_name(Context *context, Token module_name)
|
||||||
{
|
{
|
||||||
context->module_name = module_name;
|
context->module_name = module_name;
|
||||||
|
|||||||
@@ -443,7 +443,6 @@ typedef enum
|
|||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
TYPE_POISONED,
|
TYPE_POISONED,
|
||||||
TYPE_USER_DEFINED,
|
|
||||||
TYPE_VOID,
|
TYPE_VOID,
|
||||||
TYPE_BOOL,
|
TYPE_BOOL,
|
||||||
TYPE_I8,
|
TYPE_I8,
|
||||||
@@ -459,6 +458,7 @@ typedef enum
|
|||||||
TYPE_F32,
|
TYPE_F32,
|
||||||
TYPE_F64,
|
TYPE_F64,
|
||||||
TYPE_FXX,
|
TYPE_FXX,
|
||||||
|
TYPE_USER_DEFINED,
|
||||||
TYPE_POINTER,
|
TYPE_POINTER,
|
||||||
TYPE_STRING,
|
TYPE_STRING,
|
||||||
TYPE_ARRAY,
|
TYPE_ARRAY,
|
||||||
|
|||||||
@@ -144,9 +144,56 @@ static inline bool sema_expr_analyse_method_ref(Context *context, Expr *expr)
|
|||||||
TODO
|
TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool sema_expr_analyse_struct_initializer_list(Context *context, Expr *expr)
|
static inline Decl *decl_find_by_name(Decl** decls, const char *name)
|
||||||
{
|
{
|
||||||
TODO
|
VECEACH(decls, i)
|
||||||
|
{
|
||||||
|
if (decls[i]->name.string == name) return decls[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
static inline bool expr_may_be_struct_field_decl(Expr *maybe_binary)
|
||||||
|
{
|
||||||
|
if (maybe_binary->expr_kind != EXPR_BINARY) return false;
|
||||||
|
if (maybe_binary->binary_expr.operator != TOKEN_EQ) return false;
|
||||||
|
Expr *expr = maybe_binary->binary_expr.left;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (expr->expr_kind == EXPR_IDENTIFIER) return true;
|
||||||
|
if (expr->expr_kind != EXPR_ACCESS) return false;
|
||||||
|
expr = expr->access_expr.parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool sema_expr_analyse_struct_initializer_list(Context *context, Type *assigned, Expr *expr)
|
||||||
|
{
|
||||||
|
Decl **members = assigned->decl->strukt.members;
|
||||||
|
unsigned size = vec_size(members);
|
||||||
|
VECEACH(expr->initializer_expr, i)
|
||||||
|
{
|
||||||
|
Expr *field = expr->initializer_expr[i];
|
||||||
|
Decl *decl;
|
||||||
|
if (expr_may_be_struct_field_decl(field))
|
||||||
|
{
|
||||||
|
if (field->expr_kind == EXPR_IDENTIFIER)
|
||||||
|
{
|
||||||
|
decl = decl_find_by_name(members, field->identifier_expr.identifier.string);
|
||||||
|
}
|
||||||
|
TODO
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (i >= size)
|
||||||
|
{
|
||||||
|
SEMA_ERROR(field->loc, "Too many elements in initializer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
decl = members[i];
|
||||||
|
}
|
||||||
|
if (!cast(field, decl->var.type, CAST_TYPE_IMPLICIT_ASSIGN)) return false;
|
||||||
|
}
|
||||||
|
expr->type = assigned;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
static inline bool sema_expr_analyse_initializer_list(Context *context, Expr *expr)
|
static inline bool sema_expr_analyse_initializer_list(Context *context, Expr *expr)
|
||||||
{
|
{
|
||||||
@@ -156,7 +203,7 @@ static inline bool sema_expr_analyse_initializer_list(Context *context, Expr *ex
|
|||||||
switch (assigned->type_kind)
|
switch (assigned->type_kind)
|
||||||
{
|
{
|
||||||
case TYPE_USER_DEFINED:
|
case TYPE_USER_DEFINED:
|
||||||
if (decl_is_struct_type(assigned->decl)) return sema_expr_analyse_struct_initializer_list(context, expr);
|
if (decl_is_struct_type(assigned->decl)) return sema_expr_analyse_struct_initializer_list(context, assigned, expr);
|
||||||
break;
|
break;
|
||||||
case TYPE_ARRAY:
|
case TYPE_ARRAY:
|
||||||
TODO
|
TODO
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "compiler_internal.h"
|
#include "compiler_internal.h"
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
bool lexer_init_complete;
|
bool lexer_init_complete;
|
||||||
@@ -413,26 +412,40 @@ static inline Token scan_digit(void)
|
|||||||
|
|
||||||
static inline Token scan_char()
|
static inline Token scan_char()
|
||||||
{
|
{
|
||||||
next(); // Consume "'"
|
int width = 0;
|
||||||
// Handle escaped char, also handle hex code.
|
char c;
|
||||||
if (next() == '\\')
|
while ((c = next()) != '\'')
|
||||||
{
|
{
|
||||||
// Escape seq? We don't support octal.
|
if (c == '\0' || c == '\n') return error_token("Character literal did not terminate.");
|
||||||
if (next() == 'x')
|
width++;
|
||||||
|
// Was this an escape?
|
||||||
|
if (c == '\\')
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 2; i++)
|
// Yes, so check if it's hex:
|
||||||
|
if (next() == 'x')
|
||||||
{
|
{
|
||||||
if (!is_hex(next()))
|
// Walk through the two characters.
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
return error_token(
|
if (!is_hex(next()))
|
||||||
"An escape sequence starting with "
|
{
|
||||||
"'\\x' needs to be followed by "
|
return error_token(
|
||||||
"a two digit hexadecimal number.");
|
"An escape sequence starting with "
|
||||||
|
"'\\x' needs to be followed by "
|
||||||
|
"a two digit hexadecimal number.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (next() != '\'') return error_token("The character only consist of a single character, did you want to use \"\" instead?");
|
if (width == 0)
|
||||||
|
{
|
||||||
|
return error_token("The character literal was empty.");
|
||||||
|
}
|
||||||
|
if (width > 2 && width != 4 && width != 8)
|
||||||
|
{
|
||||||
|
error_token("Character literals may only be 1, 2 or 8 characters wide.");
|
||||||
|
}
|
||||||
return make_token(TOKEN_INTEGER);
|
return make_token(TOKEN_INTEGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,7 +681,12 @@ Token lexer_scan_token(void)
|
|||||||
backtrack();
|
backtrack();
|
||||||
return is_digit(c) ? scan_digit() : scan_ident();
|
return is_digit(c) ? scan_digit() : scan_ident();
|
||||||
}
|
}
|
||||||
|
if (c < 0)
|
||||||
|
{
|
||||||
|
return error_token("The 0%x character may not be placed outside of a string or comment, did you perhaps forget a \" somewhere?", (uint8_t)c);
|
||||||
|
}
|
||||||
return error_token("'%c' may not be placed outside of a string or comment, did you perhaps forget a \" somewhere?", c);
|
return error_token("'%c' may not be placed outside of a string or comment, did you perhaps forget a \" somewhere?", c);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,7 +704,6 @@ void lexer_check_init(void)
|
|||||||
|
|
||||||
void lexer_add_file_for_lexing(File *file)
|
void lexer_add_file_for_lexing(File *file)
|
||||||
{
|
{
|
||||||
LOG_FUNC
|
|
||||||
lexer_check_init();
|
lexer_check_init();
|
||||||
lexer.current_file = file;
|
lexer.current_file = file;
|
||||||
lexer.file_begin = lexer.current_file->contents;
|
lexer.file_begin = lexer.current_file->contents;
|
||||||
|
|||||||
@@ -2667,15 +2667,16 @@ static Expr *parse_string_literal(Expr *left)
|
|||||||
Expr *expr_string = EXPR_NEW_TOKEN(EXPR_CONST, tok);
|
Expr *expr_string = EXPR_NEW_TOKEN(EXPR_CONST, tok);
|
||||||
expr_string->resolve_status = RESOLVE_DONE;
|
expr_string->resolve_status = RESOLVE_DONE;
|
||||||
expr_string->type = type_string;
|
expr_string->type = type_string;
|
||||||
advance_and_verify(TOKEN_STRING);
|
|
||||||
|
|
||||||
char *str = malloc_arena(tok.span.length + 1);
|
char *str = malloc_arena(tok.span.length + 1);
|
||||||
size_t len = tok.span.length;
|
size_t len = tok.span.length;
|
||||||
|
|
||||||
memcpy(str, tok.start + tok.span.loc, tok.span.length);
|
memcpy(str, tok.start, tok.span.length);
|
||||||
|
|
||||||
// Just keep chaining if there are multiple parts.
|
// Just keep chaining if there are multiple parts.
|
||||||
|
|
||||||
|
advance_and_verify(TOKEN_STRING);
|
||||||
|
|
||||||
while (tok.type == TOKEN_STRING)
|
while (tok.type == TOKEN_STRING)
|
||||||
{
|
{
|
||||||
char *new_string = malloc_arena(len + tok.span.length + 1);
|
char *new_string = malloc_arena(len + tok.span.length + 1);
|
||||||
|
|||||||
@@ -273,23 +273,6 @@ static inline bool sema_analyse_var_decl(Context *context, Decl *decl)
|
|||||||
{
|
{
|
||||||
assert(decl->decl_kind == DECL_VAR);
|
assert(decl->decl_kind == DECL_VAR);
|
||||||
if (!sema_resolve_type(context, decl->var.type)) return false;
|
if (!sema_resolve_type(context, decl->var.type)) return false;
|
||||||
Decl *other = context_find_ident(context, decl->name.string);
|
|
||||||
if (other)
|
|
||||||
{
|
|
||||||
sema_shadow_error(decl, other);
|
|
||||||
decl_poison(decl);
|
|
||||||
decl_poison(other);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Decl *** vars = &context->active_function_for_analysis->func.annotations->vars;
|
|
||||||
unsigned num_vars = vec_size(*vars);
|
|
||||||
if (num_vars == MAX_LOCALS - 1 || context->last_local == &context->locals[MAX_LOCALS - 1])
|
|
||||||
{
|
|
||||||
SEMA_ERROR(decl->name, "Reached the maximum number of locals.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
decl->var.id = num_vars;
|
|
||||||
*vars = VECADD(*vars, decl);
|
|
||||||
if (decl->var.init_expr)
|
if (decl->var.init_expr)
|
||||||
{
|
{
|
||||||
Type *prev_type = context->left_type_in_assignment;
|
Type *prev_type = context->left_type_in_assignment;
|
||||||
@@ -302,8 +285,7 @@ static inline bool sema_analyse_var_decl(Context *context, Decl *decl)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context->last_local[0] = decl;
|
if (!context_add_local(context, decl)) return false;
|
||||||
context->last_local++;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -906,6 +888,11 @@ static inline bool sema_analyse_function_body(Context *context, Decl *func)
|
|||||||
context->in_volatile_section = 0;
|
context->in_volatile_section = 0;
|
||||||
func->func.annotations = CALLOCS(*func->func.annotations);
|
func->func.annotations = CALLOCS(*func->func.annotations);
|
||||||
context_push_scope(context);
|
context_push_scope(context);
|
||||||
|
Decl **params = func->func.function_signature.params;
|
||||||
|
VECEACH(params, i)
|
||||||
|
{
|
||||||
|
if (!context_add_local(context, params[i])) return false;
|
||||||
|
}
|
||||||
if (!sema_analyse_compound_statement_no_scope(context, func->func.body)) return false;
|
if (!sema_analyse_compound_statement_no_scope(context, func->func.body)) return false;
|
||||||
if (context->current_scope->exit != EXIT_RETURN && func->func.function_signature.rtype->canonical != type_void)
|
if (context->current_scope->exit != EXIT_RETURN && func->func.function_signature.rtype->canonical != type_void)
|
||||||
{
|
{
|
||||||
@@ -1104,6 +1091,19 @@ static inline void sema_process_imports(Context *context)
|
|||||||
}
|
}
|
||||||
void sema_analysis(Context *context)
|
void sema_analysis(Context *context)
|
||||||
{
|
{
|
||||||
|
const char *printf = "printf";
|
||||||
|
TokenType t_type = TOKEN_IDENT;
|
||||||
|
const char *interned = symtab_add(printf, (uint32_t) 6, fnv1a(printf, (uint32_t)6), &t_type);
|
||||||
|
Decl *decl = decl_new(DECL_FUNC, wrap(interned), VISIBLE_PUBLIC);
|
||||||
|
Type *type = type_new(TYPE_POINTER);
|
||||||
|
type->base = type_char;
|
||||||
|
sema_resolve_type(context, type);
|
||||||
|
Decl *param = decl_new_var(wrap("str"), type, VARDECL_PARAM, VISIBLE_LOCAL);
|
||||||
|
|
||||||
|
vec_add(decl->func.function_signature.params, param);
|
||||||
|
decl->func.function_signature.rtype = type_void;
|
||||||
|
decl->resolve_status = RESOLVE_DONE;
|
||||||
|
context_register_global_decl(context, decl);
|
||||||
sema_process_imports(context);
|
sema_process_imports(context);
|
||||||
VECEACH(context->ct_ifs, i)
|
VECEACH(context->ct_ifs, i)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user