mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Initial work on throws. Cleanup of AST printout (incomplete!). Fixed issues with dead code after return.
This commit is contained in:
@@ -39,7 +39,7 @@ There are some small work being done on the parser here, but most of the structu
|
||||
- `attribute` not analysed.
|
||||
- `$switch` and `$for` not handled.
|
||||
- Enums not correctly handled.
|
||||
- Errors not correctly handles.
|
||||
- Errors not correctly handled.
|
||||
- Type resolution not complete for all types.
|
||||
- `type` not handled.
|
||||
- `?:` not handled.
|
||||
@@ -62,9 +62,7 @@ under discussion.
|
||||
|
||||
#### What's working?
|
||||
|
||||
- The compiler can compile simple programs, but integration with C is mostly
|
||||
missing, which means that little can be *displayed* outwards.
|
||||
- Lexing and parsing works (except for the exceptions noted above).
|
||||
|
||||
- Simple "hello world"
|
||||
|
||||
If you wish to contribute with ideas, please file issues on the c3docs: https://github.com/c3lang/c3docs instead of the compiler.
|
||||
|
||||
@@ -158,7 +158,7 @@ func void hello() throws Errors
|
||||
type(foo::y) z;
|
||||
type(int) * 2;
|
||||
$error = type(int);
|
||||
int[4] a;
|
||||
double[4] a;
|
||||
foo[1 + 2] * b;
|
||||
type((i > 0) ? type(int) : type(double)) doek;
|
||||
$e = type(type(type(Bar)));
|
||||
|
||||
@@ -69,10 +69,25 @@ typedef func void(int) as Foo;
|
||||
|
||||
func void printf(char *hello);
|
||||
|
||||
macro @hello()
|
||||
{
|
||||
printf("Hello world!\n");
|
||||
}
|
||||
|
||||
func int main(int x)
|
||||
{
|
||||
int i = 0;
|
||||
JUMP:
|
||||
i = i + 1;
|
||||
//@hello();
|
||||
printf("Hello worldABC" "D" "E\u2701\n");
|
||||
if (i < 10) goto JUMP;
|
||||
goto EX;
|
||||
YEF:
|
||||
return 4 * test3();
|
||||
EX:
|
||||
printf("EX\n");
|
||||
goto YEF;
|
||||
}
|
||||
|
||||
func void test2(int* x, int y, int z)
|
||||
|
||||
@@ -43,6 +43,7 @@ Decl *decl_new_with_type(Token name, DeclKind decl_type, Visibility visibility)
|
||||
case DECL_TYPEDEF:
|
||||
kind = TYPE_TYPEDEF;
|
||||
break;
|
||||
case DECL_THROWS:
|
||||
case DECL_POISONED:
|
||||
case DECL_VAR:
|
||||
case DECL_ENUM_CONSTANT:
|
||||
@@ -369,6 +370,9 @@ void fprint_type_recursive(FILE *file, Type *type, int indent)
|
||||
fprintf_indented(file, indent, "(comp time float)\n");
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
fprintf_indented(file, indent, "(string)\n");
|
||||
break;
|
||||
case TYPE_ERROR_UNION:
|
||||
TODO
|
||||
}
|
||||
}
|
||||
@@ -390,72 +394,72 @@ const char *resolve_status_to_string(ResolveStatus status)
|
||||
|
||||
void fprint_type_info_recursive(FILE *file, TypeInfo *type_info, int indent)
|
||||
{
|
||||
fprint_indent(file, indent);
|
||||
if (!type_info)
|
||||
{
|
||||
fprintf(file, "(type_info missing)\n");
|
||||
fprintf_indented(file, indent, "(type_info missing)\n");
|
||||
return;
|
||||
}
|
||||
fprintf(file, "(type_info\n");
|
||||
fprint_indent(file, indent + 1);
|
||||
fprintf(file, "(resolve_status %s)\n", resolve_status_to_string(type_info->resolve_status));
|
||||
fprintf_indented(file, indent, "(type_info\n");
|
||||
fprintf_indented(file, indent + 1, "(resolve_status %s)\n", resolve_status_to_string(type_info->resolve_status));
|
||||
if (type_info->resolve_status == RESOLVE_DONE)
|
||||
{
|
||||
fprint_type_recursive(file, type_info->type, indent + 1);
|
||||
fprint_indent(file, indent);
|
||||
fprintf(file, ")\n");
|
||||
fprint_endparen(file, indent);
|
||||
return;
|
||||
}
|
||||
switch (type_info->kind)
|
||||
{
|
||||
case TYPE_INFO_POISON:
|
||||
fprintf(file, "(POISON)\n");
|
||||
return;
|
||||
fprintf_indented(file, indent + 1, "(POISON)\n");
|
||||
break;
|
||||
case TYPE_INFO_IDENTIFIER:
|
||||
if (type_info->unresolved.path)
|
||||
{
|
||||
if (type_info->unresolved.path->module.string)
|
||||
{
|
||||
fprintf(file, "(unresolved %s::%s::%s)\n", type_info->unresolved.path->module.string, type_info->unresolved.path->module.string, type_info->unresolved.name_loc.string);
|
||||
fprintf_indented(file, indent + 1, "(unresolved %s::%s::%s)\n", type_info->unresolved.path->module.string, type_info->unresolved.path->module.string, type_info->unresolved.name_loc.string);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(file, "(unresolved %s::%s)\n", type_info->unresolved.path->module.string, type_info->unresolved.name_loc.string);
|
||||
fprintf_indented(file, indent + 1, "(unresolved %s::%s)\n", type_info->unresolved.path->module.string, type_info->unresolved.name_loc.string);
|
||||
}
|
||||
return;
|
||||
}
|
||||
fprintf(file, "(unresolved %s)\n", type_info->unresolved.name_loc.string);
|
||||
fprintf_indented(file, indent + 1, "(unresolved %s)\n", type_info->unresolved.name_loc.string);
|
||||
break;
|
||||
case TYPE_INFO_ARRAY:
|
||||
fprintf(file, "(unresolved-array\n");
|
||||
fprint_type_info_recursive(file, type_info->array.base, indent + 1);
|
||||
fprint_expr_recursive(file, type_info->array.len, indent + 1);
|
||||
fprintf_indented(file, indent + 1, "(unresolved-array\n");
|
||||
fprint_type_info_recursive(file, type_info->array.base, indent + 2);
|
||||
if (type_info->array.len) fprint_expr_recursive(file, type_info->array.len, indent + 1);
|
||||
fprint_endparen(file, indent + 1);
|
||||
break;
|
||||
case TYPE_INFO_POINTER:
|
||||
fprintf(file, "(pointer\n");
|
||||
fprint_type_info_recursive(file, type_info->pointer, indent + 1);
|
||||
fprintf_indented(file, indent + 1, "(pointer\n");
|
||||
fprint_type_info_recursive(file, type_info->pointer, indent + 2);
|
||||
fprint_endparen(file, indent + 1);
|
||||
break;
|
||||
case TYPE_INFO_INC_ARRAY:
|
||||
fprintf(file, "(incarray\n");
|
||||
fprint_type_info_recursive(file, type_info->array.base, indent + 1);
|
||||
fprintf_indented(file, indent + 1, "(incarray\n");
|
||||
fprint_type_info_recursive(file, type_info->array.base, indent + 2);
|
||||
fprint_endparen(file, indent + 1);
|
||||
break;
|
||||
case TYPE_INFO_EXPRESSION:
|
||||
fprintf(file, "(typexpr\n");
|
||||
fprint_expr_recursive(file, type_info->unresolved_type_expr, indent + 1);
|
||||
fprintf_indented(file, indent + 1, "(typexpr\n");
|
||||
fprint_expr_recursive(file, type_info->unresolved_type_expr, indent + 2);
|
||||
fprint_endparen(file, indent + 1);
|
||||
break;
|
||||
}
|
||||
fprint_endparen(file, indent);
|
||||
}
|
||||
void fprint_expr_recursive(FILE *file, Expr *expr, int indent)
|
||||
{
|
||||
fprint_indent(file, indent);
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_IDENTIFIER:
|
||||
fprintf(file, "(ident %s)\n", expr->identifier_expr.identifier.string);
|
||||
fprintf_indented(file, indent, "(ident %s)\n", expr->identifier_expr.identifier.string);
|
||||
return;
|
||||
case EXPR_CONST:
|
||||
fprintf(file, "(const ");
|
||||
fprintf_indented(file, indent, "(const ");
|
||||
switch (expr->const_expr.type)
|
||||
{
|
||||
case CONST_NIL:
|
||||
@@ -483,37 +487,37 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent)
|
||||
}
|
||||
return;
|
||||
case EXPR_BINARY:
|
||||
fprintf(file, "(binary %s\n", token_type_to_string(expr->binary_expr.operator));
|
||||
fprintf_indented(file, indent, "(binary %s\n", token_type_to_string(expr->binary_expr.operator));
|
||||
fprint_expr_recursive(file, expr->binary_expr.left, indent + 1);
|
||||
fprint_expr_recursive(file, expr->binary_expr.right, indent + 1);
|
||||
break;
|
||||
case EXPR_UNARY:
|
||||
fprintf(file, "(unary %s\n", token_type_to_string(expr->unary_expr.operator));
|
||||
fprintf_indented(file, indent, "(unary %s\n", token_type_to_string(expr->unary_expr.operator));
|
||||
fprint_expr_recursive(file, expr->unary_expr.expr, indent + 1);
|
||||
break;
|
||||
case EXPR_POST_UNARY:
|
||||
fprintf(file, "(postunary %s\n", token_type_to_string(expr->post_expr.operator));
|
||||
fprintf_indented(file, indent, "(postunary %s\n", token_type_to_string(expr->post_expr.operator));
|
||||
fprint_expr_recursive(file, expr->post_expr.expr, indent + 1);
|
||||
break;
|
||||
case EXPR_TYPE_ACCESS:
|
||||
fprintf(file, "(typeaccess .%s\n", expr->type_access.name.string);
|
||||
fprintf_indented(file, indent, "(typeaccess .%s\n", expr->type_access.name.string);
|
||||
fprint_type_info_recursive(file, expr->type_access.type, indent + 1);
|
||||
break;
|
||||
case EXPR_STRUCT_VALUE:
|
||||
fprintf(file, "(structvalue\n");
|
||||
fprintf_indented(file, indent, "(structvalue\n");
|
||||
fprint_type_info_recursive(file, expr->struct_value_expr.type, indent + 1);
|
||||
fprint_expr_recursive(file, expr->struct_value_expr.init_expr, indent + 1);
|
||||
break;
|
||||
case EXPR_ACCESS:
|
||||
fprintf(file, "(access .%s\n", expr->access_expr.sub_element.string);
|
||||
fprintf_indented(file, indent, "(access .%s\n", expr->access_expr.sub_element.string);
|
||||
fprint_expr_recursive(file, expr->access_expr.parent, indent + 1);
|
||||
break;
|
||||
case EXPR_TYPE:
|
||||
fprintf(file, "(type\n");
|
||||
fprintf_indented(file, indent, "(type\n");
|
||||
fprint_type_info_recursive(file, expr->type_expr.type, indent + 1);
|
||||
break;
|
||||
case EXPR_CALL:
|
||||
fprintf(file, "(call\n");
|
||||
fprintf_indented(file, indent, "(call\n");
|
||||
fprint_expr_recursive(file, expr->call_expr.function, indent + 1);
|
||||
{
|
||||
VECEACH(expr->call_expr.arguments, i)
|
||||
@@ -525,19 +529,19 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent)
|
||||
case EXPR_CONDITIONAL:
|
||||
if (!expr->conditional_expr.then_expr)
|
||||
{
|
||||
fprintf(file, "(elvis\n");
|
||||
fprintf_indented(file, indent, "(elvis\n");
|
||||
fprint_expr_recursive(file, expr->conditional_expr.cond, indent + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(file, "(cond\n");
|
||||
fprintf_indented(file, indent, "(cond\n");
|
||||
fprint_expr_recursive(file, expr->conditional_expr.cond, indent + 1);
|
||||
fprint_expr_recursive(file, expr->conditional_expr.then_expr, indent + 1);
|
||||
}
|
||||
fprint_expr_recursive(file, expr->conditional_expr.else_expr, indent + 1);
|
||||
break;
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
fprintf(file, "(initializerlist\n");
|
||||
fprintf_indented(file, indent, "(initializerlist\n");
|
||||
{
|
||||
VECEACH(expr->initializer_expr, i)
|
||||
{
|
||||
@@ -546,25 +550,25 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent)
|
||||
}
|
||||
break;
|
||||
case EXPR_SUBSCRIPT:
|
||||
fprintf(file, "(subscript\n");
|
||||
fprintf_indented(file, indent, "(subscript\n");
|
||||
fprint_expr_recursive(file, expr->subscript_expr.expr, indent + 1);
|
||||
fprint_expr_recursive(file, expr->subscript_expr.index, indent + 1);
|
||||
break;
|
||||
case EXPR_TRY:
|
||||
if (!expr->try_expr.else_expr)
|
||||
{
|
||||
fprintf(file, "(try\n");
|
||||
fprintf_indented(file, indent, "(try\n");
|
||||
fprint_expr_recursive(file, expr->try_expr.expr, indent + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(file, "(try-else\n");
|
||||
fprintf_indented(file, indent, "(try-else\n");
|
||||
fprint_expr_recursive(file, expr->try_expr.expr, indent + 1);
|
||||
fprint_expr_recursive(file, expr->try_expr.else_expr, indent + 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(file, "(TODOEXPR)\n");
|
||||
fprintf_indented(file, indent, "(TODOEXPR)\n");
|
||||
return;
|
||||
}
|
||||
fprint_endparen(file, indent);
|
||||
@@ -584,11 +588,12 @@ void fprint_func_signature(FILE *file, FunctionSignature *signature, int indent)
|
||||
fprintf_indented(file, indent, "(params\n");
|
||||
fprint_decl_list(file, signature->params, indent + 1);
|
||||
fprint_endparen(file, indent);
|
||||
// TODO throws, variable
|
||||
fprintf_indented(file, indent, "(throws\n");
|
||||
fprint_decl_list(file, signature->throws, indent + 1);
|
||||
fprint_endparen(file, indent);
|
||||
}
|
||||
void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
|
||||
{
|
||||
fprint_indent(file, indent);
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_MULTI_DECL:
|
||||
@@ -597,7 +602,7 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
|
||||
fprint_endparen(file, indent);
|
||||
break;
|
||||
case DECL_VAR:
|
||||
fprintf(file, "(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.string ?: "");
|
||||
fprint_type_info_recursive(file, decl->var.type_info, indent + 1);
|
||||
if (decl->var.init_expr)
|
||||
{
|
||||
@@ -662,8 +667,7 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
|
||||
break;
|
||||
case DECL_ERROR_CONSTANT:
|
||||
fprintf_indented(file, indent, "(error-constant %s)\n", decl->name.string);
|
||||
fprint_endparen(file, indent);
|
||||
return;
|
||||
break;
|
||||
case DECL_GENERIC:
|
||||
fprintf_indented(file, indent, "(generic %s\n", decl->name.string);
|
||||
fprint_indent(file, indent + 1);
|
||||
@@ -728,8 +732,10 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
|
||||
fprintf_indented(file, indent, "(poisoned-decl)\n");
|
||||
return;
|
||||
case DECL_ARRAY_VALUE:
|
||||
TODO
|
||||
break;
|
||||
fprintf_indented(file, indent, "(array value");
|
||||
fprint_expr_recursive(file, decl->incr_array_decl, indent + 1);
|
||||
fprint_endparen(file, indent);
|
||||
return;
|
||||
case DECL_IMPORT:
|
||||
fprintf_indented(file, indent, "(import %s", decl->name.string);
|
||||
TODO
|
||||
@@ -737,6 +743,8 @@ void fprint_decl_recursive(FILE *file, Decl *decl, int indent)
|
||||
break;
|
||||
case DECL_ATTRIBUTE:
|
||||
TODO
|
||||
case DECL_THROWS:
|
||||
TODO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -957,4 +965,4 @@ void fprint_decl(FILE *file, Decl *dec)
|
||||
fprint_decl_recursive(file, dec, 0);
|
||||
}
|
||||
Module poisoned_module = { .name = "INVALID" };
|
||||
|
||||
Decl all_error = { .decl_kind = DECL_ERROR, .name = { .type = TOKEN_INVALID_TOKEN, .string = NULL } };
|
||||
|
||||
@@ -550,6 +550,8 @@ CastFunc conversion(TypeKind from, Type *to)
|
||||
if (type_is_integer(to)) return &boxi;
|
||||
if (type_is_float(to)) return &bofp;
|
||||
return &erro;
|
||||
case TYPE_ERROR_UNION:
|
||||
TODO
|
||||
case TYPE_I8:
|
||||
case TYPE_I16:
|
||||
case TYPE_I32:
|
||||
|
||||
@@ -143,7 +143,7 @@ struct _TypeInfo
|
||||
{
|
||||
TypeUnresolved unresolved;
|
||||
Expr *unresolved_type_expr;
|
||||
union
|
||||
struct
|
||||
{
|
||||
TypeInfo *base;
|
||||
Expr *len;
|
||||
@@ -224,7 +224,7 @@ typedef struct _FunctionSignature
|
||||
bool variadic : 1;
|
||||
TypeInfo *rtype;
|
||||
Decl** params;
|
||||
Token *throws;
|
||||
Decl** throws;
|
||||
const char *mangled_signature;
|
||||
} FunctionSignature;
|
||||
|
||||
@@ -702,6 +702,7 @@ typedef struct _Context
|
||||
STable local_symbols;
|
||||
Decl **header_declarations;
|
||||
Decl **enums;
|
||||
Decl **error_types;
|
||||
Decl **types;
|
||||
Decl **functions;
|
||||
Decl **struct_functions;
|
||||
@@ -741,6 +742,7 @@ extern Diagnostics diagnostics;
|
||||
|
||||
extern Token next_tok;
|
||||
extern Token tok;
|
||||
extern Decl all_error;
|
||||
|
||||
extern Type *type_bool, *type_void, *type_string, *type_voidptr;
|
||||
extern Type *type_float, *type_double;
|
||||
|
||||
@@ -131,13 +131,12 @@ void context_register_global_decl(Context *context, Decl *decl)
|
||||
case DECL_UNION:
|
||||
case DECL_TYPEDEF:
|
||||
vec_add(context->types, decl);
|
||||
|
||||
break;
|
||||
case DECL_ENUM:
|
||||
vec_add(context->enums, decl);
|
||||
break;
|
||||
case DECL_ERROR:
|
||||
TODO
|
||||
vec_add(context->error_types, decl);
|
||||
break;
|
||||
case DECL_ENUM_CONSTANT:
|
||||
case DECL_ERROR_CONSTANT:
|
||||
@@ -147,6 +146,7 @@ void context_register_global_decl(Context *context, Decl *decl)
|
||||
case DECL_CT_ELSE:
|
||||
case DECL_CT_ELIF:
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_THROWS:
|
||||
UNREACHABLE
|
||||
break;
|
||||
case DECL_CT_IF:
|
||||
@@ -255,6 +255,10 @@ void context_print_ast(Context *context, FILE *file)
|
||||
{
|
||||
fprint_decl(file, context->types[i]);
|
||||
}
|
||||
VECEACH(context->error_types, i)
|
||||
{
|
||||
fprint_decl(file, context->error_types[i]);
|
||||
}
|
||||
VECEACH(context->functions, i)
|
||||
{
|
||||
fprint_decl(file, context->functions[i]);
|
||||
|
||||
@@ -202,6 +202,7 @@ typedef enum
|
||||
DECL_CT_ELSE,
|
||||
DECL_CT_ELIF,
|
||||
DECL_ATTRIBUTE,
|
||||
DECL_THROWS,
|
||||
} DeclKind;
|
||||
|
||||
// Ordering here is in priority if two branches should have the same exit.
|
||||
@@ -519,6 +520,7 @@ typedef enum
|
||||
TYPE_FUNC,
|
||||
TYPE_STRUCT,
|
||||
TYPE_UNION,
|
||||
TYPE_ERROR_UNION,
|
||||
TYPE_TYPEDEF,
|
||||
TYPE_STRING,
|
||||
TYPE_ARRAY,
|
||||
|
||||
@@ -897,6 +897,7 @@ static bool sema_expr_analyse_not(Context *context, Expr *expr, Expr *inner)
|
||||
case TYPE_UXX:
|
||||
case TYPE_FXX:
|
||||
case TYPE_TYPEDEF:
|
||||
case TYPE_ERROR_UNION:
|
||||
UNREACHABLE
|
||||
case TYPE_FUNC:
|
||||
case TYPE_ARRAY:
|
||||
|
||||
@@ -652,7 +652,7 @@ Token lexer_scan_token(void)
|
||||
case '^':
|
||||
return match('=') ? make_token(TOKEN_BIT_XOR_ASSIGN, "^=") : make_token(TOKEN_BIT_XOR, "^");
|
||||
case '?':
|
||||
return match(':') ? make_token(TOKEN_EQEQ, "?:") : make_token(TOKEN_EQ, "?");
|
||||
return match(':') ? make_token(TOKEN_ELVIS, "?:") : make_token(TOKEN_QUESTION, "?");
|
||||
case '<':
|
||||
if (match('<')) return match('=') ? make_token(TOKEN_SHL_ASSIGN, "<<=") : make_token(TOKEN_SHL, "<<");
|
||||
return match('=') ? make_token(TOKEN_LESS_EQ, "<=") : make_token(TOKEN_LESS, "<");
|
||||
|
||||
@@ -9,6 +9,7 @@ static inline LLVMMetadataRef gencontext_create_debug_type_from_decl(GenContext
|
||||
static LLVMMetadataRef debug_params[512];
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_THROWS:
|
||||
case DECL_ATTRIBUTE:
|
||||
case DECL_ENUM_CONSTANT:
|
||||
case DECL_POISONED:
|
||||
@@ -165,6 +166,8 @@ LLVMMetadataRef gencontext_get_debug_type(GenContext *context, Type *type)
|
||||
break;
|
||||
case TYPE_SUBARRAY:
|
||||
break;
|
||||
case TYPE_ERROR_UNION:
|
||||
TODO
|
||||
}
|
||||
TODO
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ static char *mangle_name(char *buffer, Decl *decl)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void gencontext_emit_br(GenContext *context, LLVMBasicBlockRef next_block)
|
||||
bool gencontext_check_block_branch_emit(GenContext *context)
|
||||
{
|
||||
assert(context->current_block);
|
||||
// If it's not used, we can delete the previous block and skip the branch.
|
||||
@@ -44,8 +44,14 @@ void gencontext_emit_br(GenContext *context, LLVMBasicBlockRef next_block)
|
||||
{
|
||||
LLVMDeleteBasicBlock(context->current_block);
|
||||
context->current_block = NULL;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
void gencontext_emit_br(GenContext *context, LLVMBasicBlockRef next_block)
|
||||
{
|
||||
if (!gencontext_check_block_branch_emit(context)) return;
|
||||
context->current_block = NULL;
|
||||
LLVMBuildBr(context->builder, next_block);
|
||||
}
|
||||
@@ -111,8 +117,15 @@ void gencontext_emit_function_body(GenContext *context, Decl *decl)
|
||||
|
||||
gencontext_emit_compound_stmt(context, decl->func.body);
|
||||
|
||||
if (!LLVMGetFirstInstruction(context->current_block) && !LLVMGetFirstUse(LLVMBasicBlockAsValue(context->current_block)))
|
||||
{
|
||||
LLVMBasicBlockRef prev_block = LLVMGetPreviousBasicBlock(context->current_block);
|
||||
LLVMDeleteBasicBlock(context->current_block);
|
||||
context->current_block = prev_block;
|
||||
LLVMPositionBuilderAtEnd(context->builder, context->current_block);
|
||||
}
|
||||
// Insert a return if needed.
|
||||
if (!LLVMGetBasicBlockTerminator(LLVMGetInsertBlock(context->builder)))
|
||||
if (!LLVMGetBasicBlockTerminator(context->current_block))
|
||||
{
|
||||
assert(decl->func.function_signature.rtype->type->type_kind == TYPE_VOID);
|
||||
LLVMBuildRetVoid(context->builder);
|
||||
|
||||
@@ -79,6 +79,7 @@ LLVMValueRef gencontext_emit_alloca(GenContext *context, Decl *decl);
|
||||
void gencontext_emit_compound_stmt(GenContext *context, Ast *ast);
|
||||
void gencontext_emit_block(GenContext *context, LLVMBasicBlockRef next_block);
|
||||
void gencontext_emit_br(GenContext *context, LLVMBasicBlockRef next_block);
|
||||
bool gencontext_check_block_branch_emit(GenContext *context);
|
||||
void gencontext_emit_cond_br(GenContext *context, LLVMValueRef value, LLVMBasicBlockRef thenBlock, LLVMBasicBlockRef elseBlock);
|
||||
static inline LLVMBasicBlockRef gencontext_create_free_block(GenContext *context, const char *name)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,8 @@ static inline void gencontext_emit_stmt_list(GenContext *context, Ast *ast)
|
||||
|
||||
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;
|
||||
if (!ast->return_stmt.expr)
|
||||
{
|
||||
LLVMBuildRetVoid(context->builder);
|
||||
@@ -36,6 +38,10 @@ static inline void gencontext_emit_return(GenContext *context, Ast *ast)
|
||||
}
|
||||
LLVMValueRef returnValue = gencontext_emit_expr(context, ast->return_stmt.expr);
|
||||
LLVMBuildRet(context->builder, returnValue);
|
||||
context->current_block = NULL;
|
||||
LLVMBasicBlockRef post_ret_block = gencontext_create_free_block(context, "ret");
|
||||
gencontext_emit_block(context, post_ret_block);
|
||||
|
||||
}
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_cond(GenContext *context, Ast *ast)
|
||||
|
||||
@@ -83,6 +83,8 @@ static inline LLVMTypeRef gencontext_create_llvm_type_from_decl(GenContext *cont
|
||||
context->error_type = error_type;
|
||||
}
|
||||
return context->error_type;
|
||||
case DECL_THROWS:
|
||||
UNREACHABLE
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
@@ -142,6 +144,7 @@ LLVMTypeRef gencontext_get_llvm_type(GenContext *context, Type *type)
|
||||
case TYPE_UNION:
|
||||
case TYPE_ENUM:
|
||||
case TYPE_ERROR:
|
||||
case TYPE_ERROR_UNION:
|
||||
return type->backend_type = gencontext_create_llvm_type_from_decl(context, type->decl);
|
||||
case TYPE_FUNC:
|
||||
return type->backend_type = gencontext_create_llvm_func_type(context, type);
|
||||
|
||||
@@ -1948,7 +1948,7 @@ static inline Decl *parse_generics_declaration(Visibility visibility)
|
||||
rtype = TRY_TYPE_OR(parse_type_expression(), &poisoned_decl);
|
||||
}
|
||||
Path *path = parse_path();
|
||||
Decl *decl = decl_new_with_type(tok, DECL_GENERIC, visibility);
|
||||
Decl *decl = decl_new(DECL_GENERIC, tok, visibility);
|
||||
decl->generic_decl.path = path;
|
||||
if (!consume_ident("generic function name")) return &poisoned_decl;
|
||||
decl->generic_decl.rtype = rtype;
|
||||
@@ -2066,7 +2066,7 @@ static inline bool parse_param_decl(Visibility parent_visibility, Decl*** parame
|
||||
* ;
|
||||
*
|
||||
*/
|
||||
static inline bool parse_opt_throw_declaration(FunctionSignature *signature)
|
||||
static inline bool parse_opt_throw_declaration(Visibility visibility, FunctionSignature *signature)
|
||||
{
|
||||
if (tok.type == TOKEN_THROW)
|
||||
{
|
||||
@@ -2075,11 +2075,17 @@ static inline bool parse_opt_throw_declaration(FunctionSignature *signature)
|
||||
}
|
||||
|
||||
if (!try_consume(TOKEN_THROWS)) return true;
|
||||
Token *throws = NULL;
|
||||
if (tok.type != TOKEN_TYPE_IDENT)
|
||||
{
|
||||
VECADD(signature->throws, &all_error);
|
||||
return true;
|
||||
}
|
||||
Decl **throws = NULL;
|
||||
while (tok.type == TOKEN_TYPE_IDENT)
|
||||
{
|
||||
throws = VECADD(throws, tok);
|
||||
Decl *error = decl_new(DECL_ERROR, tok, visibility);
|
||||
advance();
|
||||
VECADD(throws, error);
|
||||
if (!try_consume(TOKEN_COMMA)) break;
|
||||
}
|
||||
switch (tok.type)
|
||||
@@ -2228,7 +2234,7 @@ static inline bool parse_func_typedef(Decl *decl, Visibility visibility)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return parse_opt_throw_declaration(&(decl->typedef_decl.function_signature));
|
||||
return parse_opt_throw_declaration(VISIBLE_PUBLIC, &(decl->typedef_decl.function_signature));
|
||||
|
||||
}
|
||||
|
||||
@@ -2351,7 +2357,7 @@ static inline Decl *parse_func_definition(Visibility visibility, bool is_interfa
|
||||
|
||||
if (!parse_opt_parameter_type_list(visibility, &(func->func.function_signature), is_interface)) return &poisoned_decl;
|
||||
|
||||
if (!parse_opt_throw_declaration(&(func->func.function_signature))) return &poisoned_decl;
|
||||
if (!parse_opt_throw_declaration(visibility, &(func->func.function_signature))) return &poisoned_decl;
|
||||
|
||||
// TODO remove
|
||||
is_interface = tok.type == TOKEN_EOS;
|
||||
|
||||
@@ -253,6 +253,7 @@ static inline Type *sema_analyse_function_signature(Context *context, FunctionSi
|
||||
buffer[buffer_write_offset++] = ')';
|
||||
if (vec_size(signature->throws))
|
||||
{
|
||||
buffer[buffer_write_offset++] = '!';
|
||||
VECEACH(signature->throws, i)
|
||||
{
|
||||
TODO
|
||||
@@ -1125,6 +1126,8 @@ bool sema_analyse_decl(Context *context, Decl *decl)
|
||||
decl->resolve_status = RESOLVE_RUNNING;
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_THROWS:
|
||||
TODO
|
||||
case DECL_STRUCT:
|
||||
case DECL_UNION:
|
||||
if (!sema_analyse_struct_union(context, decl)) return decl_poison(decl);
|
||||
@@ -1240,6 +1243,10 @@ void sema_analysis_pass_decls(Context *context)
|
||||
{
|
||||
sema_analyse_decl(context, context->types[i]);
|
||||
}
|
||||
VECEACH(context->error_types, i)
|
||||
{
|
||||
sema_analyse_decl(context, context->error_types[i]);
|
||||
}
|
||||
VECEACH(context->struct_functions, i)
|
||||
{
|
||||
sema_analyse_decl(context, context->struct_functions[i]);
|
||||
@@ -1273,6 +1280,8 @@ static bool sema_resolve_type_identifier(Context *context, TypeInfo *type_info)
|
||||
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_THROWS:
|
||||
TODO
|
||||
case DECL_STRUCT:
|
||||
case DECL_UNION:
|
||||
case DECL_ERROR:
|
||||
|
||||
@@ -87,6 +87,8 @@ const char *type_to_error_string(Type *type)
|
||||
case TYPE_SUBARRAY:
|
||||
asprintf(&buffer, "%s[:]", type_to_error_string(type->array.base));
|
||||
return buffer;
|
||||
case TYPE_ERROR_UNION:
|
||||
TODO
|
||||
|
||||
}
|
||||
}
|
||||
@@ -102,6 +104,7 @@ static void type_append_signature_name_user_defined(Decl *decl, char *dst, size_
|
||||
*offset += len;
|
||||
return;
|
||||
}
|
||||
case DECL_THROWS:
|
||||
case DECL_POISONED:
|
||||
case DECL_VAR:
|
||||
case DECL_ENUM_CONSTANT:
|
||||
@@ -176,6 +179,8 @@ size_t type_size(Type *canonical)
|
||||
return type_size(canonical->array.base) * canonical->array.len;
|
||||
case TYPE_SUBARRAY:
|
||||
TODO
|
||||
case TYPE_ERROR_UNION:
|
||||
TODO
|
||||
}
|
||||
TODO
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user