Partial codegen

This commit is contained in:
Christoffer Lerno
2019-09-03 17:42:08 +02:00
parent 2eb91083a6
commit 0dba2b8569
16 changed files with 1802 additions and 1661 deletions

View File

@@ -25,6 +25,6 @@ add_executable(c3c
src/compiler/source_file.c
src/compiler/diagnostics.c
src/compiler/ast.c
src/compiler/bigint.c src/compiler/bigint.h src/compiler/context.c src/compiler/builtins.c src/compiler/codegen.c src/compiler/const_folding.c src/compiler/enums.h src/compiler/casts.c src/compiler/compiler.h src/compiler/types.c)
src/compiler/bigint.c src/compiler/bigint.h src/compiler/context.c src/compiler/codegen.c src/compiler/expr_analysis.c src/compiler/enums.h src/compiler/casts.c src/compiler/compiler.h src/compiler/types.c)
target_compile_options(c3c PRIVATE -Werror -Wall -Wextra -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter)

View File

@@ -12,14 +12,50 @@ struct Bar
Foo* fooPtr;
}
func int boo()
{
bool z = 123 > 3.0;
{
int x = 0;
}
{
int x = 1;
}
int j = 10;
do
{
j = j + 10;
} while (j > 2);
return 1;
}
func void while_test()
{
int a = 10;
while (int b = 37; a > 0)
{
int xy = 1;
}
}
func void test()
{
int i = 1;
int a = 10;
while (1)
{
int xy = 1;
}
int eokfe = boo();
int i = -1;
bool dwf = !2.0;
ushort b = ~cast(byte, 0);
int j, k;
int l, m = 0;
int o = 0, p = 3;
short f = -2;
c_int x = 2;
short f = cast(byte, cast(int,-2));
//int doek = ~2;
return;
}

View File

@@ -60,6 +60,18 @@ error Errors
func Foom test(int a)
{
while (int x = 0, int y = 3; int y = foo())
{
a++;
}
while (int x = 0)
{
a++;
}
while (int x, y = 3; x > 0 && b < 0)
{
a++;
}
return 1 + 2;
}

View File

@@ -72,7 +72,7 @@ Expr poisoned_expr = { .expr_kind = EXPR_POISONED, .resolve_status = RESOLVE_DON
Type* type_int_max_type(bool is_signed)
{
return is_signed ? &type_long : &type_ulong;
return is_signed ? type_long : type_ulong;
}
/*
@@ -99,28 +99,6 @@ Type* type_get_unsigned(Type *type)
*/
BinOp bin_op[256] = {
[TOKEN_EQ] = BINOP_ASSIGN,
[TOKEN_STAR] = BINOP_MULT,
[TOKEN_PLUS] = BINOP_ADD,
[TOKEN_MINUS] = BINOP_SUB,
[TOKEN_DIV] = BINOP_DIV,
[TOKEN_MOD] = BINOP_MOD,
[TOKEN_NOT_EQUAL] = BINOP_NE,
[TOKEN_AND] = BINOP_AND,
[TOKEN_OR] = BINOP_OR,
[TOKEN_AMP] = BINOP_BIT_AND,
[TOKEN_BIT_OR] = BINOP_BIT_OR,
[TOKEN_BIT_XOR] = BINOP_BIT_XOR,
[TOKEN_EQEQ] = BINOP_EQ,
[TOKEN_GREATER] = BINOP_GT,
[TOKEN_GREATER_EQ] = BINOP_GE,
[TOKEN_LESS] = BINOP_LT,
[TOKEN_LESS_EQ] = BINOP_LE,
[TOKEN_SHR] = BINOP_SHR,
[TOKEN_SHL] = BINOP_SHL,
[TOKEN_ELVIS] = BINOP_ELVIS
};
AssignOp assign_op[256] = {
[TOKEN_EQ] = ASSIGNOP_ASSIGN,
@@ -149,10 +127,6 @@ UnaryOp unary_op[256] = {
};
BinOp binop_from_token(TokenType type)
{
return bin_op[type];
}
AssignOp assignop_from_token(TokenType type)
{
@@ -168,16 +142,6 @@ TokenType assignop_to_token(AssignOp type)
return TOKEN_INVALID_TOKEN;
}
TokenType binop_to_token(BinOp type)
{
for (unsigned i = 0; i < 256; i++)
{
if (bin_op[i] == type) return (TokenType)i;
}
return TOKEN_INVALID_TOKEN;
}
UnaryOp unaryop_from_token(TokenType type)
{
return unary_op[type];
@@ -330,16 +294,16 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent)
}
return;
case EXPR_BINARY:
fprintf(file, "(binary %s\n", token_type_to_string(binop_to_token(expr->binary_expr.operator)));
fprintf(file, "(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(unaryop_to_token(expr->unary_expr.operator)));
fprintf(file, "(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(unaryop_to_token(expr->post_expr.operator)));
fprintf(file, "(postunary %s\n", token_type_to_string(expr->post_expr.operator));
fprint_expr_recursive(file, expr->post_expr.expr, indent + 1);
break;
case EXPR_METHOD_REF:
@@ -363,9 +327,9 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent)
fprintf(file, "(call\n");
fprint_expr_recursive(file, expr->call_expr.function, indent + 1);
{
VECEACH(expr->call_expr.parameters, i)
VECEACH(expr->call_expr.arguments, i)
{
fprint_expr_recursive(file, expr->call_expr.parameters[i], indent + 1);
fprint_expr_recursive(file, expr->call_expr.arguments[i], indent + 1);
}
}
break;
@@ -397,15 +361,6 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent)
fprint_expr_recursive(file, expr->subscript_expr.expr, indent + 1);
fprint_expr_recursive(file, expr->subscript_expr.index, indent + 1);
break;
case EXPR_EXPRESSION_LIST:
fprintf(file, "(expressionlist\n");
{
VECEACH(expr->expression_list, i)
{
fprint_expr_recursive(file, expr->expression_list[i], indent + 1);
}
}
break;
case EXPR_TRY:
if (!expr->try_expr.else_expr)
{
@@ -577,6 +532,14 @@ static void fprint_decl_list(FILE *file, Decl **decls, int indent)
}
}
static void fprint_asts_recursive(FILE *file, Ast **asts, int indent)
{
VECEACH(asts, i)
{
fprint_ast_recursive(file, asts[i], indent);
}
}
static void fprint_ast_recursive(FILE *file, Ast *ast, int indent)
{
fprint_indent(file, indent);
@@ -590,10 +553,7 @@ static void fprint_ast_recursive(FILE *file, Ast *ast, int indent)
}
fprintf(file, "(compound\n");
{
VECEACH(ast->compound_stmt.stmts, i)
{
fprint_ast_recursive(file, ast->compound_stmt.stmts[i], indent + 1);
}
fprint_asts_recursive(file, ast->compound_stmt.stmts, indent + 1);
}
break;
case AST_DECLARE_STMT:
@@ -614,6 +574,10 @@ static void fprint_ast_recursive(FILE *file, Ast *ast, int indent)
fprint_ast_recursive(file, ast->do_stmt.body, indent + 1);
fprint_expr_recursive(file, ast->do_stmt.expr, indent + 1);
break;
case AST_STMT_LIST:
fprintf(file, "(stmtlist\n");
fprint_asts_recursive(file, ast->stmt_list, indent + 1);
break;
case AST_RETURN_STMT:
if (ast->return_stmt.expr)
{
@@ -638,29 +602,25 @@ static void fprint_ast_recursive(FILE *file, Ast *ast, int indent)
case AST_DEFAULT_STMT:
fprintf(file, "(default)\n");
return;
case AST_COND_STMT:
fprintf(file, "(cond\n");
if (ast->cond_stmt.expr)
{
fprint_expr_recursive(file, ast->cond_stmt.expr, indent + 1);
}
else
{
fprint_indent(file, indent);
fprintf(file, "(noexpr)");
}
fprint_asts_recursive(file, ast->cond_stmt.stmts, indent + 1);
break;
case AST_FOR_STMT:
fprintf(file, "(for\n");
if (ast->for_stmt.init)
{
fprint_ast_recursive(file, ast->for_stmt.init, indent + 1);
}
else
{
fprint_indent(file, indent + 1);
fprintf(file, "(noinit)\n");
}
if (ast->for_stmt.cond)
{
fprint_expr_recursive(file, ast->for_stmt.cond, indent + 1);
}
else
{
fprint_indent(file, indent + 1);
fprintf(file, "(nocond)\n");
}
fprint_ast_recursive(file, ast->for_stmt.cond, indent + 1);
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
{
@@ -678,24 +638,8 @@ static void fprint_ast_recursive(FILE *file, Ast *ast, int indent)
fprint_ast_recursive(file, ast->if_stmt.else_body, indent + 1);
}
break;
case AST_DECL_EXPR_LIST:
fprintf(file, "(declexprlist\n");
if (ast->decl_expr_list.list_type == DECLEXPR_EXPR)
{
fprint_expr_recursive(file, ast->decl_expr_list.expr, indent + 1);
}
else
{
fprint_decl_recursive(file, ast->decl_expr_list.decl, indent + 1);
}
break;
case AST_COND_STMT:
fprintf(file, "(condstmt\n");
fprint_decl_recursive(file, ast->cond_stmt.decl, indent + 1);
fprint_ast_recursive(file, ast->cond_stmt.decl_expr, indent + 1);
break;
case AST_SWITCH_STMT:
fprintf(file, "(condstmt\n");
fprintf(file, "(switchstmt\n");
fprint_ast_recursive(file, ast->switch_stmt.cond, indent + 1);
fprint_ast_recursive(file, ast->switch_stmt.body, indent + 1);
break;

View File

@@ -1,160 +0,0 @@
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "compiler_internal.h"
/*
BuiltinType builtin_common_type[16][16] = {
// err, wptr, nil, bool, char, short, int, long, byte,ushort, int, ulong, float,double, ctint, ctreal
{ TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR }, // Error
{ TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR }, // void
{ TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR, TERR }, // wptr
{ TERR, TERR, TERR, T_U1, T_I8, T_I16, T_I32, T_I64, T_U8, T_U16, T_U32, T_U64, T_F32, T_F64, T_U1, T_FXX }, // bool
{ TERR, TERR, TERR, T_I8, T_I8, T_I16, T_I32, T_I64, T_I8, T_I16, T_I32, T_I64, T_F32, T_F64, T_I8, T_FXX }, // char
{ TERR, TERR, TERR, T_I16, T_I16, T_I16, T_I32, T_I64, T_I16, T_I16, T_I32, T_I64, T_F32, T_F64, T_I16, T_FXX }, // short
{ TERR, TERR, TERR, T_I32, T_I32, T_I32, T_I32, T_I64, T_I32, T_I32, T_I32, T_I64, T_F32, T_F64, T_I32, T_FXX }, // int
{ TERR, TERR, TERR, T_I64, T_I64, T_I64, T_I64, T_I64, T_I64, T_I64, T_I64, T_I64, T_F32, T_F64, T_I64, T_FXX }, // long
{ TERR, TERR, TERR, T_U8, T_I8, T_I16, T_I32, T_I64, T_U8, T_U16, T_U32, T_U64, T_F32, T_F64, T_U8, T_FXX }, // byte
{ TERR, TERR, TERR, T_U16, T_I16, T_I16, T_I32, T_I64, T_U16, T_U16, T_U32, T_U64, T_F32, T_F64, T_U16, T_FXX }, // ushort
{ TERR, TERR, TERR, T_U32, T_I32, T_I32, T_I32, T_I64, T_U32, T_U32, T_U32, T_U64, T_F32, T_F64, T_U32, T_FXX }, // uint
{ TERR, TERR, TERR, T_U64, T_I64, T_I64, T_I64, T_I64, T_U64, T_U64, T_U64, T_U64, T_F32, T_F64, T_U64, T_FXX }, // ulong
{ TERR, TERR, TERR, T_F32, T_F32, T_F32, T_F32, T_F32, T_F32, T_F32, T_F32, T_F32, T_F32, T_F64, T_F32, T_F32 }, // float
{ TERR, TERR, TERR, T_F64, T_F64, T_F64, T_F64, T_F64, T_F64, T_F64, T_F64, T_F64, T_F64, T_F64, T_F64, T_F64 }, // double
{ TERR, TERR, TERR, T_U1, T_I8, T_I16, T_I32, T_I64, T_U8, T_U16, T_U32, T_U64, T_F32, T_F64, T_IXX, T_FXX }, // ctint
{ TERR, TERR, TERR, T_FXX, T_FXX, T_FXX, T_FXX, T_FXX, T_FXX, T_FXX, T_FXX, T_FXX, T_F32, T_F64, T_FXX, T_FXX }, // ctreal
};
void
BuiltinConv BUILTIN_ASSIGN_CONVERSION[16][16] = {
//e v w b c s i l b u u u f d c c
//r o p o h h n o y s i l l o t t
//r i t o a o t n t h n o o u i r
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // error
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // void =
{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // wptr =
{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // bool =
{ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }, // char =
{ 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0 }, // short =
{ 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0 }, // int =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 }, // long =
{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0 }, // byte =
{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0 }, // ushort =
{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0 }, // uint =
{ 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0 }, // ulong =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 }, // float =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // double =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ctint
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ctfloat
};
// x += x -= x /= x *=
bool BUILTIN_ASSIGN_UPDATE_CONVERSION[16][16] = {
//e v w b c s i l b u u u f d c c
//r o p o h h n o y s i l l o t t
//r i t o a o t n t h n o o u i r
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // error
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // void =
{ 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0 }, // wptr =
{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 }, // bool =
{ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }, // char =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0 }, // short =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0 }, // int =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0 }, // long =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0 }, // byte =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0 }, // ushort =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0 }, // uint =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0 }, // ulong =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // float =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // double =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ctint
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ctfloat
};
*/
/*
void builtin_convert(ExprConst *value, BuiltinConv conversion, Type *canonical_target)
{
assert(canonical_target == canonical_target->canonical);
switch (conversion)
{
case C_XXXX:
FATAL_ERROR("Should never be called");
break;
case C_FPFP:
if (canonical_target->builtin.bitsize == 16)
{
value->f = (float)value->f;
}
if (canonical_target->builtin.bitsize == 32)
{
value->f = (double)value->f;
}
break;
case C_FPSI:
if (value->f < 0)
{
value->integer.i = (uint64_t)(-value->f);
value->type = CONST_NEGATIVE_INT;
}
else
{
value->integer.i = (uint64_t)(-value->f);
value->type = CONST_POSITIVE_INT;
}
break;
case C_FPUI:
assert(value->f >= 0);
value->integer.i = (uint64_t)(value->f);
value->type = CONST_POSITIVE_INT;
break;
case C_SIFP:
case C_UIFP:
value->f = value->integer.i;
if (value->type == CONST_NEGATIVE_INT) value->f = -value->f;
value->type = CONST_FLOAT;
break;
case C_SISI:
// value_convert(value, VALUE_TYPE_INT, canonical_target->decl->builtin.bitsize, false, true);
break;
case C_SIUI:
// value_convert(value, VALUE_TYPE_INT, canonical_target->decl->builtin.bitsize, true, true);
break;
case C_UISI:
// value_convert(value, VALUE_TYPE_INT, canonical_target->decl->builtin.bitsize, false, true);
break;
case C_UIUI:
// value_convert(value, VALUE_TYPE_INT, canonical_target->decl->builtin.bitsize, true, true);
break;
case C_PTXI:
// value_convert(value, VALUE_TYPE_INT, canonical_target->decl->builtin.bitsize, true, true);
break;
case C_XIPT:
// value_convert(value, VALUE_TYPE_INT, canonical_target->decl->builtin.bitsize, true, true);
break;
case C_BOFP:
// value_convert(value, VALUE_TYPE_FLOAT, canonical_target->decl->builtin.bitsize, false, true);
break;
case C_BOSI:
// value_convert(value, VALUE_TYPE_INT, canonical_target->decl->builtin.bitsize, false, true);
break;
case C_BOUI:
// value_convert(value, VALUE_TYPE_INT, canonical_target->decl->builtin.bitsize, false, true);
break;
case C_FPBO:
// value_convert(value, VALUE_TYPE_BOOL, canonical_target->decl->builtin.bitsize, true, true);
break;
case C_XIBO:
// value_convert(value, VALUE_TYPE_BOOL, canonical_target->decl->builtin.bitsize, true, true);
break;
case C_PTBO:
// value_convert(value, VALUE_TYPE_BOOL, canonical_target->decl->builtin.bitsize, true, true);
break;
default:
UNREACHABLE
}
}
*/

View File

@@ -13,6 +13,7 @@ static inline void insert_cast(Expr *expr, CastKind kind, Type *type)
*inner = *expr;
expr->expr_kind = EXPR_CAST;
expr->expr_cast.kind = kind;
expr->expr_cast.expr = inner;
expr->type = type;
}
@@ -33,7 +34,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->name_loc.string, expr->type->name_loc.string);
SEMA_ERROR(expr->loc, "Cannot %s '%s' to '%s'", action, expr->type->name_loc.string, type->name_loc.string);
return false;
}
@@ -80,7 +81,7 @@ static inline bool may_implicitly_cast_ptr_to_ptr(Type *current_type, Type *targ
// Neither is void* or have matching bases:
// TODO recursively check for ?* or?
if (target_type->base != &type_void && current_type->base != &type_void && target_type->base != current_type->base) return false;
if (target_type->base != type_void && current_type->base != type_void && target_type->base != current_type->base) return false;
// Current is not null, or target is nullable? Ok!
return target_type->nullable || !current_type->nullable;
@@ -240,7 +241,7 @@ static int64_t int_type_min[4] = { INT8_MIN, INT16_MIN, INT32_MIN, INT64_MIN };
bool sisi(Expr* left, Type *canonical, Type *type, CastType cast_type)
{
Type *left_canonical = left->type->canonical;
bool is_narrowing = left->type->builtin.bytesize < canonical->builtin.bytesize && left_canonical->type_kind != TYPE_IXX;
bool is_narrowing = left_canonical->builtin.bytesize > canonical->builtin.bytesize && left_canonical->type_kind != TYPE_IXX;
if (is_narrowing && (cast_type != CAST_TYPE_IMPLICIT_ASSIGN_ADD && cast_type != CAST_TYPE_EXPLICIT)) EXIT_T_MISMATCH();
if (left->expr_kind == EXPR_CONST)
@@ -313,7 +314,7 @@ bool sifp(Expr* left, Type *canonical, Type *type, CastType cast_type)
if (left->expr_kind == EXPR_CONST)
{
assert(left->const_expr.type == CONST_INT);
assert(canonical->type_kind >= TYPE_F32 && canonical->type_kind <= TYPE_F64);
assert(canonical->type_kind >= TYPE_F32 && canonical->type_kind <= TYPE_FXX);
if (left->const_expr.i > (uint64_t)INT64_MAX)
{
left->const_expr.f = -((long double)(~left->const_expr.i));
@@ -322,6 +323,7 @@ bool sifp(Expr* left, Type *canonical, Type *type, CastType cast_type)
{
left->const_expr.f = left->const_expr.i;
}
left->const_expr.type = CONST_FLOAT;
left->type = type;
return true;
}
@@ -460,15 +462,15 @@ CastFunc BUILTIN_CONVERSION[19][19] = {
{ &xibo, &sisi, &erro, &sisi, &sisi, &erro, &siui, &siui, &siui, &siui, &erro, &sifp, &sifp, &erro, &sius, &erro, &erro, &erro, &erro }, // short
{ &xibo, &sisi, &sisi, &erro, &sisi, &erro, &siui, &siui, &siui, &siui, &erro, &sifp, &sifp, &erro, &sius, &xipt, &erro, &erro, &erro }, // int
{ &xibo, &sisi, &sisi, &sisi, &erro, &erro, &siui, &siui, &siui, &siui, &erro, &sifp, &sifp, &erro, &sius, &xipt, &erro, &erro, &erro }, // long
{ &xibo, &sisi, &sisi, &sisi, &sisi, &erro, &siui, &siui, &siui, &siui, &erro, &sifp, &sifp, &erro, &sius, &xipt, &erro, &erro, &erro }, // cint
{ &xibo, &sisi, &sisi, &sisi, &sisi, &erro, &siui, &siui, &siui, &siui, &erro, &sifp, &sifp, &sifp, &sius, &xipt, &erro, &erro, &erro }, // ixx
{ &xibo, &uisi, &uisi, &uisi, &uisi, &erro, &erro, &uiui, &uiui, &uiui, &erro, &uifp, &uifp, &erro, &uius, &xipt, &erro, &erro, &erro }, // byte
{ &xibo, &uisi, &uisi, &uisi, &uisi, &erro, &uiui, &erro, &uiui, &uiui, &erro, &uifp, &uifp, &erro, &uius, &xipt, &erro, &erro, &erro }, // ushort
{ &xibo, &uisi, &uisi, &uisi, &uisi, &erro, &uiui, &uiui, &erro, &uiui, &erro, &uifp, &uifp, &erro, &uius, &xipt, &erro, &erro, &erro }, // uint
{ &xibo, &uisi, &uisi, &uisi, &uisi, &erro, &uiui, &uiui, &uiui, &erro, &erro, &uifp, &uifp, &erro, &uius, &xipt, &erro, &erro, &erro }, // ulong
{ &xibo, &uisi, &uisi, &uisi, &uisi, &erro, &uiui, &uiui, &uiui, &uiui, &erro, &uifp, &uifp, &erro, &uius, &xipt, &erro, &erro, &erro }, // cuint
{ &xibo, &uisi, &uisi, &uisi, &uisi, &erro, &uiui, &uiui, &uiui, &uiui, &erro, &uifp, &uifp, &uifp, &uius, &xipt, &erro, &erro, &erro }, // uxx
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &erro, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro }, // float
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro, &erro }, // double
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro }, // cfloat
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro }, // fxx
{ &usbo, &ussi, &ussi, &ussi, &ussi, &erro, &usui, &usui, &usui, &usui, &erro, &erro, &erro, &erro, &usus, &erro, &erro, &erro, &erro }, // user
{ &ptbo, &ptxi, &ptxi, &ptxi, &ptxi, &erro, &ptxi, &ptxi, &ptxi, &ptxi, &erro, &erro, &erro, &erro, &erro, &ptpt, &ptst, &erro, &ptva }, // ptr
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro, &erro }, // str
@@ -476,31 +478,80 @@ CastFunc BUILTIN_CONVERSION[19][19] = {
{ &fpbo, &fpsi, &fpsi, &fpsi, &fpsi, &erro, &fpui, &fpui, &fpui, &fpui, &erro, &fpfp, &erro, &erro, &erro, &erro, &erro, &erro, &erro }, // varr
};
Type t_cpy = { .name_loc.string = "cpy" };
Type t_err = { .name_loc.string = "err" };
Type *ARITHMETIC_PROMOTION[19][19] = {
//other bool, char, short, int, long, ctint, byte, ushort, int, ulong, ctuint, float, double, ctreal, user, ptr, str, arr, varr // from:
{ &t_u1, &t_i8, &t_i16, &t_i32, &t_i64, &t_u1, &t_u8, &t_u16, &t_u32, &t_u64, &t_u1, &t_f32, &t_f64, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err }, // bool
{ &t_i8, &t_i8, &t_i16, &t_i32, &t_i64, &t_i8, &t_i8, &t_i16, &t_i32, &t_i64, &t_i8, &t_f32, &t_f64, &t_err, &t_err, &t_isz, &t_err, &t_err, &t_err }, // char
{ &t_i16, &t_i16, &t_i16, &t_i32, &t_i64, &t_i16, &t_i16, &t_i16, &t_i32, &t_i64, &t_i16, &t_f32, &t_f64, &t_err, &t_err, &t_isz, &t_err, &t_err, &t_err }, // short
{ &t_i32, &t_i32, &t_i32, &t_i32, &t_i64, &t_i32, &t_i32, &t_i32, &t_i32, &t_i64, &t_i32, &t_f32, &t_f64, &t_err, &t_err, &t_isz, &t_err, &t_err, &t_err }, // int
{ &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_i64, &t_f32, &t_f64, &t_err, &t_err, &t_isz, &t_err, &t_err, &t_err }, // long
{ &t_u1, &t_i8, &t_i16, &t_i32, &t_i64, &t_ixx, &t_i8, &t_i16, &t_i32, &t_i64, &t_ixx, &t_f32, &t_f64, &t_fxx, &t_err, &t_isz, &t_err, &t_err, &t_err }, // ixx
{ &t_u8, &t_i8, &t_i16, &t_i32, &t_i64, &t_uxx, &t_u8, &t_u16, &t_u32, &t_i64, &t_uxx, &t_f32, &t_f64, &t_err, &t_err, &t_usz, &t_err, &t_err, &t_err }, // byte
{ &t_u16, &t_i16, &t_i16, &t_i32, &t_i64, &t_uxx, &t_u16, &t_u16, &t_u32, &t_i64, &t_uxx, &t_f32, &t_f64, &t_err, &t_err, &t_usz, &t_err, &t_err, &t_err }, // ushort
{ &t_u32, &t_i32, &t_i32, &t_i32, &t_i64, &t_uxx, &t_u32, &t_u32, &t_u32, &t_i64, &t_uxx, &t_f32, &t_f64, &t_err, &t_err, &t_usz, &t_err, &t_err, &t_err }, // uint
{ &t_u64, &t_i64, &t_i64, &t_i64, &t_i64, &t_uxx, &t_u64, &t_u64, &t_u64, &t_i64, &t_uxx, &t_f32, &t_f64, &t_err, &t_err, &t_usz, &t_err, &t_err, &t_err }, // ulong
{ &t_u1, &t_i8, &t_i16, &t_i32, &t_i64, &t_uxx, &t_u8, &t_u16, &t_u32, &t_u64, &t_uxx, &t_f32, &t_f64, &t_fxx, &t_err, &t_usz, &t_err, &t_err, &t_err }, // uxx
{ &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f32, &t_f64, &t_f32, &t_err, &t_err, &t_err, &t_err, &t_err }, // float
{ &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_f64, &t_err, &t_err, &t_err, &t_err, &t_err }, // double
{ &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_f32, &t_f64, &t_fxx, &t_err, &t_err, &t_err, &t_err, &t_err }, // fxx
{ &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err }, // user
{ &t_err, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_cpy, &t_err, &t_err, &t_err, &t_cpy, &t_err, &t_err, &t_err }, // ptr
{ &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err }, // str
{ &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err }, // arr
{ &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err, &t_err }, // varr
};
static inline bool cannot_convert(TypeKind type_kind)
{
return type_kind <= TYPE_VOID || type_kind >= TYPE_INC_ARRAY;
}
bool cast_arithmetic(Expr *expr, Expr *other, const char *action)
{
Type *canonical = expr->type->canonical;
Type *canonical_to = other->type->canonical;
if (cannot_convert(canonical->type_kind) || cannot_convert(canonical_to->type_kind)) goto ERR;
Type *preferred_type = ARITHMETIC_PROMOTION[canonical->type_kind - TYPE_BOOL][canonical_to->type_kind - TYPE_BOOL];
if (preferred_type == &t_err) goto ERR;
if (preferred_type == &t_cpy || preferred_type == canonical) return true;
return cast(expr, preferred_type, CAST_TYPE_IMPLICIT);
ERR:
SEMA_ERROR(expr->loc, "Cannot upcast to resolve '%s' %s '%s'", expr->type->name_loc.string, action, other->type->name_loc.string);
return false;
}
bool cast_to_runtime(Expr *expr)
{
Type *canonical = expr->type->canonical;
switch (canonical->type_kind)
{
case TYPE_IXX:
return cast(expr, type_long, CAST_TYPE_IMPLICIT);
case TYPE_UXX:
return cast(expr, type_ulong, CAST_TYPE_IMPLICIT);
case TYPE_FXX:
return cast(expr, type_double, CAST_TYPE_IMPLICIT);
default:
return true;
}
}
bool cast(Expr *expr, Type *to_type, CastType cast_type)
{
Type *from_type = expr->type->canonical;
Type *canonical = to_type->canonical;
if (from_type == canonical) return true;
TypeKind from_kind = from_type->type_kind;
TypeKind to_kind = canonical->type_kind;
if (cannot_convert(from_kind) || cannot_convert(to_kind))
{
switch (cast_type)
{
case CAST_TYPE_EXPLICIT:
case CAST_TYPE_IMPLICIT:
SEMA_ERROR(expr->loc, "Cannot convert '%s' to '%s'", expr->type->name_loc.start, to_type->name_loc.start);
break;
case CAST_TYPE_IMPLICIT_ASSIGN:
case CAST_TYPE_IMPLICIT_ASSIGN_ADD:
SEMA_ERROR(expr->loc, "Cannot assign '%s' to '%s'", expr->type->name_loc.start, to_type->name_loc.start);
break;
}
sema_type_mismatch(expr, to_type, cast_type);
return false;
}
CastFunc func = BUILTIN_CONVERSION[from_type->type_kind - TYPE_BOOL][to_type->type_kind - TYPE_BOOL];

View File

@@ -7,7 +7,10 @@
#define PRINTF(...) fprintf(context->codegen_output, __VA_ARGS__)
#define PRINTTYPE(_t) print_typename(context->codegen_output, _t)
#define INDENT() indent_line(context, indent)
static void codegen_ast(Context *context, Ast *ast, int indent);
static int codegen_emit_expr(Context *context, Expr *expr, int indent);
static void print_typename(FILE *file, Type *type)
{
@@ -100,57 +103,10 @@ static void indent_line(Context *context, int indent)
{
for (int i = 0; i < indent; i++)
{
PRINTF(" ");
PRINTF(" ");
}
}
static void codegen_expr(Context *context, Expr *expr)
{
switch (expr->expr_kind)
{
case EXPR_POISONED:
UNREACHABLE;
case EXPR_TRY:
break;
case EXPR_CONST:
break;
case EXPR_BINARY:
break;
case EXPR_CONDITIONAL:
break;
case EXPR_UNARY:
break;
case EXPR_POST_UNARY:
break;
case EXPR_TYPE:
break;
case EXPR_IDENTIFIER:
break;
case EXPR_METHOD_REF:
break;
case EXPR_CALL:
break;
case EXPR_SIZEOF:
break;
case EXPR_SUBSCRIPT:
break;
case EXPR_ACCESS:
break;
case EXPR_STRUCT_VALUE:
break;
case EXPR_STRUCT_INIT_VALUES:
break;
case EXPR_INITIALIZER_LIST:
break;
case EXPR_EXPRESSION_LIST:
break;
case EXPR_DEFERRED_TOKENS:
break;
case EXPR_CAST:
break;
}
TODO
}
static inline void codegen_compound_stmt(Context *context, Ast *ast, int indent)
{
indent_line(context, indent);
@@ -169,10 +125,32 @@ static inline void codegen_emit_cast(Context *context, Type *canonical)
PRINTF("(");
TODO
}
static inline void codegen_emit_const_expr(Context *context, Expr *expr)
static inline int codegen_emit_call_expr(Context *context, Expr *expr, int indent)
{
// TODO properly
INDENT();
PRINTTYPE(expr->type);
PRINTF(" _%d = %s();\n", ++context->unique_index, expr->call_expr.function->identifier_expr.decl->name.string);
return context->unique_index;
}
static inline int codegen_emit_identifier_expr(Context *context, Expr *expr, int indent)
{
// TODO properly
INDENT();
PRINTTYPE(expr->type);
Decl *decl = expr->identifier_expr.decl;
PRINTF(" _%d = _%d_%s;\n", ++context->unique_index, decl->var.id, decl->name.string);
return context->unique_index;
}
static inline int codegen_emit_const_expr(Context *context, Expr *expr, int indent)
{
assert(expr->expr_kind == EXPR_CONST);
Type *canonical = expr->type->canonical;
INDENT();
switch (canonical->type_kind)
{
case TYPE_POISONED:
@@ -182,48 +160,50 @@ static inline void codegen_emit_const_expr(Context *context, Expr *expr)
break;
case TYPE_BOOL:
assert(expr->const_expr.type == CONST_BOOL);
PRINTF(expr->const_expr.b ? "true" : "false");
break;
PRINTTYPE(expr->type);
PRINTF(" _%d = %s;\n", ++context->unique_index, expr->const_expr.b ? "true" : "false");
return context->unique_index;
case TYPE_I8:
case TYPE_I16:
case TYPE_I32:
case TYPE_I64:
assert(expr->const_expr.type == CONST_INT);
PRINTF("((");
print_typename(context->codegen_output, canonical);
PRINTF(")");
PRINTF("%lld)", (long long)expr->const_expr.i);
break;
case TYPE_IXX:
UNREACHABLE
assert(expr->const_expr.type == CONST_INT);
PRINTTYPE(expr->type);
PRINTF(" _%d = (", ++context->unique_index);
PRINTTYPE(canonical);
PRINTF(")");
PRINTF("%lld;\n", (long long)expr->const_expr.i);
return context->unique_index;
case TYPE_U8:
case TYPE_U16:
case TYPE_U32:
case TYPE_U64:
assert(expr->const_expr.type == CONST_INT);
PRINTF("((");
print_typename(context->codegen_output, canonical);
PRINTF(")");
PRINTF("%llu)", expr->const_expr.i);
break;
case TYPE_UXX:
UNREACHABLE
assert(expr->const_expr.type == CONST_INT);
PRINTTYPE(expr->type);
PRINTF(" _%d = (", ++context->unique_index);
PRINTTYPE(canonical);
PRINTF(")");
PRINTF("%llu;\n", expr->const_expr.i);
return context->unique_index;
case TYPE_F32:
case TYPE_F64:
assert(expr->const_expr.type == CONST_FLOAT);
PRINTF("((");
print_typename(context->codegen_output, canonical);
PRINTF(")");
PRINTF("%Lf)", expr->const_expr.f);
break;
case TYPE_FXX:
UNREACHABLE
assert(expr->const_expr.type == CONST_FLOAT);
PRINTTYPE(expr->type);
PRINTF(" _%d = (", ++context->unique_index);
PRINTTYPE(canonical);
PRINTF(")");
PRINTF("%Lf;\n", expr->const_expr.f);
return context->unique_index;
case TYPE_POINTER:
assert(expr->const_expr.type == CONST_NIL);
PRINTF("((");
print_typename(context->codegen_output, canonical);
PRINTF("0)");
break;
PRINTTYPE(expr->type);
PRINTF(" _%d = ((", ++context->unique_index);
PRINTTYPE(canonical);
PRINTF("0);\n");
return context->unique_index;
case TYPE_STRING:
TODO
case TYPE_ARRAY:
@@ -234,33 +214,116 @@ static inline void codegen_emit_const_expr(Context *context, Expr *expr)
}
}
static inline void codegen_emit_expr(Context *context, Expr *expr)
static inline int codegen_emit_cast_expr(Context *context, Expr *expr, int indent)
{
int index = codegen_emit_expr(context, expr->expr_cast.expr, indent);
INDENT();
PRINTTYPE(expr->type);
PRINTF(" _%d = (", ++context->unique_index);
PRINTTYPE(expr->type);
PRINTF(") _%d;\n", index);
return context->unique_index;
}
static int codegen_emit_simple_binary_expr(Context *context, Expr *expr, int indent)
{
int l_index = codegen_emit_expr(context, expr->binary_expr.left, indent);
int r_index = codegen_emit_expr(context, expr->binary_expr.right, indent);
INDENT();
PRINTTYPE(expr->type);
PRINTF(" _%d = _%d %s _%d;\n", ++context->unique_index, l_index, token_type_to_string(expr->binary_expr.operator), r_index);
return context->unique_index;
}
static int codegen_emit_assign_expr(Context *context, Expr *expr, int indent)
{
Expr *left = expr->binary_expr.left;
Expr *right = expr->binary_expr.right;
int index = codegen_emit_expr(context, right, indent);
if (expr->binary_expr.left->expr_kind == EXPR_IDENTIFIER)
{
INDENT();
PRINTF("%s = _%d;\n", left->identifier_expr.identifier.string, index);
return index;
}
else
{
TODO
}
}
static int codegen_emit_binary_expr(Context *context, Expr *expr, int indent)
{
switch (expr->binary_expr.operator)
{
case TOKEN_EQ:
return codegen_emit_assign_expr(context, expr, indent);
case TOKEN_PLUS:
case TOKEN_MINUS:
case TOKEN_GREATER:
case TOKEN_GREATER_EQ:
case TOKEN_LESS_EQ:
case TOKEN_LESS:
case TOKEN_EQEQ:
case TOKEN_NOT_EQUAL:
case TOKEN_MOD:
case TOKEN_DIV:
case TOKEN_STAR:
return codegen_emit_simple_binary_expr(context, expr, indent);
case TOKEN_BIT_OR:
case TOKEN_AMP:
case TOKEN_BIT_XOR:
case TOKEN_SHL:
case TOKEN_SHR:
TODO
case TOKEN_MULT_ASSIGN:
case TOKEN_DIV_ASSIGN:
case TOKEN_MINUS_ASSIGN:
case TOKEN_PLUS_ASSIGN:
case TOKEN_MOD_ASSIGN:
case TOKEN_AND_ASSIGN:
case TOKEN_OR_ASSIGN:
case TOKEN_SHR_ASSIGN:
case TOKEN_SHL_ASSIGN:
case TOKEN_BIT_XOR_ASSIGN:
case TOKEN_BIT_OR_ASSIGN:
case TOKEN_BIT_AND_ASSIGN:
case TOKEN_ELVIS:
UNREACHABLE
default:
UNREACHABLE
}
}
static int codegen_emit_expr(Context *context, Expr *expr, int indent)
{
switch (expr->expr_kind)
{
case EXPR_CONST:
codegen_emit_const_expr(context, expr);
break;
return codegen_emit_const_expr(context, expr, indent);
case EXPR_CALL:
return codegen_emit_call_expr(context, expr, indent);
case EXPR_IDENTIFIER:
return codegen_emit_identifier_expr(context, expr, indent);
case EXPR_CAST:
return codegen_emit_cast_expr(context, expr, indent);
case EXPR_BINARY:
return codegen_emit_binary_expr(context, expr, indent);
default:
TODO
}
}
static inline void codegen_var_decl(Context *context, Decl *decl, int indent)
static inline int codegen_var_decl(Context *context, Decl *decl, int indent)
{
assert(decl->decl_kind == DECL_VAR);
indent_line(context, indent);
print_typename(context->codegen_output, decl->var.type);
PRINTF(" ");
PRINTF("%s", decl->name.string);
PRINTF(";\n");
if (!decl->var.init_expr) return;
indent_line(context, indent);
PRINTF("%s = ", decl->name.string);
codegen_emit_expr(context, decl->var.init_expr);
PRINTF(";\n");
if (!decl->var.init_expr) return -1;
int index = codegen_emit_expr(context, decl->var.init_expr, indent);
INDENT();
PRINTF("_%d_%s = _%d;\n", decl->var.id, decl->name.string, index);
return index;
}
static inline void codegen_declare_stmt(Context *context, Ast *ast, int indent)
{
Decl *decl = ast->declare_stmt;
@@ -277,6 +340,77 @@ static inline void codegen_declare_stmt(Context *context, Ast *ast, int indent)
}
}
static inline void codegen_emit_for_smt(Context *context, Ast *ast, int indent)
{
INDENT();
int loop = ++context->unique_index;
PRINTF("// --- Begin for id:%d ---\n", loop);
Ast **stmts = ast->for_stmt.cond->cond_stmt.stmts;
if (stmts)
{
INDENT();
PRINTF("// --- Prelude ---\n");
VECEACH(stmts, i)
{
codegen_ast(context, stmts[i], indent);
}
}
INDENT();
PRINTF("// --- Loop condition ---\n");
INDENT();
PRINTF("_FOR_%d:\n", loop);
if (ast->for_stmt.cond->cond_stmt.expr)
{
int res = codegen_emit_expr(context, ast->for_stmt.cond->cond_stmt.expr, indent);
INDENT();
PRINTF("if (!_%i) goto _FOR_EXIT_%d;\n", res, loop);
}
INDENT();
PRINTF("// --- Body ---\n");
codegen_ast(context, ast->for_stmt.body, indent);
INDENT();
PRINTF("// --- End ---\n");
INDENT();
PRINTF("goto _FOR_%d;\n", loop);
INDENT();
PRINTF("_FOR_EXIT_%d:;\n", loop);
INDENT();
PRINTF("// --- End for id:%d --- \n", loop);
}
static inline void codegen_emit_do_smt(Context *context, Ast *ast, int indent)
{
INDENT();
int loop = ++context->unique_index;
PRINTF("// --- Begin do id:%d ---\n", loop);
INDENT();
PRINTF("_DO_%d_BEGIN:\n", loop);
INDENT();
PRINTF("// --- Body ---\n");
codegen_ast(context, ast->do_stmt.body, indent);
INDENT();
PRINTF("// --- End ---\n");
INDENT();
PRINTF("_DO_%d_CONTINUE:\n", loop);
INDENT();
PRINTF("// --- Loop condition ---\n");
int res = codegen_emit_expr(context, ast->do_stmt.expr, indent);
INDENT();
PRINTF("if (_%i) goto _DO_%d_BEGIN;\n", res, loop);
INDENT();
PRINTF("_DO_%d_EXIT:;\n", loop);
INDENT();
PRINTF("// --- End do id:%d --- \n", loop);
}
static inline void codegen_emit_stmt_list(Context *context, Ast *ast, int indent)
{
VECEACH(ast->stmt_list, i)
{
codegen_ast(context, ast->stmt_list[i], indent);
}
}
static void codegen_ast(Context *context, Ast *ast, int indent)
{
switch (ast->ast_kind)
@@ -309,18 +443,19 @@ static void codegen_ast(Context *context, Ast *ast, int indent)
case AST_DECLARE_STMT:
codegen_declare_stmt(context, ast, indent);
return;
case AST_DECL_EXPR_LIST:
break;
case AST_DEFAULT_STMT:
break;
case AST_DEFER_STMT:
break;
case AST_DO_STMT:
break;
codegen_emit_do_smt(context, ast, indent);
return;
case AST_EXPR_STMT:
break;
codegen_emit_expr(context, ast->expr_stmt, indent);
return;
case AST_FOR_STMT:
break;
codegen_emit_for_smt(context, ast, indent);
return;
case AST_GOTO_STMT:
break;
case AST_IF_STMT:
@@ -330,15 +465,16 @@ static void codegen_ast(Context *context, Ast *ast, int indent)
case AST_NOP_STMT:
break;
case AST_RETURN_STMT:
indent_line(context, indent);
if (ast->return_stmt.expr)
{
PRINTF("return ");
codegen_expr(context, ast->return_stmt.expr);
int index = codegen_emit_expr(context, ast->return_stmt.expr, indent);
INDENT();
PRINTF("return _%d", index);
PRINTF(";\n");
}
else
{
INDENT();
PRINTF("return;\n");
}
return;
@@ -353,19 +489,61 @@ static void codegen_ast(Context *context, Ast *ast, int indent)
case AST_VOLATILE_STMT:
break;
case AST_WHILE_STMT:
break;
UNREACHABLE
case AST_GENERIC_CASE_STMT:
break;
case AST_GENERIC_DEFAULT_STMT:
break;
case AST_STMT_LIST:
codegen_emit_stmt_list(context, ast, indent);
return;
}
TODO
}
static inline void codegen_func_decl(Context *context, Decl *decl)
{
if (decl->visibility != VISIBLE_PUBLIC)
{
PRINTF("static ");
}
print_typename(context->codegen_output, decl->func.function_signature.rtype);
PRINTF(" %s__%s()", decl->module->name, decl->name.string);
}
static inline void codegen_func(Context *context, Decl *decl)
{
print_typename(context->codegen_output, decl->func.function_signature.rtype);
PRINTF(" %s__%s()\n", decl->module->name, decl->name.string);
codegen_ast(context, decl->func.body, 0);
codegen_func_decl(context, decl);
Ast *const body = decl->func.body;
assert(body->ast_kind == AST_COMPOUND_STMT);
PRINTF("\n{\n");
Decl **const vars = decl->func.annotations->vars;
Type *type = NULL;
VECEACH(vars, i)
{
Decl *var = vars[i];
assert(var->decl_kind == DECL_VAR);
Type *current = var->var.type->canonical;
if (type == current)
{
PRINTF(", ");
}
else
{
if (type) PRINTF(";\n");
indent_line(context, 1);
print_typename(context->codegen_output, var->var.type);
PRINTF(" ");
}
type = current;
PRINTF("_%u_%s", var->var.id, var->name.string);
}
if (type) PRINTF(";\n");
VECEACH(body->compound_stmt.stmts, i)
{
codegen_ast(context, body->compound_stmt.stmts[i], 1);
}
PRINTF("}\n");
}
static void codegen_struct_member(Context *context, Decl *decl, int indent)
@@ -405,7 +583,63 @@ static inline void codegen_struct_union(Context *context, Decl *decl)
PRINTF("} %s_%s;\n\n", decl->module->name, decl->name.string);
}
static inline void codegen_decl(Context *context, Decl *decl)
static inline void codegen_top_level_func(Context *context, Decl *decl)
{
codegen_func_decl(context, decl);
PRINTF(";\n");
}
static inline void codegen_top_level_struct_union(Context *context, Decl *decl)
{
const char* type = decl->decl_kind == DECL_UNION ? "union" : "struct";
PRINTF("typedef %s _%s_%s %s_%s;\n", type, decl->module->name, decl->name.string, decl->module->name, decl->name.string);
}
static inline void codegen_top_level_decl_header(Context *context, Decl *decl)
{
switch (decl->decl_kind)
{
case DECL_POISONED:
FATAL_ERROR("Tried to codegen broken code");
return;
case DECL_FUNC:
codegen_top_level_func(context, decl);
return;
case DECL_VAR:
break;
case DECL_TYPEDEF:
TODO
case DECL_STRUCT:
case DECL_UNION:
codegen_top_level_struct_union(context, decl);
return;
case DECL_ENUM:
TODO
// codegen_top_level_enum(context, decl);
return;
case DECL_ERROR:
TODO
case DECL_MULTI_DECL:
TODO
break;
case DECL_CT_IF:
case DECL_CT_ELSE:
case DECL_CT_ELIF:
case DECL_ENUM_CONSTANT:
case DECL_ARRAY_VALUE:
case DECL_IMPORT:
case DECL_ERROR_CONSTANT:
UNREACHABLE
case DECL_MACRO:
case DECL_GENERIC:
break;
}
TODO
}
static inline void codegen_top_level_decl(Context *context, Decl *decl)
{
switch (decl->decl_kind)
{
@@ -435,17 +669,16 @@ static inline void codegen_decl(Context *context, Decl *decl)
break;
case DECL_IMPORT:
break;
case DECL_MACRO:
break;
return;
case DECL_MULTI_DECL:
break;
case DECL_GENERIC:
break;
case DECL_CT_IF:
break;
case DECL_CT_ELSE:
break;
case DECL_CT_ELIF:
UNREACHABLE
case DECL_MACRO:
case DECL_GENERIC:
break;
}
TODO
@@ -454,6 +687,11 @@ void codegen(Context *context)
{
VECEACH(context->declarations, i)
{
codegen_decl(context, context->declarations[i]);
codegen_top_level_decl_header(context, context->declarations[i]);
}
VECEACH(context->declarations, i)
{
codegen_top_level_decl(context, context->declarations[i]);
}
}

View File

@@ -17,7 +17,6 @@ typedef uint32_t SourceLoc;
#define MAX_LOCALS 0xFFFF
#define MAX_SCOPE_DEPTH 0xFF
typedef struct _Ast Ast;
typedef struct _Decl Decl;
typedef struct _Type Type;
@@ -140,6 +139,7 @@ typedef struct
typedef struct _VarDecl
{
unsigned id : 16;
VarDeclKind kind : 3;
Type *type;
Expr *init_expr;
@@ -181,12 +181,18 @@ typedef struct
Token *throws;
} FunctionSignature;
typedef struct
{
Decl **vars;
} FuncAnnotations;
typedef struct
{
const char *full_name;
Type *struct_parent;
FunctionSignature function_signature;
struct _Ast *body;
Ast *body;
FuncAnnotations *annotations;
} FuncDecl;
typedef struct
@@ -283,7 +289,7 @@ typedef struct
{
Expr *left;
Expr *right;
BinOp operator;
TokenType operator;
} ExprBinary;
typedef struct
@@ -296,7 +302,7 @@ typedef struct
typedef struct
{
Expr* expr;
UnaryOp operator;
TokenType operator;
} ExprUnary;
@@ -320,7 +326,7 @@ typedef struct
{
bool is_struct_function;
Expr *function;
Expr **parameters;
Expr **arguments;
} ExprCall;
typedef struct
@@ -448,17 +454,16 @@ typedef struct
typedef struct
{
Ast *init;
Expr *cond;
Expr *incr;
Ast *cond;
Ast *incr;
Ast *body;
} AstForStmt;
typedef struct
{
Decl *decl;
Ast *decl_expr;
Ast **stmts;
Expr *expr;
} AstCondStmt;
@@ -544,6 +549,7 @@ typedef struct _Ast
AstDeclExprList decl_expr_list;
AstGenericCaseStmt generic_case_stmt;
struct _Ast* generic_default_stmt;
Ast** stmt_list;
};
} Ast;
@@ -565,16 +571,19 @@ typedef struct _Module
STable public_symbols;
} Module;
typedef struct _DynamicScope
{
int flags;
int flags_created;
ScopeFlags flags;
ScopeFlags flags_created;
unsigned errors;
Decl **local_decl_start;
Ast *defer_stack_start;
Ast *active_defer;
ExitType exit;
} DynamicScope;
typedef struct _Context
{
Token module_name;
@@ -591,6 +600,10 @@ typedef struct _Context
Decl **last_local;
DynamicScope scopes[MAX_SCOPE_DEPTH];
DynamicScope *current_scope;
int unique_index;
Decl *evaluating_macro;
Type *rtype;
int in_volatile_section;
} Context;
extern Context *current_context;
@@ -604,18 +617,25 @@ extern Module poisoned_module;
extern Token next_tok;
extern Token tok;
extern Type type_bool, type_void, type_string;
extern Type type_half, type_float, type_double, type_quad;
extern Type type_char, type_short, type_int, type_long, type_isize;
extern Type type_byte, type_ushort, type_uint, type_ulong, type_usize;
extern Type type_compint, type_compuint, type_compfloat;
extern Type type_c_short, type_c_int, type_c_long, type_c_longlong;
extern Type type_c_ushort, type_c_uint, type_c_ulong, type_c_ulonglong;
extern Type *type_bool, *type_void, *type_string;
extern Type *type_float, *type_double;
extern Type *type_char, *type_short, *type_int, *type_long, *type_isize;
extern Type *type_byte, *type_ushort, *type_uint, *type_ulong, *type_usize;
extern Type *type_compint, *type_compuint, *type_compfloat;
extern Type *type_c_short, *type_c_int, *type_c_long, *type_c_longlong;
extern Type *type_c_ushort, *type_c_uint, *type_c_ulong, *type_c_ulonglong;
extern Type t_i8, t_i16, t_i32, t_i64, t_isz, t_ixx;
extern Type t_u1, t_u8, t_u16, t_u32, t_u64, t_usz, t_uxx;
extern Type t_f32, t_f64, t_fxx;
extern Type t_u0, t_str;
extern Type t_cus, t_cui, t_cul, t_cull;
extern Type t_cs, t_ci, t_cl, t_cll;
#define AST_NEW(_kind, _token) new_ast(_kind, _token)
static inline bool ast_ok(Ast *ast) { return ast == NULL || ast->ast_kind != AST_POISONED; }
static inline void ast_poison(Ast *ast) { 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 = malloc_arena(sizeof(Ast));
@@ -677,13 +697,13 @@ static inline ConstType sign_from_type(Type *type)
}
bool cast(Expr *expr, Type *to_type, CastType cast_type);
bool cast_arithmetic(Expr *expr, Expr *other, const char *action);
bool cast_to_runtime(Expr *expr);
void codegen(Context *context);
bool sema_expr_analysis(Context *context, Expr *expr);
Context *context_create(File *file);
void context_push(Context *context);
@@ -692,6 +712,7 @@ bool context_add_import(Context *context, Token module_name, Token alias, Import
bool context_set_module_from_filename(Context *context);
bool context_set_module(Context *context, Token module_name, Token *generic_parameters);
void context_print_ast(Context *context, FILE *file);
Decl *context_find_ident(Context *context, const char *symbol);
Decl *decl_new(DeclKind decl_kind, Token name, Visibility visibility);
Decl *decl_new_user_defined_type(Token name, DeclKind decl_type, Visibility visibility);
@@ -709,12 +730,17 @@ 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);
static inline bool expr_ok(Expr *expr) { return expr == NULL || expr->expr_kind != EXPR_POISONED; }
static inline void expr_poison(Expr *expr) { expr->expr_kind = EXPR_POISONED; expr->resolve_status = RESOLVE_DONE; }
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;
*expr = *replacement;
expr->loc = loc;
}
void fprint_ast(FILE *file, Ast *ast);
void fprint_decl(FILE *file, Decl *dec);
@@ -748,12 +774,16 @@ static inline void advance_and_verify(TokenType token_type)
advance();
}
Decl *module_find_symbol(Module *module, const char *symbol);
void parse_file(File *file);
#define SEMA_ERROR(_tok, ...) sema_error_range(_tok.span, __VA_ARGS__)
void sema_init(File *file);
void sema_analysis(Context *context);
bool sema_const_fold_binary(Context *context, Expr *expr);
bool sema_analyse_statement(Context *context, Ast *statement);
bool sema_resolve_type(Context *context, Type *type);
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);
@@ -762,7 +792,6 @@ void sema_error(const char *message, ...);
void sema_prev_at_range(SourceRange span, const char *message, ...);
void sema_prev_at(SourceLoc loc, const char *message, ...);
File *source_file_load(const char *filename, bool *already_loaded);
File *source_file_from_position(SourceLoc loc);
@@ -797,14 +826,23 @@ static inline bool type_is_signed(Type *type) { return type->type_kind >= TYPE_I
static inline bool type_is_unsigned(Type *type) { return type->type_kind >= TYPE_U8 && type->type_kind <= TYPE_UXX; }
static inline bool type_ok(Type *type) { return !type || type->type_kind != TYPE_POISONED; }
static inline void type_poison(Type *type) { type->type_kind = TYPE_POISONED; type->resolve_status = RESOLVE_DONE; }
static inline bool type_is_integer(Type *type)
{
assert(type == type->canonical);
return type->type_kind >= TYPE_I8 && type->type_kind <= TYPE_UXX;
}
static inline bool type_is_number(Type *type)
{
assert(type == type->canonical);
return type->type_kind >= TYPE_I8 && type->type_kind <= TYPE_FXX;
}
#define TYPE_MODULE_UNRESOLVED(_module, _name) ({ Type *__type = type_new(TYPE_USER_DEFINED); \
__type->name_loc = _name; __type->unresolved.module = _module; __type; })
#define TYPE_UNRESOLVED(_name) ({ Type *__type = type_new(TYPE_USER_DEFINED); __type->name_loc = _name; __type; })
AssignOp assignop_from_token(TokenType type);
BinOp binop_from_token(TokenType type);
TokenType binop_to_token(BinOp type);
UnaryOp unaryop_from_token(TokenType type);
Decl *struct_find_name(Decl *decl, const char* name);

View File

@@ -1,158 +0,0 @@
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "compiler_internal.h"
#define COMP_OP(comp) \
switch (left->type)\
{ case CONST_NIL: result->b = 0 comp 0; break;\
case CONST_BOOL: result->b = left->b comp right->b; break;\
case CONST_STRING: UNREACHABLE;\
case CONST_FLOAT: result->b = left->f comp right->f; break;\
case CONST_INT: result->b = left->i comp right->i; break;\
default: UNREACHABLE }\
result->type = CONST_BOOL; expr->expr_kind = EXPR_CONST; expr->type = &type_bool; return true;
#define BOOL_COMP(comp) \
switch (left->type)\
{ case CONST_NIL: result->b = 0 comp 0; break;\
case CONST_BOOL: result->b = left->b comp right->b; break;\
case CONST_STRING: UNREACHABLE;\
case CONST_FLOAT: result->b = (left->f != 0) comp (right->f != 0); break;\
case CONST_INT: result->b = (left->i != 0) comp (right->i != 0); break;\
default: break; }\
result->type = CONST_BOOL; expr->expr_kind = EXPR_CONST; expr->type = &type_bool; return true
#define BITOP(op)\
switch (left->type)\
{ case CONST_NIL: break; \
case CONST_BOOL: result->b = left->b op right->b; break; \
case CONST_STRING: case CONST_FLOAT: UNREACHABLE; \
case CONST_INT: result->b = left->i op right->i; break; \
default: UNREACHABLE; \
} break
#define ARITH(op)\
switch (left->type)\
{ case CONST_NIL: case CONST_BOOL: case CONST_STRING: UNREACHABLE; \
case CONST_FLOAT: result->f = left->f op right->f; break;\
case CONST_INT: result->i = left->i op right->i; break; \
default: UNREACHABLE; \
} break
bool sema_const_fold_binary(Context *context, Expr *expr)
{
Expr *left_expr = expr->binary_expr.left;
Expr *right_expr = expr->binary_expr.right;
if (left_expr->expr_kind != EXPR_CONST || right_expr->expr_kind != EXPR_CONST) return true;
Type *type = left_expr->type->canonical;
assert(type == right_expr->type->canonical);
ExprConst *left = &left_expr->const_expr;
ExprConst *right = &right_expr->const_expr;
ExprConst *result = &expr->const_expr;
switch (expr->binary_expr.operator)
{
case BINOP_ERROR:
case BINOP_ASSIGN:
case BINOP_MULT_ASSIGN:
case BINOP_ADD_ASSIGN:
case BINOP_SUB_ASSIGN:
case BINOP_DIV_ASSIGN:
case BINOP_MOD_ASSIGN:
case BINOP_AND_ASSIGN:
case BINOP_OR_ASSIGN:
case BINOP_BIT_AND_ASSIGN:
case BINOP_BIT_OR_ASSIGN:
case BINOP_BIT_XOR_ASSIGN:
case BINOP_SHR_ASSIGN:
case BINOP_SHL_ASSIGN:
SEMA_ERROR(expr->loc, "Invalid operation '%s' %s '%s.", left_expr->type->name_loc.string, token_type_to_string(binop_to_token(expr->binary_expr.operator)), right_expr->type->name_loc.string);
return false;
case BINOP_MULT:
ARITH(*);
case BINOP_ADD:
ARITH(+);
case BINOP_SUB:
ARITH(-);
case BINOP_DIV:
switch (left->type)
{
case CONST_NIL:
case CONST_BOOL:
case CONST_STRING:
UNREACHABLE;
case CONST_INT:
if (right->i == 0)
{
SEMA_ERROR(expr->binary_expr.right->loc, "Division by zero not allowed.");
return false;
}
result->i = left->i / right->i;
break;
case CONST_FLOAT:
if (right->f == 0)
{
SEMA_ERROR(expr->binary_expr.right->loc, "Division by zero not allowed.");
return false;
}
expr->const_expr.f = left->f / right->f;
expr->const_expr.type = CONST_FLOAT;
break;
}
break;
case BINOP_MOD:
switch (left->type)
{
case CONST_NIL:
case CONST_BOOL:
case CONST_STRING:
case CONST_FLOAT:
UNREACHABLE;
case CONST_INT:
if (right->i == 0)
{
SEMA_ERROR(expr->binary_expr.right->loc, "Cannot do mod by zero.");
return false;
}
result->i = left->i % right->i;
break;
}
break;
case BINOP_AND:
BOOL_COMP(&&);
case BINOP_OR:
BOOL_COMP(||);
case BINOP_BIT_AND:
BITOP(&);
case BINOP_BIT_OR:
BITOP(|);
case BINOP_BIT_XOR:
BITOP(^);
case BINOP_NE:
COMP_OP(!=)
case BINOP_EQ:
COMP_OP(==)
case BINOP_GE:
COMP_OP(>=)
case BINOP_GT:
COMP_OP(>)
case BINOP_LE:
COMP_OP(<=)
case BINOP_LT:
COMP_OP(<)
case BINOP_SHR:
TODO
break;
case BINOP_SHL:
TODO
break;
case BINOP_ELVIS:
TODO
break;
}
expr->type = type;
expr->expr_kind = EXPR_CONST;
return true;
}

View File

@@ -41,8 +41,6 @@ static inline bool create_module_or_check_name(Context *context, Token module_na
bool context_set_module_from_filename(Context *context)
{
LOG_FUNC
char buffer[MAX_IDENTIFIER_LENGTH + 1];
int len = filename_to_module(context->file->full_path, buffer);
if (!len)
@@ -64,7 +62,6 @@ bool context_set_module_from_filename(Context *context)
bool context_set_module(Context *context, Token module_name, Token *generic_parameters)
{
LOG_FUNC
DEBUG_LOG("CONTEXT: Setting module to '%s'.", module_name.string);
// Note that we allow the illegal name for now, to be able to parse further.
context->module_name = module_name;
@@ -96,7 +93,6 @@ void context_register_global_decl(Context *context, Decl *decl)
bool context_add_import(Context *context, Token module_name, Token alias, ImportType import_type, Expr** generic_parameters)
{
LOG_FUNC
DEBUG_LOG("SEMA: Add import of '%s'.", module_name.string);
if (!is_all_lower(module_name.string))
{

View File

@@ -37,25 +37,25 @@ typedef enum
AST_CT_ELIF_STMT,
AST_CT_ELSE_STMT,
AST_DECLARE_STMT,
AST_DECL_EXPR_LIST,
AST_DEFAULT_STMT,
AST_DEFER_STMT,
AST_DO_STMT,
AST_EXPR_STMT,
AST_FOR_STMT,
AST_GENERIC_CASE_STMT,
AST_GENERIC_DEFAULT_STMT,
AST_GOTO_STMT,
AST_IF_STMT,
AST_LABEL,
AST_NOP_STMT,
AST_RETURN_STMT,
AST_STMT_LIST,
AST_SWITCH_STMT,
AST_THROW_STMT,
AST_TRY_STMT,
AST_NEXT_STMT,
AST_VOLATILE_STMT,
AST_WHILE_STMT,
AST_GENERIC_CASE_STMT,
AST_GENERIC_DEFAULT_STMT,
} AstKind;
typedef enum
@@ -64,42 +64,7 @@ typedef enum
ATTR_UNRESOLVED,
} AttrKind;
typedef enum
{
BINOP_ERROR,
BINOP_ASSIGN,
BINOP_MULT,
BINOP_MULT_ASSIGN,
BINOP_ADD,
BINOP_ADD_ASSIGN,
BINOP_SUB,
BINOP_SUB_ASSIGN,
BINOP_DIV,
BINOP_DIV_ASSIGN,
BINOP_MOD,
BINOP_MOD_ASSIGN,
BINOP_AND,
BINOP_AND_ASSIGN,
BINOP_OR,
BINOP_OR_ASSIGN,
BINOP_BIT_AND,
BINOP_BIT_AND_ASSIGN,
BINOP_BIT_OR,
BINOP_BIT_OR_ASSIGN,
BINOP_BIT_XOR,
BINOP_BIT_XOR_ASSIGN,
BINOP_NE,
BINOP_EQ,
BINOP_GE,
BINOP_GT,
BINOP_LE,
BINOP_LT,
BINOP_SHR,
BINOP_SHR_ASSIGN,
BINOP_SHL,
BINOP_SHL_ASSIGN,
BINOP_ELVIS
} BinOp;
typedef enum
{
@@ -227,7 +192,6 @@ typedef enum
EXPR_STRUCT_INIT_VALUES,
EXPR_INITIALIZER_LIST,
EXPR_EXPRESSION_LIST,
EXPR_DEFERRED_TOKENS,
EXPR_CAST,
} ExprKind;
@@ -263,7 +227,7 @@ typedef enum
NUMBER_TYPE_UNSIGNED_INT,
} NumberType;
typedef enum _Precedence
typedef enum
{
PREC_NONE,
PREC_ASSIGNMENT, // =, *=, /=, %=, ...
@@ -278,6 +242,14 @@ typedef enum _Precedence
PREC_CALL, // . () [] postfix ++/--
} Precedence;
typedef enum
{
SCOPE_NONE = 0,
SCOPE_BREAK = 1 << 0,
SCOPE_CONTINUE = 1 << 1,
SCOPE_CONTROL = 1 << 2,
} ScopeFlags;
typedef enum
{
RESOLVE_NOT_DONE = 0,
@@ -513,7 +485,6 @@ typedef enum
VARDECL_LOCAL = 2,
VARDECL_PARAM = 3,
VARDECL_MEMBER = 4,
VARDECL_MULTI = 5,
} VarDeclKind;
typedef enum

View File

@@ -0,0 +1,599 @@
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "compiler_internal.h"
typedef bool(*ExprAnalysis)(Context *, Expr*);
typedef bool(*ExprBinopAnalysis)(Context *, Expr*, Expr*, Expr*);
typedef bool(*ExprUnaryAnalysis)(Context *, Expr*, Expr*);
static ExprBinopAnalysis BINOP_ANALYSIS[TOKEN_EOF];
static ExprUnaryAnalysis UNARYOP_ANALYSIS[TOKEN_EOF + 1];
static ExprUnaryAnalysis POSTUNARYOP_ANALYSIS[TOKEN_EOF + 1];
static inline bool sema_type_error_on_binop(const char *op, Expr *expr)
{
SEMA_ERROR(expr->loc, "Cannot perform '%s' %s '%s'.", expr->binary_expr.left->type->name_loc.string, op, expr->binary_expr.right->type->name_loc.string);
return false;
}
static inline bool sema_expr_analyse_conditional(Context *context, Expr *expr)
{
TODO
}
static inline bool sema_expr_analyse_identifier(Context *context, Expr *expr)
{
// TODO what about struct functions
if (expr->identifier_expr.module.string)
{
TODO
}
Decl *decl = context_find_ident(context, expr->identifier_expr.identifier.string);
if (decl == NULL)
{
SEMA_ERROR(expr->loc, "Unknown identifier %s.", expr->identifier_expr.identifier.string);
return false;
}
expr->identifier_expr.decl = decl;
expr->type = decl->var.type;
return true;
}
static inline bool sema_expr_analyse_var_call(Context *context, Expr *expr) { TODO }
static inline bool sema_expr_analyse_macro_call(Context *context, Expr *expr, Decl *macro)
{
Ast macro_parent;
// TODO handle loops
Decl *stored_macro = context->evaluating_macro;
Type *stored_rtype = context->rtype;
context->evaluating_macro = macro;
context->rtype = macro->macro_decl.rtype;
// Handle escaping macro
bool success = sema_analyse_statement(context, macro->macro_decl.body);
context->evaluating_macro = stored_macro;
context->rtype = stored_rtype;
if (!success) return false;
TODO
return success;
};
static inline bool sema_expr_analyse_generic_call(Context *context, Expr *expr) { TODO };
static inline bool sema_expr_analyse_func_call(Context *context, Expr *expr, Decl *decl)
{
if (decl->func.function_signature.throws != NULL) TODO
Expr **args =expr->call_expr.arguments;
Decl **func_params = decl->func.function_signature.params;
unsigned num_args = vec_size(args);
// unsigned num_params = vec_size(func_params);
// TODO handle named parameters, handle default parameters, varargs etc
for (unsigned i = 0; i < num_args; i++)
{
Expr *arg = args[i];
if (!sema_expr_analysis(context, arg)) return false;
if (!cast(arg, func_params[i]->var.type, CAST_TYPE_IMPLICIT_ASSIGN)) return false;
}
expr->type = decl->func.function_signature.rtype;
return true;
}
static inline bool sema_expr_analyse_call(Context *context, Expr *expr)
{
Expr *func_expr = expr->call_expr.function;
if (!sema_expr_analysis(context, func_expr)) return false;
if (func_expr->expr_kind != EXPR_IDENTIFIER)
{
TODO
}
Decl *decl = func_expr->identifier_expr.decl;
switch (decl->decl_kind)
{
case DECL_VAR:
return sema_expr_analyse_var_call(context, expr);
case DECL_FUNC:
return sema_expr_analyse_func_call(context, expr, decl);
case DECL_MACRO:
return sema_expr_analyse_macro_call(context, expr, decl);
case DECL_GENERIC:
return sema_expr_analyse_generic_call(context, expr);
default:
SEMA_ERROR(expr->loc, "The expression cannot be called.");
return false;
break;
}
}
static inline bool sema_expr_analyse_struct_value(Context *context, Expr *expr)
{
TODO
}
static inline bool sema_expr_analyse_struct_init_values(Context *context, Expr *expr)
{
TODO
}
static inline bool sema_expr_analyse_subscript(Context *context, Expr *expr)
{
TODO
}
static inline bool sema_expr_analyse_access(Context *context, Expr *expr)
{
TODO
}
static inline bool sema_expr_analyse_method_ref(Context *context, Expr *expr)
{
TODO
}
static inline bool sema_expr_analyse_initializer_list(Context *context, Expr *expr)
{
TODO
}
static inline bool sema_expr_analyse_sizeof(Context *context, Expr *expr)
{
TODO
}
static inline bool sema_expr_analyse_cast(Context *context, Expr *expr)
{
Expr *inner = expr->expr_cast.expr;
if (!sema_resolve_type(context, expr->type)) return false;
if (!sema_expr_analysis(context, inner)) return false;
if (!cast(inner, expr->type, CAST_TYPE_EXPLICIT)) return false;
// Overwrite cast.
Token loc = expr->loc;
*expr = *inner;
expr->loc = loc;
return true;
}
static bool sema_expr_analyse_assign(Context *context, Expr *expr, Expr *left, Expr *right)
{
if (!cast(right, left->type, CAST_TYPE_IMPLICIT_ASSIGN)) return false;
// Check assignable
return true;
}
static inline bool both_const(Expr *left, Expr *right)
{
return left->expr_kind == EXPR_CONST && right->expr_kind == EXPR_CONST;
}
static bool sema_expr_analyse_add(Context *context, Expr *expr, Expr *left, Expr *right)
{
Type *left_type = left->type->canonical;
Type *right_type = right->type->canonical;
if (left_type->type_kind == TYPE_POINTER)
{
if (!cast_arithmetic(right, left, "+")) return false;
expr->type = left_type;
return true;
}
if (right_type->type_kind == TYPE_POINTER)
{
if (!cast_arithmetic(left, right, "+")) return false;
expr->type = right_type;
return true;
}
if (!cast_arithmetic(left, right, "+")) return false;
if (!cast_arithmetic(right, left, "+")) return false;
Type *canonical = left->type->canonical;
if (!type_is_number(canonical))
{
SEMA_ERROR(expr->loc, "Add is not allowed");
return false;
}
if (both_const(left, right))
{
switch (left->const_expr.type)
{
case CONST_INT:
expr->const_expr.i = left->const_expr.i + right->const_expr.i;
break;
case CONST_FLOAT:
expr->const_expr.f = left->const_expr.f + right->const_expr.f;
break;
default:
UNREACHABLE
}
expr->expr_kind = EXPR_CONST;
expr->const_expr.type = left->const_expr.type;
}
expr->type = left->type;
return true;
}
static bool sema_expr_analyse_add_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_sub(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_sub_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_mult(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_mult_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_div(Context *context, Expr *expr, Expr *left, Expr *right)
{
/*
switch (left->type)
{
case CONST_NIL:
case CONST_BOOL:
case CONST_STRING:
UNREACHABLE;
case CONST_INT:
if (right->i == 0)
{
SEMA_ERROR(expr->binary_expr.right->loc, "Division by zero not allowed.");
return false;
}
result->i = left->i / right->i;
break;
case CONST_FLOAT:
if (right->f == 0)
{
SEMA_ERROR(expr->binary_expr.right->loc, "Division by zero not allowed.");
return false;
}
expr->const_expr.f = left->f / right->f;
expr->const_expr.type = CONST_FLOAT;
break;
}*/
return false;
}
static bool sema_expr_analyse_div_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_mod(Context *context, Expr *expr, Expr *left, Expr *right)
{
if (!cast_arithmetic(left, right, "%")) return false;
if (!type_is_integer(right->type->canonical) || !type_is_integer(left->type->canonical)) return sema_type_error_on_binop("%", expr);
if (right->expr_kind == EXPR_CONST)
{
if (right->const_expr.i == 0)
{
SEMA_ERROR(expr->binary_expr.right->loc, "Cannot perform mod by zero.");
return false;
}
if (left->expr_kind == EXPR_CONST)
{
// TODO negative
expr->const_expr.i = left->const_expr.i / right->const_expr.i;
expr->type = right->type;
expr->expr_kind = EXPR_CONST;
expr->const_expr.type = CONST_INT;
}
}
return true;
}
static bool sema_expr_analyse_mod_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_bit_and(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_bit_and_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_bit_or(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_bit_or_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_bit_xor(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_bit_xor_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_shr(Context *context, Expr *expr, Expr *left, Expr *right)
{ TODO }
static bool sema_expr_analyse_shr_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_shl(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_shl_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_and(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_and_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_or(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_or_assign(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_eq(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_ne(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_ge(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_gt(Context *context, Expr *expr, Expr *left, Expr *right)
{
if (!cast_arithmetic(left, right, ">")) return false;
if (!cast_arithmetic(right, left, ">")) return false;
if (both_const(left, right))
{
switch (left->const_expr.type)
{
case CONST_FLOAT:
expr->const_expr.b = left->const_expr.f > right->const_expr.f;
break;
case CONST_BOOL:
expr->const_expr.b = left->const_expr.b > right->const_expr.b;
break;
case CONST_INT:
expr->const_expr.b = left->const_expr.i > right->const_expr.i;
break;
default:
UNREACHABLE
}
expr->const_expr.type = CONST_BOOL;
expr->expr_kind = EXPR_CONST;
}
if (!cast_to_runtime(left) || !cast_to_runtime(right)) return false;
expr->type = type_bool;
return true;
}
static bool sema_expr_analyse_le(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_lt(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_elvis(Context *context, Expr *expr, Expr *left, Expr *right) { TODO }
static bool sema_expr_analyse_deref(Context *context, Expr *expr, Expr *inner) { TODO }
static bool sema_expr_analyse_addr(Context *context, Expr *expr, Expr *inner) { TODO }
static bool sema_expr_analyse_neg(Context *context, Expr *expr, Expr *inner)
{
Type *canonical = inner->type->canonical;
if (!builtin_may_negate(canonical))
{
SEMA_ERROR(expr->loc, "Cannot negate %s.", inner->type->name_loc.string);
return false;
}
if (inner->expr_kind != EXPR_CONST)
{
expr->type = inner->type;
return true;
}
// TODO UXX CAP
expr_replace(expr, inner);
switch (expr->const_expr.type)
{
case CONST_INT:
expr->const_expr.i = ~expr->const_expr.i;
break;
case CONST_FLOAT:
expr->const_expr.f = -expr->const_expr.i;
break;
default:
UNREACHABLE
}
return true;
}
static bool sema_expr_analyse_bit_not(Context *context, Expr *expr, Expr *inner)
{
Type *canonical = inner->type->canonical;
if (!type_is_integer(canonical) && canonical != type_bool)
{
SEMA_ERROR(expr->loc, "Cannot bit negate %s.", inner->type->name_loc.string);
}
if (inner->expr_kind != EXPR_CONST)
{
expr->type = inner->type;
return true;
}
expr_replace(expr, inner);
// TODO UXX CAP
switch (expr->const_expr.type)
{
case CONST_INT:
expr->const_expr.i = ~expr->const_expr.i;
break;
case CONST_BOOL:
expr->const_expr.b = !expr->const_expr.b;
break;
default:
UNREACHABLE
}
return true;
}
static bool sema_expr_analyse_not(Context *context, Expr *expr, Expr *inner)
{
if (inner->expr_kind == EXPR_CONST)
{
switch (expr->const_expr.type)
{
case CONST_NIL:
expr->const_expr.b = true;
break;
case CONST_BOOL:
expr->const_expr.b = !inner->const_expr.b;
break;
case CONST_INT:
expr->const_expr.b = inner->const_expr.i == 0;
break;
case CONST_FLOAT:
expr->const_expr.b = inner->const_expr.f == 0;
break;
case CONST_STRING:
expr->const_expr.b = !inner->const_expr.string.len;
break;
}
expr->const_expr.type = CONST_BOOL;
expr->type = type_bool;
expr->expr_kind = EXPR_CONST;
return true;
}
Type *canonical = inner->type->canonical;
switch (canonical->type_kind)
{
case TYPE_POISONED:
case TYPE_IXX:
case TYPE_UXX:
case TYPE_FXX:
case TYPE_INC_ARRAY:
case TYPE_EXPRESSION:
UNREACHABLE
case TYPE_ARRAY:
case TYPE_POINTER:
case TYPE_VARARRAY:
case TYPE_BOOL:
case TYPE_I8:
case TYPE_I16:
case TYPE_I32:
case TYPE_I64:
case TYPE_U8:
case TYPE_U16:
case TYPE_U32:
case TYPE_U64:
case TYPE_F32:
case TYPE_F64:
return true;
case TYPE_USER_DEFINED:
case TYPE_VOID:
case TYPE_STRING:
SEMA_ERROR(expr->loc, "Cannot use 'not' on %s", inner->type->name_loc.string);
return false;
}
UNREACHABLE
}
static bool sema_expr_analyse_preinc(Context *context, Expr *expr, Expr *inner) { TODO }
static bool sema_expr_analyse_predec(Context *context, Expr *expr, Expr *inner) { TODO }
static bool sema_expr_analyse_postinc(Context *context, Expr *expr, Expr *inner) { TODO }
static bool sema_expr_analyse_postdec(Context *context, Expr *expr, Expr *inner) { TODO }
static inline bool sema_expr_analyse_binary(Context *context, Expr *expr)
{
assert(expr->resolve_status == RESOLVE_RUNNING);
Expr *left = expr->binary_expr.left;
Expr *right = expr->binary_expr.right;
if (!sema_expr_analysis(context, left)) return false;
if (!sema_expr_analysis(context, right)) return false;
return BINOP_ANALYSIS[expr->binary_expr.operator](context, expr, left, right);
}
static inline bool sema_expr_analyse_unary(Context *context, Expr *expr)
{
assert(expr->resolve_status == RESOLVE_RUNNING);
Expr *inner = expr->unary_expr.expr;
if (!sema_expr_analysis(context, inner)) return false;
return UNARYOP_ANALYSIS[expr->unary_expr.operator](context, expr, inner);
}
static inline bool sema_expr_analyse_postunary(Context *context, Expr *expr)
{
assert(expr->resolve_status == RESOLVE_RUNNING);
Expr *inner = expr->post_expr.expr;
if (!sema_expr_analysis(context, inner)) return false;
return POSTUNARYOP_ANALYSIS[expr->post_expr.operator](context, expr, inner);
}
static inline bool sema_expr_analyse_try(Context *context, Expr *expr)
{
if (!sema_expr_analysis(context, expr->try_expr.expr)) return false;
expr->type = expr->try_expr.expr->type;
if (expr->try_expr.else_expr)
{
if (!sema_expr_analysis(context, expr->try_expr.else_expr)) return false;
if (!cast(expr->try_expr.else_expr, expr->type, CAST_TYPE_IMPLICIT)) return false;
}
// Check errors!
TODO
return true;
}
static inline bool sema_expr_analyse_type(Context *context, Expr *expr)
{
TODO
return true;
}
static ExprBinopAnalysis BINOP_ANALYSIS[TOKEN_EOF] = {
[TOKEN_EQ] = &sema_expr_analyse_assign,
[TOKEN_STAR] = &sema_expr_analyse_mult,
[TOKEN_MULT_ASSIGN] = &sema_expr_analyse_mult_assign,
[TOKEN_PLUS] = &sema_expr_analyse_add,
[TOKEN_PLUS_ASSIGN] = &sema_expr_analyse_add_assign,
[TOKEN_MINUS] = &sema_expr_analyse_sub,
[TOKEN_MINUS_ASSIGN] = &sema_expr_analyse_sub_assign,
[TOKEN_DIV] = &sema_expr_analyse_div,
[TOKEN_DIV_ASSIGN] = &sema_expr_analyse_div_assign,
[TOKEN_MOD] = &sema_expr_analyse_mod,
[TOKEN_MOD_ASSIGN] = &sema_expr_analyse_mod_assign,
[TOKEN_AND] = &sema_expr_analyse_and,
[TOKEN_AND_ASSIGN] = &sema_expr_analyse_and_assign,
[TOKEN_OR] = &sema_expr_analyse_bit_or,
[TOKEN_OR_ASSIGN] = &sema_expr_analyse_or_assign,
[TOKEN_AMP] = &sema_expr_analyse_bit_and,
[TOKEN_BIT_AND_ASSIGN] = &sema_expr_analyse_bit_and_assign,
[TOKEN_BIT_OR] = &sema_expr_analyse_bit_or,
[TOKEN_BIT_OR_ASSIGN] = &sema_expr_analyse_bit_or_assign,
[TOKEN_BIT_XOR] = &sema_expr_analyse_bit_xor,
[TOKEN_BIT_XOR_ASSIGN] = &sema_expr_analyse_bit_xor_assign,
[TOKEN_NOT_EQUAL] = &sema_expr_analyse_ne,
[TOKEN_EQEQ] = &sema_expr_analyse_eq,
[TOKEN_GREATER_EQ] = &sema_expr_analyse_ge,
[TOKEN_GREATER] = &sema_expr_analyse_gt,
[TOKEN_LESS_EQ] = &sema_expr_analyse_le,
[TOKEN_LESS] = &sema_expr_analyse_lt,
[TOKEN_SHR] = &sema_expr_analyse_shr,
[TOKEN_SHR_ASSIGN] = &sema_expr_analyse_shr_assign,
[TOKEN_SHL] = &sema_expr_analyse_shl,
[TOKEN_SHL_ASSIGN] = &sema_expr_analyse_shl_assign,
[TOKEN_ELVIS] = &sema_expr_analyse_elvis,
};
static ExprUnaryAnalysis UNARYOP_ANALYSIS[TOKEN_EOF + 1] = {
[TOKEN_STAR] = &sema_expr_analyse_deref,
[TOKEN_AMP] = &sema_expr_analyse_addr,
[TOKEN_MINUS] = &sema_expr_analyse_neg,
[TOKEN_BIT_NOT] = &sema_expr_analyse_bit_not,
[TOKEN_NOT] = &sema_expr_analyse_not,
[TOKEN_PLUSPLUS] = &sema_expr_analyse_preinc,
[TOKEN_MINUSMINUS] = &sema_expr_analyse_predec,
};
static ExprUnaryAnalysis POSTUNARYOP_ANALYSIS[TOKEN_EOF + 1] = {
[TOKEN_PLUSPLUS] = &sema_expr_analyse_postinc,
[TOKEN_MINUSMINUS] = &sema_expr_analyse_postdec,
};
static ExprAnalysis EXPR_ANALYSIS[EXPR_CAST + 1] = {
[EXPR_TRY] = &sema_expr_analyse_try,
[EXPR_CONST] = NULL,
[EXPR_BINARY] = &sema_expr_analyse_binary,
[EXPR_CONDITIONAL] = &sema_expr_analyse_conditional,
[EXPR_UNARY] = &sema_expr_analyse_unary,
[EXPR_POST_UNARY] = &sema_expr_analyse_postunary,
[EXPR_TYPE] = &sema_expr_analyse_type,
[EXPR_IDENTIFIER] = &sema_expr_analyse_identifier,
[EXPR_METHOD_REF] = &sema_expr_analyse_method_ref,
[EXPR_CALL] = &sema_expr_analyse_call,
[EXPR_SIZEOF] = &sema_expr_analyse_sizeof,
[EXPR_SUBSCRIPT] = &sema_expr_analyse_subscript,
[EXPR_ACCESS] = &sema_expr_analyse_access,
[EXPR_STRUCT_VALUE] = &sema_expr_analyse_struct_value,
[EXPR_STRUCT_INIT_VALUES] = &sema_expr_analyse_struct_init_values,
[EXPR_INITIALIZER_LIST] = &sema_expr_analyse_initializer_list,
[EXPR_CAST] = &sema_expr_analyse_cast,
};
bool sema_expr_analysis(Context *context, Expr *expr)
{
switch (expr->resolve_status)
{
case RESOLVE_NOT_DONE:
expr->resolve_status = RESOLVE_RUNNING;
break;
case RESOLVE_RUNNING:
SEMA_ERROR(expr->loc, "Recursive resolution of expression");
return expr_poison(expr);
case RESOLVE_DONE:
return expr_ok(expr);
}
if (!EXPR_ANALYSIS[expr->expr_kind](context, expr)) return expr_poison(expr);
expr->resolve_status = RESOLVE_DONE;
return true;
}

View File

@@ -124,7 +124,6 @@ static bool consume_const_name(const char* type)
*/
static void recover_top_level(void)
{
LOG_FUNC
advance();
while (tok.type != TOKEN_EOF)
{
@@ -190,7 +189,6 @@ SEMA_ERROR(tok, "Expected ',' or ')'"); return _res; } } while(0)
static Ast* parse_compound_stmt()
{
LOG_FUNC
CONSUME_OR(TOKEN_LBRACE, &poisoned_ast);
Ast *ast = AST_NEW(AST_COMPOUND_STMT, tok);
while (!try_consume(TOKEN_RBRACE))
@@ -226,8 +224,6 @@ static Ast* parse_compound_stmt()
*/
static inline Type *parse_base_type(void)
{
LOG_FUNC
if (tok.type == TOKEN_IDENT && next_tok.type == TOKEN_SCOPE)
{
Type *type = type_new(TYPE_USER_DEFINED);
@@ -254,70 +250,70 @@ static inline Type *parse_base_type(void)
EXPECT_OR(TOKEN_RPAREN, &poisoned_type);
break;
case TOKEN_VOID:
type = &type_void;
type = type_void;
break;
case TOKEN_BOOL:
type = &type_bool;
type = type_bool;
break;
case TOKEN_BYTE:
type = &type_byte;
type = type_byte;
break;
case TOKEN_CHAR:
type = &type_char;
type = type_char;
break;
case TOKEN_DOUBLE:
type = &type_double;
type = type_double;
break;
case TOKEN_FLOAT:
type = &type_float;
type = type_float;
break;
case TOKEN_INT:
type = &type_int;
type = type_int;
break;
case TOKEN_ISIZE:
type = &type_isize;
type = type_isize;
break;
case TOKEN_LONG:
type = &type_long;
type = type_long;
break;
case TOKEN_SHORT:
type = &type_short;
type = type_short;
break;
case TOKEN_UINT:
type = &type_uint;
type = type_uint;
break;
case TOKEN_ULONG:
type = &type_ulong;
type = type_ulong;
break;
case TOKEN_USHORT:
type = &type_ushort;
type = type_ushort;
break;
case TOKEN_USIZE:
type = &type_usize;
type = type_usize;
break;
case TOKEN_C_SHORT:
type = &type_c_short;
type = type_c_short;
break;
case TOKEN_C_INT:
type = &type_c_int;
type = type_c_int;
break;
case TOKEN_C_LONG:
type = &type_c_long;
type = type_c_long;
break;
case TOKEN_C_LONGLONG:
type = &type_c_longlong;
type = type_c_longlong;
break;
case TOKEN_C_USHORT:
type = &type_c_ushort;
type = type_c_ushort;
break;
case TOKEN_C_UINT:
type = &type_c_uint;
type = type_c_uint;
break;
case TOKEN_C_ULONG:
type = &type_c_ulong;
type = type_c_ulong;
break;
case TOKEN_C_ULONGLONG:
type = &type_c_ulonglong;
type = type_c_ulonglong;
break;
default:
@@ -341,7 +337,6 @@ static inline Type *parse_base_type(void)
*/
static inline Type *parse_array_type_index(Type *type)
{
LOG_FUNC
assert(type_ok(type));
@@ -380,7 +375,6 @@ static inline Type *parse_array_type_index(Type *type)
*/
static Type *parse_type_expression(void)
{
LOG_FUNC
Type *type = parse_base_type();
while (type->type_kind != TYPE_POISONED)
@@ -552,19 +546,21 @@ static Ast *parse_expr_stmt(void)
* : expression
* | expression_list ',' expression
* ;
* @return Expr *
* @return Ast *
*/
static inline Expr *parse_expression_list(void)
static inline Ast *parse_expression_list(void)
{
Expr *exp_list = EXPR_NEW_TOKEN(EXPR_EXPRESSION_LIST, tok);
Expr **expressions = NULL;
Ast *statement_list = new_ast(AST_STMT_LIST, tok);
Ast **stmts = NULL;
do
{
Expr *expr = TRY_EXPR_OR(parse_expr(), &poisoned_expr);
expressions = VECADD(expressions, expr);
Expr *expr = TRY_EXPR_OR(parse_expr(), &poisoned_ast);
Ast *ast = new_ast(AST_EXPR_STMT, expr->loc);
ast->expr_stmt = expr;
stmts = VECADD(stmts, ast);
} while (try_consume(TOKEN_COMMA));
exp_list->expression_list = expressions;
return exp_list;
statement_list->stmt_list = stmts;
return statement_list;
}
/**
@@ -573,42 +569,35 @@ static inline Expr *parse_expression_list(void)
* | declaration_list
* ;
*
* @return Ast*
* @return bool
*/
static inline Ast* parse_decl_expr_list(void)
static inline bool parse_decl_expr_list(Ast ***stmt_list)
{
Expr *expr = NULL;
Type *type = NULL;
Ast *decl_expr_list = AST_NEW(AST_DECL_EXPR_LIST, tok);
if (!parse_type_or_expr(&expr, &type)) return false;
if (!parse_type_or_expr(&expr, &type)) return &poisoned_ast;
if (expr)
{
if (try_consume(TOKEN_COMMA))
while (1)
{
Expr **expressions = NULL;
expressions = VECADD(expressions, expr);
do
{
expr = TRY_EXPR_OR(parse_expr(), &poisoned_ast);
expressions = VECADD(expressions, expr);
} while (try_consume(TOKEN_COMMA));
Expr *exp_list = EXPR_NEW_EXPR(EXPR_EXPRESSION_LIST, expr);
exp_list->expression_list = expressions;
expr = exp_list;
Ast *stmt = new_ast(AST_EXPR_STMT, expr->loc);
stmt->expr_stmt = expr;
*stmt_list = VECADD(*stmt_list, stmt);
if (!try_consume(TOKEN_COMMA)) break;
expr = TRY_EXPR_OR(parse_expr(), &poisoned_ast);
}
decl_expr_list->decl_expr_list.expr = expr;
decl_expr_list->decl_expr_list.list_type = DECLEXPR_EXPR;
return decl_expr_list;
}
decl_expr_list->decl_expr_list.list_type = DECLEXPR_DECL;
decl_expr_list->decl_expr_list.decl = TRY_DECL_OR(parse_decl_after_type(false, type), &poisoned_ast);
return decl_expr_list;
else
{
Decl *decl = TRY_DECL_OR(parse_decl_after_type(false, type), &poisoned_ast);
Ast *stmt = new_ast(AST_DECLARE_STMT, decl->name);
stmt->declare_stmt = decl;
*stmt_list = VECADD(*stmt_list, stmt);
}
return true;
}
/**
@@ -621,28 +610,30 @@ static inline Ast* parse_decl_expr_list(void)
*/
static inline Ast *parse_control_expression()
{
Ast *cond = TRY_AST(parse_decl_expr_list());
Ast *stmt_list = AST_NEW(AST_STMT_LIST, tok);
if (cond->decl_expr_list.list_type == DECLEXPR_EXPR)
Ast ***stmt_ref = &stmt_list->stmt_list;
if (!parse_decl_expr_list(stmt_ref)) return &poisoned_ast;
assert(*stmt_ref != NULL);
if (VECLAST(*stmt_ref)->ast_kind == AST_EXPR_STMT)
{
if (tok.type == TOKEN_EOS)
{
SEMA_ERROR(tok, "Unexpected ';'.");
return &poisoned_ast;
}
return cond;
return stmt_list;
}
if (!try_consume(TOKEN_EOS))
{
return cond;
return stmt_list;
}
Decl *decls = cond->decl_expr_list.decl;
cond->ast_kind = AST_COND_STMT;
cond->cond_stmt.decl = decls;
cond->cond_stmt.decl_expr = TRY_AST(parse_decl_expr_list());
return cond;
if (!parse_decl_expr_list(stmt_ref)) return &poisoned_ast;
return stmt_list;
}
/**
@@ -655,7 +646,6 @@ static inline Ast *parse_control_expression()
*/
static inline Ast* parse_if_stmt(void)
{
LOG_FUNC
Ast *if_ast = AST_NEW(AST_IF_STMT, tok);
advance_and_verify(TOKEN_IF);
CONSUME_OR(TOKEN_LPAREN, &poisoned_ast);
@@ -802,12 +792,17 @@ static inline Ast* parse_for_stmt(void)
advance_and_verify(TOKEN_FOR);
CONSUME_OR(TOKEN_LPAREN, &poisoned_ast);
ast->for_stmt.init = TRY_AST(parse_decl_expr_list());
Ast *cond = new_ast(AST_COND_STMT, tok);
if (!parse_decl_expr_list(&cond->cond_stmt.stmts)) return &poisoned_ast;
CONSUME_OR(TOKEN_EOS, &poisoned_ast);
if (tok.type != TOKEN_EOS)
{
ast->for_stmt.cond = TRY_EXPR_OR(parse_expr(), &poisoned_ast);
cond->cond_stmt.expr = TRY_EXPR_OR(parse_expr(), &poisoned_ast);
}
ast->for_stmt.cond = cond;
CONSUME_OR(TOKEN_EOS, &poisoned_ast);
if (!try_consume(TOKEN_RPAREN))
@@ -880,7 +875,6 @@ static inline Ast* parse_ct_switch_stmt(void)
static inline Ast* parse_ct_else_stmt(void)
{
LOG_FUNC
Ast *ast = AST_NEW(AST_CT_ELSE_STMT, tok);
advance_and_verify(TOKEN_CT_ELSE);
ast->ct_elif_stmt.then = TRY_AST(parse_compound_stmt());
@@ -894,7 +888,6 @@ static inline Ast* parse_ct_else_stmt(void)
*/
static inline Ast *parse_ct_elif_stmt(void)
{
LOG_FUNC
Ast *ast = AST_NEW(AST_CT_ELIF_STMT, tok);
advance_and_verify(TOKEN_CT_ELIF);
@@ -924,7 +917,6 @@ static inline Ast *parse_ct_elif_stmt(void)
*/
static inline Ast* parse_ct_if_stmt(void)
{
LOG_FUNC
Ast *ast = AST_NEW(AST_CT_IF_STMT, tok);
advance_and_verify(TOKEN_CT_IF);
ast->ct_if_stmt.expr = TRY_EXPR_OR(parse_paren_expr(), &poisoned_ast);
@@ -959,7 +951,6 @@ static inline Ast* parse_ct_each_stmt(void)
*/
static Ast *parse_return_stmt(void)
{
LOG_FUNC
advance_and_verify(TOKEN_RETURN);
Ast *ast = AST_NEW(AST_RETURN_STMT, tok);
@@ -1018,7 +1009,6 @@ bool is_valid_try_statement(TokenType type)
static inline Ast *parse_label_stmt(void)
{
LOG_FUNC
Ast *ast = AST_NEW(AST_LABEL, tok);
advance_and_verify(TOKEN_CONST_IDENT);
advance_and_verify(TOKEN_COLON);
@@ -1132,7 +1122,6 @@ static inline Ast *parse_decl_or_expr_stmt(void)
static Ast *parse_stmt(void)
{
LOG_FUNC
switch (tok.type)
{
case TOKEN_LBRACE:
@@ -1370,7 +1359,6 @@ static Ast *parse_stmt(void)
*/
static inline bool parse_optional_module_params(Token **tokens)
{
LOG_FUNC
*tokens = NULL;
@@ -1418,7 +1406,6 @@ static inline bool parse_optional_module_params(Token **tokens)
*/
static inline void parse_module(void)
{
LOG_FUNC
if (!try_consume(TOKEN_MODULE))
{
@@ -1448,81 +1435,7 @@ static inline void parse_module(void)
TRY_CONSUME_EOS_OR();
}
/**
* Parse any deferred expression, correctly handling nesting.
*
* @return A non null expression. Poisoned if this fails.
*/
static inline Expr* parse_deferred_expression(void)
{
LOG_FUNC
Expr *expr = expr_new(EXPR_DEFERRED_TOKENS, next_tok);
int paren = 0;
int brace = 0;
int bracket = 0;
expr->deferred_tokens = NULL;
while (1)
{
switch (next_tok.type)
{
case TOKEN_LPAREN:
paren++;
break;
case TOKEN_LBRACE:
brace++;
break;
case TOKEN_LBRACKET:
bracket++;
break;
case TOKEN_RPAREN:
if (--paren < 0)
{
if (brace > 0 || bracket > 0)
{
sema_error_range(next_tok.span, "I found a mismatched ')' here, did you add one too many?");
expr->expr_kind = EXPR_POISONED;
}
return expr;
}
break;
case TOKEN_RBRACE:
if (--brace < 0)
{
if (paren > 0 || bracket > 0)
{
sema_error_range(next_tok.span, "I found a mismatched '}' here, did you add one too many?");
expr->expr_kind = EXPR_POISONED;
}
return expr;
}
break;
case TOKEN_RBRACKET:
if (--bracket < 0)
{
if (paren > 0 || brace > 0)
{
sema_error_range(next_tok.span, "I found a mismatched ']' here, did you add one too many?");
expr->expr_kind = EXPR_POISONED;
}
return expr;
}
break;
case TOKEN_COMMA:
if (bracket == 0 && brace == 0 && paren == 0) return expr;
break;
case TOKEN_EOF:
case TOKEN_INVALID_TOKEN:
expr->expr_kind = EXPR_POISONED;
return expr;
default:
break;
}
expr->deferred_tokens = VECADD(expr->deferred_tokens, next_tok);
advance();
}
}
/**
* Only call this if the first '(' has been detected.
*
@@ -1535,7 +1448,6 @@ static inline Expr* parse_deferred_expression(void)
*/
static inline bool parse_macro_parameter_list(Expr*** result)
{
LOG_FUNC
TODO
advance_and_verify(TOKEN_LPAREN);
*result = NULL;
@@ -1567,7 +1479,6 @@ static inline bool parse_macro_parameter_list(Expr*** result)
*/
static inline bool parse_import()
{
LOG_FUNC
advance_and_verify(TOKEN_IMPORT);
@@ -1620,7 +1531,6 @@ static Expr *parse_precedence(Precedence precedence)
static inline Expr* parse_expr(void)
{
LOG_FUNC
Token start = tok;
bool found_try = try_consume(TOKEN_TRY);
@@ -1654,7 +1564,6 @@ static inline Expr *parse_paren_expr(void)
*/
static inline void parse_imports(void)
{
LOG_FUNC
while (tok.type == TOKEN_IMPORT)
{
@@ -1677,8 +1586,6 @@ static inline Decl *parse_attribute_declaration(Visibility visibility)
*/
static inline Decl *parse_const_declaration(Visibility visibility)
{
LOG_FUNC
advance_and_verify(TOKEN_CONST);
Decl *decl = decl_new_var(tok, NULL, VARDECL_CONST, visibility);
@@ -1716,7 +1623,6 @@ static inline Decl *parse_const_declaration(Visibility visibility)
*/
static inline Decl *parse_global_declaration(Visibility visibility)
{
LOG_FUNC
Type *type = TRY_TYPE_OR(parse_type_expression(), &poisoned_decl);
@@ -1749,7 +1655,6 @@ static inline Decl *parse_global_declaration(Visibility visibility)
*/
static inline bool parse_attributes(Decl *parent_decl)
{
LOG_FUNC
parent_decl->attributes = NULL;
while (tok.type == TOKEN_AT_IDENT || (tok.type == TOKEN_IDENT && next_tok.type == TOKEN_SCOPE))
{
@@ -1812,7 +1717,6 @@ static inline bool parse_attributes(Decl *parent_decl)
*/
bool parse_struct_body(Decl *parent, Decl *visible_parent)
{
LOG_FUNC
CONSUME_OR(TOKEN_LBRACE, false);
@@ -2333,8 +2237,6 @@ static inline Decl *parse_func_definition(Visibility visibility, bool is_interfa
*/
static inline Decl *parse_error_declaration(Visibility visibility)
{
LOG_FUNC
advance_and_verify(TOKEN_ERROR_TYPE);
Decl *error_decl = decl_new_user_defined_type(tok, DECL_ERROR, visibility);
@@ -2384,8 +2286,6 @@ static inline Decl *parse_error_declaration(Visibility visibility)
*/
static inline Decl *parse_enum_declaration(Visibility visibility)
{
LOG_FUNC
advance_and_verify(TOKEN_ENUM);
Decl *decl = decl_new_user_defined_type(tok, DECL_ENUM, visibility);
@@ -2400,7 +2300,7 @@ static inline Decl *parse_enum_declaration(Visibility visibility)
CONSUME_OR(TOKEN_LBRACE, false);
decl->enums.type = type ? type : &type_int;
decl->enums.type = type ? type : type_int;
while (!try_consume(TOKEN_RBRACE))
{
Decl *enum_const = decl_new(DECL_ENUM_CONSTANT, tok, decl->visibility);
@@ -2435,20 +2335,6 @@ static inline Decl *parse_enum_declaration(Visibility visibility)
}
/**
*
*/
static inline void parse_macro_var(void)
{
LOG_FUNC
advance_and_verify(TOKEN_CT_IDENT);
Token var_name = tok;
// TODO use the result
parse_deferred_expression();
}
static inline bool parse_conditional_top_level(Decl ***decls)
@@ -2472,7 +2358,6 @@ static inline bool parse_conditional_top_level(Decl ***decls)
static inline Decl *parse_ct_if_top_level(void)
{
LOG_FUNC
Decl *ct = decl_new(DECL_CT_IF, tok, VISIBLE_LOCAL);
advance_and_verify(TOKEN_CT_IF);
ct->ct_if_decl.expr = TRY_EXPR_OR(parse_paren_expr(), &poisoned_decl);
@@ -2519,8 +2404,6 @@ static inline Decl *parse_ct_if_top_level(void)
*/
static inline Decl *parse_top_level(void)
{
LOG_FUNC
Visibility visibility = VISIBLE_MODULE;
switch (tok.type)
{
@@ -2585,12 +2468,10 @@ static inline Decl *parse_top_level(void)
void parse_current(void)
{
LOG_FUNC
// Prime everything
advance(); advance();
parse_module();
parse_imports();
LOG_FUNC
while (tok.type != TOKEN_EOF)
{
Decl *decl = parse_top_level();
@@ -2607,7 +2488,6 @@ void parse_current(void)
void parse_file(File *file)
{
LOG_FUNC
lexer_add_file_for_lexing(file);
Context *context = context_create(file);
context_push(context);
@@ -2647,7 +2527,7 @@ static Expr *parse_unary_expr(Expr *left)
TokenType operator_type = tok.type;
Expr *unary = EXPR_NEW_TOKEN(EXPR_UNARY, tok);
unary->unary_expr.operator = unaryop_from_token(operator_type);
unary->unary_expr.operator = operator_type;
Precedence rule_precedence = rules[operator_type].precedence;
advance();
Expr *right_side = parse_precedence(rule_precedence);
@@ -2661,9 +2541,9 @@ static Expr *parse_unary_expr(Expr *left)
static Expr *parse_post_unary(Expr *left)
{
assert(expr_ok(left));
Expr *unary = EXPR_NEW_EXPR(EXPR_POST_UNARY, left);
Expr *unary = EXPR_NEW_TOKEN(EXPR_POST_UNARY, tok);
unary->post_expr.expr = left;
unary->post_expr.operator = unaryop_from_token(tok.type);
unary->post_expr.operator = tok.type;
advance();
return unary;
}
@@ -2702,7 +2582,7 @@ static Expr *parse_binary(Expr *left_side)
}
Expr *expr = EXPR_NEW_EXPR(EXPR_BINARY, left_side);
expr->binary_expr.operator = binop_from_token(operator_type);
expr->binary_expr.operator = operator_type;
expr->binary_expr.left = left_side;
expr->binary_expr.right = right_side;
return expr;
@@ -2723,7 +2603,7 @@ static Expr *parse_call_expr(Expr *left)
}
Expr *call = EXPR_NEW_EXPR(EXPR_CALL, left);
call->call_expr.function = left;
call->call_expr.parameters = params;
call->call_expr.arguments = params;
return call;
}
@@ -2759,7 +2639,7 @@ static Expr *parse_string_literal(Expr *left)
assert(!left && "Had left hand side");
Expr *expr_string = EXPR_NEW_TOKEN(EXPR_CONST, tok);
expr_string->resolve_status = RESOLVE_DONE;
expr_string->type = &type_string;
expr_string->type = type_string;
advance_and_verify(TOKEN_STRING);
char *str = malloc_arena(tok.span.length + 1);
@@ -2781,7 +2661,7 @@ static Expr *parse_string_literal(Expr *left)
str[len] = '\0';
expr_string->const_expr.string.chars = str;
expr_string->const_expr.string.len = len;
expr_string->type = &type_string;
expr_string->type = type_string;
expr_string->const_expr.type = CONST_STRING;
return expr_string;
}
@@ -2871,7 +2751,7 @@ static Expr *parse_integer(Expr *left)
}
expr_int->const_expr.i = i;
expr_int->const_expr.type = CONST_INT;
expr_int->type = i > INT64_MAX ? &type_compuint : &type_compint;
expr_int->type = i > INT64_MAX ? type_compuint : type_compint;
expr_int->resolve_status = RESOLVE_DONE;
advance();
return expr_int;
@@ -2892,7 +2772,7 @@ static Expr *parse_double(Expr *left)
}
advance();
number->const_expr.f = fval;
number->type = &type_compfloat;
number->type = type_compfloat;
number->const_expr.type = CONST_FLOAT;
number->resolve_status = RESOLVE_DONE;
return number;
@@ -2903,7 +2783,7 @@ static Expr *parse_bool(Expr *left)
assert(!left && "Had left hand side");
Expr *number = EXPR_NEW_TOKEN(EXPR_CONST, tok);
number->const_expr = (ExprConst) { .b = tok.type == TOKEN_TRUE, .type = CONST_BOOL };
number->type = &type_bool;
number->type = type_bool;
number->resolve_status = RESOLVE_DONE;
advance();
return number;
@@ -2914,7 +2794,7 @@ static Expr *parse_nil(Expr *left)
assert(!left && "Had left hand side");
Expr *number = EXPR_NEW_TOKEN(EXPR_CONST, tok);
number->const_expr.type = CONST_NIL;
number->type = type_get_canonical_ptr(&type_void);
number->type = type_get_canonical_ptr(type_void);
number->resolve_status = RESOLVE_DONE;
advance();
return number;

File diff suppressed because it is too large Load Diff

View File

@@ -4,24 +4,31 @@
#include "compiler_internal.h"
Type type_bool;
Type type_void, type_string;
Type *type_bool, *type_void, *type_string;
Type *type_float, *type_double;
Type *type_char, *type_short, *type_int, *type_long, *type_isize;
Type *type_byte, *type_ushort, *type_uint, *type_ulong, *type_usize;
Type *type_compint, *type_compuint, *type_compfloat;
Type *type_c_short, *type_c_int, *type_c_long, *type_c_longlong;
Type *type_c_ushort, *type_c_uint, *type_c_ulong, *type_c_ulonglong;
Type t_u0, t_str;
Type t_u1, t_i8, t_i16, t_i32, t_i64, t_ixx;
Type t_u8, t_u16, t_u32, t_u64, t_uxx;
Type t_f32, t_f64, t_fxx;
Type t_usz, t_isz;
Type t_cus, t_cui, t_cul, t_cull;
Type t_cs, t_ci, t_cl, t_cll;
Type type_half, type_float, type_double, type_quad;
Type type_char, type_short, type_int, type_long, type_isize;
Type type_byte, type_ushort, type_uint, type_ulong, type_usize;
Type type_compint, type_compuint, type_compfloat;
Type type_c_short, type_c_int, type_c_long, type_c_longlong;
Type type_c_ushort, type_c_uint, type_c_ulong, type_c_ulonglong;
Type *type_signed_int_by_size(int bitsize)
{
switch (bitsize)
{
case 1: return &type_char;
case 2: return &type_short;
case 4: return &type_int;
case 8: return &type_long;
case 1: return type_char;
case 2: return type_short;
case 4: return type_int;
case 8: return type_long;
default: FATAL_ERROR("Illegal bitsize %d", bitsize);
}
}
@@ -29,10 +36,10 @@ Type *type_unsigned_int_by_size(int bitsize)
{
switch (bitsize)
{
case 1: return &type_byte;
case 2: return &type_ushort;
case 4: return &type_uint;
case 8: return &type_ulong;
case 1: return type_byte;
case 2: return type_ushort;
case 4: return type_uint;
case 8: return type_ulong;
default: FATAL_ERROR("Illegal bitsize %d", bitsize);
}
}
@@ -77,7 +84,7 @@ size_t type_size(Type *canonical)
case TYPE_POINTER:
case TYPE_VARARRAY:
case TYPE_STRING:
return type_isize.canonical->builtin.bytesize;
return t_usz.canonical->builtin.bytesize;
case TYPE_ARRAY:
return type_size(canonical->base) * canonical->len;
}
@@ -156,69 +163,71 @@ Type *type_get_canonical_array(Type *arr_type)
return canonical;
}
static void create_type(const char *name, Type *location, TypeKind kind, unsigned bytesize, unsigned bitsize)
static void create_type(const char *name, Type *location, Type **ptr, TypeKind kind, unsigned bytesize, unsigned bitsize)
{
*location = (Type) { .type_kind = kind, .resolve_status = RESOLVE_DONE, .builtin.bytesize = bytesize, .builtin.bitsize = bitsize };
location->name_loc.string = name;
location->name_loc.span.length = strlen(name);
location->canonical = location;
*ptr = location;
}
static void type_create_alias(const char *name, Type *location, Type *canonical)
static void type_create_alias(const char *name, Type *location, Type **ptr, Type *canonical)
{
*location = (Type) { .type_kind = TYPE_USER_DEFINED, .resolve_status = RESOLVE_DONE };
location->name_loc.string = name;
location->name_loc.span.length = strlen(name);
location->canonical = canonical;
*ptr = location;
}
void builtin_setup()
{
create_type("void", &type_void, TYPE_VOID, 1, 8);
create_type("void", &t_u0, &type_void, TYPE_VOID, 1, 8);
create_type("string", &t_str, &type_string, TYPE_STRING, build_options.pointer_size, build_options.pointer_size * 8);
/*TODO
* decl_string = (Decl) { .decl_kind = DECL_BUILTIN, .name.string = "string" };
create_type(&decl_string, &type_string);
type_string.type_kind = TYPE_STRING;
*/
#define DEF_TYPE(_name, _type, _bits) \
create_type(#_name, &type_ ## _name, _type, (_bits + 7) / 8, _bits);
#define DEF_TYPE(_name, _shortname, _type, _bits) \
create_type(#_name, &_shortname, &type_ ## _name, _type, (_bits + 7) / 8, _bits);
DEF_TYPE(compint, TYPE_IXX, 64);
DEF_TYPE(compuint, TYPE_UXX, 64);
DEF_TYPE(compfloat, TYPE_FXX, 64);
DEF_TYPE(bool, TYPE_BOOL, 1);
DEF_TYPE(compint, t_ixx, TYPE_IXX, 64);
DEF_TYPE(compuint, t_uxx, TYPE_UXX, 64);
DEF_TYPE(compfloat, t_fxx, TYPE_FXX, 64);
DEF_TYPE(bool, t_u1, TYPE_BOOL, 1);
// DEF_TYPE(half, 2, 16, NUMBER_TYPE_FLOAT, "half", T_F16);
DEF_TYPE(float, TYPE_F32, 32);
DEF_TYPE(double, TYPE_F64, 64);
// DEF_TYPE(quad, 16, 128, NUMBER_TYPE_FLOAT, "long double", T_F128);
DEF_TYPE(float, t_f32, TYPE_F32, 32);
DEF_TYPE(double, t_f64, TYPE_F64, 64);
DEF_TYPE(char, TYPE_I8, 8);
DEF_TYPE(short, TYPE_I16, 16);
DEF_TYPE(int, TYPE_I32, 32);
DEF_TYPE(long, TYPE_I64, 64);
DEF_TYPE(char, t_i8, TYPE_I8, 8);
DEF_TYPE(short, t_i16, TYPE_I16, 16);
DEF_TYPE(int, t_i32, TYPE_I32, 32);
DEF_TYPE(long, t_i64, TYPE_I64, 64);
DEF_TYPE(byte, TYPE_U8, 8);
DEF_TYPE(ushort, TYPE_U16, 16);
DEF_TYPE(uint, TYPE_U32, 32);
DEF_TYPE(ulong, TYPE_U64, 64);
DEF_TYPE(byte, t_u8, TYPE_U8, 8);
DEF_TYPE(ushort, t_u16, TYPE_U16, 16);
DEF_TYPE(uint, t_u32, TYPE_U32, 32);
DEF_TYPE(ulong, t_u64, TYPE_U64, 64);
type_create_alias("usize", &type_usize, type_unsigned_int_by_size(build_options.pointer_size));
type_create_alias("isize", &type_isize, type_signed_int_by_size(build_options.pointer_size));
type_create_alias("usize", &t_usz, &type_usize, type_unsigned_int_by_size(build_options.pointer_size));
type_create_alias("isize", &t_isz, &type_isize, type_signed_int_by_size(build_options.pointer_size));
type_create_alias("c_ushort", &type_c_ushort, type_unsigned_int_by_size(build_options.cshort_size));
type_create_alias("c_uint", &type_c_uint, type_unsigned_int_by_size(build_options.cint_size));
type_create_alias("c_ulong", &type_c_ulong, type_unsigned_int_by_size(build_options.clong_size));
type_create_alias("c_ulonglong", &type_c_ulonglong, type_unsigned_int_by_size(build_options.clonglong_size));
type_create_alias("c_ushort", &t_cus, &type_c_ushort, type_unsigned_int_by_size(build_options.cshort_size));
type_create_alias("c_uint", &t_cui, &type_c_uint, type_unsigned_int_by_size(build_options.cint_size));
type_create_alias("c_ulong", &t_cul, &type_c_ulong, type_unsigned_int_by_size(build_options.clong_size));
type_create_alias("c_ulonglong", &t_cull, &type_c_ulonglong, type_unsigned_int_by_size(build_options.clonglong_size));
type_create_alias("c_short", &type_c_short, type_signed_int_by_size(build_options.cshort_size));
type_create_alias("c_int", &type_c_int, type_signed_int_by_size(build_options.cint_size));
type_create_alias("c_long", &type_c_long, type_signed_int_by_size(build_options.clong_size));
type_create_alias("c_longlong", &type_c_longlong, type_signed_int_by_size(build_options.clonglong_size));
type_create_alias("c_short", &t_cs, &type_c_short, type_signed_int_by_size(build_options.cshort_size));
type_create_alias("c_int", &t_ci, &type_c_int, type_signed_int_by_size(build_options.cint_size));
type_create_alias("c_long", &t_cl, &type_c_long, type_signed_int_by_size(build_options.clong_size));
type_create_alias("c_longlong", &t_cll, &type_c_longlong, type_signed_int_by_size(build_options.clonglong_size));
#undef DEF_TYPE
}
}

View File

@@ -18,6 +18,7 @@ void run_arena_allocator_tests(void);
#define MALLOC(mem) malloc_arena(mem)
#define MALLOCS(type) malloc_arena(sizeof(type))
#define CALLOCS(type) ({ void *__x = malloc_arena(sizeof(type)); memset(__x, 0, sizeof(type)); __x; })
static inline bool is_power_of_two(uint64_t x)
{
@@ -213,7 +214,12 @@ static inline unsigned vec_size(const void*vec)
return vec ? (((_VHeader *)vec) - 1)->size : 0;
}
static inline void vec_pop(const void *vec)
{
assert(vec);
assert(vec_size(vec) > 0);
(((_VHeader *)vec) - 1)->size--;
}
static inline void* _expand(void *vec, size_t element_size)
{
if (vec == NULL)