[ ] Hex literals
+ [ ] All code paths return correct value
+
[ ] #file_contents
[ ] #initialize structs
// Structure Nodes
struct AstBlock { AstNode_base; AstNode *body; Scope *scope; };
-struct AstWhile { AstNode_base; AstTyped *cond; AstNode *stmt; };
+struct AstWhile { AstNode_base; AstTyped *cond; AstBlock *stmt; };
struct AstDefer { AstNode_base; AstNode *stmt; };
struct AstFor {
AstNode_base;
AstTyped *start, *end, *step;
- AstNode *stmt;
+ AstBlock *stmt;
};
struct AstIf {
AstNode_base;
AstTyped *cond;
- AstNode* true_stmt;
- AstNode* false_stmt;
+ AstBlock *true_stmt;
+ AstBlock *false_stmt;
};
// Type Nodes
Token_Type_Keyword_Sizeof,
Token_Type_Keyword_Alignof,
Token_Type_Keyword_Defer,
+ Token_Type_Keyword_Do,
Token_Type_Right_Arrow,
Token_Type_Left_Arrow,
}
heap_alloc :: proc (size_: u32, align: u32) -> rawptr {
- if size_ == 0 return null;
+ if size_ == 0 do return null;
size := size_ + sizeof heap_block;
if size % align != 0 {
return cast(rawptr) (cast(u32) ret + sizeof heap_block);
}
- new_pages :: (size - heap_state.remaining_space) >> 16;
+ new_pages :: ((size - heap_state.remaining_space) >> 16) + 1;
if memory_grow(new_pages) == -1 {
// out of memory
return null;
}
heap_alloc_proc :: proc (data: rawptr, aa: AllocAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
- if aa == AllocAction.Alloc return heap_alloc(size, align);
+ if aa == AllocAction.Alloc do return heap_alloc(size, align);
if aa == AllocAction.Free {
heap_free(oldptr);
return null;
deferred_example :: proc -> i32 {
arr := cast([] i32) malloc(sizeof [8] i32);
- defer if cast(rawptr) arr != null mfree(arr);
+ defer if cast(rawptr) arr != null do mfree(arr);
- for i: 0, 8 arr[i] = i * i;
- for i: 0, 8 print(arr[i]);
+ for i: 0, 8 do arr[i] = i * i;
+ for i: 0, 8 do print(arr[i]);
return arr[1] + arr[7];
}
print(deferred_example());
first := cast([] i32) malloc(sizeof [4] i32);
- for i: 0, 4 first[i] = i * 2;
+ for i: 0, 4 do first[i] = i * 2;
second := cast([] f32) malloc(sizeof [24] f32);
- for i: 0, 24 second[i] = cast(f32) i;
+ for i: 0, 24 do second[i] = cast(f32) i;
print(cast(u32) first);
print(cast(u32) second);
- for i: 0, 4 print(first[i]);
- for i: 0, 24 print(second[i]);
+ for i: 0, 4 do print(first[i]);
+ for i: 0, 24 do print(second[i]);
mfree(first);
}
print_i32arr :: proc (arr: [] i32, len: i32) {
- for i: 0, len print(arr[i]);
+ for i: 0, len do print(arr[i]);
}
print_i64arr :: proc (arr: [] i64, len: i32) {
- for i: 0, len print(arr[i]);
+ for i: 0, len do print(arr[i]);
}
print_f32arr :: proc (arr: [] f32, len: i32) {
- for i: 0, len print(arr[i]);
+ for i: 0, len do print(arr[i]);
}
print_f64arr :: proc (arr: [] f64, len: i32) {
- for i: 0, len print(arr[i]);
+ for i: 0, len do print(arr[i]);
}
// NOTE: print null-terminated string
}
print_str_len :: proc (str: [] u8, len: i32) {
- for i: 0, len print(cast(i32) str[i]);
+ for i: 0, len do print(cast(i32) str[i]);
}
print :: proc #overloaded {
return 1;
}
- if (ifnode->true_stmt) if (check_statement(ifnode->true_stmt)) return 1;
- if (ifnode->false_stmt) if (check_statement(ifnode->false_stmt)) return 1;
+ if (ifnode->true_stmt) if (check_statement((AstNode *) ifnode->true_stmt)) return 1;
+ if (ifnode->false_stmt) if (check_statement((AstNode *) ifnode->false_stmt)) return 1;
return 0;
}
return 1;
}
- return check_statement(whilenode->stmt);
+ return check_block(whilenode->stmt);
}
CHECK(for, AstFor* fornode) {
}
- if (check_statement(fornode->stmt)) return 1;
+ if (check_block(fornode->stmt)) return 1;
return 0;
}
"sizeof",
"alignof",
"defer",
+ "do",
"->",
"<-",
LITERAL_TOKEN("sizeof", 1, Token_Type_Keyword_Sizeof);
LITERAL_TOKEN("alignof", 1, Token_Type_Keyword_Alignof);
LITERAL_TOKEN("defer", 1, Token_Type_Keyword_Defer);
+ LITERAL_TOKEN("do", 1, Token_Type_Keyword_Do);
LITERAL_TOKEN("true", 1, Token_Type_Literal_True);
LITERAL_TOKEN("false", 1, Token_Type_Literal_False);
LITERAL_TOKEN("->", 0, Token_Type_Right_Arrow);
expect_token(parser, Token_Type_Keyword_If);
AstTyped* cond = parse_expression(parser);
- AstNode* true_stmt = parse_statement(parser);
+ AstBlock* true_stmt = parse_block(parser);
AstIf* if_node = make_node(AstIf, Ast_Kind_If);
AstIf* root_if = if_node;
AstIf* elseif_node = make_node(AstIf, Ast_Kind_If);
cond = parse_expression(parser);
- true_stmt = parse_statement(parser);
+ true_stmt = parse_block(parser);
elseif_node->cond = cond;
if (true_stmt != NULL)
elseif_node->true_stmt = true_stmt;
- if_node->false_stmt = (AstNode *) elseif_node;
+ if_node->false_stmt = (AstBlock *) elseif_node;
if_node = elseif_node;
}
if (parser->curr->type == Token_Type_Keyword_Else) {
consume_token(parser);
- AstNode* false_stmt = parse_statement(parser);
+ AstBlock* false_stmt = parse_block(parser);
if (false_stmt != NULL)
if_node->false_stmt = false_stmt;
}
OnyxToken* while_token = expect_token(parser, Token_Type_Keyword_While);
AstTyped* cond = parse_expression(parser);
- AstNode* stmt = parse_statement(parser);
+ AstBlock* stmt = parse_block(parser);
AstWhile* while_node = make_node(AstWhile, Ast_Kind_While);
while_node->token = while_token;
for_node->step = parse_expression(parser);
}
- for_node->stmt = parse_statement(parser);
+ for_node->stmt = parse_block(parser);
return for_node;
}
case '{':
case Token_Type_Empty_Block:
+ case Token_Type_Keyword_Do:
needs_semicolon = 0;
retval = (AstNode *) parse_block(parser);
break;
return block;
}
+ if (parser->curr->type == Token_Type_Keyword_Do) {
+ consume_token(parser);
+ block->body = parse_statement(parser);
+ return block;
+ }
+
+ if (parser->curr->type != '{') {
+ expect_token(parser, '{');
+ find_token(parser, '}');
+ return block;
+ }
expect_token(parser, '{');
AstNode** next = &block->body;
//
// The declaration will cause a problem but semantically the above
// doesn't make sense.
- if (ifnode->true_stmt != NULL) symres_statement(ifnode->true_stmt);
- if (ifnode->false_stmt != NULL) symres_statement(ifnode->false_stmt);
+ if (ifnode->true_stmt != NULL) symres_statement((AstNode *) ifnode->true_stmt);
+ if (ifnode->false_stmt != NULL) symres_statement((AstNode *) ifnode->false_stmt);
}
static void symres_while(AstWhile* whilenode) {
symres_expression(&whilenode->cond);
- symres_statement(whilenode->stmt);
+ symres_block(whilenode->stmt);
}
static void symres_for(AstFor* fornode) {
symres_expression(&fornode->end);
if (fornode->step) symres_expression(&fornode->step);
- symres_statement(fornode->stmt);
+ symres_block(fornode->stmt);
scope_leave();
}
bh_arr_push(mod->structured_jump_target, 0);
if (if_node->true_stmt) {
- if (if_node->true_stmt->kind == Ast_Kind_Block) {
- forll (AstNode, stmt, ((AstBlock *) if_node->true_stmt)->body, next) {
- compile_statement(mod, &code, stmt);
- }
- } else {
- compile_statement(mod, &code, if_node->true_stmt);
+ forll (AstNode, stmt, if_node->true_stmt->body, next) {
+ compile_statement(mod, &code, stmt);
}
}
if (if_node->false_stmt) {
WI(WI_ELSE);
- if (if_node->false_stmt->kind == Ast_Kind_Block) {
+ if (if_node->false_stmt->kind == Ast_Kind_If) {
+ compile_if(mod, &code, (AstIf *) if_node->false_stmt);
+ } else {
forll (AstNode, stmt, ((AstBlock *) if_node->false_stmt)->body, next) {
compile_statement(mod, &code, stmt);
}
- } else {
- compile_statement(mod, &code, if_node->false_stmt);
}
}
bh_arr_push(mod->structured_jump_target, 1);
bh_arr_push(mod->structured_jump_target, 2);
- if (while_node->stmt->kind == Ast_Kind_Block) {
- forll (AstNode, stmt, ((AstBlock *) while_node->stmt)->body, next) {
- compile_statement(mod, &code, stmt);
- }
- } else {
- compile_statement(mod, &code, while_node->stmt);
+ forll (AstNode, stmt, while_node->stmt->body, next) {
+ compile_statement(mod, &code, stmt);
}
compile_deferred_stmts(mod, &code, (AstNode *) while_node);
WI(WI_I32_GE_S);
WID(WI_COND_JUMP, 0x01);
- if (for_node->stmt->kind == Ast_Kind_Block) {
- forll (AstNode, stmt, ((AstBlock *) for_node->stmt)->body, next) {
- compile_statement(mod, &code, stmt);
- }
- } else {
- compile_statement(mod, &code, for_node->stmt);
+ forll (AstNode, stmt, for_node->stmt->body, next) {
+ compile_statement(mod, &code, stmt);
}
if (for_node->step == NULL)