Add static and runtime assert
This commit is contained in:
22
ast.cpp
22
ast.cpp
@@ -20,6 +20,8 @@ enum Ast_Kind: U32{
|
||||
AST_CALL_ITEM,
|
||||
AST_CALL,
|
||||
|
||||
AST_CONSTANT_ASSERT,
|
||||
AST_RUNTIME_ASSERT,
|
||||
AST_SIZE_OF,
|
||||
AST_LENGTH_OF,
|
||||
AST_ALIGN_OF,
|
||||
@@ -119,7 +121,8 @@ struct Ast_Binary: Ast_Expr{
|
||||
|
||||
struct Ast_Builtin: Ast_Expr{
|
||||
Ast_Expr *expr;
|
||||
U64 padding[3]; // For folding constants into atoms
|
||||
Intern_String assert_message;
|
||||
U64 padding[1]; // For folding constants into atoms
|
||||
};
|
||||
|
||||
// Problem: We are parsing out of order, in the middle of parsing a function
|
||||
@@ -197,7 +200,6 @@ struct Ast_Scope: Ast{
|
||||
Ast_Module *module;
|
||||
};
|
||||
|
||||
|
||||
struct Ast_Module: Ast_Scope{
|
||||
Array<Ast_File *> all_loaded_files;
|
||||
};
|
||||
@@ -507,6 +509,22 @@ ast_module(Intern_String filename){
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Builtin *
|
||||
ast_runtime_assert(Token *pos, Ast_Expr *expr, Intern_String message){
|
||||
AST_NEW(Builtin, RUNTIME_ASSERT, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
result->assert_message = message;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Builtin *
|
||||
ast_constant_assert(Token *pos, Ast_Expr *expr, Intern_String message){
|
||||
AST_NEW(Builtin, CONSTANT_ASSERT, pos, AST_EXPR);
|
||||
result->expr = expr;
|
||||
result->assert_message = message;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Builtin *
|
||||
ast_sizeof(Token *pos, Ast_Expr *expr){
|
||||
AST_NEW(Builtin, SIZE_OF, pos, AST_EXPR);
|
||||
|
||||
13
ccodegen.cpp
13
ccodegen.cpp
@@ -365,6 +365,18 @@ function void
|
||||
gen_ast(Ast *ast){
|
||||
switch(ast->kind){
|
||||
|
||||
CASE(RUNTIME_ASSERT, Builtin){
|
||||
if(node->assert_message.len == 0) gen("assert");
|
||||
else gen("assert_msg");
|
||||
gen("(");
|
||||
gen_expr(node->expr);
|
||||
if(node->assert_message.len){
|
||||
gen(", \"%s\"", node->assert_message.str);
|
||||
}
|
||||
gen(");");
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(RETURN, Return){
|
||||
gen("return");
|
||||
if(node->expr){
|
||||
@@ -504,6 +516,7 @@ gen_ast(Ast *ast){
|
||||
BREAK();
|
||||
}
|
||||
|
||||
case AST_CONSTANT_ASSERT:
|
||||
case AST_MODULE_NAMESPACE:
|
||||
CASE(FILE_NAMESPACE, File_Namespace){unused(node); BREAK();}
|
||||
|
||||
|
||||
@@ -164,6 +164,7 @@ Intern_String keyword_false;
|
||||
Intern_String keyword_for;
|
||||
Intern_String keyword_pass;
|
||||
Intern_String keyword_elif;
|
||||
Intern_String keyword_assert;
|
||||
Intern_String keyword_sizeof;
|
||||
Intern_String keyword_alignof;
|
||||
Intern_String keyword_lengthof;
|
||||
@@ -211,6 +212,7 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){
|
||||
keyword_true = l->intern("true"_s);
|
||||
keyword_false = l->intern("false"_s);
|
||||
keyword_return = l->intern("return"_s);
|
||||
keyword_assert = l->intern("assert"_s);
|
||||
keyword_if = l->intern("if"_s);
|
||||
keyword_elif = l->intern("elif"_s);
|
||||
keyword_pass = l->intern("pass"_s);
|
||||
|
||||
24
parsing.cpp
24
parsing.cpp
@@ -224,6 +224,30 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0){
|
||||
scope->stmts.add(ast_pass(token));
|
||||
}
|
||||
|
||||
else if(token_match_keyword(keyword_assert)){
|
||||
token_expect(TK_OpenParen);
|
||||
Ast_Expr *expr = parse_expr();
|
||||
Intern_String message = {};
|
||||
if(token_match(TK_Comma)){
|
||||
Token *t = token_expect(TK_StringLit);
|
||||
message = t->intern_val;
|
||||
}
|
||||
token_expect(TK_CloseParen);
|
||||
scope->stmts.add(ast_runtime_assert(token, expr, message));
|
||||
}
|
||||
|
||||
else if(token_match_pound(keyword_assert)){
|
||||
token_expect(TK_OpenParen);
|
||||
Ast_Expr *expr = parse_expr();
|
||||
Intern_String message = {};
|
||||
if(token_match(TK_Comma)){
|
||||
Token *t = token_expect(TK_StringLit);
|
||||
message = t->intern_val;
|
||||
}
|
||||
token_expect(TK_CloseParen);
|
||||
scope->stmts.add(ast_constant_assert(token, expr, message));
|
||||
}
|
||||
|
||||
else if(token_match_keyword(keyword_for)){
|
||||
Ast_Scope *for_scope = begin_stmt_scope(scratch, token_get());
|
||||
Ast_Expr *init = 0;
|
||||
|
||||
@@ -13,8 +13,6 @@ UTF16_Result :: struct
|
||||
len : S32
|
||||
error : S32
|
||||
|
||||
BINARY :: 0b1001
|
||||
|
||||
utf8_to_utf32 :: (c: *U8, max_advance: S64): UTF32_Result
|
||||
result: UTF32_Result
|
||||
if (c[0] & 0b10000000) == 0
|
||||
@@ -91,18 +89,14 @@ utf32_to_utf16 :: (codepoint: U32): UTF16_Result
|
||||
// return result;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
Vec2I :: struct;; x: S32; y: S32
|
||||
Vec2 :: struct;; x: F32; y: F32
|
||||
Windows_Bitmap :: struct
|
||||
size: Vec2I
|
||||
data: *U32
|
||||
hdc: HDC
|
||||
dib: HBITMAP
|
||||
|
||||
Vec2I :: struct;; x: S32; y: S32
|
||||
Vec2 :: struct;; x: F32; y: F32
|
||||
|
||||
|
||||
create_bitmap :: (size: Vec2I, bottom_up: Bool = true): Windows_Bitmap
|
||||
result: Windows_Bitmap = {size = size}
|
||||
if bottom_up == false
|
||||
@@ -136,6 +130,7 @@ window_procedure :: (hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM): LRE
|
||||
main :: (argc: int, argv: **char): int
|
||||
bitmap := create_bitmap({1280, 720})
|
||||
result := utf8_to_utf32(&"A"[0], 1)
|
||||
assert(result.out_str == 'A, "Invalid decode")
|
||||
result = utf8_to_utf32(&"ć"[0], 2)
|
||||
result = utf8_to_utf32(&"ó"[0], 2)
|
||||
|
||||
|
||||
@@ -443,6 +443,20 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(RUNTIME_ASSERT, Builtin){
|
||||
resolve_and_require_bool("Assert condition is not boolean", node->expr, AST_CAN_BE_NULL);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(CONSTANT_ASSERT, Builtin){
|
||||
Operand op = resolve_and_require_bool("Assert condition is not boolean", node->expr, AST_CAN_BE_NULL);
|
||||
if(!op.is_const) compiler_error(node->pos, "#assert expression required to be constant");
|
||||
if(op.bool_val == false){
|
||||
compiler_error(node->pos, "#assert condition not met :: %.*s", (int)node->assert_message.len, node->assert_message.str);
|
||||
}
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(FOR, For){
|
||||
if(node->init && node->cond == 0 && node->iter == 0){
|
||||
if(!is_flag_set(node->init->flags, AST_STMT)){
|
||||
|
||||
Reference in New Issue
Block a user