Merge pull request #20 from c3lang/develop

Some work towards automated testing. Fixes to bigint. Removed implici…
This commit is contained in:
Christoffer Lerno
2020-04-02 23:15:11 +02:00
committed by GitHub
25 changed files with 897 additions and 608 deletions

View File

@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
project(c3c) project(c3c)
#set(CMAKE_BUILD_TYPE Release)
#set(CMAKE_CXX_FLAGS_RELEASE "-O3") #set(CMAKE_CXX_FLAGS_RELEASE "-O3")
find_package(LLVM REQUIRED CONFIG) find_package(LLVM REQUIRED CONFIG)

View File

@@ -0,0 +1,48 @@
module conversion;
func int test(int a0, uint b0, ushort c0, short d0)
{
int a = 0;
uint b = 0;
ushort c = 0;
short d = 0;
a = a0;
b = b0;
c = c0;
d = d0;
b += 1;
a += 2;
// a += b; Error
a += c;
b += c;
a += d;
// b += d; Error
b = b + b;
a = c + c;
a = c - c;
a = c * c;
a = c / c;
a = c % c;
a = c +% c;
a = c -% c;
a = c *% c;
a = d + cast(c + c, ushort);
// a = c << 2; TODO
//a = c << c;
//a <<= c;
//a >>= c;
//a = c >> c;
// a = 2 << c; TODO
return a;
}
func int test_top_down(int a0, uint b0, ushort c0, short d0)
{
int a = 0;
uint b = 0;
ushort c = 0;
short d = 0;
a = d + cast(c +% c, ushort);
return a;
}

View File

@@ -423,6 +423,21 @@ func int xxxx(int x)
return 1; return 1;
} }
func int testPointers(int x)
{
1 ? 1 : 2;
int y = 0;
int* z = &y;
int d = *(z + y);
isize e = z - &y;
int* eff = &y + 1;
short x1 = 2;
float f = x1 +% x1 + 1.0;
float f2 = x1 -% x1 + 1.0;
usize ef = z - &y > 0 ? 1 : z - &y;
z - &y > 0 ? 1 : z - &y;
return 1;
}
func int main(int x) func int main(int x)
{ {
int efd = 9; int efd = 9;
@@ -447,9 +462,12 @@ func int main(int x)
} }
} }
next; next;
case 1000 >> 2:
printf("case 1000 >> 2\n");
case (1 << 200) >> 197:
printf("case 1 << 3\n");
default: default:
printf("default\n"); printf("default\n");
break;
} }
int aa = x++; int aa = x++;
int bb = x--; int bb = x--;
@@ -489,12 +507,12 @@ func int main(int x)
if (ef == 4) printf("Works5!\n"); if (ef == 4) printf("Works5!\n");
if (ef == 4) printf("Works1!\n"); if (ef == 4) printf("Works1!\n");
ef = 0; ef = 0;
/*
byte a = 2; byte a = 2;
short b = 3; short b = 3;
int c = 4; int c = 4;
bool eok = true; bool eok = true;
long deee = (eok ? a : b) + (eok ? b : c);*/ long deee = (eok ? a : b) + (eok ? b : c);
int i = 0; int i = 0;
JUMP: JUMP:

View File

@@ -0,0 +1,38 @@
module arithmetics;
func void testAdd(int a, int b)
{
a = a + b;
a = a +% b;
a +%= b;
a += b;
a += 1;
a +%= 1;
}
func void testSub(int a, int b)
{
a = a - b;
a = a -% b;
a -%= b;
a -= b;
a -%= 1;
a -= 1;
}
func void testMult(int a, int b)
{
a = a * b;
a = a *% b;
a *%= b;
/*a *= b;
a *%= 1;
a *= 1;*/
}
func void testDiv(int a, int b)
{
a = a / b;
a /= b;
a /= 1;
}

View File

@@ -114,6 +114,7 @@ typedef enum
TARGET_TYPE_EXECUTABLE, TARGET_TYPE_EXECUTABLE,
TARGET_TYPE_STATIC_LIB, TARGET_TYPE_STATIC_LIB,
TARGET_TYPE_DYNAMIC_LIB, TARGET_TYPE_DYNAMIC_LIB,
TARGET_TYPE_TEST
} TargetType; } TargetType;
typedef struct typedef struct

View File

@@ -236,8 +236,6 @@ static BinaryOp assign_binop[BINARYOP_LAST + 1] = {
[BINARYOP_SUB_MOD_ASSIGN] = BINARYOP_SUB_MOD, [BINARYOP_SUB_MOD_ASSIGN] = BINARYOP_SUB_MOD,
[BINARYOP_DIV_ASSIGN] = BINARYOP_DIV, [BINARYOP_DIV_ASSIGN] = BINARYOP_DIV,
[BINARYOP_MOD_ASSIGN] = BINARYOP_MOD, [BINARYOP_MOD_ASSIGN] = BINARYOP_MOD,
[BINARYOP_AND_ASSIGN] = BINARYOP_AND,
[BINARYOP_OR_ASSIGN] = BINARYOP_OR,
[BINARYOP_BIT_AND_ASSIGN] = BINARYOP_BIT_AND, [BINARYOP_BIT_AND_ASSIGN] = BINARYOP_BIT_AND,
[BINARYOP_BIT_OR_ASSIGN] = BINARYOP_BIT_OR, [BINARYOP_BIT_OR_ASSIGN] = BINARYOP_BIT_OR,
[BINARYOP_BIT_XOR_ASSIGN] = BINARYOP_BIT_XOR, [BINARYOP_BIT_XOR_ASSIGN] = BINARYOP_BIT_XOR,

View File

@@ -61,7 +61,7 @@ static char digit_to_char(uint8_t digit, bool upper)
} }
if (digit <= 35) if (digit <= 35)
{ {
return (char) (digit + (upper ? 'A' : 'a')); return (char) (digit + (upper ? 'A' : 'a') - 10);
} }
FATAL_ERROR("Can't reach"); FATAL_ERROR("Can't reach");
} }
@@ -1579,12 +1579,15 @@ void bigint_shl_int(BigInt *dest, const BigInt *op1, uint64_t shift)
bigint_init_bigint(dest, op1); bigint_init_bigint(dest, op1);
return; return;
} }
if (op1->digit_count == 0) if (op1->digit_count == 0)
{ {
bigint_init_unsigned(dest, 0); bigint_init_unsigned(dest, 0);
return; return;
} }
const uint64_t *op1_digits = bigint_ptr(op1); const uint64_t *op1_digits = bigint_ptr(op1);
if (op1->digit_count == 1 && shift < 64) if (op1->digit_count == 1 && shift < 64)
{ {
dest->digit = op1_digits[0] << shift; dest->digit = op1_digits[0] << shift;
@@ -1596,18 +1599,17 @@ void bigint_shl_int(BigInt *dest, const BigInt *op1, uint64_t shift)
} }
} }
unsigned digit_shift_count = (unsigned int) (shift / 64); uint64_t digit_shift_count = shift / 64;
unsigned leftover_shift_count = (unsigned int) (shift % 64); uint64_t leftover_shift_count = shift % 64;
dest->digits = alloc_digits(op1->digit_count + digit_shift_count + 1); dest->digits = alloc_digits(op1->digit_count + digit_shift_count + 1);
dest->digit_count = digit_shift_count; dest->digit_count = digit_shift_count;
uint64_t carry = 0; uint64_t carry = 0;
for (size_t i = 0; i < op1->digit_count; i += 1) for (size_t i = 0; i < op1->digit_count; i += 1)
{ {
uint64_t uint64_t digit = op1_digits[i];
digit = op1_digits[i];
dest->digits[dest->digit_count] = carry | (digit << leftover_shift_count); dest->digits[dest->digit_count] = carry | (digit << leftover_shift_count);
dest->digit_count += 1; dest->digit_count++;
if (leftover_shift_count > 0) if (leftover_shift_count > 0)
{ {
carry = digit >> (64 - leftover_shift_count); carry = digit >> (64 - leftover_shift_count);
@@ -1654,15 +1656,15 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2)
if (op1->digit_count == 1) if (op1->digit_count == 1)
{ {
dest->digit = op1_digits[0] >> shift_amt; dest->digit = shift_amt < 64 ? op1_digits[0] >> shift_amt : 0;
dest->digit_count = 1; dest->digit_count = 1;
dest->is_negative = op1->is_negative; dest->is_negative = op1->is_negative;
normalize(dest); normalize(dest);
return; return;
} }
unsigned digit_shift_count = (unsigned int) (shift_amt / 64); uint64_t digit_shift_count = shift_amt / 64;
unsigned leftover_shift_count = (unsigned int) (shift_amt % 64); uint64_t leftover_shift_count = shift_amt % 64;
if (digit_shift_count >= op1->digit_count) if (digit_shift_count >= op1->digit_count)
{ {
@@ -1670,19 +1672,26 @@ void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2)
} }
dest->digit_count = op1->digit_count - digit_shift_count; dest->digit_count = op1->digit_count - digit_shift_count;
dest->digits = alloc_digits(dest->digit_count); uint64_t *digits;
uint64_t if (dest->digit_count == 1)
carry = 0; {
digits = &dest->digit;
}
else
{
digits = alloc_digits(dest->digit_count);
dest->digits = digits;
}
uint64_t carry = 0;
for (size_t op_digit_index = op1->digit_count - 1;;) for (size_t op_digit_index = op1->digit_count - 1;;)
{ {
uint64_t uint64_t digit = op1_digits[op_digit_index];
digit = op1_digits[op_digit_index];
size_t dest_digit_index = op_digit_index - digit_shift_count; size_t dest_digit_index = op_digit_index - digit_shift_count;
dest->digits[dest_digit_index] = carry | (digit >> leftover_shift_count); digits[dest_digit_index] = carry | (digit >> leftover_shift_count);
carry = digit << (64 - leftover_shift_count); carry = digit << (64 - leftover_shift_count);
if (dest_digit_index == 0) if (dest_digit_index == 0) break;
{ break; }
op_digit_index -= 1; op_digit_index -= 1;
} }
dest->is_negative = op1->is_negative; dest->is_negative = op1->is_negative;
@@ -1851,7 +1860,7 @@ void bigint_print(BigInt *bigint, uint64_t base)
bigint_init_bigint(a, bigint); bigint_init_bigint(a, bigint);
BigInt base_bi = { 0 }; BigInt base_bi = { 0 };
bigint_init_unsigned(&base_bi, 10); bigint_init_unsigned(&base_bi, base);
for (;;) for (;;)
{ {
@@ -1903,7 +1912,7 @@ const char *bigint_to_error_string(const BigInt *bigint, uint64_t base)
bigint_init_bigint(a, bigint); bigint_init_bigint(a, bigint);
BigInt base_bi = { 0 }; BigInt base_bi = { 0 };
bigint_init_unsigned(&base_bi, 10); bigint_init_unsigned(&base_bi, base);
for (;;) for (;;)
{ {
@@ -1934,7 +1943,7 @@ const char *bigint_to_error_string(const BigInt *bigint, uint64_t base)
*(current++) = *ptr; *(current++) = *ptr;
} }
*(current++) = '\0'; *(current++) = '\0';
return current; return out;
} }
void bigint_fprint(FILE *file, BigInt *bigint, uint64_t base) void bigint_fprint(FILE *file, BigInt *bigint, uint64_t base)
@@ -1966,7 +1975,7 @@ void bigint_fprint(FILE *file, BigInt *bigint, uint64_t base)
bigint_init_bigint(a, bigint); bigint_init_bigint(a, bigint);
BigInt base_bi = { 0 }; BigInt base_bi = { 0 };
bigint_init_unsigned(&base_bi, 10); bigint_init_unsigned(&base_bi, base);
for (;;) for (;;)
{ {

View File

@@ -7,7 +7,7 @@
#define EXIT_T_MISMATCH() return sema_type_mismatch(left, canonical, cast_type) #define EXIT_T_MISMATCH() return sema_type_mismatch(left, canonical, cast_type)
#define IS_EXPLICT() #define IS_EXPLICT()
#define RETURN_NON_CONST_CAST(kind) do { if (left->expr_kind == EXPR_CONST) { insert_cast(left, kind, canonical); return true; } } while (0) #define RETURN_NON_CONST_CAST(kind) do { if (left->expr_kind != EXPR_CONST) { insert_cast(left, kind, canonical); return true; } } while (0)
static inline void insert_cast(Expr *expr, CastKind kind, Type *canonical) static inline void insert_cast(Expr *expr, CastKind kind, Type *canonical)
{ {
@@ -34,11 +34,8 @@ static bool sema_type_mismatch(Expr *expr, Type *type, CastType cast_type)
case CAST_TYPE_IMPLICIT: case CAST_TYPE_IMPLICIT:
action = "implicitly cast"; action = "implicitly cast";
break; break;
case CAST_TYPE_IMPLICIT_ASSIGN: case CAST_TYPE_OPTIONAL_IMPLICIT:
case CAST_TYPE_IMPLICIT_ASSIGN_ADD: UNREACHABLE
action = "assign";
break;
} }
SEMA_ERROR(expr, "Cannot %s '%s' to '%s'.", action, type_to_error_string(expr->type), type_to_error_string(type)); SEMA_ERROR(expr, "Cannot %s '%s' to '%s'.", action, type_to_error_string(expr->type), type_to_error_string(type));
return false; return false;
@@ -52,7 +49,11 @@ bool erro(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_typ
bool ptxi(Expr *left, Type *canonical, Type *type, CastType cast_type) bool ptxi(Expr *left, Type *canonical, Type *type, CastType cast_type)
{ {
if (cast_type != CAST_TYPE_EXPLICIT) EXIT_T_MISMATCH(); if (cast_type != CAST_TYPE_EXPLICIT)
{
if (cast_type == CAST_TYPE_OPTIONAL_IMPLICIT) return true;
EXIT_T_MISMATCH();
}
RETURN_NON_CONST_CAST(CAST_PTRXI); RETURN_NON_CONST_CAST(CAST_PTRXI);
assert(left->const_expr.kind == TYPE_POINTER); assert(left->const_expr.kind == TYPE_POINTER);
@@ -62,9 +63,9 @@ bool ptxi(Expr *left, Type *canonical, Type *type, CastType cast_type)
return true; return true;
} }
bool ptbo(Expr *left, Type *canonical, Type *type, CastType cast_type) bool ptbo(Expr *left, Type *canonical, Type *type, CastType cast_type)
{ {
if (cast_type >= CAST_TYPE_IMPLICIT_ASSIGN) EXIT_T_MISMATCH();
RETURN_NON_CONST_CAST(CAST_PTRBOOL); RETURN_NON_CONST_CAST(CAST_PTRBOOL);
assert(left->const_expr.kind == TYPE_POINTER); assert(left->const_expr.kind == TYPE_POINTER);
@@ -196,7 +197,7 @@ bool boxi(Expr *left, Type *canonical, Type *type, CastType cast_type)
*/ */
bool bofp(Expr *left, Type *canonical, Type *type, CastType cast_type) bool bofp(Expr *left, Type *canonical, Type *type, CastType cast_type)
{ {
if (cast_type >= CAST_TYPE_IMPLICIT_ASSIGN) EXIT_T_MISMATCH(); // if (cast_type >= CAST_TYPE_IMPLICIT_ASSIGN) EXIT_T_MISMATCH();
RETURN_NON_CONST_CAST(CAST_BOOLFP); RETURN_NON_CONST_CAST(CAST_BOOLFP);
assert(left->const_expr.kind == TYPE_BOOL); assert(left->const_expr.kind == TYPE_BOOL);
@@ -211,7 +212,7 @@ bool bofp(Expr *left, Type *canonical, Type *type, CastType cast_type)
*/ */
bool xibo(Expr *left, Type *canonical, Type *type, CastType cast_type) bool xibo(Expr *left, Type *canonical, Type *type, CastType cast_type)
{ {
if (cast_type >= CAST_TYPE_IMPLICIT_ASSIGN) EXIT_T_MISMATCH(); // if (cast_type >= CAST_TYPE_IMPLICIT_ASSIGN) EXIT_T_MISMATCH();
RETURN_NON_CONST_CAST(CAST_INTBOOL); RETURN_NON_CONST_CAST(CAST_INTBOOL);
expr_const_set_bool(&left->const_expr, bigint_cmp_zero(&left->const_expr.i) != CMP_EQ); expr_const_set_bool(&left->const_expr, bigint_cmp_zero(&left->const_expr.i) != CMP_EQ);
@@ -225,7 +226,7 @@ bool xibo(Expr *left, Type *canonical, Type *type, CastType cast_type)
*/ */
bool fpbo(Expr *left, Type *canonical, Type *type, CastType cast_type) bool fpbo(Expr *left, Type *canonical, Type *type, CastType cast_type)
{ {
if (cast_type >= CAST_TYPE_IMPLICIT_ASSIGN) EXIT_T_MISMATCH(); // if (cast_type >= CAST_TYPE_IMPLICIT_ASSIGN) EXIT_T_MISMATCH();
RETURN_NON_CONST_CAST(CAST_FPBOOL); RETURN_NON_CONST_CAST(CAST_FPBOOL);
expr_const_set_bool(&left->const_expr, left->const_expr.f != 0.0); expr_const_set_bool(&left->const_expr, left->const_expr.f != 0.0);
@@ -242,7 +243,7 @@ bool fpfp(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_typ
{ {
bool is_narrowing = from->builtin.bytesize < canonical->builtin.bytesize && from->type_kind != TYPE_FXX; bool is_narrowing = from->builtin.bytesize < canonical->builtin.bytesize && from->type_kind != TYPE_FXX;
if (is_narrowing && cast_type == CAST_TYPE_IMPLICIT_ASSIGN) EXIT_T_MISMATCH(); // if (is_narrowing && cast_type == CAST_TYPE_IMPLICIT_ASSIGN) EXIT_T_MISMATCH();
RETURN_NON_CONST_CAST(CAST_FPFP); RETURN_NON_CONST_CAST(CAST_FPFP);
@@ -287,8 +288,9 @@ bool ixxxi(Expr *left, Type *canonical, Type *type, CastType cast_type)
{ {
bool is_signed = canonical->type_kind < TYPE_U8; bool is_signed = canonical->type_kind < TYPE_U8;
int bitsize = canonical->builtin.bitsize; int bitsize = canonical->builtin.bitsize;
if (cast_is_implicit(cast_type) && !bigint_fits_in_bits(&left->const_expr.i, bitsize, is_signed)) if (cast_type != CAST_TYPE_EXPLICIT && !bigint_fits_in_bits(&left->const_expr.i, bitsize, is_signed))
{ {
if (cast_type == CAST_TYPE_OPTIONAL_IMPLICIT) return true;
SEMA_ERROR(left, "'%s' does not fit into '%s'", expr_const_to_error_string(&left->const_expr), canonical->name); SEMA_ERROR(left, "'%s' does not fit into '%s'", expr_const_to_error_string(&left->const_expr), canonical->name);
return false; return false;
} }
@@ -308,7 +310,11 @@ bool sisi(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_typ
{ {
bool is_narrowing = from->builtin.bytesize > canonical->builtin.bytesize; bool is_narrowing = from->builtin.bytesize > canonical->builtin.bytesize;
if (is_narrowing && (cast_type != CAST_TYPE_IMPLICIT_ASSIGN_ADD && cast_type != CAST_TYPE_EXPLICIT)) EXIT_T_MISMATCH(); if (is_narrowing && cast_type != CAST_TYPE_EXPLICIT)
{
if (cast_type == CAST_TYPE_OPTIONAL_IMPLICIT) return true;
EXIT_T_MISMATCH();
}
RETURN_NON_CONST_CAST(CAST_SISI); RETURN_NON_CONST_CAST(CAST_SISI);
@@ -328,7 +334,11 @@ bool uiui(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_typ
{ {
bool is_narrowing = from->builtin.bytesize > canonical->builtin.bytesize; bool is_narrowing = from->builtin.bytesize > canonical->builtin.bytesize;
if (is_narrowing && (cast_type != CAST_TYPE_IMPLICIT_ASSIGN_ADD && cast_type != CAST_TYPE_EXPLICIT)) EXIT_T_MISMATCH(); if (is_narrowing && cast_type != CAST_TYPE_EXPLICIT)
{
if (cast_type == CAST_TYPE_OPTIONAL_IMPLICIT) return true;
EXIT_T_MISMATCH();
}
RETURN_NON_CONST_CAST(CAST_UIUI); RETURN_NON_CONST_CAST(CAST_UIUI);
@@ -349,7 +359,11 @@ bool uisi(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_typ
{ {
bool is_widening = from->builtin.bytesize < canonical->builtin.bytesize; bool is_widening = from->builtin.bytesize < canonical->builtin.bytesize;
if (!is_widening && cast_type != CAST_TYPE_IMPLICIT_ASSIGN_ADD && cast_type != CAST_TYPE_EXPLICIT) EXIT_T_MISMATCH(); if (!is_widening && cast_type != CAST_TYPE_EXPLICIT)
{
if (cast_type == CAST_TYPE_OPTIONAL_IMPLICIT) return true;
EXIT_T_MISMATCH();
}
RETURN_NON_CONST_CAST(CAST_UISI); RETURN_NON_CONST_CAST(CAST_UISI);
@@ -367,7 +381,7 @@ bool uisi(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_typ
*/ */
bool siui(Expr *left, Type *canonical, Type *type, CastType cast_type) bool siui(Expr *left, Type *canonical, Type *type, CastType cast_type)
{ {
if (cast_type != CAST_TYPE_IMPLICIT_ASSIGN_ADD && cast_type != CAST_TYPE_EXPLICIT) EXIT_T_MISMATCH(); if (cast_type != CAST_TYPE_EXPLICIT) EXIT_T_MISMATCH();
RETURN_NON_CONST_CAST(CAST_SIUI); RETURN_NON_CONST_CAST(CAST_SIUI);
@@ -455,17 +469,20 @@ bool uius(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_typ
* Cast comptime, signed or unsigned -> pointer. * Cast comptime, signed or unsigned -> pointer.
* @return true unless the constant value evaluates to zero. * @return true unless the constant value evaluates to zero.
*/ */
bool xipt(Expr *left, Type *canonical, Type *type) bool xipt(Expr *left, Type *from, Type *canonical, Type *type, CastType cast_type)
{ {
RETURN_NON_CONST_CAST(CAST_XIPTR); if (cast_type == CAST_TYPE_EXPLICIT && left->expr_kind == EXPR_CONST)
if (bigint_cmp_zero(&left->const_expr.i) != CMP_EQ)
{ {
SEMA_ERROR(left, "Only constants evaluating to zero can be cast to pointers."); RETURN_NON_CONST_CAST(CAST_XIPTR);
return false; if (bigint_cmp_zero(&left->const_expr.i) != CMP_EQ)
{
SEMA_ERROR(left, "Cannot cast non zero constants into pointers.");
return false;
}
expr_const_set_nil(&left->const_expr);
left->type = type;
} }
expr_const_set_nil(&left->const_expr); return cast(left, type_is_unsigned(from) ? type_usize : type_isize, cast_type);
left->type = type;
return true;
} }
bool usus(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_type) bool usus(Expr* left, Type *from, Type *canonical, Type *type, CastType cast_type)
@@ -548,6 +565,24 @@ bool cast_to_runtime(Expr *expr)
} }
} }
void cast_to_smallest_runtime(Expr *expr)
{
Type *canonical = expr->type->canonical;
int success;
switch (canonical->type_kind)
{
case TYPE_IXX:
success = cast(expr, type_long, CAST_TYPE_IMPLICIT);
break;
case TYPE_FXX:
success = cast(expr, type_double, CAST_TYPE_IMPLICIT);
break;
default:
return;
}
assert(success && "This should always work");
}
bool cast_implicit(Expr *expr, Type *to_type) bool cast_implicit(Expr *expr, Type *to_type)
{ {
if (!to_type) return true; if (!to_type) return true;
@@ -620,7 +655,7 @@ bool cast(Expr *expr, Type *to_type, CastType cast_type)
if (type_is_integer(canonical)) return ixxxi(expr, canonical, to_type, cast_type); if (type_is_integer(canonical)) return ixxxi(expr, canonical, to_type, cast_type);
if (type_is_float(canonical)) return ixxfp(expr, canonical, to_type, cast_type); if (type_is_float(canonical)) return ixxfp(expr, canonical, to_type, cast_type);
if (canonical == type_bool) return ixxbo(expr, to_type); if (canonical == type_bool) return ixxbo(expr, to_type);
if (canonical->type_kind == TYPE_POINTER) return xipt(expr, canonical, to_type); if (canonical->type_kind == TYPE_POINTER) return xipt(expr, from_type, canonical, to_type, cast_type);
break; break;
case TYPE_I8: case TYPE_I8:
case TYPE_I16: case TYPE_I16:
@@ -630,7 +665,7 @@ bool cast(Expr *expr, Type *to_type, CastType cast_type)
if (type_is_signed_integer(canonical)) return sisi(expr, from_type, canonical, to_type, cast_type); if (type_is_signed_integer(canonical)) return sisi(expr, from_type, canonical, to_type, cast_type);
if (type_is_float(canonical)) return sifp(expr, canonical, to_type); if (type_is_float(canonical)) return sifp(expr, canonical, to_type);
if (canonical == type_bool) return xibo(expr, canonical, to_type, cast_type); if (canonical == type_bool) return xibo(expr, canonical, to_type, cast_type);
if (canonical->type_kind == TYPE_POINTER) return xipt(expr, canonical, to_type); if (canonical->type_kind == TYPE_POINTER) return xipt(expr, from_type, canonical, to_type, cast_type);
break; break;
case TYPE_U8: case TYPE_U8:
case TYPE_U16: case TYPE_U16:
@@ -640,7 +675,7 @@ bool cast(Expr *expr, Type *to_type, CastType cast_type)
if (type_is_signed_integer(canonical)) return uisi(expr, from_type, canonical, to_type, cast_type); if (type_is_signed_integer(canonical)) return uisi(expr, from_type, canonical, to_type, cast_type);
if (type_is_float(canonical)) return uifp(expr, canonical, to_type); if (type_is_float(canonical)) return uifp(expr, canonical, to_type);
if (canonical == type_bool) return xibo(expr, canonical, to_type, cast_type); if (canonical == type_bool) return xibo(expr, canonical, to_type, cast_type);
if (canonical->type_kind == TYPE_POINTER) return xipt(expr, canonical, to_type); if (canonical->type_kind == TYPE_POINTER) return xipt(expr, from_type, canonical, to_type, cast_type);
break; break;
case TYPE_F32: case TYPE_F32:
case TYPE_F64: case TYPE_F64:

View File

@@ -582,16 +582,7 @@ typedef struct
typedef struct typedef struct
{ {
union Expr *expr; // NULL == DEFAULT
{
Expr *expr;
struct
{
uint64_t val;
CaseValueType value_type : 3;
bool has_next;
};
};
Ast *body; Ast *body;
void *backend_value; void *backend_value;
} AstCaseStmt; } AstCaseStmt;
@@ -982,15 +973,13 @@ bool cast(Expr *expr, Type *to_type, CastType cast_type);
bool cast_binary_arithmetic(Expr *left, Expr *right, const char *action); bool cast_binary_arithmetic(Expr *left, Expr *right, const char *action);
CastKind cast_to_bool_kind(Type *type); CastKind cast_to_bool_kind(Type *type);
bool cast_to_runtime(Expr *expr); bool cast_to_runtime(Expr *expr);
static inline bool cast_is_implicit(CastType cast_type) void cast_to_smallest_runtime(Expr *expr);
{
return cast_type == CAST_TYPE_IMPLICIT_ASSIGN_ADD || cast_type == CAST_TYPE_IMPLICIT || cast_type == CAST_TYPE_IMPLICIT_ASSIGN;
}
void llvm_codegen(Context *context); void llvm_codegen(Context *context);
void llvm_set_struct_size_alignment(Decl *decl); void llvm_set_struct_size_alignment(Decl *decl);
bool sema_analyse_expr_of_required_type(Context *context, Type *to, Expr *expr);
bool sema_analyse_expr(Context *context, Type *to, Expr *expr); bool sema_analyse_expr(Context *context, Type *to, Expr *expr);
bool sema_analyse_decl(Context *context, Decl *decl); bool sema_analyse_decl(Context *context, Decl *decl);
@@ -1237,7 +1226,7 @@ static inline bool type_convert_will_trunc(Type *destination, Type *source)
return (unsigned)destination->canonical->builtin.bitsize < (unsigned)source->canonical->builtin.bitsize; return (unsigned)destination->canonical->builtin.bitsize < (unsigned)source->canonical->builtin.bitsize;
} }
static inline bool type_is_number(Type *type) static inline bool type_is_numeric(Type *type)
{ {
assert(type == type->canonical); assert(type == type->canonical);
return type->type_kind >= TYPE_I8 && type->type_kind <= TYPE_FXX; return type->type_kind >= TYPE_I8 && type->type_kind <= TYPE_FXX;

View File

@@ -14,11 +14,6 @@ void diag_reset(void)
diagnostics.warnings = 0; diagnostics.warnings = 0;
} }
void reset_panic_mode(void)
{
diagnostics.panic_mode = false;
}
typedef enum typedef enum
{ {
PRINT_TYPE_ERROR, PRINT_TYPE_ERROR,

View File

@@ -57,8 +57,6 @@ typedef enum
BINARYOP_SUB_MOD_ASSIGN, BINARYOP_SUB_MOD_ASSIGN,
BINARYOP_DIV_ASSIGN, BINARYOP_DIV_ASSIGN,
BINARYOP_MOD_ASSIGN, BINARYOP_MOD_ASSIGN,
BINARYOP_AND_ASSIGN,
BINARYOP_OR_ASSIGN,
BINARYOP_BIT_AND_ASSIGN, BINARYOP_BIT_AND_ASSIGN,
BINARYOP_BIT_OR_ASSIGN, BINARYOP_BIT_OR_ASSIGN,
BINARYOP_BIT_XOR_ASSIGN, BINARYOP_BIT_XOR_ASSIGN,
@@ -113,12 +111,6 @@ typedef enum
ATTR_UNRESOLVED, ATTR_UNRESOLVED,
} AttrKind; } AttrKind;
typedef enum
{
CASE_VALUE_INT,
CASE_VALUE_UINT,
CASE_VALUE_DEFAULT
} CaseValueType;
typedef enum typedef enum
{ {
@@ -175,8 +167,7 @@ typedef enum _CastType
{ {
CAST_TYPE_EXPLICIT, CAST_TYPE_EXPLICIT,
CAST_TYPE_IMPLICIT, CAST_TYPE_IMPLICIT,
CAST_TYPE_IMPLICIT_ASSIGN, CAST_TYPE_OPTIONAL_IMPLICIT,
CAST_TYPE_IMPLICIT_ASSIGN_ADD,
} CastType; } CastType;
@@ -355,7 +346,7 @@ typedef enum
TOKEN_RPARBRA, // }) TOKEN_RPARBRA, // })
TOKEN_SCOPE, // :: TOKEN_SCOPE, // ::
TOKEN_SHR, // >> TOKEN_SHR, // >>
TOKEN_SHL, // >> TOKEN_SHL, // <<
// Three or more // Three or more
TOKEN_ELIPSIS, // ... TOKEN_ELIPSIS, // ...
@@ -459,16 +450,6 @@ typedef enum
TOKEN_VOLATILE, TOKEN_VOLATILE,
TOKEN_WHILE, TOKEN_WHILE,
TOKEN_AT_PARAM, // @param
TOKEN_AT_THROWS, // @throws
TOKEN_AT_RETURN, // @return
TOKEN_AT_ENSURE, // @ensure
TOKEN_AT_REQUIRE, // @require
TOKEN_AT_PURE, // @pure
TOKEN_AT_CONST, // @const
TOKEN_AT_REQPARSE, // @reqparse
TOKEN_AT_DEPRECATED, // @deprecated
TOKEN_CT_CASE, // $case TOKEN_CT_CASE, // $case
TOKEN_CT_DEFAULT, // $default TOKEN_CT_DEFAULT, // $default
TOKEN_CT_FOR, // $for TOKEN_CT_FOR, // $for

View File

@@ -519,7 +519,7 @@ Token lexer_scan_token(Lexer *lexer)
if (match(lexer, '+')) return parse_nested_comment(lexer); if (match(lexer, '+')) return parse_nested_comment(lexer);
return match(lexer, '=') ? make_token(lexer, TOKEN_DIV_ASSIGN, "/=") : make_token(lexer, TOKEN_DIV, "/"); return match(lexer, '=') ? make_token(lexer, TOKEN_DIV_ASSIGN, "/=") : make_token(lexer, TOKEN_DIV, "/");
case '*': case '*':
if (match(lexer, '%')) return match(lexer, '=') ? make_token(lexer, TOKEN_MINUS_MOD_ASSIGN, "*%=") : make_token(lexer, TOKEN_MULT_MOD, "*%"); if (match(lexer, '%')) return match(lexer, '=') ? make_token(lexer, TOKEN_MULT_MOD_ASSIGN, "*%=") : make_token(lexer, TOKEN_MULT_MOD, "*%");
return match(lexer, '=') ? make_token(lexer, TOKEN_MULT_ASSIGN, "*=") : make_token(lexer, TOKEN_STAR, "*"); return match(lexer, '=') ? make_token(lexer, TOKEN_MULT_ASSIGN, "*=") : make_token(lexer, TOKEN_STAR, "*");
case '=': case '=':
return match(lexer, '=') ? make_token(lexer, TOKEN_EQEQ, "==") : make_token(lexer, TOKEN_EQ, "="); return match(lexer, '=') ? make_token(lexer, TOKEN_EQEQ, "==") : make_token(lexer, TOKEN_EQ, "=");
@@ -607,5 +607,15 @@ Token lexer_scan_ident_test(Lexer *lexer, const char *scan)
lexer->current_file->end_id = 1000; lexer->current_file->end_id = 1000;
lexer->current_file->name = "Foo"; lexer->current_file->name = "Foo";
if (scan[0] == '$')
{
next(lexer);
return scan_prefixed_ident(lexer, TOKEN_CT_IDENT, TOKEN_DOLLAR, false, "$");
}
if (scan[0] == '#')
{
next(lexer);
return scan_prefixed_ident(lexer, TOKEN_HASH_IDENT, TOKEN_HASH, false, "#");
}
return scan_ident(lexer); return scan_ident(lexer);
} }

View File

@@ -551,8 +551,6 @@ static LLVMValueRef gencontext_emit_binary(GenContext *context, Expr *expr, LLVM
case BINARYOP_SUB_MOD_ASSIGN: case BINARYOP_SUB_MOD_ASSIGN:
case BINARYOP_DIV_ASSIGN: case BINARYOP_DIV_ASSIGN:
case BINARYOP_MOD_ASSIGN: case BINARYOP_MOD_ASSIGN:
case BINARYOP_AND_ASSIGN:
case BINARYOP_OR_ASSIGN:
case BINARYOP_BIT_AND_ASSIGN: case BINARYOP_BIT_AND_ASSIGN:
case BINARYOP_BIT_OR_ASSIGN: case BINARYOP_BIT_OR_ASSIGN:
case BINARYOP_BIT_XOR_ASSIGN: case BINARYOP_BIT_XOR_ASSIGN:

View File

@@ -426,7 +426,6 @@ void gencontext_emit_switch(GenContext *context, Ast *ast)
// TODO check defer correctness // TODO check defer correctness
if (ast->switch_stmt.decl) gencontext_emit_decl_expr_list_ignore_result(context, ast->switch_stmt.decl); if (ast->switch_stmt.decl) gencontext_emit_decl_expr_list_ignore_result(context, ast->switch_stmt.decl);
LLVMValueRef switch_value = gencontext_emit_decl_expr_list(context, ast->switch_stmt.cond, false); LLVMValueRef switch_value = gencontext_emit_decl_expr_list(context, ast->switch_stmt.cond, false);
size_t cases = vec_size(ast->switch_stmt.cases); size_t cases = vec_size(ast->switch_stmt.cases);
if (!cases) if (!cases)
{ {
@@ -438,7 +437,7 @@ void gencontext_emit_switch(GenContext *context, Ast *ast)
VECEACH(ast->switch_stmt.cases, i) VECEACH(ast->switch_stmt.cases, i)
{ {
Ast *case_stmt = ast->switch_stmt.cases[i]; Ast *case_stmt = ast->switch_stmt.cases[i];
if (case_stmt->case_stmt.value_type == CASE_VALUE_DEFAULT) if (!case_stmt->case_stmt.expr)
{ {
if (case_stmt->case_stmt.body) if (case_stmt->case_stmt.body)
{ {
@@ -494,7 +493,7 @@ void gencontext_emit_switch(GenContext *context, Ast *ast)
LLVMBasicBlockRef block = case_stmt->case_stmt.backend_value; LLVMBasicBlockRef block = case_stmt->case_stmt.backend_value;
if (case_stmt != default_case) if (case_stmt != default_case)
{ {
LLVMValueRef case_value = LLVMConstInt(LLVMTypeOf(switch_value), case_stmt->case_stmt.val, case_stmt->case_stmt.value_type == CASE_VALUE_INT); LLVMValueRef case_value = gencontext_emit_expr(context, case_stmt->case_stmt.expr);
LLVMAddCase(switch_stmt, case_value, block); LLVMAddCase(switch_stmt, case_value, block);
} }

View File

@@ -162,6 +162,7 @@ static Expr *parse_unary_expr(Context *context, Expr *left)
CHECK_EXPR(right_side); CHECK_EXPR(right_side);
unary->unary_expr.expr = right_side; unary->unary_expr.expr = right_side;
unary->span.end_loc = right_side->span.end_loc;
return unary; return unary;
} }

View File

@@ -197,7 +197,7 @@ static inline Ast *parse_default_stmt(Context *context)
TRY_CONSUME_OR(TOKEN_COLON, "Expected ':' after 'default'.", &poisoned_ast); TRY_CONSUME_OR(TOKEN_COLON, "Expected ':' after 'default'.", &poisoned_ast);
extend_ast_with_prev_token(context, ast); extend_ast_with_prev_token(context, ast);
ast->case_stmt.body = TRY_AST(parse_case_stmts(context)); ast->case_stmt.body = TRY_AST(parse_case_stmts(context));
ast->case_stmt.value_type = CASE_VALUE_DEFAULT; ast->case_stmt.expr = NULL;
return ast; return ast;
} }
@@ -796,15 +796,6 @@ Ast *parse_stmt(Context *context)
case TOKEN_UNTIL: case TOKEN_UNTIL:
case TOKEN_ATTRIBUTE: case TOKEN_ATTRIBUTE:
case TOKEN_VAR: case TOKEN_VAR:
case TOKEN_AT_PARAM:
case TOKEN_AT_THROWS:
case TOKEN_AT_RETURN:
case TOKEN_AT_ENSURE:
case TOKEN_AT_REQUIRE:
case TOKEN_AT_PURE:
case TOKEN_AT_CONST:
case TOKEN_AT_REQPARSE:
case TOKEN_AT_DEPRECATED:
case TOKEN_DOCS_START: case TOKEN_DOCS_START:
case TOKEN_DOCS_END: case TOKEN_DOCS_END:
case TOKEN_DOCS_EOL: case TOKEN_DOCS_EOL:

View File

@@ -514,6 +514,7 @@ Decl *parse_decl_after_type(Context *context, bool local, TypeInfo *type)
SEMA_TOKEN_ERROR(context->tok, "Expected '{'."); SEMA_TOKEN_ERROR(context->tok, "Expected '{'.");
return &poisoned_decl; return &poisoned_decl;
} }
EXPECT_IDENT_FOR_OR("variable_name", &poisoned_decl); EXPECT_IDENT_FOR_OR("variable_name", &poisoned_decl);
Token name = context->tok; Token name = context->tok;
@@ -607,6 +608,13 @@ static inline Decl *parse_global_declaration(Context *context, Visibility visibi
Decl *decl = decl_new_var(context->tok, type, VARDECL_GLOBAL, visibility); Decl *decl = decl_new_var(context->tok, type, VARDECL_GLOBAL, visibility);
if (context->tok.type == TOKEN_FUNC)
{
SEMA_TOKEN_ERROR(context->tok, "'func' can't appear here, maybe you intended to put 'func' the type?");
advance(context);
return false;
}
if (!consume_ident(context, "global variable")) return &poisoned_decl; if (!consume_ident(context, "global variable")) return &poisoned_decl;
if (try_consume(context, TOKEN_EQ)) if (try_consume(context, TOKEN_EQ))

View File

@@ -121,7 +121,7 @@ static inline bool sema_analyse_function_param(Context *context, Decl *param, bo
if (param->var.init_expr) if (param->var.init_expr)
{ {
Expr *expr = param->var.init_expr; Expr *expr = param->var.init_expr;
if (!sema_analyse_expr(context, param->type, expr)) return false; if (!sema_analyse_expr_of_required_type(context, param->type, expr)) return false;
if (expr->expr_kind != EXPR_CONST) if (expr->expr_kind != EXPR_CONST)
{ {
SEMA_ERROR(expr, "Only constant expressions may be used as default values."); SEMA_ERROR(expr, "Only constant expressions may be used as default values.");
@@ -291,7 +291,7 @@ static inline bool sema_analyse_enum(Context *context, Decl *decl)
} }
// We try to convert to the desired type. // We try to convert to the desired type.
if (!sema_analyse_expr(context, type, expr)) if (!sema_analyse_expr_of_required_type(context, type, expr))
{ {
success = false; success = false;
enum_value->resolve_status = RESOLVE_DONE; enum_value->resolve_status = RESOLVE_DONE;
@@ -404,7 +404,7 @@ static inline bool sema_analyse_global(Context *context, Decl *decl)
if (!sema_resolve_type_info(context, decl->var.type_info)) return false; if (!sema_resolve_type_info(context, decl->var.type_info)) return false;
if (decl->var.init_expr) if (decl->var.init_expr)
{ {
if (!sema_analyse_expr(context, decl->type, decl->var.init_expr)) return false; if (!sema_analyse_expr_of_required_type(context, decl->type, decl->var.init_expr)) return false;
if (decl->var.init_expr->expr_kind != EXPR_CONST) if (decl->var.init_expr->expr_kind != EXPR_CONST)
{ {
SEMA_ERROR(decl->var.init_expr, "The expression must be a constant value."); SEMA_ERROR(decl->var.init_expr, "The expression must be a constant value.");

File diff suppressed because it is too large Load Diff

View File

@@ -109,7 +109,13 @@ static inline bool sema_analyse_block_return_stmt(Context *context, Ast *stateme
{ {
assert(context->current_scope->flags & SCOPE_EXPR_BLOCK); assert(context->current_scope->flags & SCOPE_EXPR_BLOCK);
UPDATE_EXIT(EXIT_RETURN); UPDATE_EXIT(EXIT_RETURN);
if (statement->return_stmt.expr && !sema_analyse_expr(context, context->expected_block_type, statement->return_stmt.expr)) return false; if (statement->return_stmt.expr
&& !sema_analyse_expr_of_required_type(context,
context->expected_block_type,
statement->return_stmt.expr))
{
return false;
}
vec_add(context->returns, statement); vec_add(context->returns, statement);
return true; return true;
} }
@@ -147,7 +153,7 @@ static inline bool sema_analyse_return_stmt(Context *context, Ast *statement)
SEMA_ERROR(statement, "You can't return a value from a void function, you need to add a return type."); SEMA_ERROR(statement, "You can't return a value from a void function, you need to add a return type.");
return false; return false;
} }
if (!sema_analyse_expr(context, expected_rtype, return_expr)) return false; if (!sema_analyse_expr_of_required_type(context, expected_rtype, return_expr)) return false;
if (!expected_rtype) if (!expected_rtype)
{ {
assert(context->evaluating_macro); assert(context->evaluating_macro);
@@ -167,7 +173,7 @@ static inline bool sema_analyse_var_decl(Context *context, Decl *decl)
decl->type = decl->var.type_info->type; decl->type = decl->var.type_info->type;
if (decl->var.init_expr) if (decl->var.init_expr)
{ {
if (!sema_analyse_expr(context, decl->type, decl->var.init_expr)) return decl_poison(decl); if (!sema_analyse_expr_of_required_type(context, decl->type, decl->var.init_expr)) return decl_poison(decl);
} }
if (!sema_add_local(context, decl)) return decl_poison(decl); if (!sema_add_local(context, decl)) return decl_poison(decl);
return true; return true;
@@ -262,7 +268,7 @@ static inline bool sema_analyse_do_stmt(Context *context, Ast *statement)
context_pop_scope(context); context_pop_scope(context);
if (!success) return false; if (!success) return false;
context_push_scope(context); context_push_scope(context);
success = sema_analyse_expr(context, type_bool, expr); success = sema_analyse_expr_of_required_type(context, type_bool, expr);
statement->do_stmt.expr = context_pop_defers_and_wrap_expr(context, expr); statement->do_stmt.expr = context_pop_defers_and_wrap_expr(context, expr);
context_pop_scope(context); context_pop_scope(context);
return success; return success;
@@ -315,7 +321,7 @@ static inline bool sema_analyse_for_stmt(Context *context, Ast *statement)
// Conditional scope start // Conditional scope start
context_push_scope(context); context_push_scope(context);
Expr *cond = statement->for_stmt.cond; Expr *cond = statement->for_stmt.cond;
success = sema_analyse_expr(context, type_bool, cond); success = sema_analyse_expr_of_required_type(context, type_bool, cond);
statement->for_stmt.cond = context_pop_defers_and_wrap_expr(context, cond); statement->for_stmt.cond = context_pop_defers_and_wrap_expr(context, cond);
// Conditional scope end // Conditional scope end
context_pop_scope(context); context_pop_scope(context);
@@ -550,35 +556,22 @@ static bool sema_analyse_case_expr(Context *context, Type* to_type, Ast *case_st
Expr *case_expr = case_stmt->case_stmt.expr; Expr *case_expr = case_stmt->case_stmt.expr;
// TODO handle enums // TODO handle enums
// TODO string expr // TODO string expr
if (!sema_analyse_expr(context, to_type, case_expr)) return false; if (!sema_analyse_expr_of_required_type(context, to_type, case_expr)) return false;
if (case_expr->expr_kind != EXPR_CONST) if (case_expr->expr_kind != EXPR_CONST)
{ {
SEMA_ERROR(case_expr, "This must be a constant expression."); SEMA_ERROR(case_expr, "This must be a constant expression.");
return false; return false;
} }
// As a special case, we handle bools, converting them to 0 / 1 if (!cast_to_runtime(case_expr)) return false;
if (case_expr->const_expr.kind == TYPE_BOOL)
{
case_stmt->case_stmt.value_type = CASE_VALUE_UINT;
case_stmt->case_stmt.val = case_expr->const_expr.b ? 1 : 0;
return true;
}
// TODO check for int if (case_expr->const_expr.kind == TYPE_BOOL) return true;
/*
if (case_expr->const_expr.kind < TYPE__!= CONST_INT && case_expr->const_expr.type != CONST_BOOL) if (!type_is_integer(case_expr->type))
{ {
SEMA_ERROR(case_expr, "The 'case' value must be a boolean or integer constant."); SEMA_ERROR(case_expr, "The 'case' value must be a boolean or integer constant.");
return false; return false;
}*/ }
case_stmt->case_stmt.value_type = type_is_signed(case_expr->type->canonical) ? CASE_VALUE_INT : CASE_VALUE_UINT;
assert(case_expr->type->canonical->type_kind != TYPE_IXX);
// TODO this is incorrect
TODO
uint64_t val = (uint64_t)bigint_as_signed(&case_expr->const_expr.i);
case_stmt->case_stmt.val = val;
return true; return true;
} }
@@ -649,7 +642,7 @@ static bool sema_analyse_switch_stmt(Context *context, Ast *statement)
for (unsigned j = 0; j < i; j++) for (unsigned j = 0; j < i; j++)
{ {
Ast *other = statement->switch_stmt.cases[j]; Ast *other = statement->switch_stmt.cases[j];
if (other->ast_kind == AST_CASE_STMT && other->case_stmt.val == stmt->case_stmt.val) if (other->ast_kind == AST_CASE_STMT && expr_const_compare(&other->case_stmt.expr->const_expr, &stmt->case_stmt.expr->const_expr, BINARYOP_EQ))
{ {
SEMA_ERROR(stmt, "The same case value appears more than once."); SEMA_ERROR(stmt, "The same case value appears more than once.");
SEMA_PREV(other, "Here is the previous use of that value."); SEMA_PREV(other, "Here is the previous use of that value.");

View File

@@ -28,7 +28,7 @@ static inline bool sema_resolve_array_type(Context *context, TypeInfo *type)
uint64_t len = 0; uint64_t len = 0;
if (type->array.len) if (type->array.len)
{ {
if (!sema_analyse_expr(context, type_usize, type->array.len)) return type_info_poison(type); if (!sema_analyse_expr_of_required_type(context, type_usize, type->array.len)) return type_info_poison(type);
if (type->array.len->expr_kind != EXPR_CONST) if (type->array.len->expr_kind != EXPR_CONST)
{ {
SEMA_ERROR(type->array.len, "Expected a constant value as array size."); SEMA_ERROR(type->array.len, "Expected a constant value as array size.");

View File

@@ -316,26 +316,6 @@ const char *token_type_to_string(TokenType type)
case TOKEN_DOCS_LINE: case TOKEN_DOCS_LINE:
return "DOCS_LINE"; return "DOCS_LINE";
case TOKEN_AT_CONST:
return "@const";
case TOKEN_AT_DEPRECATED:
return "@deprecated";
case TOKEN_AT_ENSURE:
return "@ensure";
case TOKEN_AT_PARAM:
return "@param";
case TOKEN_AT_PURE:
return "@pure";
case TOKEN_AT_RETURN:
return "@return";
case TOKEN_AT_REQUIRE:
return "@require";
case TOKEN_AT_THROWS:
return "@throws";
case TOKEN_AT_REQPARSE:
return "@reqparse";
case TOKEN_CT_CASE: case TOKEN_CT_CASE:
return "$case"; return "$case";
case TOKEN_CT_DEFAULT: case TOKEN_CT_DEFAULT:

View File

@@ -8,7 +8,7 @@ Type *type_bool, *type_void, *type_string, *type_voidptr;
Type *type_float, *type_double; Type *type_float, *type_double;
Type *type_char, *type_short, *type_int, *type_long, *type_isize; Type *type_char, *type_short, *type_int, *type_long, *type_isize;
Type *type_byte, *type_ushort, *type_uint, *type_ulong, *type_usize; Type *type_byte, *type_ushort, *type_uint, *type_ulong, *type_usize;
Type *type_compint, *type_compuint, *type_compfloat; Type *type_compint, *type_compfloat;
Type *type_c_short, *type_c_int, *type_c_long, *type_c_longlong; 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_c_ushort, *type_c_uint, *type_c_ulong, *type_c_ulonglong;
@@ -196,7 +196,7 @@ size_t type_size(Type *canonical)
case TYPE_F64: case TYPE_F64:
return canonical->builtin.bytesize; return canonical->builtin.bytesize;
case TYPE_IXX: case TYPE_IXX:
return 4; return 8;
case TYPE_FXX: case TYPE_FXX:
return 8; return 8;
case TYPE_FUNC: case TYPE_FUNC:

View File

@@ -18,7 +18,7 @@ static void test_lexer(void)
printf("Begin lexer testing.\n"); printf("Begin lexer testing.\n");
printf("-- Check number of keywords...\n"); printf("-- Check number of keywords...\n");
int tokens_found = 0; int tokens_found = 0;
const int EXPECTED_TOKENS = 12 + 73 + 9; const int EXPECTED_TOKENS = TOKEN_CT_SWITCH - TOKEN_ALIAS + 1 + TOKEN_C_ULONGLONG - TOKEN_VOID + 1;
const char* tokens[TOKEN_EOF]; const char* tokens[TOKEN_EOF];
int len[TOKEN_EOF]; int len[TOKEN_EOF];
Lexer lexer; Lexer lexer;
@@ -26,7 +26,7 @@ static void test_lexer(void)
{ {
const char* token = token_type_to_string((TokenType)i); const char* token = token_type_to_string((TokenType)i);
tokens[i] = token; tokens[i] = token;
len[i] = strlen(token); len[i] = (int)strlen(token);
TokenType lookup = TOKEN_IDENT; TokenType lookup = TOKEN_IDENT;
const char* interned = symtab_add(token, len[i], fnv1a(token, len[i]), &lookup); const char* interned = symtab_add(token, len[i], fnv1a(token, len[i]), &lookup);
if (lookup != TOKEN_IDENT) if (lookup != TOKEN_IDENT)
@@ -48,7 +48,7 @@ static void test_lexer(void)
printf("-> %d keywords found.\n", tokens_found); printf("-> %d keywords found.\n", tokens_found);
EXPECT("Keywords", tokens_found, EXPECTED_TOKENS); EXPECT("Keywords", tokens_found, EXPECTED_TOKENS);
const int BENCH_REPEATS = 100000; const int BENCH_REPEATS = 10000;
printf("-- Test keyword lexing speed...\n"); printf("-- Test keyword lexing speed...\n");
bench_begin(); bench_begin();
@@ -56,7 +56,10 @@ static void test_lexer(void)
{ {
for (int i = 1; i < TOKEN_EOF; i++) for (int i = 1; i < TOKEN_EOF; i++)
{ {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-variable"
volatile TokenType t = lexer_scan_ident_test(&lexer, tokens[i]).type; volatile TokenType t = lexer_scan_ident_test(&lexer, tokens[i]).type;
#pragma clang diagnostic pop
} }
} }
@@ -95,7 +98,27 @@ static void test_lexer(void)
void test_compiler(void) void test_compiler(void)
{ {
compiler_init(); const char **files = NULL;
file_add_wildcard_files(&files, "tests", true);
if (!vec_size(files))
{
error_exit("No test files could be found.");
}
const char **single_file = VECNEW(const char *, 1);
vec_add(single_file, files[0]);
VECEACH(files, i)
{
printf("Running %s...\n", files[i]);
char *res = NULL;
asprintf(&res, "tests/%s", files[i]);
single_file[0] = res;
BuildTarget target = { .type = TARGET_TYPE_EXECUTABLE, .sources = single_file, .name = "a.out" };
compile_files(&target);
free(res);
}
} }
void test_file(void) void test_file(void)

View File

@@ -10,6 +10,9 @@ int main(int argc, const char *argv[])
// First setup memory // First setup memory
memory_init(); memory_init();
// Init the compiler
compiler_init();
// Parse arguments. // Parse arguments.
parse_arguments(argc, argv); parse_arguments(argc, argv);