Some limited calls now working correctly.

This commit is contained in:
Christoffer Lerno
2019-09-11 23:20:37 +02:00
parent 000d1fea4a
commit e04213d420
10 changed files with 230 additions and 65 deletions

View File

@@ -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))
{
sema_type_mismatch(left, type, cast_type);
return sema_type_mismatch(left, type, cast_type);
}
if (left->expr_kind == EXPR_CONST)
{
@@ -109,21 +109,17 @@ bool ptpt(Expr* left, Type *canonical, Type *type, CastType cast_type)
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 (left->expr_kind == EXPR_CONST)
if (canonical->base != type_char && canonical->base != type_byte)
{
assert(left->const_expr.type == CONST_INT && type_is_unsigned(left->type->canonical));
assert(canonical->type_kind >= TYPE_F32 && canonical->type_kind <= TYPE_F64);
left->const_expr.f = left->const_expr.i;
left->type = type;
return true;
return sema_type_mismatch(left, type, cast_type);
}
insert_cast(left, CAST_UIFP, canonical);
left->type = canonical;
return true;
}
bool boxi(Expr* left, Type *canonical, Type *type, CastType cast_type)
{
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] = {
//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
{ &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
@@ -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, &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
{ &ptbo, &ptxi, &ptxi, &ptxi, &ptxi, &erro, &ptxi, &ptxi, &ptxi, &ptxi, &erro, &erro, &erro, &erro, &erro, &ptpt, &ptst, &erro, &ptva }, // ptr
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro, &erro }, // str
{ &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, &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, &erro, &erro, &erro, &erro, &erro, &erro, &erro }, // varr
};

View File

@@ -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)
{
// 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();
PRINTTYPE(expr->type);
Decl *func = expr->call_expr.function->identifier_expr.decl;
PRINTF(" _%d = %s__%s();\n", ++context->unique_index, func->module->name, func->name.string);
bool has_return = expr->type->type_kind != TYPE_VOID;
if (has_return) PRINTTYPE(expr->type);
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;
}
@@ -180,16 +208,27 @@ static inline void codegen_emit_const_expr_raw(Context *context, Expr *expr)
case TYPE_F32:
case TYPE_F64:
case TYPE_FXX:
assert(expr->const_expr.type == CONST_INT);
assert(expr->const_expr.type == CONST_FLOAT);
PRINTF("(");
PRINTTYPE(canonical);
PRINTF(")");
PRINTF("%Lf", expr->const_expr.f);
return;
case TYPE_POINTER:
PRINTF("((");
PRINTTYPE(canonical);
PRINTF("0)");
if (expr->const_expr.type == CONST_NIL)
{
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;
case TYPE_STRING:
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)
{
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);
case EXPR_UNARY:
return codegen_emit_unary_expr(context, expr, indent);
case EXPR_INITIALIZER_LIST:
return codegen_emit_initializer_list(context, expr, indent);
default:
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);
if (strcmp("main", decl->name.string) == 0)
{
PRINTF(" %s()", decl->name.string);
PRINTF(" %s(", decl->name.string);
}
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)
@@ -750,6 +813,7 @@ static inline void codegen_func(Context *context, Decl *decl)
{
Decl *var = vars[i];
assert(var->decl_kind == DECL_VAR);
if (var->var.kind == VARDECL_PARAM) continue;
Type *current = var->var.type->canonical;
if (type == current)
{

View File

@@ -723,6 +723,7 @@ bool context_set_module(Context *context, Token module_name, Token *generic_para
void context_print_ast(Context *context, FILE *file);
Decl *context_find_ident(Context *context, const char *symbol);
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_user_defined_type(Token name, DeclKind decl_type, Visibility visibility);

View File

@@ -26,6 +26,30 @@ void context_add_header_decl(Context *context, Decl *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)
{
context->module_name = module_name;

View File

@@ -443,7 +443,6 @@ typedef enum
typedef enum
{
TYPE_POISONED,
TYPE_USER_DEFINED,
TYPE_VOID,
TYPE_BOOL,
TYPE_I8,
@@ -459,6 +458,7 @@ typedef enum
TYPE_F32,
TYPE_F64,
TYPE_FXX,
TYPE_USER_DEFINED,
TYPE_POINTER,
TYPE_STRING,
TYPE_ARRAY,

View File

@@ -144,9 +144,56 @@ static inline bool sema_expr_analyse_method_ref(Context *context, Expr *expr)
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)
{
@@ -156,7 +203,7 @@ static inline bool sema_expr_analyse_initializer_list(Context *context, Expr *ex
switch (assigned->type_kind)
{
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;
case TYPE_ARRAY:
TODO

View File

@@ -4,7 +4,6 @@
#include "compiler_internal.h"
typedef struct
{
bool lexer_init_complete;
@@ -413,26 +412,40 @@ static inline Token scan_digit(void)
static inline Token scan_char()
{
next(); // Consume "'"
// Handle escaped char, also handle hex code.
if (next() == '\\')
int width = 0;
char c;
while ((c = next()) != '\'')
{
// Escape seq? We don't support octal.
if (next() == 'x')
if (c == '\0' || c == '\n') return error_token("Character literal did not terminate.");
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(
"An escape sequence starting with "
"'\\x' needs to be followed by "
"a two digit hexadecimal number.");
if (!is_hex(next()))
{
return error_token(
"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);
}
@@ -668,7 +681,12 @@ Token lexer_scan_token(void)
backtrack();
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);
}
}
@@ -686,7 +704,6 @@ void lexer_check_init(void)
void lexer_add_file_for_lexing(File *file)
{
LOG_FUNC
lexer_check_init();
lexer.current_file = file;
lexer.file_begin = lexer.current_file->contents;

View File

@@ -2667,15 +2667,16 @@ static Expr *parse_string_literal(Expr *left)
Expr *expr_string = EXPR_NEW_TOKEN(EXPR_CONST, tok);
expr_string->resolve_status = RESOLVE_DONE;
expr_string->type = type_string;
advance_and_verify(TOKEN_STRING);
char *str = malloc_arena(tok.span.length + 1);
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.
advance_and_verify(TOKEN_STRING);
while (tok.type == TOKEN_STRING)
{
char *new_string = malloc_arena(len + tok.span.length + 1);

View File

@@ -273,23 +273,6 @@ static inline bool sema_analyse_var_decl(Context *context, Decl *decl)
{
assert(decl->decl_kind == DECL_VAR);
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)
{
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;
}
}
context->last_local[0] = decl;
context->last_local++;
if (!context_add_local(context, decl)) return false;
return true;
}
@@ -906,6 +888,11 @@ static inline bool sema_analyse_function_body(Context *context, Decl *func)
context->in_volatile_section = 0;
func->func.annotations = CALLOCS(*func->func.annotations);
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 (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)
{
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);
VECEACH(context->ct_ifs, i)
{