Introduced a Lexer context, comment parsing now actually works properly. Token use in decl/ast/expr is moved to SourceRange instead. And the SourceRange used start/end, which is better than using start + len for many uses.

This commit is contained in:
Christoffer Lerno
2020-01-23 19:38:48 +01:00
parent cdc1bfe267
commit 7b4ed09517
26 changed files with 1848 additions and 1754 deletions

View File

@@ -1,8 +1,8 @@
import curl;
int main(void)
func int main(void)
{
try Curl curl = Curl.new();
try Curl curl = curl::newCurl();
catch (error e)
{

View File

@@ -2,6 +2,15 @@ module bar;
typedef int as Bob;
/* hello *//* there */
/+ why /+ you /* lucky +/ +/
// Whut
// Here
//
//---
/*
Hello
*/
struct Test
{
@@ -91,6 +100,7 @@ func int test3()
return 5;
}
typedef func void() as FEok;
typedef func void(int) as Foo;
//typedef int as Foo;
@@ -111,6 +121,16 @@ func void bob()
}
func int xxxx(int x)
{
{
defer printf("Defer says hello!\n");
LABEL:
x--;
}
if (x > 0) goto LABEL;
return 1;
}
func int main(int x)
{
@@ -189,6 +209,9 @@ JUMP:
func void test2(int* x, int y, int z)
{
*(&(&x)[0]);
float cheat = cast(int, x);
x++;
z = 0;
z ? y : z;

View File

@@ -9,7 +9,9 @@ Decl *decl_new(DeclKind decl_kind, Token name, Visibility visibility)
assert(name.string);
Decl *decl = CALLOCS(Decl);
decl->decl_kind = decl_kind;
decl->name = name;
decl->name_span = name.span;
decl->span = name.span;
decl->name = name.string;
decl->visibility = visibility;
return decl;
}
@@ -22,11 +24,11 @@ void decl_set_external_name(Decl *decl)
{
if (decl->visibility == VISIBLE_EXTERN)
{
decl->external_name = decl->name.string;
decl->external_name = decl->name;
return;
}
char buffer[1024];
uint32_t len = sprintf(buffer, "%s::%s", decl->module->name->module, decl->name.string);
uint32_t len = sprintf(buffer, "%s::%s", decl->module->name->module, decl->name);
assert(len);
TokenType type = TOKEN_INVALID_TOKEN;
decl->external_name = symtab_add(buffer, len, fnv1a(buffer, len), &type);
@@ -64,7 +66,6 @@ Decl *decl_new_with_type(Token name, DeclKind decl_type, Visibility visibility)
case DECL_ARRAY_VALUE:
case DECL_IMPORT:
case DECL_MACRO:
case DECL_MULTI_DECL:
case DECL_GENERIC:
case DECL_CT_IF:
case DECL_CT_ELSE:
@@ -113,22 +114,29 @@ Decl *struct_find_name(Decl *decl, const char* name)
VECEACH(compare_members, i)
{
Decl *member = compare_members[i];
if (member->name.type == TOKEN_INVALID_TOKEN)
if (!member->name)
{
Decl *found = struct_find_name(member, name);
if (found) return found;
}
else if (member->name.string == name) return member;
else if (member->name == name) return member;
}
return NULL;
}
Ast *ast_from_expr(Expr *expr)
{
if (!expr_ok(expr)) return &poisoned_ast;
Ast *ast = AST_NEW(AST_EXPR_STMT, expr->span);
ast->expr_stmt = expr;
return ast;
}
Expr *expr_new(ExprKind kind, Token start)
Expr *expr_new(ExprKind kind, SourceRange start)
{
Expr *expr = malloc_arena(sizeof(Expr));
expr->expr_kind = kind;
expr->loc = start;
expr->span = start;
expr->type = NULL;
return expr;
}
@@ -344,21 +352,21 @@ void fprint_type_recursive(FILE *file, Type *type, int indent)
fprintf_indented(file, indent, "(type-func %s)\n", type->func.signature->mangled_signature);
return;
case TYPE_STRUCT:
fprintf_indented(file, indent, "(struct %s::%s)\n", type->decl->module->name, type->decl->name.string);
fprintf_indented(file, indent, "(struct %s::%s)\n", type->decl->module->name, type->decl->name);
return;
case TYPE_UNION:
fprintf_indented(file, indent, "(union %s::%s)\n", type->decl->module->name, type->decl->name.string);
fprintf_indented(file, indent, "(union %s::%s)\n", type->decl->module->name, type->decl->name);
return;
case TYPE_ENUM:
fprintf_indented(file, indent, "(enum %s::%s)\n", type->decl->module->name, type->decl->name.string);
fprintf_indented(file, indent, "(enum %s::%s)\n", type->decl->module->name, type->decl->name);
return;
case TYPE_ERROR:
fprintf_indented(file, indent, "(error %s::%s)\n", type->decl->module->name, type->decl->name.string);
fprintf_indented(file, indent, "(error %s::%s)\n", type->decl->module->name, type->decl->name);
return;
case TYPE_TYPEDEF:
if (type->canonical != type)
{
fprintf_indented(file, indent, "(user-defined %s::%s\n", type->decl->module->name, type->decl->name.string);
fprintf_indented(file, indent, "(user-defined %s::%s\n", type->decl->module->name, type->decl->name);
fprint_type_recursive(file, type->canonical, indent + 1);
fprint_endparen(file, indent);
break;
@@ -504,7 +512,7 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent)
switch (expr->expr_kind)
{
case EXPR_IDENTIFIER:
fprintf_indented(file, indent, "(ident %s\n", expr->identifier_expr.identifier.string);
fprintf_indented(file, indent, "(ident %s\n", expr->identifier_expr.identifier);
fprint_expr_common(file, expr, indent + 1);
break;
case EXPR_CONST:
@@ -675,13 +683,8 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
{
switch (decl->decl_kind)
{
case DECL_MULTI_DECL:
fprintf_indented(file, indent, "(multi-decl\n");
fprint_decl_list(file, decl->multi_decl, indent + 1);
fprint_endparen(file, indent);
break;
case DECL_VAR:
fprintf_indented(file, indent, "(var-%s %s\n", decl_var_to_string(decl->var.kind), decl->name.string ?: "");
fprintf_indented(file, indent, "(var-%s %s\n", decl_var_to_string(decl->var.kind), decl->name ?: "");
fprint_type_info_recursive(file, decl->var.type_info, indent + 1);
if (decl->var.init_expr)
{
@@ -690,7 +693,7 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
fprint_endparen(file, indent);
break;
case DECL_MACRO:
fprintf_indented(file, indent, "(macro %s\n", decl->name.string);
fprintf_indented(file, indent, "(macro %s\n", decl->name);
fprint_type_info_recursive(file, decl->macro_decl.rtype, indent + 1);
fprint_indent(file, indent + 1);
fprintf(file, "(params\n");
@@ -700,7 +703,7 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
fprint_endparen(file, indent);
break;
case DECL_FUNC:
fprintf_indented(file, indent, "(func %s\n", decl->name.string);
fprintf_indented(file, indent, "(func %s\n", decl->name);
if (decl->func.type_parent)
{
fprint_indent(file, indent + 1);
@@ -714,41 +717,41 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
fprint_endparen(file, indent);
break;
case DECL_STRUCT:
fprintf_indented(file, indent, "(struct %s\n", decl->name.string);
fprintf_indented(file, indent, "(struct %s\n", decl->name);
fprint_decl_list(file, decl->strukt.members, indent + 1);
fprint_endparen(file, indent);
break;
case DECL_UNION:
fprintf_indented(file, indent, "(union %s\n", decl->name.string);
fprintf_indented(file, indent, "(union %s\n", decl->name);
fprint_decl_list(file, decl->strukt.members, indent + 1);
fprint_endparen(file, indent);
break;
case DECL_ENUM:
fprintf_indented(file, indent, "(enum %s\n", decl->name.string);
fprintf_indented(file, indent, "(enum %s\n", decl->name);
fprint_type_info_recursive(file, decl->enums.type_info, indent + 1);
fprint_decl_list(file, decl->enums.values, indent + 1);
fprint_endparen(file, indent);
break;
case DECL_ERROR:
fprintf_indented(file, indent, "(error %s\n", decl->name.string);
fprintf_indented(file, indent, "(error %s\n", decl->name);
fprint_decl_list(file, decl->error.error_constants, indent + 1);
fprint_endparen(file, indent);
break;
case DECL_ENUM_CONSTANT:
if (!decl->enum_constant.expr)
{
fprintf_indented(file, indent, "(enum-constant %s)\n", decl->name.string);
fprintf_indented(file, indent, "(enum-constant %s)\n", decl->name);
return;
}
fprintf_indented(file, indent, "(enum-constant %s\n", decl->name.string);
fprintf_indented(file, indent, "(enum-constant %s\n", decl->name);
fprint_expr_recursive(file, decl->enum_constant.expr, indent + 1);
fprint_endparen(file, indent);
break;
case DECL_ERROR_CONSTANT:
fprintf_indented(file, indent, "(error-constant %s)\n", decl->name.string);
fprintf_indented(file, indent, "(error-constant %s)\n", decl->name);
break;
case DECL_GENERIC:
fprintf_indented(file, indent, "(generic %s\n", decl->name.string);
fprintf_indented(file, indent, "(generic %s\n", decl->name);
fprint_indent(file, indent + 1);
fprintf(file, "(params\n");
{
@@ -771,7 +774,7 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
fprint_endparen(file, indent);
break;
case DECL_TYPEDEF:
fprintf_indented(file, indent, "(typedef %s\n", decl->name.string);
fprintf_indented(file, indent, "(typedef %s\n", decl->name);
if (decl->typedef_decl.is_func)
{
fprint_func_signature(file, &decl->typedef_decl.function_signature, indent + 1);
@@ -816,7 +819,7 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
fprint_endparen(file, indent);
return;
case DECL_IMPORT:
fprintf_indented(file, indent, "(import %s", decl->name.string);
fprintf_indented(file, indent, "(import %s", decl->name);
TODO
fprint_endparen(file, indent);
break;
@@ -848,6 +851,18 @@ static void fprint_ast_recursive(FILE *file, Ast *ast, int indent)
fprint_indent(file, indent);
switch (ast->ast_kind)
{
case AST_FUNCTION_BLOCK_STMT:
if (!ast->compound_stmt.stmts)
{
fprintf(file, "(function_block)\n");
return;
}
fprintf(file, "(function_block\n");
{
fprint_asts_recursive(file, ast->compound_stmt.stmts, indent + 1);
}
break;
case AST_COMPOUND_STMT:
if (!ast->compound_stmt.stmts)
{
@@ -931,7 +946,7 @@ static void fprint_ast_recursive(FILE *file, Ast *ast, int indent)
}
if (ast->for_stmt.incr)
{
fprint_expr_recursive(file, ast->for_stmt.incr, indent + 1);
fprint_ast_recursive(file, ast->for_stmt.incr, indent + 1);
}
else
{
@@ -1010,10 +1025,10 @@ static void fprint_ast_recursive(FILE *file, Ast *ast, int indent)
TODO
break;
case AST_GOTO_STMT:
fprintf(file, "(goto %s)\n", ast->token.string);
fprintf(file, "(goto %s)\n", ast->goto_stmt.label_name);
return;
case AST_LABEL:
fprintf(file, "(label %s)\n", ast->token.string);
fprintf(file, "(label %s)\n", ast->label_stmt.name);
return;
case AST_NOP_STMT:
TODO
@@ -1040,5 +1055,5 @@ void fprint_decl(FILE *file, Decl *dec)
fprint_decl_recursive(file, dec, 0);
}
Module poisoned_module = { .name = NULL };
Decl all_error = { .decl_kind = DECL_ERROR, .name = { .type = TOKEN_INVALID_TOKEN, .string = NULL } };
Decl all_error = { .decl_kind = DECL_ERROR, .name = NULL };

View File

@@ -38,7 +38,7 @@ static bool sema_type_mismatch(Expr *expr, Type *type, CastType cast_type)
break;
}
SEMA_ERROR(expr->loc, "Cannot %s '%s' to '%s'", action, type_to_error_string(expr->type), type_to_error_string(type));
SEMA_ERROR(expr, "Cannot %s '%s' to '%s'", action, type_to_error_string(expr->type), type_to_error_string(type));
return false;
}
@@ -294,7 +294,7 @@ bool sisi(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_typ
{
if ((i > int_type_max[index]) || (i < int_type_min[index]))
{
SEMA_ERROR(left->loc, "'%lld' does not fit into '%s'", i, canonical->name);
SEMA_ERROR(left, "'%lld' does not fit into '%s'", i, canonical->name);
return false;
}
}
@@ -383,7 +383,7 @@ bool uisi(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_typ
{
if (left->const_expr.i > (uint64_t)int_type_max[index])
{
SEMA_ERROR(left->loc, "Cannot implicitly convert value '%llu' into %s - it will not fit.", left->const_expr.i, type_to_error_string(type));
SEMA_ERROR(left, "Cannot implicitly convert value '%llu' into %s - it will not fit.", left->const_expr.i, type_to_error_string(type));
return false;
}
}
@@ -413,7 +413,7 @@ bool uiui(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_typ
{
if (left->const_expr.i > uint_type_max[index])
{
SEMA_ERROR(left->loc, "Cannot implicitly convert value '%llu' into %s - it will not fit.", type_to_error_string(type));
SEMA_ERROR(left, "Cannot implicitly convert value '%llu' into %s - it will not fit.", type_to_error_string(type));
return false;
}
}

View File

@@ -20,11 +20,12 @@ static void compiler_lex(BuildTarget *target)
bool loaded = false;
File *file = source_file_load(target->sources[i], &loaded);
if (loaded) continue;
lexer_add_file_for_lexing(file);
Lexer lexer;
lexer_add_file_for_lexing(&lexer, file);
printf("# %s\n", file->full_path);
while (1)
{
Token token = lexer_scan_token();
Token token = lexer_scan_token(&lexer);
printf("%s ", token_type_to_string(token.type));
if (token.type == TOKEN_EOF) break;
}
@@ -212,9 +213,9 @@ Module *compiler_find_or_create_module(Path *module_name)
void compiler_register_public_symbol(Decl *decl)
{
Decl *prev = stable_get(&compiler.global_symbols, decl->name.string);
Decl *prev = stable_get(&compiler.global_symbols, decl->name);
// If the previous symbol was already declared globally, remove it.
stable_set(&compiler.global_symbols, decl->name.string, prev ? &poisoned_decl : decl);
stable_set(&compiler.global_symbols, decl->name, prev ? &poisoned_decl : decl);
STable *sub_module_space = stable_get(&compiler.qualified_symbols, decl->module->name->module);
if (!sub_module_space)
{
@@ -222,6 +223,6 @@ void compiler_register_public_symbol(Decl *decl)
stable_init(sub_module_space, 0x100);
stable_set(&compiler.qualified_symbols, decl->module->name->module, sub_module_space);
}
prev = stable_get(sub_module_space, decl->name.string);
stable_set(sub_module_space, decl->name.string, prev ? &poisoned_decl : decl);
prev = stable_get(sub_module_space, decl->name);
stable_set(sub_module_space, decl->name, prev ? &poisoned_decl : decl);
}

View File

@@ -3,6 +3,7 @@
// Use of this source code is governed by the GNU LGPLv3.0 license
// a copy of which can be found in the LICENSE file.
#include <histedit.h>
#include "../utils/common.h"
#include "../utils/errors.h"
#include "../utils/lib.h"
@@ -17,6 +18,7 @@ typedef uint32_t SourceLoc;
#define MAX_LOCALS 0xFFFF
#define MAX_SCOPE_DEPTH 0xFF
#define MAX_PATH 1024
#define MAX_DEFERS 0xFFFF
typedef struct _Ast Ast;
typedef struct _Decl Decl;
@@ -24,15 +26,21 @@ typedef struct _TypeInfo TypeInfo;
typedef struct _Expr Expr;
typedef struct _Module Module;
typedef struct _Type Type;
typedef uint16_t DeferId;
typedef bool(*CastFunc)(Expr *, Type *, Type *, Type *, CastType cast_type);
typedef struct
{
SourceLoc loc;
uint32_t length;
SourceLoc end_loc;
} SourceRange;
typedef struct
{
DeferId start;
DeferId end;
} DeferList;
typedef struct
{
@@ -74,9 +82,8 @@ typedef struct
const char *full_path;
SourceLoc start_id;
SourceLoc end_id;
SourceLoc *line_start;
SourceLoc *lines;
SourceLoc current_line_start;
int last_line_found;
} File;
typedef struct
@@ -287,7 +294,9 @@ typedef struct
typedef struct _Decl
{
Token name;
const char *name;
SourceRange name_span;
SourceRange span;
const char *external_name;
DeclKind decl_kind : 6;
Visibility visibility : 2;
@@ -326,7 +335,6 @@ typedef struct _Decl
FuncDecl func;
AttrDecl attr;
TypedefDecl typedef_decl;
Decl** multi_decl;
MacroDecl macro_decl;
GenericDecl generic_decl;
CtIfDecl ct_if_decl;
@@ -428,7 +436,7 @@ typedef struct
typedef struct
{
Path *path;
Token identifier;
const char *identifier;
bool is_ref;
Decl *decl;
} ExprIdentifier;
@@ -455,7 +463,7 @@ struct _Expr
{
ExprKind expr_kind : 8;
ResolveStatus resolve_status : 3;
Token loc;
SourceRange span;
Type *type;
union {
ExprCast cast_expr;
@@ -486,14 +494,15 @@ typedef struct
typedef struct
{
struct _Ast **stmts;
// DeferList defer_list; TODO
DeferList defer_list;
} AstCompoundStmt;
typedef struct
{
const char *name;
uint16_t last_goto;
bool is_used : 1;
struct _Ast *defer;
Ast *defer;
struct _Ast *in_defer;
void *backend_value;
} AstLabelStmt;
@@ -501,7 +510,7 @@ typedef struct
typedef struct
{
Expr *expr; // May be NULL
struct _Ast *defer;
Ast *defer;
} AstReturnStmt;
typedef struct
@@ -515,6 +524,8 @@ typedef struct
{
Expr *expr;
Ast *body;
DeferList expr_defer;
DeferList body_defer;
} AstDoStmt;
typedef struct
@@ -554,8 +565,9 @@ typedef struct
{
Ast *init;
Expr *cond;
Expr *incr;
Ast *incr;
Ast *body;
DeferList cond_defer;
} AstForStmt;
@@ -563,8 +575,9 @@ typedef struct
typedef struct
{
GotoType type : 2;
const char *label_name;
Ast *label;
struct _Ast *defer;
Ast *defer;
union
{
struct _Ast *in_defer;
@@ -577,6 +590,7 @@ typedef struct _AstDeferStmt
bool emit_boolean : 1;
struct _Ast *body; // Compound statement
struct _Ast *prev_defer;
DeferId id;
} AstDeferStmt;
typedef struct _AstCatchStmt
@@ -626,14 +640,14 @@ typedef struct
typedef struct _Ast
{
SourceRange span;
AstKind ast_kind : 8;
ExitType exit : 3;
Token token;
union
{
AstAttribute attribute;
AstCompoundStmt compound_stmt;
AstCompoundStmt function_block_stmt;
Decl *declare_stmt;
Expr *expr_stmt;
Expr *throw_stmt;
@@ -690,11 +704,24 @@ typedef struct _DynamicScope
ScopeFlags flags_created;
unsigned errors;
Decl **local_decl_start;
unsigned defer_start;
DeferId defer_top;
DeferId defer_last;
ExitType exit;
} DynamicScope;
typedef struct
{
const char *file_begin;
const char *lexing_start;
const char *current;
uint16_t source_file;
File *current_file;
SourceLoc last_in_range;
Token tok;
Token next_tok;
} Lexer;
typedef struct _Context
{
BuildTarget *target;
@@ -705,7 +732,6 @@ typedef struct _Context
Decl *specified_imports;
Module *module;
STable local_symbols;
Decl **header_declarations;
Decl **enums;
Decl **error_types;
Decl **types;
@@ -718,6 +744,10 @@ typedef struct _Context
Decl **last_local;
Ast **labels;
Ast **gotos;
Token *comments;
Token *lead_comment;
Token *trailing_comment;
Token *next_lead_comment;
DynamicScope *current_scope;
Decl *evaluating_macro;
Type *rtype;
@@ -729,6 +759,18 @@ typedef struct _Context
STable external_symbols;
Decl **external_symbol_list;
};
STable scratch_table;
Lexer lexer;
SourceLoc prev_tok_end;
Token tok;
Token next_tok;
struct
{
const char *current;
const char *start;
Token tok;
Token next_tok;
} stored;
} Context;
typedef struct
@@ -739,7 +781,6 @@ typedef struct
Type **type;
} Compiler;
extern Context *current_context;
extern Compiler compiler;
extern Ast poisoned_ast;
extern Decl poisoned_decl;
@@ -749,8 +790,6 @@ extern TypeInfo poisoned_type_info;
extern Module poisoned_module;
extern Diagnostics diagnostics;
extern Token next_tok;
extern Token tok;
extern Decl all_error;
extern Type *type_bool, *type_void, *type_string, *type_voidptr;
@@ -771,20 +810,35 @@ extern Type t_voidstar;
extern const char *main_name;
#define AST_NEW(_kind, _token) new_ast(_kind, _token)
#define AST_NEW_TOKEN(_kind, _token) new_ast(_kind, _token.span)
#define AST_NEW(_kind, _loc) new_ast(_kind, _loc)
static inline bool ast_ok(Ast *ast) { return ast == NULL || ast->ast_kind != AST_POISONED; }
static inline bool ast_poison(Ast *ast) { ast->ast_kind = AST_POISONED; return false; }
static inline Ast *new_ast(AstKind kind, Token token)
Ast *ast_from_expr(Expr *expr);
static inline Ast *new_ast(AstKind kind, SourceRange range)
{
Ast *ast = malloc_arena(sizeof(Ast));
memset(ast, 0, sizeof(Ast));
ast->token = token;
ast->span = range;
ast->ast_kind = kind;
ast->exit = EXIT_NONE;
return ast;
}
static inline Ast *extend_ast(Ast *ast, Token token)
{
ast->span.end_loc = token.span.end_loc;
return ast;
}
static inline Ast *extend_ast_with_prev_token(Context *context, Ast *ast)
{
ast->span.end_loc = context->prev_tok_end;
return ast;
}
void builtin_setup();
@@ -852,16 +906,12 @@ Module *compiler_find_or_create_module(Path *module_name);
void compiler_register_public_symbol(Decl *decl);
Context *context_create(File *file, BuildTarget *target);
void context_push(Context *context);
void context_register_global_decl(Context *context, Decl *decl);
void context_register_external_symbol(Context *context, Decl *decl);
bool context_add_import(Context *context, Path *path, Token symbol, Token alias);
bool context_set_module_from_filename(Context *context);
bool context_set_module(Context *context, Path *path, Token *generic_parameters);
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_with_type(Token name, DeclKind decl_type, Visibility visibility);
@@ -883,16 +933,16 @@ void diag_reset(void);
void diag_error_range(SourceRange span, const char *message, ...);
void diag_verror_range(SourceRange span, const char *message, va_list args);
#define EXPR_NEW_EXPR(_kind, _expr) expr_new(_kind, _expr->loc)
#define EXPR_NEW_TOKEN(_kind, _tok) expr_new(_kind, _tok)
Expr *expr_new(ExprKind kind, Token start);
#define EXPR_NEW_EXPR(_kind, _expr) expr_new(_kind, _expr->span)
#define EXPR_NEW_TOKEN(_kind, _tok) expr_new(_kind, _tok.span)
Expr *expr_new(ExprKind kind, SourceRange start);
static inline bool expr_ok(Expr *expr) { return expr == NULL || expr->expr_kind != EXPR_POISONED; }
static inline bool expr_poison(Expr *expr) { expr->expr_kind = EXPR_POISONED; expr->resolve_status = RESOLVE_DONE; return false; }
static inline void expr_replace(Expr *expr, Expr *replacement)
{
Token loc = expr->loc;
SourceRange loc = expr->span;
*expr = *replacement;
expr->loc = loc;
expr->span = loc;
}
void fprint_ast(FILE *file, Ast *ast);
@@ -901,31 +951,13 @@ void fprint_type_info_recursive(FILE *file, TypeInfo *type_info, int indent);
void fprint_expr_recursive(FILE *file, Expr *expr, int indent);
Token lexer_scan_token(void);
Token lexer_scan_ident_test(const char *scan);
void lexer_test_setup(const char *text, size_t len);
void lexer_add_file_for_lexing(File *file);
File* lexer_current_file(void);
Token lexer_scan_token(Lexer *lexer);
Token lexer_scan_ident_test(Lexer *lexer, const char *scan);
void lexer_test_setup(Lexer *lexer, const char *text, size_t len);
void lexer_add_file_for_lexing(Lexer *lexer, File *file);
File* lexer_current_file(Lexer *lexer);
void lexer_check_init(void);
void lexer_store_state(void);
void lexer_restore_state(void);
static inline void advance(void)
{
tok = next_tok;
while (1)
{
next_tok = lexer_scan_token();
// printf(">>> %.*s => %s\n", tok.length, tok.start, token_type_to_string(tok.type));
if (next_tok.type != TOKEN_INVALID_TOKEN) break;
}
}
static inline void advance_and_verify(TokenType token_type)
{
assert(tok.type == token_type);
advance();
}
typedef enum
{
@@ -942,12 +974,12 @@ Path *path_find_parent_path(Path *path);
const char *resolve_status_to_string(ResolveStatus status);
#define SEMA_ERROR(_tok, ...) sema_error_range(_tok.span, __VA_ARGS__)
void sema_init(File *file);
#define SEMA_TOKEN_ERROR(_tok, ...) sema_error_range(_tok.span, __VA_ARGS__)
#define SEMA_ERROR(_node, ...) sema_error_range(_node->span, __VA_ARGS__)
#define SEMA_PREV(_node, ...) sema_prev_at_range(_node->span, __VA_ARGS__)
void sema_analysis_pass_process_imports(Context *context);
void sema_analysis_pass_conditional_compilation(Context *context);
void sema_analysis_pass_decls(Context *context);
void sema_analysis_pass_3(Context *context);
bool sema_add_local(Context *context, Decl *decl);
bool sema_analyse_statement(Context *context, Ast *statement);
@@ -958,7 +990,7 @@ void sema_error_at(SourceLoc loc, const char *message, ...);
void sema_error_range(SourceRange range, const char *message, ...);
void sema_verror_at(SourceLoc loc, const char *message, va_list args);
void sema_verror_range(SourceRange range, const char *message, va_list args);
void sema_error(const char *message, ...);
void sema_error(Context *context, const char *message, ...);
void sema_prev_at_range(SourceRange span, const char *message, ...);
void sema_prev_at(SourceLoc loc, const char *message, ...);
void sema_shadow_error(Decl *decl, Decl *old);
@@ -969,7 +1001,7 @@ void source_file_append_line_end(File *file, SourceLoc loc);
SourcePosition source_file_find_position_in_file(File *file, SourceLoc loc);
SourcePosition source_file_find_position(SourceLoc loc);
SourceRange source_range_from_ranges(SourceRange first, SourceRange last);
static inline unsigned source_range_len(SourceRange range) { return range.end_loc - range.loc; }
void stable_init(STable *table, uint32_t initial_size);
void *stable_set(STable *table, const char *key, void *value);
@@ -1112,4 +1144,5 @@ static inline const char* struct_union_name_from_token(TokenType type)
#define BACKEND_TYPE_GLOBAL(type) gencontext_get_llvm_type(NULL, type)
#define DEBUG_TYPE(type) gencontext_get_debug_type(context, type)
void advance(Context *context);
void advance_and_verify(Context *context, TokenType token_type);

View File

@@ -4,7 +4,6 @@
#include "compiler_internal.h"
Context *current_context;
Context *context_create(File *file, BuildTarget *target)
{
@@ -14,43 +13,10 @@ Context *context_create(File *file, BuildTarget *target)
context->target = target;
stable_init(&context->local_symbols, 256);
stable_init(&context->external_symbols, 256);
stable_init(&context->scratch_table, 32);
return context;
}
void context_push(Context *context)
{
current_context = context;
}
void context_add_header_decl(Context *context, Decl *decl)
{
DEBUG_LOG("Adding %s to header", decl->name.string);
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, Path *module_name)
{
@@ -74,7 +40,7 @@ bool context_set_module_from_filename(Context *context)
int len = filename_to_module(context->file->full_path, buffer);
if (!len)
{
sema_error("The filename '%s' could not be converted to a valid module name, try using an explicit module name.");
sema_error(context, "The filename '%s' could not be converted to a valid module name, try using an explicit module name.");
return false;
}
@@ -82,7 +48,7 @@ bool context_set_module_from_filename(Context *context)
const char *module_name = symtab_add(buffer, (uint32_t) len, fnv1a(buffer, (uint32_t) len), &type);
if (type != TOKEN_IDENT)
{
sema_error("Generating a filename from the file '%s' resulted in a name that is a reserved keyword, "
sema_error(context, "Generating a filename from the file '%s' resulted in a name that is a reserved keyword, "
"try using an explicit module name.");
return false;
}
@@ -162,7 +128,6 @@ void context_register_global_decl(Context *context, Decl *decl)
case DECL_ERROR_CONSTANT:
case DECL_ARRAY_VALUE:
case DECL_IMPORT:
case DECL_MULTI_DECL:
case DECL_CT_ELSE:
case DECL_CT_ELIF:
case DECL_ATTRIBUTE:
@@ -173,17 +138,17 @@ void context_register_global_decl(Context *context, Decl *decl)
vec_add(context->ct_ifs, decl);
return;
}
DEBUG_LOG("Registering symbol '%s'.", decl->name.string);
DEBUG_LOG("Registering symbol '%s'.", decl->name);
Decl *old = stable_set(&context->local_symbols, decl->name.string, decl);
Decl *old = stable_set(&context->local_symbols, decl->name, decl);
if (!old && decl->visibility != VISIBLE_LOCAL)
{
old = stable_set(&context->module->symbols, decl->name.string, decl);
old = stable_set(&context->module->symbols, decl->name, decl);
}
if (!old && decl->visibility == VISIBLE_PUBLIC)
{
compiler_register_public_symbol(decl);
old = stable_set(&context->module->public_symbols, decl->name.string, decl);
old = stable_set(&context->module->public_symbols, decl->name, decl);
}
if (old != NULL)
{

View File

@@ -46,15 +46,15 @@ static void print_error(SourceRange source_range, const char *message, PrintType
break;
}
}
size_t lines_in_file = vec_size(position.file->line_start);
size_t lines_in_file = vec_size(position.file->lines);
for (unsigned i = LINES_SHOWN; i > 0; i--)
{
if (position.line < i) continue;
uint32_t line_number = position.line + 1 - i;
SourceLoc line_start = position.file->line_start[line_number - 1];
SourceLoc line_start = position.file->lines[line_number - 1];
SourceLoc line_end = line_number == lines_in_file ? position.file->end_id :
position.file->line_start[line_number];
position.file->lines[line_number];
uint32_t line_len = line_end - line_start - 1;
eprintf(number_buffer, line_number, line_len, position.file->contents + line_start - position.file->start_id);
}
@@ -74,7 +74,7 @@ static void print_error(SourceRange source_range, const char *message, PrintType
eprintf(" ");
}
}
for (uint32_t i = 0; i < source_range.length; i++)
for (uint32_t i = 0; i < source_range_len(source_range); i++)
{
eprintf("^");
}
@@ -142,7 +142,7 @@ void sema_error_range(SourceRange range, const char *message, ...)
void sema_verror_at(SourceLoc loc, const char *message, va_list args)
{
vprint_error((SourceRange) { loc, 1 }, message, args);
vprint_error((SourceRange) { loc, loc + 1 }, message, args);
diagnostics.errors++;
}
@@ -152,9 +152,9 @@ void sema_verror_range(SourceRange range, const char *message, va_list args)
diagnostics.errors++;
}
void sema_error(const char *message, ...)
void sema_error(Context *context, const char *message, ...)
{
File *file = lexer_current_file();
File *file = lexer_current_file(&context->lexer);
va_list list;
va_start(list, message);
eprintf("(%s:0) Error: ", file->name);
@@ -179,7 +179,7 @@ void sema_prev_at(SourceLoc loc, const char *message, ...)
va_start(args, message);
char buffer[256];
vsnprintf(buffer, 256, message, args);
print_error((SourceRange){ loc, 1 }, buffer, PRINT_TYPE_PREV);
print_error((SourceRange){ loc, loc + 1 }, buffer, PRINT_TYPE_PREV);
va_end(args);
}

View File

@@ -88,6 +88,7 @@ typedef enum
AST_DO_STMT,
AST_EXPR_STMT,
AST_FOR_STMT,
AST_FUNCTION_BLOCK_STMT,
AST_GENERIC_CASE_STMT,
AST_GENERIC_DEFAULT_STMT,
AST_GOTO_STMT,
@@ -201,7 +202,6 @@ typedef enum
DECL_ARRAY_VALUE,
DECL_IMPORT,
DECL_MACRO,
DECL_MULTI_DECL,
DECL_GENERIC,
DECL_CT_IF,
DECL_CT_ELSE,
@@ -251,13 +251,6 @@ typedef enum
} GotoType;
typedef enum
{
LEXER_STATE_NORMAL,
LEXER_STATE_DOCS_PARSE,
LEXER_STATE_DOCS_PARSE_DIRECTIVE,
} LexerState;
typedef enum
{
NUMBER_TYPE_BOOL,
@@ -286,9 +279,8 @@ typedef enum
SCOPE_NONE = 0,
SCOPE_BREAK = 1 << 0,
SCOPE_CONTINUE = 1 << 1,
SCOPE_CONTROL = 1 << 2,
SCOPE_NEXT = 1 << 3,
SCOPE_DEFER = 1 << 4,
SCOPE_NEXT = 1 << 2,
SCOPE_DEFER = 1 << 3,
} ScopeFlags;
typedef enum
@@ -417,12 +409,15 @@ typedef enum
// Otherwise we allow things like "@ foo" which would be pretty bad.
TOKEN_AT_IDENT, // @foobar
TOKEN_HASH_IDENT, // #foobar
TOKEN_CT_IDENT, // $foobar
TOKEN_CT_IDENT, // $foobar
TOKEN_STRING, // "Teststring"
TOKEN_INTEGER, // 123 0x23 0b10010 0o327
TOKEN_REAL, // 0x23.2p-2a 43.23e23
TOKEN_COMMENT, // Comment
TOKEN_DOC_COMMENT, // Doc Comment
// Keywords
TOKEN_ALIAS, // Reserved
TOKEN_AS,

View File

@@ -37,8 +37,11 @@ static bool expr_is_ltype(Expr *expr)
static inline bool sema_type_error_on_binop(Expr *expr)
{
const char *c = token_type_to_string(binaryop_to_token(expr->binary_expr.operator));
SEMA_ERROR(expr->loc, "Cannot perform '%s' %s '%s'.",
type_to_error_string(expr->binary_expr.left->type), c, type_to_error_string(expr->binary_expr.right->type));
SEMA_ERROR(expr,
"Cannot perform '%s' %s '%s'.",
type_to_error_string(expr->binary_expr.left->type),
c,
type_to_error_string(expr->binary_expr.right->type));
return false;
}
@@ -60,7 +63,7 @@ static inline bool sema_expr_analyse_ternary(Context *context, Type *to, Expr *e
Type *type = cond->type->canonical;
if (type->type_kind != TYPE_BOOL && cast_to_bool_kind(type) == CAST_ERROR)
{
SEMA_ERROR(cond->loc, "Cannot convert expression to boolean.");
SEMA_ERROR(cond, "Cannot convert expression to boolean.");
return false;
}
left = cond;
@@ -76,8 +79,8 @@ static inline bool sema_expr_analyse_ternary(Context *context, Type *to, Expr *e
Type *max = type_find_max_type(left_canonical, right_canonical);
if (!max)
{
SEMA_ERROR(expr->loc, "Cannot find a common parent type of '%s' and '%s'",
type_to_error_string(left_canonical), type_to_error_string(right_canonical));
SEMA_ERROR(expr, "Cannot find a common parent type of '%s' and '%s'",
type_to_error_string(left_canonical), type_to_error_string(right_canonical));
return false;
}
if (!cast_implicit(left, max) || !cast_implicit(right, max)) return false;
@@ -92,25 +95,27 @@ static inline bool sema_expr_analyse_identifier(Context *context, Type *to, Expr
{
// TODO what about struct functions
Decl *ambiguous_decl;
Decl *decl = sema_resolve_symbol(context, expr->identifier_expr.identifier.string, expr->identifier_expr.path, &ambiguous_decl);
Decl *decl = sema_resolve_symbol(context, expr->identifier_expr.identifier, expr->identifier_expr.path, &ambiguous_decl);
if (!decl)
{
SEMA_ERROR(expr->identifier_expr.identifier, "Unknown symbol '%s'.", expr->identifier_expr.identifier.string);
SEMA_ERROR(expr, "Unknown symbol '%s'.", expr->identifier_expr.identifier);
return false;
}
if (ambiguous_decl)
{
SEMA_ERROR(expr->identifier_expr.identifier, "Ambiguous symbol '%s' both defined in %s and %s, please add the module name to resolve the ambiguity",
expr->identifier_expr.identifier.string,
decl->module->name->module, ambiguous_decl->module->name->module);
SEMA_ERROR(expr,
"Ambiguous symbol '%s' both defined in %s and %s, please add the module name to resolve the ambiguity",
expr->identifier_expr.identifier,
decl->module->name->module,
ambiguous_decl->module->name->module);
return false;
}
if (decl->decl_kind == DECL_FUNC && !expr->identifier_expr.path && decl->module != context->module)
{
SEMA_ERROR(expr->identifier_expr.identifier, "Functions from other modules, must be prefixed with the module name");
SEMA_ERROR(expr, "Functions from other modules, must be prefixed with the module name");
return false;
}
@@ -191,7 +196,7 @@ static inline bool sema_expr_analyse_call(Context *context, Type *to, Expr *expr
case DECL_POISONED:
return false;
default:
SEMA_ERROR(expr->loc, "The expression cannot be called.");
SEMA_ERROR(expr, "The expression cannot be called.");
return false;
}
}
@@ -227,7 +232,7 @@ static inline bool sema_expr_analyse_subscript(Context *context, Type *to, Expr
inner_type = type_char;
break;
default:
SEMA_ERROR(expr->subscript_expr.expr->loc, "Cannot index '%s'.", type_to_error_string(type));
SEMA_ERROR(expr->subscript_expr.expr, "Cannot index '%s'.", type_to_error_string(type));
return false;
}
@@ -243,13 +248,13 @@ static inline bool sema_expr_analyse_method_function(Context *context, Expr *exp
VECEACH(decl->method_functions, i)
{
Decl *function = decl->method_functions[i];
if (function->name.string == name)
if (function->name == name)
{
// TODO
return true;
}
}
SEMA_ERROR(expr->loc, "Cannot find method function '%s.%s'", decl->name.string, name);
SEMA_ERROR(expr, "Cannot find method function '%s.%s'", decl->name, name);
return false;
}
@@ -259,14 +264,14 @@ static inline bool sema_expr_analyse_enum_constant(Context *context, Expr *expr,
VECEACH(decl->enums.values, i)
{
Decl *enum_constant = decl->enums.values[i];
if (enum_constant->name.string == name)
if (enum_constant->name == name)
{
assert(enum_constant->resolve_status == RESOLVE_DONE);
expr_replace(expr, enum_constant->enum_constant.expr);
return true;
}
}
SEMA_ERROR(expr->loc, "'%s' has no enumeration value '%s'.", decl->name.string, name);
SEMA_ERROR(expr, "'%s' has no enumeration value '%s'.", decl->name, name);
return false;
}
@@ -276,7 +281,7 @@ static inline bool sema_expr_analyse_error_constant(Context *context, Expr *expr
VECEACH(decl->error.error_constants, i)
{
Decl *error_constant = decl->error.error_constants[i];
if (error_constant->name.string == name)
if (error_constant->name == name)
{
assert(error_constant->resolve_status == RESOLVE_DONE);
expr->type = decl->type;
@@ -286,7 +291,7 @@ static inline bool sema_expr_analyse_error_constant(Context *context, Expr *expr
return true;
}
}
SEMA_ERROR(expr->loc, "'%s' has no error type '%s'.", decl->name.string, name);
SEMA_ERROR(expr, "'%s' has no error type '%s'.", decl->name, name);
return false;
}
@@ -296,8 +301,8 @@ static Decl *strukt_recursive_search_member(Decl *strukt, const char *name, int
{
(*index)++;
Decl *member = strukt->strukt.members[i];
if (member->name.string == name) return member;
if (!member->name.string && decl_is_struct_type(member))
if (member->name == name) return member;
if (!member->name && decl_is_struct_type(member))
{
Decl *result = strukt_recursive_search_member(member, name, index);
if (result) return result;
@@ -319,7 +324,7 @@ static inline bool sema_expr_analyse_access(Context *context, Type *to, Expr *ex
}
if (!type_may_have_method_functions(type))
{
SEMA_ERROR(expr->loc, "Cannot access '%s' on '%s'", expr->access_expr.sub_element.string, type_to_error_string(parent_type));
SEMA_ERROR(expr, "Cannot access '%s' on '%s'", expr->access_expr.sub_element.string, type_to_error_string(parent_type));
return false;
}
Decl *decl = type->decl;
@@ -338,12 +343,12 @@ static inline bool sema_expr_analyse_access(Context *context, Type *to, Expr *ex
Decl *member = strukt_recursive_search_member(decl, expr->access_expr.sub_element.string, &index);
if (!member)
{
SEMA_ERROR(expr->access_expr.sub_element, "There is no element '%s.%s'.", decl->name.string, expr->access_expr.sub_element.string);
SEMA_TOKEN_ERROR(expr->access_expr.sub_element, "There is no element '%s.%s'.", decl->name, expr->access_expr.sub_element.string);
return false;
}
if (is_pointer)
{
Expr *deref = expr_new(EXPR_UNARY, expr->loc);
Expr *deref = expr_new(EXPR_UNARY, expr->span);
deref->unary_expr.operator = UNARYOP_DEREF;
deref->unary_expr.expr = expr->access_expr.parent;
deref->resolve_status = RESOLVE_DONE;
@@ -361,7 +366,7 @@ static inline bool sema_expr_analyse_type_access(Context *context, Type *to, Exp
if (!sema_resolve_type_info(context, type_info)) return false;
if (!type_may_have_method_functions(type_info->type))
{
SEMA_ERROR(expr->loc, "'%s' does not have method functions.", type_to_error_string(type_info->type));
SEMA_ERROR(expr, "'%s' does not have method functions.", type_to_error_string(type_info->type));
return false;
}
Decl *decl = type_info->type->decl;
@@ -384,14 +389,14 @@ static inline bool sema_expr_analyse_type_access(Context *context, Type *to, Exp
VECEACH(type_info->type->decl->method_functions, i)
{
Decl *function = type_info->type->decl->method_functions[i];
if (expr->type_access.name.string == function->name.string)
if (expr->type_access.name.string == function->name)
{
expr->type_access.method = function;
expr->type = function->func.function_signature.rtype->type;
return true;
}
}
SEMA_ERROR(expr->loc, "No function '%s.%s' found.", type_to_error_string(type_info->type), expr->type_access.name.string);
SEMA_ERROR(expr, "No function '%s.%s' found.", type_to_error_string(type_info->type), expr->type_access.name.string);
return false;
}
@@ -399,7 +404,7 @@ static inline Decl *decl_find_by_name(Decl** decls, const char *name)
{
VECEACH(decls, i)
{
if (decls[i]->name.string == name) return decls[i];
if (decls[i]->name == name) return decls[i];
}
return NULL;
}
@@ -428,7 +433,7 @@ static inline bool sema_expr_analyse_struct_initializer_list(Context *context, T
{
if (field->expr_kind == EXPR_IDENTIFIER)
{
decl = decl_find_by_name(members, field->identifier_expr.identifier.string);
decl = decl_find_by_name(members, field->identifier_expr.identifier);
}
TODO
}
@@ -436,7 +441,7 @@ static inline bool sema_expr_analyse_struct_initializer_list(Context *context, T
{
if (i >= size)
{
SEMA_ERROR(field->loc, "Too many elements in initializer");
SEMA_ERROR(field, "Too many elements in initializer");
return false;
}
decl = members[i];
@@ -464,7 +469,7 @@ static inline bool sema_expr_analyse_initializer_list(Context *context, Type *to
default:
break;
}
SEMA_ERROR(expr->loc, "Cannot assign expression to '%s'.", type_to_error_string(to));
SEMA_ERROR(expr, "Cannot assign expression to '%s'.", type_to_error_string(to));
return false;
}
@@ -494,9 +499,9 @@ static inline bool sema_expr_analyse_cast(Context *context, Type *to, Expr *expr
// TODO above is probably not right, cast type not set.
// Overwrite cast.
Token loc = expr->loc;
SourceRange loc = expr->span;
*expr = *inner;
expr->loc = loc;
expr->span = loc;
return true;
}
@@ -508,7 +513,7 @@ static bool sema_expr_analyse_assign(Context *context, Type *to, Expr *expr, Exp
if (!expr_is_ltype(left))
{
SEMA_ERROR(left->loc, "Expression is not assignable.");
SEMA_ERROR(left, "Expression is not assignable.");
return false;
}
if (!sema_analyse_expr(context, left->type, right)) return false;
@@ -527,7 +532,7 @@ static bool sema_expr_analyse_bit_and_assign(Context *context, Type *to, Expr *e
if (!type_is_number(left->type))
{
SEMA_ERROR(left->loc, "Expected a numeric type here.");
SEMA_ERROR(left, "Expected a numeric type here.");
return false;
}
@@ -535,7 +540,7 @@ static bool sema_expr_analyse_bit_and_assign(Context *context, Type *to, Expr *e
if (!type_is_number(right->type))
{
SEMA_ERROR(right->loc, "Expected a numeric type here.");
SEMA_ERROR(right, "Expected a numeric type here.");
return false;
}
@@ -549,7 +554,7 @@ static bool sema_expr_analyse_bit_or_assign(Context *context, Type *to, Expr *ex
if (!type_is_number(left->type))
{
SEMA_ERROR(left->loc, "Expected a numeric type here.");
SEMA_ERROR(left, "Expected a numeric type here.");
return false;
}
@@ -557,7 +562,7 @@ static bool sema_expr_analyse_bit_or_assign(Context *context, Type *to, Expr *ex
if (!type_is_number(right->type))
{
SEMA_ERROR(right->loc, "Expected a numeric type here.");
SEMA_ERROR(right, "Expected a numeric type here.");
return false;
}
@@ -571,7 +576,7 @@ static bool sema_expr_analyse_bit_xor_assign(Context *context, Type *to, Expr *e
if (!type_is_number(left->type))
{
SEMA_ERROR(left->loc, "Expected a numeric type here.");
SEMA_ERROR(left, "Expected a numeric type here.");
return false;
}
@@ -579,7 +584,7 @@ static bool sema_expr_analyse_bit_xor_assign(Context *context, Type *to, Expr *e
if (!type_is_number(right->type))
{
SEMA_ERROR(right->loc, "Expected a numeric type here.");
SEMA_ERROR(right, "Expected a numeric type here.");
return false;
}
@@ -594,7 +599,7 @@ static bool sema_expr_analyse_div_assign(Context *context, Type *to, Expr *expr,
if (!type_is_number(left->type))
{
SEMA_ERROR(left->loc, "Expected a numeric type here.");
SEMA_ERROR(left, "Expected a numeric type here.");
return false;
}
@@ -602,7 +607,7 @@ static bool sema_expr_analyse_div_assign(Context *context, Type *to, Expr *expr,
if (!type_is_number(right->type))
{
SEMA_ERROR(right->loc, "Expected a numeric type here.");
SEMA_ERROR(right, "Expected a numeric type here.");
return false;
}
@@ -616,7 +621,7 @@ static bool sema_expr_analyse_mult_assign(Context *context, Type *to, Expr *expr
if (!type_is_number(left->type))
{
SEMA_ERROR(left->loc, "Expected a numeric type here.");
SEMA_ERROR(left, "Expected a numeric type here.");
return false;
}
@@ -624,7 +629,7 @@ static bool sema_expr_analyse_mult_assign(Context *context, Type *to, Expr *expr
if (!type_is_number(right->type))
{
SEMA_ERROR(right->loc, "Expected a numeric type here.");
SEMA_ERROR(right, "Expected a numeric type here.");
return false;
}
@@ -647,7 +652,7 @@ static bool sema_expr_analyse_sub_assign(Context *context, Type *to, Expr *expr,
Type *right_type = right->type->canonical;
if (!type_is_integer(right_type))
{
SEMA_ERROR(right->loc, "Expected an integer type instead.");
SEMA_ERROR(right, "Expected an integer type instead.");
return false;
}
expr->type = left->type;
@@ -658,13 +663,13 @@ static bool sema_expr_analyse_sub_assign(Context *context, Type *to, Expr *expr,
if (!type_is_number(left->type))
{
SEMA_ERROR(left->loc, "Expected a numeric type here.");
SEMA_ERROR(left, "Expected a numeric type here.");
return false;
}
if (!type_is_number(right->type))
{
SEMA_ERROR(right->loc, "Expected a numeric type here.");
SEMA_ERROR(right, "Expected a numeric type here.");
return false;
}
@@ -687,7 +692,7 @@ static bool sema_expr_analyse_add_assign(Context *context, Type *to, Expr *expr,
Type *right_type = right->type->canonical;
if (!type_is_integer(right_type))
{
SEMA_ERROR(right->loc, "Expected an integer type instead.");
SEMA_ERROR(right, "Expected an integer type instead.");
return false;
}
expr->type = left->type;
@@ -698,13 +703,13 @@ static bool sema_expr_analyse_add_assign(Context *context, Type *to, Expr *expr,
if (!type_is_number(left->type))
{
SEMA_ERROR(left->loc, "Expected a numeric type here.");
SEMA_ERROR(left, "Expected a numeric type here.");
return false;
}
if (!type_is_number(right->type))
{
SEMA_ERROR(right->loc, "Expected a numeric type here.");
SEMA_ERROR(right, "Expected a numeric type here.");
return false;
}
@@ -750,7 +755,7 @@ static bool sema_expr_analyse_sub(Context *context, Type *to, Expr *expr, Expr *
return true;
ERR:
SEMA_ERROR(expr->loc, "Cannot subtract '%s' from '%s'", type_to_error_string(left_type), type_to_error_string(right_type));
SEMA_ERROR(expr, "Cannot subtract '%s' from '%s'", type_to_error_string(left_type), type_to_error_string(right_type));
return false;
}
@@ -787,7 +792,7 @@ static bool sema_expr_analyse_add(Context *context, Type *to, Expr *expr, Expr *
return true;
ERR:
SEMA_ERROR(expr->loc, "Cannot add '%s' to '%s'", type_to_error_string(left_type), type_to_error_string(right_type));
SEMA_ERROR(expr, "Cannot add '%s' to '%s'", type_to_error_string(left_type), type_to_error_string(right_type));
return false;
}
@@ -806,7 +811,7 @@ static bool sema_expr_analyse_mult(Context *context, Type *to, Expr *expr, Expr
return true;
ERR:
SEMA_ERROR(expr->loc, "Cannot multiply '%s' and '%s'", type_to_error_string(left_type), type_to_error_string(right_type));
SEMA_ERROR(expr, "Cannot multiply '%s' and '%s'", type_to_error_string(left_type), type_to_error_string(right_type));
return false;
}
@@ -827,14 +832,14 @@ static bool sema_expr_analyse_div(Context *context, Type *to, Expr *expr, Expr *
case CONST_INT:
if (right->const_expr.i == 0)
{
SEMA_ERROR(right->loc, "Division by zero not allowed.");
SEMA_ERROR(right, "Division by zero not allowed.");
return false;
}
break;
case CONST_FLOAT:
if (right->const_expr.f == 0)
{
SEMA_ERROR(right->loc, "Division by zero not allowed.");
SEMA_ERROR(right, "Division by zero not allowed.");
return false;
}
break;
@@ -849,7 +854,7 @@ static bool sema_expr_analyse_div(Context *context, Type *to, Expr *expr, Expr *
return true;
ERR:
SEMA_ERROR(expr->loc, "Cannot divide '%s' by '%s'", type_to_error_string(left_type), type_to_error_string(right_type));
SEMA_ERROR(expr, "Cannot divide '%s' by '%s'", type_to_error_string(left_type), type_to_error_string(right_type));
return false;
}
@@ -862,7 +867,7 @@ static bool sema_expr_analyse_mod(Context *context, Type *to, Expr *expr, Expr *
if (right->expr_kind == EXPR_CONST && right->const_expr.i == 0)
{
SEMA_ERROR(expr->binary_expr.right->loc, "Cannot perform mod by zero.");
SEMA_ERROR(expr->binary_expr.right, "Cannot perform mod by zero.");
return false;
}
// TODO Insert trap on negative right.
@@ -946,7 +951,7 @@ static bool sema_expr_analyse_shr(Context *context, Type *to, Expr *expr, Expr *
{
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));
SEMA_ERROR(right, "Rightshift exceeds bitsize of '%s'", type_to_error_string(left->type));
return false;
}
if (left->expr_kind == EXPR_CONST)
@@ -970,7 +975,7 @@ static bool sema_expr_analyse_shr_assign(Context *context, Type *to, Expr *expr,
if (!expr_is_ltype(left))
{
SEMA_ERROR(left->loc, "Expression is not assignable.");
SEMA_ERROR(left, "Expression is not assignable.");
return false;
}
@@ -981,7 +986,7 @@ static bool sema_expr_analyse_shr_assign(Context *context, Type *to, Expr *expr,
{
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));
SEMA_ERROR(right, "Rightshift exceeds bitsize of '%s'", type_to_error_string(left->type));
return false;
}
}
@@ -1007,7 +1012,7 @@ static bool sema_expr_analyse_shl(Context *context, Type *to, Expr *expr, Expr *
{
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));
SEMA_ERROR(right, "Leftshift exceeds bitsize of '%s'", type_to_error_string(left->type));
return false;
}
if (left->expr_kind == EXPR_CONST)
@@ -1031,7 +1036,7 @@ static bool sema_expr_analyse_shl_assign(Context *context, Type *to, Expr *expr,
if (!expr_is_ltype(left))
{
SEMA_ERROR(left->loc, "Expression is not assignable.");
SEMA_ERROR(left, "Expression is not assignable.");
return false;
}
@@ -1044,7 +1049,7 @@ static bool sema_expr_analyse_shl_assign(Context *context, Type *to, Expr *expr,
{
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));
SEMA_ERROR(right, "Leftshift exceeds bitsize of '%s'", type_to_error_string(left->type));
return false;
}
}
@@ -1095,7 +1100,7 @@ static bool sema_expr_analyse_comp(Context *context, Type *to, Expr *expr, Expr
bool success = max && cast_implicit(left, max) && cast_implicit(right, max);
if (!success)
{
SEMA_ERROR(expr->loc, "Cannot implicitly convert types to evaluate '%s' %s '%s'", type_to_error_string(left_type), token_type_to_string(binaryop_to_token(expr->binary_expr.operator)), type_to_error_string(right_type));
SEMA_ERROR(expr, "Cannot implicitly convert types to evaluate '%s' %s '%s'", type_to_error_string(left_type), token_type_to_string(binaryop_to_token(expr->binary_expr.operator)), type_to_error_string(right_type));
return false;
}
if (both_const(left, right))
@@ -1157,12 +1162,12 @@ static bool sema_expr_analyse_deref(Context *context, Type *to, Expr *expr, Expr
Type *canonical = inner->type->canonical;
if (canonical->type_kind != TYPE_POINTER)
{
SEMA_ERROR(inner->loc, "Cannot take the dereference of a value of type '%s'", type_to_error_string(inner->type));
SEMA_ERROR(inner, "Cannot take the dereference of a value of type '%s'", type_to_error_string(inner->type));
return false;
}
if (inner->expr_kind == EXPR_CONST)
{
SEMA_ERROR(inner->loc, "Dereferencing nil is not allowed.");
SEMA_ERROR(inner, "Dereferencing nil is not allowed.");
return false;
}
Type *deref_type = inner->type->type_kind != TYPE_POINTER ? inner->type : canonical;
@@ -1174,7 +1179,7 @@ static bool sema_expr_analyse_addr(Context *context, Type *to, Expr *expr, Expr
{
if (!expr_is_ltype(inner))
{
SEMA_ERROR(inner->loc, "Cannot take the address of a value of type '%s'", type_to_error_string(inner->type));
SEMA_ERROR(inner, "Cannot take the address of a value of type '%s'", type_to_error_string(inner->type));
return false;
}
expr->type = type_get_ptr(inner->type);
@@ -1186,7 +1191,7 @@ static bool sema_expr_analyse_neg(Context *context, Type *to, Expr *expr, Expr *
Type *canonical = inner->type->canonical;
if (!builtin_may_negate(canonical))
{
SEMA_ERROR(expr->loc, "Cannot negate %s.", type_to_error_string(inner->type));
SEMA_ERROR(expr, "Cannot negate %s.", type_to_error_string(inner->type));
return false;
}
if (inner->expr_kind != EXPR_CONST)
@@ -1214,7 +1219,7 @@ static bool sema_expr_analyse_bit_not(Context *context, Type *to, Expr *expr, Ex
Type *canonical = inner->type->canonical;
if (!type_is_integer(canonical) && canonical != type_bool)
{
SEMA_ERROR(expr->loc, "Cannot bit negate %s.", type_to_error_string(inner->type));
SEMA_ERROR(expr, "Cannot bit negate %s.", type_to_error_string(inner->type));
}
if (inner->expr_kind != EXPR_CONST)
{
@@ -1296,7 +1301,7 @@ static bool sema_expr_analyse_not(Context *context, Type *to, Expr *expr, Expr *
case TYPE_STRING:
case TYPE_ENUM:
case TYPE_ERROR:
SEMA_ERROR(expr->loc, "Cannot use 'not' on %s", type_to_error_string(inner->type));
SEMA_ERROR(expr, "Cannot use 'not' on %s", type_to_error_string(inner->type));
return false;
}
UNREACHABLE
@@ -1306,12 +1311,12 @@ static inline bool sema_expr_analyse_incdec(Context *context, Type *to, Expr *ex
{
if (!expr_is_ltype(inner))
{
SEMA_ERROR(inner->loc, "Expression cannot be assigned to");
SEMA_ERROR(inner, "Expression cannot be assigned to");
return false;
}
if (!type_is_number(inner->type->canonical) && inner->type->canonical->type_kind != TYPE_POINTER)
{
SEMA_ERROR(inner->loc, "Expression must be a number or a pointer");
SEMA_ERROR(inner, "Expression must be a number or a pointer");
return false;
}
expr->type = inner->type;
@@ -1516,7 +1521,7 @@ bool sema_analyse_expr(Context *context, Type *to, Expr *expr)
expr->resolve_status = RESOLVE_RUNNING;
break;
case RESOLVE_RUNNING:
SEMA_ERROR(expr->loc, "Recursive resolution of expression");
SEMA_ERROR(expr, "Recursive resolution of expression");
return expr_poison(expr);
case RESOLVE_DONE:
return expr_ok(expr);

File diff suppressed because it is too large Load Diff

View File

@@ -46,7 +46,7 @@ static void gencontext_emit_global_variable_definition(GenContext *context, Decl
}
// TODO fix name
decl->var.backend_ref = LLVMAddGlobal(context->module, decl->type->backend_type, decl->name.string);
decl->var.backend_ref = LLVMAddGlobal(context->module, decl->type->backend_type, decl->name);
// If read only: LLVMSetGlobalConstant(decl->var.backend_ref, 1);
@@ -70,8 +70,8 @@ static void gencontext_emit_global_variable_definition(GenContext *context, Decl
{
decl->var.backend_debug_ref = LLVMDIBuilderCreateGlobalVariableExpression(context->debug.builder,
NULL /*scope*/,
decl->name.string,
decl->name.span.length,
decl->name,
source_range_len(decl->name_span),
"linkagename",
2,
context->debug.file,

View File

@@ -14,7 +14,6 @@ static inline LLVMMetadataRef gencontext_create_debug_type_from_decl(GenContext
case DECL_ENUM_CONSTANT:
case DECL_POISONED:
case DECL_GENERIC:
case DECL_MULTI_DECL:
case DECL_MACRO:
case DECL_CT_IF:
case DECL_CT_ELSE:

View File

@@ -34,14 +34,16 @@ static inline LLVMValueRef gencontext_emit_sub_int(GenContext *context, Type *ty
static inline LLVMValueRef gencontext_emit_subscript_addr(GenContext *context, Expr *expr)
{
LLVMValueRef index = gencontext_emit_expr(context, expr->subscript_expr.index);
switch (expr->subscript_expr.expr->type->canonical->type_kind)
Type *type = expr->subscript_expr.expr->type->canonical;
switch (type->type_kind)
{
case TYPE_ARRAY:
TODO
case TYPE_POINTER:
return LLVMBuildGEP(context->builder,
gencontext_emit_expr(context, expr->subscript_expr.expr),
&index, 1, "[]");
return LLVMBuildGEP2(context->builder,
BACKEND_TYPE(type->pointer),
gencontext_emit_expr(context, expr->subscript_expr.expr),
&index, 1, "[]");
case TYPE_VARARRAY:
case TYPE_SUBARRAY:
case TYPE_STRING:
@@ -54,7 +56,7 @@ static inline LLVMValueRef gencontext_emit_subscript_addr(GenContext *context, E
static inline LLVMValueRef gencontext_emit_access_addr(GenContext *context, Expr *expr)
{
LLVMValueRef value = gencontext_emit_address(context, expr->access_expr.parent);
return LLVMBuildStructGEP(context->builder, value, (unsigned)expr->access_expr.index, "");
return LLVMBuildStructGEP2(context->builder, BACKEND_TYPE(expr->access_expr.parent->type), value, (unsigned)expr->access_expr.index, "");
}
LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
@@ -216,7 +218,7 @@ LLVMValueRef gencontext_emit_unary_expr(GenContext *context, Expr *expr)
case UNARYOP_ADDR:
return gencontext_emit_address(context, expr->unary_expr.expr);
case UNARYOP_DEREF:
return LLVMBuildLoad(context->builder, gencontext_emit_expr(context, expr->unary_expr.expr), "deref");
return LLVMBuildLoad2(context->builder, BACKEND_TYPE(expr->unary_expr.expr->type), gencontext_emit_expr(context, expr->unary_expr.expr), "deref");
case UNARYOP_INC:
return gencontext_emit_pre_inc_dec(context, expr->unary_expr.expr, 1, false);
case UNARYOP_DEC:
@@ -514,7 +516,7 @@ LLVMValueRef gencontext_emit_ternary_expr(GenContext *context, Expr *expr)
static LLVMValueRef gencontext_emit_identifier_expr(GenContext *context, Expr *expr)
{
return LLVMBuildLoad2(context->builder, expr->identifier_expr.decl->type->canonical->backend_type,
expr->identifier_expr.decl->var.backend_ref, expr->identifier_expr.decl->name.string);
expr->identifier_expr.decl->var.backend_ref, expr->identifier_expr.decl->name);
}
LLVMValueRef gencontext_emit_const_expr(GenContext *context, Expr *expr)
@@ -575,7 +577,7 @@ static inline LLVMValueRef gencontext_emit_access_expr(GenContext *context, Expr
{
// Improve, add string description to the access?
LLVMValueRef value = gencontext_emit_address(context, expr->access_expr.parent);
LLVMValueRef val = LLVMBuildStructGEP(context->builder, value, (unsigned)expr->access_expr.index, "");
LLVMValueRef val = LLVMBuildStructGEP2(context->builder, BACKEND_TYPE(expr->access_expr.parent->type), value, (unsigned)expr->access_expr.index, "");
return LLVMBuildLoad2(context->builder, gencontext_get_llvm_type(context, expr->type), val, "");
}
@@ -612,6 +614,13 @@ static inline LLVMValueRef gencontext_emit_struct_init_values_expr(GenContext *c
TODO
}
LLVMValueRef gencontext_emit_ast_expr(GenContext *context, Ast *expr)
{
assert(expr->ast_kind == AST_EXPR_STMT);
LLVMValueRef value = gencontext_emit_expr(context, expr->expr_stmt);
// gencontext_emit_defer(context, expr);
return value;
}
LLVMValueRef gencontext_emit_expr(GenContext *context, Expr *expr)
{

View File

@@ -78,7 +78,7 @@ static inline void gencontext_emit_parameter(GenContext *context, Decl *decl, un
assert(decl->decl_kind == DECL_VAR && decl->var.kind == VARDECL_PARAM);
// Allocate room on stack and copy.
decl->var.backend_ref = gencontext_emit_alloca(context, BACKEND_TYPE(decl->type), decl->name.string);
decl->var.backend_ref = gencontext_emit_alloca(context, BACKEND_TYPE(decl->type), decl->name);
LLVMBuildStore(context->builder, LLVMGetParam(context->function, index), decl->var.backend_ref);
}
@@ -109,7 +109,7 @@ void gencontext_emit_function_body(GenContext *context, Decl *decl)
VECEACH(decl->func.labels, i)
{
Ast *label = decl->func.labels[i];
label->label_stmt.backend_value = gencontext_create_free_block(context, label->token.string);
label->label_stmt.backend_value = gencontext_create_free_block(context, label->label_stmt.name);
}
gencontext_emit_compound_stmt(context, decl->func.body);
@@ -178,11 +178,11 @@ void gencontext_emit_function_decl(GenContext *context, Decl *decl)
flags |= LLVMDIFlagPublic;
break;
}
SourcePosition decl_position = source_file_find_position(decl->name.span.loc);
SourcePosition decl_position = source_file_find_position(decl->name_span.loc);
context->debug.function = LLVMDIBuilderCreateFunction(context->debug.builder,
context->debug.compile_unit,
decl->name.string, decl->name.span.length,
decl->name.string, decl->name.span.length,
decl->name, source_range_len(decl->name_span),
decl->name, source_range_len(decl->name_span),
context->debug.file,
decl_position.line,
decl->type->backend_debug_type,
@@ -228,7 +228,6 @@ void gencontext_emit_extern_decl(GenContext *context, Decl *decl)
case DECL_ARRAY_VALUE:
case DECL_IMPORT:
case DECL_MACRO:
case DECL_MULTI_DECL:
case DECL_GENERIC:
case DECL_CT_IF:
case DECL_CT_ELSE:

View File

@@ -72,7 +72,9 @@ typedef struct
void gencontext_begin_module(GenContext *context);
void gencontext_end_module(GenContext *context);
void gencontext_emit_stmt(GenContext *context, Ast *ast);
void gencontext_emit_defer(GenContext *context, DeferList defer_list);
LLVMValueRef gencontext_emit_expr(GenContext *context, Expr *expr);
LLVMValueRef gencontext_emit_ast_expr(GenContext *context, Ast *expr);
LLVMMetadataRef gencontext_get_debug_type(GenContext *context, Type *type);
void gencontext_emit_debug_location(GenContext *context, SourceRange location);
LLVMMetadataRef gencontext_create_builtin_debug_type(GenContext *context, Type *builtin_type);

View File

@@ -22,7 +22,7 @@ static LLVMValueRef gencontext_emit_decl(GenContext *context, Ast *ast)
{
Decl *decl = ast->declare_stmt;
decl->var.backend_ref = gencontext_emit_alloca(context, BACKEND_TYPE(decl->type), decl->name.string);
decl->var.backend_ref = gencontext_emit_alloca(context, BACKEND_TYPE(decl->type), decl->name);
// TODO NRVO
// TODO debug info
/*
@@ -99,6 +99,13 @@ static inline void gencontext_emit_return(GenContext *context, Ast *ast)
{
// Ensure we are on a branch that is non empty.
if (!gencontext_check_block_branch_emit(context)) return;
Ast *defer = ast->return_stmt.defer;
while (defer)
{
gencontext_emit_stmt(context, defer->defer_stmt.body);
// TODO boolean
defer = defer->defer_stmt.prev_defer;
}
if (!ast->return_stmt.expr)
{
LLVMBuildRetVoid(context->builder);
@@ -109,7 +116,6 @@ static inline void gencontext_emit_return(GenContext *context, Ast *ast)
context->current_block = NULL;
LLVMBasicBlockRef post_ret_block = gencontext_create_free_block(context, "ret");
gencontext_emit_block(context, post_ret_block);
}
@@ -219,6 +225,7 @@ void gencontext_emit_for_stmt(GenContext *context, Ast *ast)
gencontext_emit_br(context, cond_block);
gencontext_emit_block(context, cond_block);
value = gencontext_emit_expr(context, ast->for_stmt.cond);
gencontext_emit_defer(context, ast->for_stmt.cond_defer);
// If we have a body, conditionally jump to it.
if (body_block)
{
@@ -251,7 +258,7 @@ void gencontext_emit_for_stmt(GenContext *context, Ast *ast)
{
// Emit the block
gencontext_emit_block(context, inc_block);
gencontext_emit_expr(context, ast->for_stmt.incr);
gencontext_emit_expr(context, ast->for_stmt.incr->expr_stmt);
}
// Loop back.
@@ -451,11 +458,23 @@ void gencontext_emit_switch(GenContext *context, Ast *ast)
gencontext_emit_block(context, exit_block);
}
void gencontext_emit_defer(GenContext *context, DeferList defer_list)
{
if (defer_list.start == defer_list.end) return;
Ast *defer = context->ast_context->defers[defer_list.start - 1];
while (defer && defer->defer_stmt.id != defer_list.end)
{
gencontext_emit_stmt(context, defer->defer_stmt.body);
// TODO boolean
}
}
void gencontext_emit_stmt(GenContext *context, Ast *ast)
{
switch (ast->ast_kind)
{
case AST_FUNCTION_BLOCK_STMT:
TODO
case AST_POISONED:
UNREACHABLE
case AST_EXPR_STMT:
@@ -495,9 +514,9 @@ void gencontext_emit_stmt(GenContext *context, Ast *ast)
gencontext_emit_jmp(context, context->break_continue_stack[context->break_continue_stack_index - 1].next_block);
break;
case AST_NOP_STMT:
case AST_DEFER_STMT:
break;
case AST_CATCH_STMT:
case AST_DEFER_STMT:
case AST_TRY_STMT:
case AST_THROW_STMT:
// Should have been lowered.

View File

@@ -15,7 +15,6 @@ static inline LLVMTypeRef gencontext_create_llvm_type_from_decl(GenContext *cont
case DECL_ENUM_CONSTANT:
case DECL_POISONED:
case DECL_GENERIC:
case DECL_MULTI_DECL:
case DECL_MACRO:
case DECL_CT_IF:
case DECL_CT_ELSE:

File diff suppressed because it is too large Load Diff

View File

@@ -67,7 +67,7 @@ Decl *sema_resolve_symbol(Context *context, const char *symbol, Path *path, Decl
Decl **current = context->last_local - 1;
while (current >= first)
{
if (current[0]->name.string == symbol) return current[0];
if (current[0]->name == symbol) return current[0];
current--;
}
}
@@ -108,7 +108,7 @@ Decl *sema_resolve_symbol(Context *context, const char *symbol, Path *path, Decl
bool sema_add_local(Context *context, Decl *decl)
{
Decl *dummy;
Decl *other = sema_resolve_symbol(context, decl->name.string, NULL, &dummy);
Decl *other = sema_resolve_symbol(context, decl->name, NULL, &dummy);
if (other)
{
sema_shadow_error(decl, other);
@@ -120,7 +120,7 @@ bool sema_add_local(Context *context, Decl *decl)
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.");
SEMA_ERROR(decl, "Reached the maximum number of locals.");
return false;
}
decl->var.id = num_vars;

View File

@@ -6,6 +6,12 @@
typedef bool(*AstAnalysis)(Context *, Ast*);
static inline DeferId defer_id_from_ast(Ast *ast)
{
if (!ast) return 0;
assert(ast->ast_kind == AST_DEFER_STMT);
return ast->defer_stmt.id;
}
static inline Type *ast_cond_type(Ast *ast)
{
assert(ast->ast_kind == AST_DECL_EXPR_LIST);
@@ -21,47 +27,11 @@ static inline Type *ast_cond_type(Ast *ast)
}
}
void sema_init(File *file)
{
}
void sema_shadow_error(Decl *decl, Decl *old)
{
sema_error_range(decl->name.span, "The '%s' would shadow a previous declaration.", decl->name.string);
sema_prev_at_range(old->name.span, "The previous use of '%s' was here.", decl->name.string);
}
Decl *context_find_ident(Context *context, const char *symbol)
{
Decl **first = &context->locals[0];
Decl **current = context->last_local - 1;
while (current >= first)
{
if (current[0]->name.string == symbol) return current[0];
current--;
}
Decl *found = module_find_symbol(context->module, symbol, MODULE_SYMBOL_SEARCH_THIS);
if (found) return found;
Decl *symbol_found = NULL;
VECEACH(context->imports, i)
{
Decl *import = context->imports[i];
// Partial imports
if (import->import.symbol.string && import->import.symbol.string != symbol) continue;
Decl *decl = module_find_symbol(import->module, symbol, MODULE_SYMBOL_SEARCH_EXTERNAL);
if (!decl) continue;
if (symbol_found)
{
symbol_found = NULL;
continue;
}
symbol_found = decl;
}
return symbol_found;
SEMA_ERROR(decl, "The '%s' would shadow a previous declaration.", decl->name);
SEMA_PREV(old, "The previous use of '%s' was here.", decl->name);
}
@@ -72,10 +42,12 @@ static inline void context_push_scope_with_flags(Context *context, ScopeFlags fl
FATAL_ERROR("Too deeply nested scopes.");
}
ScopeFlags previous_flags = context->current_scope->flags;
DeferId parent_defer = context->current_scope->defer_last;
context->current_scope++;
context->current_scope->exit = EXIT_NONE;
context->current_scope->local_decl_start = context->last_local;
context->current_scope->defer_start = vec_size(context->defers);
context->current_scope->defer_top = parent_defer;
context->current_scope->defer_last = parent_defer;
context->current_scope->flags = previous_flags | flags;
context->current_scope->flags_created = flags;
}
@@ -85,14 +57,15 @@ static inline void context_push_scope(Context *context)
context_push_scope_with_flags(context, SCOPE_NONE);
}
static inline void context_pop_scope(Context *context)
static inline void context_pop_scope(Context *context, Ast **ast, Expr **expr)
{
assert(context->current_scope != &context->scopes[0]);
context->last_local = context->current_scope->local_decl_start;
assert(vec_size(context->defers) == context->current_scope->defer_start);
ExitType exit_type = context->current_scope->exit;
vec_resize(context->defers, context->current_scope->defer_start);
if (context->current_scope->defer_top != context->current_scope->defer_last)
{
TODO;
}
context->current_scope--;
if (context->current_scope->exit < exit_type)
{
@@ -113,26 +86,6 @@ static bool sema_resolve_ptr_type(Context *context, TypeInfo *type_info)
return true;
}
static void sema_build_defer_chain(Context *context, Ast ***statement_list)
{
unsigned size = vec_size(context->defers);
unsigned start = context->current_scope->defer_start;
for (unsigned i = size; i > start; i--)
{
vec_add(*statement_list, context->defers[i - 1]);
}
}
static void sema_release_defer_chain(Context *context, Ast ***statement_list)
{
unsigned size = vec_size(context->defers);
unsigned start = context->current_scope->defer_start;
for (unsigned i = size; i > start; i--)
{
vec_add(*statement_list, context->defers[i - 1]->defer_stmt.body);
}
vec_resize(context->defers, start);
}
static bool sema_resolve_array_type(Context *context, TypeInfo *type)
{
@@ -145,7 +98,7 @@ static bool sema_resolve_array_type(Context *context, TypeInfo *type)
if (!sema_analyse_expr(context, type_usize, type->array.len)) return type_info_poison(type);
if (type->array.len->expr_kind != EXPR_CONST)
{
SEMA_ERROR(type->array.len->loc, "Expected a constant value as array size.");
SEMA_ERROR(type->array.len, "Expected a constant value as array size.");
return type_info_poison(type);
}
}
@@ -195,7 +148,7 @@ static inline bool sema_analyse_struct_member(Context *context, Decl *decl)
static inline bool sema_analyse_struct_union(Context *context, Decl *decl)
{
DEBUG_LOG("Beginning analysis of %s.", decl->name.string);
DEBUG_LOG("Beginning analysis of %s.", decl->name);
assert(decl->decl_kind == DECL_STRUCT || decl->decl_kind == DECL_UNION);
VECEACH(decl->strukt.members, i)
{
@@ -233,7 +186,7 @@ static inline bool sema_analyse_function_param(Context *context, Decl *param, bo
param->type = param->var.type_info->type;
if (param->var.init_expr && !is_function)
{
SEMA_ERROR(param->var.init_expr->loc, "Function types may not have default arguments.");
SEMA_ERROR(param->var.init_expr, "Function types may not have default arguments.");
return false;
}
if (param->var.init_expr)
@@ -242,7 +195,7 @@ static inline bool sema_analyse_function_param(Context *context, Decl *param, bo
if (!sema_analyse_expr(context, param->type, expr)) return false;
if (expr->expr_kind != EXPR_CONST)
{
SEMA_ERROR(expr->loc, "Only constant expressions may be used as default values.");
SEMA_ERROR(expr, "Only constant expressions may be used as default values.");
return false;
}
}
@@ -260,7 +213,8 @@ static inline Type *sema_analyse_function_signature(Context *context, FunctionSi
type_append_signature_name(signature->rtype->type, buffer, &buffer_write_offset);
buffer[buffer_write_offset++] = '(';
}
// TODO check parameter name appearing more than once.
STable *names = &context->scratch_table;
stable_clear(names);
VECEACH(signature->params, i)
{
Decl *param = signature->params[i];
@@ -278,8 +232,26 @@ static inline Type *sema_analyse_function_signature(Context *context, FunctionSi
buffer[buffer_write_offset++] = ',';
}
type_append_signature_name(param->var.type_info->type, buffer, &buffer_write_offset);
if (param->name)
{
Decl *prev = stable_set(names, param->name, param);
if (prev)
{
SEMA_ERROR(param, "Duplicate parameter name %s.", param->name);
SEMA_PREV(prev, "Previous use of the name was here.");
decl_poison(prev);
decl_poison(param);
all_ok = false;
}
}
}
if (signature->variadic)
{
buffer[buffer_write_offset++] = ',';
buffer[buffer_write_offset++] = '.';
buffer[buffer_write_offset++] = '.';
buffer[buffer_write_offset++] = '.';
}
// TODO variadic
buffer[buffer_write_offset++] = ')';
if (vec_size(signature->throws))
{
@@ -335,6 +307,7 @@ static inline bool sema_analyse_return_stmt(Context *context, Ast *statement)
context->current_scope->exit = EXIT_RETURN;
Type *expected_rtype = context->rtype;
Expr *return_expr = statement->return_stmt.expr;
statement->return_stmt.defer = VECLAST(context->defers);
if (return_expr == NULL)
{
if (!expected_rtype)
@@ -345,7 +318,7 @@ static inline bool sema_analyse_return_stmt(Context *context, Ast *statement)
}
if (expected_rtype->canonical != type_void)
{
SEMA_ERROR(statement->token, "Expected to return a result of type %s.", type_to_error_string(expected_rtype));
SEMA_ERROR(statement, "Expected to return a result of type %s.", type_to_error_string(expected_rtype));
return false;
}
return true;
@@ -382,7 +355,7 @@ static inline bool sema_analyse_var_decl(Context *context, Decl *decl)
static inline Ast *convert_expr_to_ast(Expr *expr)
{
Ast *ast = new_ast(AST_EXPR_STMT, expr->loc);
Ast *ast = AST_NEW(AST_EXPR_STMT, expr->span);
ast->expr_stmt = expr;
return ast;
}
@@ -391,9 +364,9 @@ static inline Expr *convert_decl_to_expr(Context *context, Decl *decl)
assert(decl->decl_kind == DECL_VAR);
assert(decl->decl_kind == VARDECL_LOCAL);
if (!decl->var.init_expr) return NULL;
Expr *assign_expr = expr_new(EXPR_BINARY, decl->name);
Expr *assign_expr = expr_new(EXPR_BINARY, decl->span);
assign_expr->resolve_status = RESOLVE_DONE;
Expr *identifier = expr_new(EXPR_IDENTIFIER, decl->name);
Expr *identifier = expr_new(EXPR_IDENTIFIER, decl->span);
identifier->resolve_status = RESOLVE_DONE;
identifier->identifier_expr.identifier = decl->name;
identifier->identifier_expr.decl = decl;
@@ -413,7 +386,7 @@ static inline bool convert_decl_for_cond(Context *context, Decl *decl, Ast*** st
{
if (is_last)
{
SEMA_ERROR(decl->name, "Expected an initializer for '%s'.", decl->name.string);
SEMA_ERROR(decl, "Expected an initializer for '%s'.", decl->name);
return false;
}
// Simply skip declarations if they don't have an initializer, since they're already registered anyway.
@@ -431,52 +404,10 @@ static inline bool convert_decl_for_cond(Context *context, Decl *decl, Ast*** st
return true;
}
static inline bool convert_stmt_for_cond(Context *context, Ast *stmt, Ast*** stmt_list, Expr** last, bool is_last)
static inline bool sema_analyse_function_block_stmt(Context *context, Ast *stmt)
{
if (stmt->ast_kind == AST_EXPR_STMT)
{
if (is_last)
{
*last = stmt->expr_stmt;
return true;
}
*stmt_list = VECADD(*stmt_list, stmt);
return true;
}
assert(stmt->ast_kind == AST_DECLARE_STMT);
Decl *decl = stmt->declare_stmt;
if (decl->decl_kind != DECL_MULTI_DECL)
{
return convert_decl_for_cond(context, decl, stmt_list, last, is_last);
}
Decl **decls = decl->multi_decl;
assert(vec_size(decls) > 0);
unsigned last_element = vec_size(decls) - 1;
for (unsigned i = 0; i <= last_element; i++)
{
Decl *sub_decl = decls[i];
if (!convert_decl_for_cond(context, sub_decl, stmt_list, last, is_last && last_element == i)) return false;
}
return true;
}
static inline bool decl_or_expr_to_expr_stmt(Context *context, Ast *stmt)
{
if (stmt->ast_kind == AST_EXPR_STMT) return true;
assert(stmt->ast_kind == AST_DECLARE_STMT);
stmt->ast_kind = AST_EXPR_STMT;
Decl *decl = stmt->declare_stmt;
assert(decl->decl_kind == DECL_VAR);
assert(decl->decl_kind == VARDECL_LOCAL);
if (decl->var.init_expr == NULL)
{
SEMA_ERROR(decl->name, "'%s' needs to be assigned.", decl->name.string);
return false;
}
stmt->expr_stmt = decl->var.init_expr;
return true;
TODO
}
static inline bool sema_analyse_decl_expr_list(Context *context, Ast *stmt)
@@ -498,7 +429,7 @@ static inline bool sema_analyse_cond(Context *context, Ast *stmt, bool cast_to_b
size_t size = vec_size(stmt->decl_expr_stmt);
if (!size)
{
SEMA_ERROR(stmt->token, "Expected a boolean expression");
SEMA_ERROR(stmt, "Expected a boolean expression");
return false;
}
@@ -518,13 +449,13 @@ static inline bool sema_analyse_cond(Context *context, Ast *stmt, bool cast_to_b
Expr *init = last->declare_stmt->var.init_expr;
if (!init)
{
SEMA_ERROR(last->token, "Expected a declaration with initializer.");
SEMA_ERROR(last, "Expected a declaration with initializer.");
return false;
}
if (cast_to_bool && init->type->type_kind != TYPE_BOOL &&
cast_to_bool_kind(last->declare_stmt->var.type_info->type) == CAST_ERROR)
{
SEMA_ERROR(last->declare_stmt->var.init_expr->loc, "The expression needs to be convertible to a boolean.");
SEMA_ERROR(last->declare_stmt->var.init_expr, "The expression needs to be convertible to a boolean.");
return false;
}
return true;
@@ -539,14 +470,15 @@ static inline bool sema_analyse_while_stmt(Context *context, Ast *statement)
Ast *decl = statement->while_stmt.decl;
Ast *cond = statement->while_stmt.cond;
Ast *body = statement->while_stmt.body;
context_push_scope_with_flags(context, SCOPE_CONTROL);
context_push_scope(context);
bool success = !decl || sema_analyse_statement(context, decl);
context_push_scope(context);
success = success && sema_analyse_cond(context, cond, true);
context_push_scope_with_flags(context, SCOPE_BREAK | SCOPE_CONTINUE); // NOLINT(hicpp-signed-bitwise)
success = success && sema_analyse_statement(context, body);
context_pop_scope(context);
context_pop_scope(context);
context_pop_scope(context, &body, NULL);
context_pop_scope(context, &cond, NULL);
context_pop_scope(context, &decl, NULL);
if (!success) return false;
return success;
}
@@ -558,28 +490,15 @@ static inline bool sema_analyse_do_stmt(Context *context, Ast *statement)
bool success;
context_push_scope_with_flags(context, SCOPE_BREAK | SCOPE_CONTINUE); // NOLINT(hicpp-signed-bitwise)
success = sema_analyse_statement(context, body);
context_pop_scope(context);
context_pop_scope(context, &body, NULL);
if (!success) return false;
context_push_scope_with_flags(context, SCOPE_CONTROL);
context_push_scope(context);
success = sema_analyse_expr(context, type_bool, expr);
context_pop_scope(context);
context_pop_scope(context, NULL, &expr);
return success;
}
static inline bool sema_analyse_multi_decl(Context *context, Ast *statement)
{
Decl *decl = statement->declare_stmt;
VECEACH(statement->declare_stmt->multi_decl, i)
{
if (!sema_analyse_var_decl(context, statement->declare_stmt->multi_decl[i]))
{
decl_poison(decl);
return false;
}
}
return true;
}
static inline bool sema_analyse_declare_stmt(Context *context, Ast *statement)
{
@@ -601,34 +520,57 @@ static inline bool sema_analyse_defer_stmt(Context *context, Ast *statement)
bool success = sema_analyse_statement(context, statement->defer_stmt.body);
context_pop_scope(context);
context_pop_scope(context, &statement->defer_stmt.body, NULL);
if (!success) return false;
statement->defer_stmt.prev_defer = VECLAST(context->defers);
vec_add(context->defers, statement);
statement->defer_stmt.id = vec_size(context->defers);
return true;
}
static inline bool sema_analyse_default_stmt(Context *context, Ast *statement)
{
SEMA_ERROR(statement->token, "Unexpected 'default' outside of switch");
SEMA_ERROR(statement, "Unexpected 'default' outside of switch");
return false;
}
static inline bool sema_analyse_for_stmt(Context *context, Ast *statement)
{
context_push_scope_with_flags(context, SCOPE_CONTROL);
bool success = true;
bool success = !statement->for_stmt.init || sema_analyse_statement(context, statement->for_stmt.init);
success = success && (!statement->for_stmt.cond || sema_analyse_expr(context, type_bool, statement->for_stmt.cond));
success = success && (!statement->for_stmt.incr || sema_analyse_expr(context, NULL, statement->for_stmt.incr));
context_pop_scope(context);
// Enter for scope
context_push_scope(context);
if (statement->for_stmt.init)
{
success = sema_analyse_statement(context, statement->for_stmt.init);
}
if (success && statement->for_stmt.cond)
{
// Conditional scope start
context_push_scope(context);
success = sema_analyse_expr(context, type_bool, statement->for_stmt.cond);
// Conditional scope end
context_pop_scope(context, NULL, &statement->for_stmt.cond);
}
if (success && statement->for_stmt.incr)
{
// Incr scope start
context_push_scope(context);
success = sema_analyse_statement(context, statement->for_stmt.incr);
// Incr scope end
context_pop_scope(context, &statement->for_stmt.incr, NULL);
}
if (!success) return false;
// Create the for body scope.
context_push_scope_with_flags(context, SCOPE_BREAK | SCOPE_CONTINUE); // NOLINT(hicpp-signed-bitwise)
success = sema_analyse_statement(context, statement->for_stmt.body);
context_pop_scope(context);
// End for body scope
context_pop_scope(context, &statement->for_stmt.body, NULL);
// End for scope
context_pop_scope(context, &statement, NULL);
return success;
}
@@ -637,7 +579,7 @@ static inline bool sema_analyse_goto_stmt(Context *context, Ast *statement)
VECEACH(context->labels, i)
{
Ast *label = context->labels[i];
if (statement->token.string == label->token.string)
if (statement->goto_stmt.label_name == label->label_stmt.name)
{
statement->goto_stmt.type = GOTO_JUMP_BACK;
label->label_stmt.is_used = true;
@@ -655,21 +597,34 @@ static inline bool sema_analyse_if_stmt(Context *context, Ast *statement)
// if (!x) A(); else B();
// into
// if (x) B(); else A();
context_push_scope(context);
Ast *cond = statement->if_stmt.cond;
context_push_scope_with_flags(context, SCOPE_CONTROL);
context_push_scope(context);
bool success = sema_analyse_cond(context, cond, true);
if (statement->if_stmt.else_body)
{
if (statement->if_stmt.then_body->ast_kind != AST_COMPOUND_STMT)
{
SEMA_ERROR(statement->if_stmt.then_body, "if-statements with an 'else' must use '{ }' even around a single statement.");
success = false;
}
if (success && statement->if_stmt.else_body->ast_kind != AST_COMPOUND_STMT)
{
SEMA_ERROR(statement->if_stmt.else_body,
"An 'else' must use '{ }' even around a single statement.");
success = false;
}
}
context_push_scope(context);
success = success && sema_analyse_statement(context, statement->if_stmt.then_body);
context_pop_scope(context);
context_pop_scope(context, &statement->if_stmt.then_body, NULL);
// TODO null flowcheck
if (statement->if_stmt.else_body)
{
context_push_scope(context);
success = success && sema_analyse_statement(context, statement->if_stmt.else_body);
context_pop_scope(context);
context_pop_scope(context, &statement->if_stmt.else_body, NULL);
}
context_pop_scope(context);
context_pop_scope(context, &statement, NULL);
return success;
}
@@ -678,10 +633,10 @@ static inline bool sema_analyse_label(Context *context, Ast *statement)
VECEACH(context->labels, i)
{
Ast *label = context->labels[i];
if (label->token.string == statement->token.string)
if (label->label_stmt.name == statement->label_stmt.name)
{
SEMA_ERROR(tok, "This duplicate label '%s'.", statement->token.string);
sema_prev_at_range(label->token.span, "The previous declaration was here.");
SEMA_ERROR(statement, "This duplicate label '%s'.", statement->label_stmt.name);
sema_prev_at_range(label->span, "The previous declaration was here.");
ast_poison(label);
ast_poison(statement);
return false;
@@ -691,7 +646,7 @@ static inline bool sema_analyse_label(Context *context, Ast *statement)
VECEACH(context->gotos, i)
{
Ast *the_goto = context->gotos[i];
if (the_goto->token.string == statement->token.string)
if (the_goto->goto_stmt.label_name == statement->label_stmt.name)
{
the_goto->goto_stmt.type = GOTO_JUMP_FORWARD;
the_goto->goto_stmt.label = statement;
@@ -723,7 +678,7 @@ static bool sema_analyse_break_stmt(Context *context, Ast *statement)
{
if (!(context->current_scope->flags & SCOPE_BREAK)) // NOLINT(hicpp-signed-bitwise)
{
SEMA_ERROR(statement->token, "'break' is not allowed here.");
SEMA_ERROR(statement, "'break' is not allowed here.");
return false;
}
return true;
@@ -731,7 +686,7 @@ static bool sema_analyse_break_stmt(Context *context, Ast *statement)
static bool sema_analyse_case_stmt(Context *context, Ast *statement)
{
SEMA_ERROR(statement->token, "Unexpected 'case' outside of switch");
SEMA_ERROR(statement, "Unexpected 'case' outside of switch");
return false;
}
@@ -739,10 +694,9 @@ static bool sema_analyse_continue_stmt(Context *context, Ast *statement)
{
if (!(context->current_scope->flags & SCOPE_CONTINUE)) // NOLINT(hicpp-signed-bitwise)
{
SEMA_ERROR(statement->token, "'continue' is not allowed here.");
SEMA_ERROR(statement, "'continue' is not allowed here.");
return false;
}
sema_build_defer_chain(context, &statement->continue_stmt.defers);
return true;
}
@@ -759,7 +713,7 @@ static int sema_check_comp_time_bool(Context *context, Expr *expr)
if (!sema_analyse_expr(context, type_bool, expr)) return -1;
if (expr->expr_kind != EXPR_CONST)
{
SEMA_ERROR(expr->loc, "$if requires a compile time constant value.");
SEMA_ERROR(expr, "$if requires a compile time constant value.");
return -1;
}
return expr->const_expr.b;
@@ -807,14 +761,14 @@ static bool sema_analyse_switch_case(Context *context, Ast*** prev_cases, Ast *c
if (*prev_case)
{
// sema_build_defer_chain(context, prev_cases);
context_pop_scope(context);
context_pop_scope(context, prev_case, NULL);
*prev_case = NULL;
}
Expr *case_expr = case_stmt->case_stmt.expr;
if (!sema_analyse_expr(context, switch_type, case_expr)) return false;
if (case_expr->expr_kind != EXPR_CONST)
{
SEMA_ERROR(case_expr->loc, "This must be a constant expression.");
SEMA_ERROR(case_expr, "This must be a constant expression.");
return false;
}
assert(case_expr->const_expr.type == CONST_INT);
@@ -826,8 +780,8 @@ static bool sema_analyse_switch_case(Context *context, Ast*** prev_cases, Ast *c
{
if ((*prev_cases)[i]->case_stmt.val == val)
{
SEMA_ERROR(case_stmt->token, "Duplicate case value.");
sema_prev_at_range((*prev_cases)[i]->token.span, "Previous use was here.");
SEMA_ERROR(case_stmt, "Duplicate case value.");
sema_prev_at_range((*prev_cases)[i]->span, "Previous use was here.");
return false;
}
}
@@ -842,7 +796,7 @@ static bool sema_analyse_switch_case(Context *context, Ast*** prev_cases, Ast *c
case_stmt->case_stmt.block = NULL;
if (*prev_case)
{
context_pop_scope(context);
context_pop_scope(context, prev_case, NULL);
}
context_push_scope(context);
*prev_case = case_stmt;
@@ -851,7 +805,7 @@ static bool sema_analyse_switch_case(Context *context, Ast*** prev_cases, Ast *c
}
if (!*prev_case)
{
SEMA_ERROR(case_stmt->token, "Expected a 'case' or 'default' statement.");
SEMA_ERROR(case_stmt, "Expected a 'case' or 'default' statement.");
return false;
}
if (case_stmt->ast_kind == AST_NEXT_STMT)
@@ -865,7 +819,7 @@ static bool sema_analyse_switch_case(Context *context, Ast*** prev_cases, Ast *c
}
if (!(*prev_case)->case_stmt.block)
{
(*prev_case)->case_stmt.block = new_ast(AST_COMPOUND_STMT, (*prev_case)->token);
(*prev_case)->case_stmt.block = AST_NEW(AST_COMPOUND_STMT, (*prev_case)->span);
}
vec_add((*prev_case)->case_stmt.block->compound_stmt.stmts, case_stmt);
return true;
@@ -873,7 +827,7 @@ static bool sema_analyse_switch_case(Context *context, Ast*** prev_cases, Ast *c
static bool sema_analyse_switch_stmt(Context *context, Ast *statement)
{
context_push_scope_with_flags(context, SCOPE_CONTROL);
context_push_scope(context);
bool success = sema_analyse_statement(context, statement->switch_stmt.cond);
Ast *cond = statement->switch_stmt.cond;
success = success && sema_analyse_cond(context, cond, false);
@@ -883,7 +837,7 @@ static bool sema_analyse_switch_stmt(Context *context, Ast *statement)
Type *switch_type = ast_cond_type(cond)->canonical;
if (!type_is_integer(switch_type))
{
SEMA_ERROR(cond->token, "Expected an integer or enum type, was '%s'.", type_to_error_string(switch_type));
SEMA_ERROR(cond, "Expected an integer or enum type, was '%s'.", type_to_error_string(switch_type));
return false;
}
Ast *in_case = NULL;
@@ -893,10 +847,10 @@ static bool sema_analyse_switch_stmt(Context *context, Ast *statement)
}
if (in_case)
{
context_pop_scope(context);
context_pop_scope(context, &in_case, NULL);
}
context_pop_scope(context);
context_pop_scope(context);
context_pop_scope(context, &cond, NULL);
context_pop_scope(context, &statement, NULL);
return success;
}
@@ -923,52 +877,116 @@ static bool sema_analyse_compound_stmt(Context *context, Ast *statement)
{
context_push_scope(context);
bool success = sema_analyse_compound_statement_no_scope(context, statement);
context_pop_scope(context);
context_pop_scope(context, &statement, NULL);
return success;
}
static AstAnalysis AST_ANALYSIS[AST_WHILE_STMT + 1] =
static inline bool sema_analyse_statement_inner(Context *context, Ast *statement)
{
[AST_ASM_STMT] = &sema_analyse_asm_stmt,
[AST_ATTRIBUTE] = NULL,
[AST_BREAK_STMT] = &sema_analyse_break_stmt,
[AST_CASE_STMT] = &sema_analyse_case_stmt,
[AST_CATCH_STMT] = &sema_analyse_catch_stmt,
[AST_COMPOUND_STMT] = &sema_analyse_compound_stmt,
[AST_CONTINUE_STMT] = &sema_analyse_continue_stmt,
[AST_CT_IF_STMT] = &sema_analyse_ct_if_stmt,
[AST_DECLARE_STMT] = &sema_analyse_declare_stmt,
[AST_DEFAULT_STMT] = &sema_analyse_default_stmt,
[AST_DEFER_STMT] = &sema_analyse_defer_stmt,
[AST_DO_STMT] = &sema_analyse_do_stmt,
[AST_EXPR_STMT] = &sema_analyse_expr_stmt,
[AST_FOR_STMT] = &sema_analyse_for_stmt,
[AST_GOTO_STMT] = &sema_analyse_goto_stmt,
[AST_IF_STMT] = &sema_analyse_if_stmt,
[AST_LABEL] = &sema_analyse_label,
[AST_NOP_STMT] = &sema_analyse_nop_stmt,
[AST_RETURN_STMT] = &sema_analyse_return_stmt,
[AST_SWITCH_STMT] = &sema_analyse_switch_stmt,
[AST_TRY_STMT] = &sema_analyse_try_stmt,
[AST_THROW_STMT] = &sema_analyse_throw_stmt,
[AST_NEXT_STMT] = NULL, // Never reached
[AST_VOLATILE_STMT] = &sema_analyse_volatile_stmt,
[AST_WHILE_STMT] = &sema_analyse_while_stmt,
[AST_DECL_EXPR_LIST] = &sema_analyse_decl_expr_list,
};
switch (statement->ast_kind)
{
case AST_POISONED:
return false;
case AST_ATTRIBUTE:
UNREACHABLE
case AST_ASM_STMT:
return sema_analyse_asm_stmt(context, statement);
case AST_BREAK_STMT:
return sema_analyse_break_stmt(context, statement);
case AST_CASE_STMT:
return sema_analyse_case_stmt(context, statement);
case AST_CATCH_STMT:
return sema_analyse_catch_stmt(context, statement);
case AST_COMPOUND_STMT:
return sema_analyse_compound_stmt(context, statement);
case AST_CONTINUE_STMT:
return sema_analyse_continue_stmt(context, statement);
case AST_CT_IF_STMT:
return sema_analyse_ct_if_stmt(context, statement);
case AST_DECLARE_STMT:
return sema_analyse_declare_stmt(context, statement);
case AST_DEFAULT_STMT:
return sema_analyse_default_stmt(context, statement);
case AST_DEFER_STMT:
return sema_analyse_defer_stmt(context, statement);
case AST_DO_STMT:
return sema_analyse_do_stmt(context, statement);
case AST_EXPR_STMT:
return sema_analyse_expr_stmt(context, statement);
case AST_FOR_STMT:
return sema_analyse_for_stmt(context, statement);
case AST_GOTO_STMT:
return sema_analyse_goto_stmt(context, statement);
case AST_IF_STMT:
return sema_analyse_if_stmt(context, statement);
case AST_LABEL:
return sema_analyse_label(context, statement);
case AST_NOP_STMT:
return sema_analyse_nop_stmt(context, statement);
case AST_RETURN_STMT:
return sema_analyse_return_stmt(context, statement);
case AST_SWITCH_STMT:
return sema_analyse_switch_stmt(context, statement);
case AST_THROW_STMT:
return sema_analyse_throw_stmt(context, statement);
case AST_TRY_STMT:
return sema_analyse_try_stmt(context, statement);
case AST_NEXT_STMT:
UNREACHABLE
case AST_VOLATILE_STMT:
return sema_analyse_volatile_stmt(context, statement);
case AST_WHILE_STMT:
return sema_analyse_while_stmt(context, statement);
case AST_DECL_EXPR_LIST:
return sema_analyse_decl_expr_list(context, statement);
case AST_FUNCTION_BLOCK_STMT:
return sema_analyse_function_block_stmt(context, statement);
case AST_CT_ELIF_STMT:
case AST_CT_ELSE_STMT:
UNREACHABLE
case AST_CT_FOR_STMT:
case AST_CT_SWITCH_STMT:
case AST_CT_DEFAULT_STMT:
case AST_CT_CASE_STMT:
case AST_GENERIC_CASE_STMT:
case AST_GENERIC_DEFAULT_STMT:
TODO
}
}
bool sema_analyse_statement(Context *context, Ast *statement)
{
if (AST_ANALYSIS[statement->ast_kind](context, statement)) return true;
if (sema_analyse_statement_inner(context, statement)) return true;
return ast_poison(statement);
}
static inline int defer_depth(Ast *defer_stmt)
{
int depth = 0;
while (defer_stmt)
{
defer_stmt = defer_stmt->defer_stmt.prev_defer;
depth++;
}
return depth;
}
static inline void defer_list_walk_to_common_depth(Ast **defer_stmt, int this_depth, int other_depth)
{
int steps = this_depth - other_depth;
for (int i = 0; i < steps; i++)
{
*defer_stmt = (*defer_stmt)->defer_stmt.prev_defer;
}
}
static inline bool sema_analyse_function_body(Context *context, Decl *func)
{
context->active_function_for_analysis = func;
context->rtype = func->func.function_signature.rtype->type;
context->current_scope = &context->scopes[0];
context->current_scope->local_decl_start = 0;
// Clean out the current scope.
memset(context->current_scope, 0, sizeof(*context->current_scope));
context->labels = NULL;
context->gotos = NULL;
context->last_local = &context->locals[0];
@@ -985,13 +1003,54 @@ static inline bool sema_analyse_function_body(Context *context, Decl *func)
{
if (func->func.function_signature.rtype->type->canonical != type_void)
{
SEMA_ERROR(func->name, "Missing return statement at the end of the function.");
SEMA_ERROR(func, "Missing return statement at the end of the function.");
return false;
}
sema_release_defer_chain(context, &func->func.body->compound_stmt.stmts);
}
VECEACH(context->gotos, i)
{
Ast *goto_stmt = context->gotos[i];
Ast *label_target = goto_stmt->goto_stmt.label;
if (!label_target)
{
SEMA_ERROR(goto_stmt, "Goto to a missing label %s.", goto_stmt->goto_stmt.label_name);
return false;
}
// If there are no defers, then that's fine.
if (!goto_stmt->goto_stmt.defer && !label_target->label_stmt.defer) continue;
// First we need to search for the common depth.
int label_depth = defer_depth(label_target->label_stmt.defer);
int goto_depth = defer_depth(goto_stmt->goto_stmt.defer);
Ast *common_depth_label = label_target->label_stmt.defer;
Ast *common_depth_goto = goto_stmt->goto_stmt.defer;
// Now walk up to the common depth.
defer_list_walk_to_common_depth(&common_depth_label, label_depth, goto_depth);
defer_list_walk_to_common_depth(&common_depth_goto, goto_depth, label_depth);
// We might still not match, so walk upwards until we have a match:
while (common_depth_goto != common_depth_label)
{
assert(common_depth_goto && common_depth_label);
common_depth_goto = common_depth_goto->defer_stmt.prev_defer;
common_depth_label = common_depth_label->defer_stmt.prev_defer;
}
// We now know the top defer (which we won't actually generate)
goto_stmt->goto_stmt.defer_end = common_depth_goto;
// Mark all defers that occur on the way "up" to the common depth conditional.
Ast *current = label_target->label_stmt.defer;
while (current != common_depth_goto)
{
current->defer_stmt.emit_boolean = true;
}
}
func->func.labels = context->labels;
context_pop_scope(context);
context_pop_scope(context, &func->func.body, NULL);
context->current_scope = NULL;
return true;
}
@@ -1003,28 +1062,28 @@ static inline bool sema_analyse_method_function(Context *context, Decl *decl)
if (!sema_resolve_type_info(context, parent_type)) return false;
if (!type_may_have_method_functions(parent_type->type))
{
SEMA_ERROR(decl->name, "Method functions can not be associated with '%s'", type_to_error_string(decl->func.type_parent->type));
SEMA_ERROR(decl, "Method functions can not be associated with '%s'", type_to_error_string(decl->func.type_parent->type));
return false;
}
Decl *parent = parent_type->type->decl;
VECEACH(parent->method_functions, i)
{
Decl *function = parent->method_functions[i];
if (function->name.string == decl->name.string)
if (function->name == decl->name)
{
SEMA_ERROR(decl->name, "Duplicate name '%s' for method function.", function->name);
sema_prev_at_range(function->name.span, "Previous definition here.");
SEMA_ERROR(decl, "Duplicate name '%s' for method function.", function->name);
SEMA_PREV(function, "Previous definition here.");
return false;
}
}
DEBUG_LOG("Method function '%s.%s' analysed.", parent->name.string, decl->name.string);
DEBUG_LOG("Method function '%s.%s' analysed.", parent->name, decl->name);
vec_add(parent->method_functions, decl);
return true;
}
static inline bool sema_analyse_func(Context *context, Decl *decl)
{
DEBUG_LOG("Analysing function %s", decl->name.string);
DEBUG_LOG("Analysing function %s", decl->name);
Type *func_type = sema_analyse_function_signature(context, &decl->func.function_signature, true);
decl->type = func_type;
if (!func_type) return decl_poison(decl);
@@ -1033,11 +1092,11 @@ static inline bool sema_analyse_func(Context *context, Decl *decl)
if (!sema_analyse_method_function(context, decl)) return decl_poison(decl);
}
if (decl->func.body && !sema_analyse_function_body(context, decl)) return decl_poison(decl);
if (decl->name.string == main_name)
if (decl->name == main_name)
{
if (decl->visibility == VISIBLE_LOCAL)
{
SEMA_ERROR(decl->name, "'main' cannot have local visibility.");
SEMA_ERROR(decl, "'main' cannot have local visibility.");
return false;
}
decl->visibility = VISIBLE_EXTERN;
@@ -1068,7 +1127,7 @@ static inline bool sema_analyse_global(Context *context, Decl *decl)
if (!sema_analyse_expr(context, decl->type, decl->var.init_expr)) 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.");
SEMA_ERROR(decl->var.init_expr, "The expression must be a constant value.");
return false;
}
}
@@ -1122,7 +1181,7 @@ static inline bool sema_analyse_enum(Context *context, Decl *decl)
Expr *expr = enum_value->enum_constant.expr;
if (!expr)
{
expr = expr_new(EXPR_CONST, EMPTY_TOKEN);
expr = expr_new(EXPR_CONST, INVALID_RANGE);
expr->type = type;
expr->resolve_status = RESOLVE_DONE;
expr->const_expr.type = CONST_INT;
@@ -1138,7 +1197,7 @@ static inline bool sema_analyse_enum(Context *context, Decl *decl)
assert(type_is_integer(expr->type->canonical));
if (expr->expr_kind != EXPR_CONST)
{
SEMA_ERROR(expr->loc, "Expected a constant expression for enum");
SEMA_ERROR(expr, "Expected a constant expression for enum");
success = false;
}
enum_value->resolve_status = RESOLVE_DONE;
@@ -1157,10 +1216,10 @@ bool sema_analyse_decl(Context *context, Decl *decl)
{
if (decl->resolve_status == RESOLVE_DONE) return decl_ok(decl);
DEBUG_LOG("Analyse %s", decl->name.string);
DEBUG_LOG("Analyse %s", decl->name);
if (decl->resolve_status == RESOLVE_RUNNING)
{
SEMA_ERROR(decl->name, "Recursive dependency on %s.", decl->name.string);
SEMA_ERROR(decl, "Recursive dependency on %s.", decl->name);
decl_poison(decl);
return false;
}
@@ -1208,7 +1267,6 @@ bool sema_analyse_decl(Context *context, Decl *decl)
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
@@ -1273,7 +1331,7 @@ void sema_analysis_pass_process_imports(Context *context)
Module *module = stable_get(&compiler.modules, path->module);
if (!module)
{
SEMA_ERROR(import->name, "No module named '%s' could be found.", path->module);
SEMA_ERROR(import, "No module named '%s' could be found.", path->module);
decl_poison(import);
continue;
}
@@ -1333,14 +1391,14 @@ static bool sema_resolve_type_identifier(Context *context, TypeInfo *type_info)
if (!decl)
{
SEMA_ERROR(type_info->unresolved.name_loc, "Unknown type '%s'.", type_info->unresolved.name_loc.string);
SEMA_TOKEN_ERROR(type_info->unresolved.name_loc, "Unknown type '%s'.", type_info->unresolved.name_loc.string);
return type_info_poison(type_info);
}
if (ambiguous_decl)
{
SEMA_ERROR(type_info->unresolved.name_loc, "Ambiguous type '%s' both defined in %s and %s, please add the module name to resolve the ambiguity", type_info->unresolved.name_loc.string,
decl->module->name->module, ambiguous_decl->module->name->module);
SEMA_TOKEN_ERROR(type_info->unresolved.name_loc, "Ambiguous type '%s' both defined in %s and %s, please add the module name to resolve the ambiguity", type_info->unresolved.name_loc.string,
decl->module->name->module, ambiguous_decl->module->name->module);
return type_info_poison(type_info);
}
switch (decl->decl_kind)
@@ -1376,9 +1434,8 @@ static bool sema_resolve_type_identifier(Context *context, TypeInfo *type_info)
case DECL_IMPORT:
case DECL_MACRO:
case DECL_GENERIC:
SEMA_ERROR(type_info->unresolved.name_loc, "This is not a type.");
SEMA_TOKEN_ERROR(type_info->unresolved.name_loc, "This is not a type.");
return type_info_poison(type_info);
case DECL_MULTI_DECL:
case DECL_CT_ELSE:
case DECL_CT_IF:
case DECL_CT_ELIF:
@@ -1396,7 +1453,7 @@ bool sema_resolve_type_shallow(Context *context, TypeInfo *type_info)
if (type_info->resolve_status == RESOLVE_RUNNING)
{
// TODO this is incorrect for unresolved expressions
SEMA_ERROR(type_info->unresolved.name_loc, "Circular dependency resolving type '%s'.", type_info->unresolved.name_loc.string);
SEMA_TOKEN_ERROR(type_info->unresolved.name_loc, "Circular dependency resolving type '%s'.", type_info->unresolved.name_loc.string);
return type_info_poison(type_info);
}

View File

@@ -44,7 +44,7 @@ File *source_file_load(const char *filename, bool *already_loaded)
size_t size;
const char* source_text = read_file(filename, &size);
File *file = malloc(sizeof(File));
File *file = CALLOCS(File);
file->full_path = full_path;
file->start_id = vec_size(source_files.files) ? VECLAST(source_files.files)->end_id : 0;
@@ -53,10 +53,10 @@ File *source_file_load(const char *filename, bool *already_loaded)
ASSERT(file->start_id + size < UINT32_MAX, "Total files loaded exceeded %d bytes", UINT32_MAX);
file->end_id = (SourceLoc) (file->start_id + size);
size_t pre_allocated_lines = size / 40;
file->line_start = VECNEW(SourceLoc, pre_allocated_lines < 16 ? 16 : pre_allocated_lines);
VECADD(file->line_start, file->start_id);
file->lines = VECNEW(SourceLoc, pre_allocated_lines < 16 ? 16 : pre_allocated_lines);
vec_add(file->lines, file->start_id);
path_get_dir_and_filename_from_full(file->full_path, &file->name, &file->dir_path);
VECADD(source_files.files, file);
vec_add(source_files.files, file);
return file;
}
@@ -64,14 +64,14 @@ void source_file_append_line_end(File *file, SourceLoc loc)
{
if (file->current_line_start > loc) return;
file->current_line_start = loc + 1;
VECADD(file->line_start, file->current_line_start);
vec_add(file->lines, file->current_line_start);
}
SourceRange source_range_from_ranges(SourceRange first, SourceRange last)
{
return (SourceRange) {
.loc = first.loc,
.length = last.loc - first.loc + last.length
.end_loc = last.end_loc
};
}
@@ -85,7 +85,7 @@ SourcePosition source_file_find_position_in_file(File *file, SourceLoc loc)
{
assert(file->start_id <= loc);
size_t lines = vec_size(file->line_start);
size_t lines = vec_size(file->lines);
unsigned low = 0;
unsigned high = lines;
while (1)
@@ -95,13 +95,13 @@ SourcePosition source_file_find_position_in_file(File *file, SourceLoc loc)
uint32_t mid = (high + low) / 2;
// Mid is before the location.
SourceLoc line_start = file->line_start[mid];
SourceLoc line_start = file->lines[mid];
if (line_start > loc)
{
high = mid;
continue;
}
if (mid + 1 != lines && file->line_start[mid + 1] < loc)
if (mid + 1 != lines && file->lines[mid + 1] <= loc)
{
low = mid;
continue;

View File

@@ -159,6 +159,12 @@ const char *token_type_to_string(TokenType type)
case TOKEN_REAL:
return "FLOAT";
// Comments
case TOKEN_COMMENT:
return "COMMENT";
case TOKEN_DOC_COMMENT:
return "DOC_COMMENT";
// Keywords
case TOKEN_ALIAS:
return "alias";

View File

@@ -113,7 +113,6 @@ static void type_append_signature_name_user_defined(Decl *decl, char *dst, size_
case DECL_ARRAY_VALUE:
case DECL_IMPORT:
case DECL_MACRO:
case DECL_MULTI_DECL:
case DECL_GENERIC:
case DECL_CT_IF:
case DECL_CT_ELSE:
@@ -124,9 +123,13 @@ static void type_append_signature_name_user_defined(Decl *decl, char *dst, size_
case DECL_UNION:
case DECL_ENUM:
case DECL_ERROR:
memcpy(dst + *offset, decl->name.string, decl->name.span.length);
*offset += decl->name.span.length;
{
unsigned len = source_range_len(decl->name_span);
memcpy(dst + *offset, decl->name, len);
*offset += len;
return;
}
}
UNREACHABLE
}

View File

@@ -21,6 +21,7 @@ static void test_lexer(void)
const int EXPECTED_TOKENS = 12 + 73 + 9;
const char* tokens[TOKEN_EOF];
int len[TOKEN_EOF];
Lexer lexer;
lexer_check_init();
for (int i = 1; i < TOKEN_EOF; i++)
{
@@ -31,7 +32,7 @@ static void test_lexer(void)
const char* interned = symtab_add(token, len[i], fnv1a(token, len[i]), &lookup);
if (lookup != TOKEN_IDENT)
{
Token scanned = lexer_scan_ident_test(token);
Token scanned = lexer_scan_ident_test(&lexer, token);
TEST_ASSERT(scanned.type == i, "Mismatch scanning: was '%s', expected '%s' - lookup: %s - interned: %s.",
token_type_to_string(scanned.type),
token_type_to_string(i),
@@ -56,7 +57,7 @@ static void test_lexer(void)
{
for (int i = 1; i < TOKEN_EOF; i++)
{
volatile TokenType t = lexer_scan_ident_test(tokens[i]).type;
volatile TokenType t = lexer_scan_ident_test(&lexer, tokens[i]).type;
}
}
@@ -77,11 +78,11 @@ static void test_lexer(void)
size_t test_len = strlen(test_parse);
for (int b = 0; b < BENCH_REPEATS; b++)
{
lexer_test_setup(test_parse, test_len);
lexer_test_setup(&lexer, test_parse, test_len);
Token token;
while (1)
{
token = lexer_scan_token();
token = lexer_scan_token(&lexer);
if (token.type == TOKEN_EOF) break;
TEST_ASSERT(token.type != TOKEN_INVALID_TOKEN, "Got invalid token");
@@ -103,7 +104,7 @@ void test_file(void)
File file;
memset(&file, 0, sizeof(file));
file.start_id = 3;
VECADD(file.line_start, file.start_id);
VECADD(file.lines, file.start_id);
TEST_ASSERT(source_file_find_position_in_file(&file, 3).line == 1, "Expected first line");
TEST_ASSERT(source_file_find_position_in_file(&file, 10).line == 1, "Expected first line");
source_file_append_line_end(&file, 9);

View File

@@ -274,7 +274,8 @@ static inline void* _expand(void *vec, size_t element_size)
_vec = __temp; })
#define vec_add(_vec, _value) do { (_vec) = VECADD((_vec), _value); } while (0)
#define VECLAST(_vec) ( (_vec) ? (_vec)[vec_size(_vec) - 1] : NULL)
#define VECLAST(_vec) ({ unsigned _size = vec_size(_vec); _size ? (_vec)[_size - 1] : NULL; })
static inline bool is_all_upper(const char* string)
{