mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
Remove while loop and readd c-style for loops i.e. all loops are just for
This commit is contained in:
+15
-26
@@ -168,25 +168,25 @@ special_expressions :: proc() {
|
|||||||
|
|
||||||
loops :: proc() {
|
loops :: proc() {
|
||||||
|
|
||||||
// while loops
|
// The C-style for loop
|
||||||
while true {
|
for i := 0; i < 123; i += 1 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while x := 123; x < 124 {
|
for i := 0; i < 123; {
|
||||||
x += 2;
|
break;
|
||||||
|
}
|
||||||
|
for false {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
for i in 0..<123 { // 123 exclusive
|
||||||
This only C-style for loop has now been removed
|
|
||||||
|
|
||||||
for i := 0; i < 123; i += 1 {
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
for i in 0..<123 {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..122 {
|
for i in 0..122 { // 122 inclusive
|
||||||
}
|
}
|
||||||
|
|
||||||
for val, idx in 12..<16 {
|
for val, idx in 12..<16 {
|
||||||
@@ -214,26 +214,15 @@ loops :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
when false {
|
when false {
|
||||||
while i := 0; i < name.count {
|
for i, size := 0; i < name.count; i += size {
|
||||||
r, size := utf8.decode_rune(name[i:]);
|
r: rune;
|
||||||
i += size;
|
r, size = utf8.decode_rune(name[i:]);
|
||||||
fmt.printf("%r\n", r);
|
fmt.printf("%r\n", r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Emulate a C-style loop (not exactly the same though)
|
|
||||||
while x := 0; x < 10 {
|
|
||||||
defer x += 2;
|
|
||||||
|
|
||||||
/* rest of the code */
|
|
||||||
// If `break` is used, the `defer` is still called so it's not the same
|
|
||||||
// as a C-style for loop
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
procedure_overloading();
|
procedure_overloading();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -36,7 +36,7 @@ fetch_or :: proc(a: ^i32, operand: i32) -> i32 {
|
|||||||
spin_lock :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
spin_lock :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
||||||
old_value := compare_exchange(a, 1, 0);
|
old_value := compare_exchange(a, 1, 0);
|
||||||
counter := 0;
|
counter := 0;
|
||||||
while old_value != 0 && (time_out < 0 || counter < time_out) {
|
for old_value != 0 && (time_out < 0 || counter < time_out) {
|
||||||
counter += 1;
|
counter += 1;
|
||||||
yield_thread();
|
yield_thread();
|
||||||
old_value = compare_exchange(a, 1, 0);
|
old_value = compare_exchange(a, 1, 0);
|
||||||
@@ -80,7 +80,7 @@ fetch_or :: proc(a: ^i64, operand: i64) -> i64 {
|
|||||||
spin_lock :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
spin_lock :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
||||||
old_value := compare_exchange(a, 1, 0);
|
old_value := compare_exchange(a, 1, 0);
|
||||||
counter := 0;
|
counter := 0;
|
||||||
while old_value != 0 && (time_out < 0 || counter < time_out) {
|
for old_value != 0 && (time_out < 0 || counter < time_out) {
|
||||||
counter += 1;
|
counter += 1;
|
||||||
yield_thread();
|
yield_thread();
|
||||||
old_value = compare_exchange(a, 1, 0);
|
old_value = compare_exchange(a, 1, 0);
|
||||||
|
|||||||
+6
-7
@@ -460,7 +460,7 @@ fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: stri
|
|||||||
panic("fmt_integer: unknown base, whoops");
|
panic("fmt_integer: unknown base, whoops");
|
||||||
}
|
}
|
||||||
|
|
||||||
while b := cast(u64)base; u >= b {
|
for b := cast(u64)base; u >= b; {
|
||||||
i -= 1;
|
i -= 1;
|
||||||
next := u / b;
|
next := u / b;
|
||||||
buf[i] = digits[u%b];
|
buf[i] = digits[u%b];
|
||||||
@@ -468,7 +468,7 @@ fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: stri
|
|||||||
}
|
}
|
||||||
i -= 1;
|
i -= 1;
|
||||||
buf[i] = digits[u];
|
buf[i] = digits[u];
|
||||||
while i > 0 && prec > buf.count-i {
|
for i > 0 && prec > buf.count-i {
|
||||||
i -= 1;
|
i -= 1;
|
||||||
buf[i] = '0';
|
buf[i] = '0';
|
||||||
}
|
}
|
||||||
@@ -598,7 +598,7 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) {
|
|||||||
case fi.space: fill = ' ';
|
case fi.space: fill = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
while width > 0 {
|
for width > 0 {
|
||||||
width -= 1;
|
width -= 1;
|
||||||
buffer_write_byte(fi.buf, fill);
|
buffer_write_byte(fi.buf, fill);
|
||||||
}
|
}
|
||||||
@@ -885,11 +885,11 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ..any) -> int {
|
|||||||
end := fmt.count;
|
end := fmt.count;
|
||||||
arg_index := 0;
|
arg_index := 0;
|
||||||
was_prev_index := false;
|
was_prev_index := false;
|
||||||
while i := 0; i < end {
|
for i := 0; i < end; {
|
||||||
fi = Fmt_Info{buf = b, good_arg_index = true};
|
fi = Fmt_Info{buf = b, good_arg_index = true};
|
||||||
|
|
||||||
prev_i := i;
|
prev_i := i;
|
||||||
while i < end && fmt[i] != '%' {
|
for i < end && fmt[i] != '%' {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
if i > prev_i {
|
if i > prev_i {
|
||||||
@@ -903,7 +903,7 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ..any) -> int {
|
|||||||
i += 1;
|
i += 1;
|
||||||
|
|
||||||
|
|
||||||
while i < end {
|
for ; i < end; i += 1 {
|
||||||
skip_loop := false;
|
skip_loop := false;
|
||||||
c := fmt[i];
|
c := fmt[i];
|
||||||
match c {
|
match c {
|
||||||
@@ -925,7 +925,6 @@ bprintf :: proc(b: ^Buffer, fmt: string, args: ..any) -> int {
|
|||||||
if skip_loop {
|
if skip_loop {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
arg_index, i, was_prev_index = arg_number(^fi, arg_index, fmt, i, args.count);
|
arg_index, i, was_prev_index = arg_number(^fi, arg_index, fmt, i, args.count);
|
||||||
|
|||||||
+1
-1
@@ -108,7 +108,7 @@ murmur64 :: proc(data_: rawptr, len: int) -> u64 {
|
|||||||
data := slice_ptr(cast(^u32)data_, len/size_of(u32));
|
data := slice_ptr(cast(^u32)data_, len/size_of(u32));
|
||||||
|
|
||||||
i := 0;
|
i := 0;
|
||||||
while len >= 8 {
|
for len >= 8 {
|
||||||
k1, k2: u32;
|
k1, k2: u32;
|
||||||
k1 = data[i]; i += 1;
|
k1 = data[i]; i += 1;
|
||||||
k1 *= m;
|
k1 *= m;
|
||||||
|
|||||||
+2
-3
@@ -75,14 +75,13 @@ allocation_header_fill :: proc(header: ^Allocation_Header, data: rawptr, size: i
|
|||||||
header.size = size;
|
header.size = size;
|
||||||
ptr := cast(^int)(header+1);
|
ptr := cast(^int)(header+1);
|
||||||
|
|
||||||
while i := 0; cast(rawptr)ptr < data {
|
for i := 0; cast(rawptr)ptr < data; i += 1 {
|
||||||
(ptr+i)^ = -1;
|
(ptr+i)^ = -1;
|
||||||
i += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
allocation_header :: proc(data: rawptr) -> ^Allocation_Header {
|
allocation_header :: proc(data: rawptr) -> ^Allocation_Header {
|
||||||
p := cast(^int)data;
|
p := cast(^int)data;
|
||||||
while (p-1)^ == -1 {
|
for (p-1)^ == -1 {
|
||||||
p = (p-1);
|
p = (p-1);
|
||||||
}
|
}
|
||||||
return cast(^Allocation_Header)p-1;
|
return cast(^Allocation_Header)p-1;
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) {
|
|||||||
single_read_length: i32;
|
single_read_length: i32;
|
||||||
total_read: i64;
|
total_read: i64;
|
||||||
|
|
||||||
while total_read < length {
|
for total_read < length {
|
||||||
remaining := length - total_read;
|
remaining := length - total_read;
|
||||||
to_read: u32;
|
to_read: u32;
|
||||||
MAX :: 1<<32-1;
|
MAX :: 1<<32-1;
|
||||||
|
|||||||
+3
-4
@@ -143,8 +143,7 @@ valid_rune :: proc(r: rune) -> bool {
|
|||||||
|
|
||||||
valid_string :: proc(s: string) -> bool {
|
valid_string :: proc(s: string) -> bool {
|
||||||
n := s.count;
|
n := s.count;
|
||||||
i := 0;
|
for i := 0; i < n; {
|
||||||
while i < n {
|
|
||||||
si := s[i];
|
si := s[i];
|
||||||
if si < RUNE_SELF { // ascii
|
if si < RUNE_SELF { // ascii
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -178,8 +177,8 @@ valid_string :: proc(s: string) -> bool {
|
|||||||
rune_count :: proc(s: string) -> int {
|
rune_count :: proc(s: string) -> int {
|
||||||
count := 0;
|
count := 0;
|
||||||
n := s.count;
|
n := s.count;
|
||||||
i := 0;
|
|
||||||
while i < n {
|
for i := 0; i < n; {
|
||||||
defer count += 1;
|
defer count += 1;
|
||||||
si := s[i];
|
si := s[i];
|
||||||
if si < RUNE_SELF { // ascii
|
if si < RUNE_SELF { // ascii
|
||||||
|
|||||||
+21
-15
@@ -127,13 +127,13 @@ bool check_is_terminating(AstNode *node) {
|
|||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(ws, WhileStmt, node);
|
case_ast_node(fs, ForStmt, node);
|
||||||
if (ws->cond != NULL && !check_has_break(ws->body, true)) {
|
if (!check_has_break(fs->body, true)) {
|
||||||
return check_is_terminating(ws->body);
|
return check_is_terminating(fs->body);
|
||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(rs, ForStmt, node);
|
case_ast_node(rs, RangeStmt, node);
|
||||||
if (!check_has_break(rs->body, true)) {
|
if (!check_has_break(rs->body, true)) {
|
||||||
return check_is_terminating(rs->body);
|
return check_is_terminating(rs->body);
|
||||||
}
|
}
|
||||||
@@ -566,27 +566,33 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(ws, WhileStmt, node);
|
case_ast_node(fs, ForStmt, node);
|
||||||
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
|
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
|
||||||
check_open_scope(c, node);
|
check_open_scope(c, node);
|
||||||
|
|
||||||
if (ws->init != NULL) {
|
if (fs->init != NULL) {
|
||||||
check_stmt(c, ws->init, 0);
|
check_stmt(c, fs->init, 0);
|
||||||
}
|
}
|
||||||
if (ws->cond) {
|
if (fs->cond != NULL) {
|
||||||
Operand operand = {Addressing_Invalid};
|
Operand o = {Addressing_Invalid};
|
||||||
check_expr(c, &operand, ws->cond);
|
check_expr(c, &o, fs->cond);
|
||||||
if (operand.mode != Addressing_Invalid &&
|
if (o.mode != Addressing_Invalid && !is_type_boolean(o.type)) {
|
||||||
!is_type_boolean(operand.type)) {
|
error_node(fs->cond, "Non-boolean condition in `for` statement");
|
||||||
error_node(ws->cond, "Non-boolean condition in `while` statement");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
check_stmt(c, ws->body, new_flags);
|
if (fs->post != NULL) {
|
||||||
|
check_stmt(c, fs->post, 0);
|
||||||
|
|
||||||
|
if (fs->post->kind != AstNode_AssignStmt) {
|
||||||
|
error_node(fs->post, "`for` statement post statement must be an assignment");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
check_stmt(c, fs->body, new_flags);
|
||||||
|
|
||||||
check_close_scope(c);
|
check_close_scope(c);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(rs, ForStmt, node);
|
case_ast_node(rs, RangeStmt, node);
|
||||||
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
|
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
|
||||||
check_open_scope(c, node);
|
check_open_scope(c, node);
|
||||||
|
|
||||||
|
|||||||
@@ -4470,44 +4470,54 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
proc->curr_block = done;
|
proc->curr_block = done;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(ws, WhileStmt, node);
|
case_ast_node(fs, ForStmt, node);
|
||||||
ir_emit_comment(proc, str_lit("WhileStmt"));
|
ir_emit_comment(proc, str_lit("ForStmt"));
|
||||||
if (ws->init != NULL) {
|
if (fs->init != NULL) {
|
||||||
irBlock *init = ir_add_block(proc, node, "while.init");
|
irBlock *init = ir_add_block(proc, node, "for.init");
|
||||||
ir_emit_jump(proc, init);
|
ir_emit_jump(proc, init);
|
||||||
proc->curr_block = init;
|
proc->curr_block = init;
|
||||||
ir_build_stmt(proc, ws->init);
|
ir_build_stmt(proc, fs->init);
|
||||||
}
|
}
|
||||||
irBlock *body = ir_add_block(proc, node, "while.body");
|
irBlock *body = ir_add_block(proc, node, "for.body");
|
||||||
irBlock *done = ir_add_block(proc, node, "while.done"); // NOTE(bill): Append later
|
irBlock *done = ir_add_block(proc, node, "for.done"); // NOTE(bill): Append later
|
||||||
|
|
||||||
irBlock *loop = body;
|
irBlock *loop = body;
|
||||||
|
if (fs->cond != NULL) {
|
||||||
if (ws->cond != NULL) {
|
loop = ir_add_block(proc, node, "for.loop");
|
||||||
loop = ir_add_block(proc, node, "while.loop");
|
}
|
||||||
|
irBlock *cont = loop;
|
||||||
|
if (fs->post != NULL) {
|
||||||
|
cont = ir_add_block(proc, node, "for.post");
|
||||||
}
|
}
|
||||||
ir_emit_jump(proc, loop);
|
ir_emit_jump(proc, loop);
|
||||||
proc->curr_block = loop;
|
proc->curr_block = loop;
|
||||||
|
|
||||||
if (loop != body) {
|
if (loop != body) {
|
||||||
ir_build_cond(proc, ws->cond, body, done);
|
ir_build_cond(proc, fs->cond, body, done);
|
||||||
proc->curr_block = body;
|
proc->curr_block = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir_push_target_list(proc, done, loop, NULL);
|
ir_push_target_list(proc, done, cont, NULL);
|
||||||
|
|
||||||
ir_open_scope(proc);
|
ir_open_scope(proc);
|
||||||
ir_build_stmt(proc, ws->body);
|
ir_build_stmt(proc, fs->body);
|
||||||
ir_close_scope(proc, irDeferExit_Default, NULL);
|
ir_close_scope(proc, irDeferExit_Default, NULL);
|
||||||
|
|
||||||
ir_pop_target_list(proc);
|
ir_pop_target_list(proc);
|
||||||
ir_emit_jump(proc, loop);
|
|
||||||
|
ir_emit_jump(proc, cont);
|
||||||
|
|
||||||
|
if (fs->post != NULL) {
|
||||||
|
proc->curr_block = cont;
|
||||||
|
ir_build_stmt(proc, fs->post);
|
||||||
|
ir_emit_jump(proc, loop);
|
||||||
|
}
|
||||||
|
|
||||||
proc->curr_block = done;
|
proc->curr_block = done;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|
||||||
case_ast_node(rs, ForStmt, node);
|
case_ast_node(rs, RangeStmt, node);
|
||||||
ir_emit_comment(proc, str_lit("ForStmt"));
|
ir_emit_comment(proc, str_lit("RangeStmt"));
|
||||||
|
|
||||||
Type *val_type = NULL;
|
Type *val_type = NULL;
|
||||||
Type *idx_type = NULL;
|
Type *idx_type = NULL;
|
||||||
|
|||||||
+123
-62
@@ -221,16 +221,18 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
|
|||||||
Token token; \
|
Token token; \
|
||||||
AstNodeArray results; \
|
AstNodeArray results; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(WhileStmt, "while statement", struct { \
|
AST_NODE_KIND(ForStmt, "for statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *init; \
|
AstNode *init; \
|
||||||
AstNode *cond; \
|
AstNode *cond; \
|
||||||
|
AstNode *post; \
|
||||||
AstNode *body; \
|
AstNode *body; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ForStmt, "range statement", struct { \
|
AST_NODE_KIND(RangeStmt, "range statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *value; \
|
AstNode *value; \
|
||||||
AstNode *index; \
|
AstNode *index; \
|
||||||
|
Token in_token; \
|
||||||
AstNode *expr; \
|
AstNode *expr; \
|
||||||
AstNode *body; \
|
AstNode *body; \
|
||||||
}) \
|
}) \
|
||||||
@@ -501,8 +503,10 @@ Token ast_node_token(AstNode *node) {
|
|||||||
return node->WhenStmt.token;
|
return node->WhenStmt.token;
|
||||||
case AstNode_ReturnStmt:
|
case AstNode_ReturnStmt:
|
||||||
return node->ReturnStmt.token;
|
return node->ReturnStmt.token;
|
||||||
case AstNode_WhileStmt:
|
case AstNode_ForStmt:
|
||||||
return node->WhileStmt.token;
|
return node->ForStmt.token;
|
||||||
|
case AstNode_RangeStmt:
|
||||||
|
return node->RangeStmt.token;
|
||||||
case AstNode_MatchStmt:
|
case AstNode_MatchStmt:
|
||||||
return node->MatchStmt.token;
|
return node->MatchStmt.token;
|
||||||
case AstNode_CaseClause:
|
case AstNode_CaseClause:
|
||||||
@@ -904,24 +908,28 @@ AstNode *make_return_stmt(AstFile *f, Token token, AstNodeArray results) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *make_while_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *body) {
|
|
||||||
AstNode *result = make_node(f, AstNode_WhileStmt);
|
AstNode *make_for_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *post, AstNode *body) {
|
||||||
result->WhileStmt.token = token;
|
|
||||||
result->WhileStmt.init = init;
|
|
||||||
result->WhileStmt.cond = cond;
|
|
||||||
result->WhileStmt.body = body;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
AstNode *make_for_stmt(AstFile *f, Token token, AstNode *value, AstNode *index, AstNode *expr, AstNode *body) {
|
|
||||||
AstNode *result = make_node(f, AstNode_ForStmt);
|
AstNode *result = make_node(f, AstNode_ForStmt);
|
||||||
result->ForStmt.token = token;
|
result->ForStmt.token = token;
|
||||||
result->ForStmt.value = value;
|
result->ForStmt.init = init;
|
||||||
result->ForStmt.index = index;
|
result->ForStmt.cond = cond;
|
||||||
result->ForStmt.expr = expr;
|
result->ForStmt.post = post;
|
||||||
result->ForStmt.body = body;
|
result->ForStmt.body = body;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstNode *make_range_stmt(AstFile *f, Token token, AstNode *value, AstNode *index, Token in_token, AstNode *expr, AstNode *body) {
|
||||||
|
AstNode *result = make_node(f, AstNode_RangeStmt);
|
||||||
|
result->RangeStmt.token = token;
|
||||||
|
result->RangeStmt.value = value;
|
||||||
|
result->RangeStmt.index = index;
|
||||||
|
result->RangeStmt.in_token = in_token;
|
||||||
|
result->RangeStmt.expr = expr;
|
||||||
|
result->RangeStmt.body = body;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
AstNode *make_match_stmt(AstFile *f, Token token, AstNode *init, AstNode *tag, AstNode *body) {
|
AstNode *make_match_stmt(AstFile *f, Token token, AstNode *init, AstNode *tag, AstNode *body) {
|
||||||
AstNode *result = make_node(f, AstNode_MatchStmt);
|
AstNode *result = make_node(f, AstNode_MatchStmt);
|
||||||
result->MatchStmt.token = token;
|
result->MatchStmt.token = token;
|
||||||
@@ -1258,7 +1266,6 @@ void fix_advance_to_next_stmt(AstFile *f) {
|
|||||||
case Token_if:
|
case Token_if:
|
||||||
case Token_when:
|
case Token_when:
|
||||||
case Token_return:
|
case Token_return:
|
||||||
case Token_while:
|
|
||||||
case Token_range:
|
case Token_range:
|
||||||
case Token_match:
|
case Token_match:
|
||||||
case Token_defer:
|
case Token_defer:
|
||||||
@@ -1626,7 +1633,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, AstNode **foreign_library_token, Str
|
|||||||
|
|
||||||
AstNodeArray parse_lhs_expr_list(AstFile *f);
|
AstNodeArray parse_lhs_expr_list(AstFile *f);
|
||||||
AstNodeArray parse_rhs_expr_list(AstFile *f);
|
AstNodeArray parse_rhs_expr_list(AstFile *f);
|
||||||
AstNode * parse_simple_stmt (AstFile *f);
|
AstNode * parse_simple_stmt (AstFile *f, bool in_stmt_ok);
|
||||||
AstNode * parse_type (AstFile *f);
|
AstNode * parse_type (AstFile *f);
|
||||||
|
|
||||||
AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) {
|
AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) {
|
||||||
@@ -1673,7 +1680,7 @@ AstNode *parse_if_expr(AstFile *f) {
|
|||||||
if (allow_token(f, Token_Semicolon)) {
|
if (allow_token(f, Token_Semicolon)) {
|
||||||
cond = parse_expr(f, false);
|
cond = parse_expr(f, false);
|
||||||
} else {
|
} else {
|
||||||
init = parse_simple_stmt(f);
|
init = parse_simple_stmt(f, false);
|
||||||
if (allow_token(f, Token_Semicolon)) {
|
if (allow_token(f, Token_Semicolon)) {
|
||||||
cond = parse_expr(f, false);
|
cond = parse_expr(f, false);
|
||||||
} else {
|
} else {
|
||||||
@@ -2261,7 +2268,8 @@ AstNode *parse_value_decl(AstFile *f, AstNodeArray lhs) {
|
|||||||
return make_value_decl(f, is_mutable, lhs, type, values);
|
return make_value_decl(f, is_mutable, lhs, type, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *parse_simple_stmt(AstFile *f) {
|
|
||||||
|
AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) {
|
||||||
AstNodeArray lhs = parse_lhs_expr_list(f);
|
AstNodeArray lhs = parse_lhs_expr_list(f);
|
||||||
Token token = f->curr_token;
|
Token token = f->curr_token;
|
||||||
switch (token.kind) {
|
switch (token.kind) {
|
||||||
@@ -2293,6 +2301,28 @@ AstNode *parse_simple_stmt(AstFile *f) {
|
|||||||
return make_assign_stmt(f, token, lhs, rhs);
|
return make_assign_stmt(f, token, lhs, rhs);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Token_in:
|
||||||
|
if (in_stmt_ok) {
|
||||||
|
allow_token(f, Token_in);
|
||||||
|
AstNode *expr = parse_expr(f, false);
|
||||||
|
switch (f->curr_token.kind) {
|
||||||
|
case Token_HalfOpenRange:
|
||||||
|
case Token_Ellipsis: {
|
||||||
|
Token op = f->curr_token;
|
||||||
|
next_token(f);
|
||||||
|
AstNode *right = parse_expr(f, false);
|
||||||
|
expr = make_interval_expr(f, op, expr, right);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNodeArray rhs = {0};
|
||||||
|
array_init_count(&rhs, heap_allocator(), 1);
|
||||||
|
rhs.e[0] = expr;
|
||||||
|
|
||||||
|
return make_assign_stmt(f, token, lhs, rhs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case Token_Colon:
|
case Token_Colon:
|
||||||
return parse_value_decl(f, lhs);
|
return parse_value_decl(f, lhs);
|
||||||
}
|
}
|
||||||
@@ -2782,7 +2812,7 @@ AstNode *parse_if_stmt(AstFile *f) {
|
|||||||
if (allow_token(f, Token_Semicolon)) {
|
if (allow_token(f, Token_Semicolon)) {
|
||||||
cond = parse_expr(f, false);
|
cond = parse_expr(f, false);
|
||||||
} else {
|
} else {
|
||||||
init = parse_simple_stmt(f);
|
init = parse_simple_stmt(f, false);
|
||||||
if (allow_token(f, Token_Semicolon)) {
|
if (allow_token(f, Token_Semicolon)) {
|
||||||
cond = parse_expr(f, false);
|
cond = parse_expr(f, false);
|
||||||
} else {
|
} else {
|
||||||
@@ -2900,47 +2930,78 @@ AstNode *parse_give_stmt(AstFile *f) {
|
|||||||
return make_expr_stmt(f, ge);
|
return make_expr_stmt(f, ge);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *parse_while_stmt(AstFile *f) {
|
|
||||||
if (f->curr_proc == NULL) {
|
|
||||||
syntax_error(f->curr_token, "You cannot use a while statement in the file scope");
|
|
||||||
return make_bad_stmt(f, f->curr_token, f->curr_token);
|
|
||||||
}
|
|
||||||
|
|
||||||
Token token = expect_token(f, Token_while);
|
|
||||||
|
|
||||||
AstNode *init = NULL;
|
|
||||||
AstNode *cond = NULL;
|
|
||||||
AstNode *body = NULL;
|
|
||||||
|
|
||||||
isize prev_level = f->expr_level;
|
|
||||||
f->expr_level = -1;
|
|
||||||
|
|
||||||
|
|
||||||
cond = parse_simple_stmt(f);
|
|
||||||
if (is_ast_node_complex_stmt(cond)) {
|
|
||||||
syntax_error(f->curr_token, "You are not allowed that type of statement in a while statement, it is too complex!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allow_token(f, Token_Semicolon)) {
|
|
||||||
init = cond;
|
|
||||||
cond = parse_simple_stmt(f);
|
|
||||||
}
|
|
||||||
f->expr_level = prev_level;
|
|
||||||
|
|
||||||
body = parse_block_stmt(f, false);
|
|
||||||
|
|
||||||
cond = convert_stmt_to_expr(f, cond, str_lit("boolean expression"));
|
|
||||||
|
|
||||||
return make_while_stmt(f, token, init, cond, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
AstNode *parse_for_stmt(AstFile *f) {
|
AstNode *parse_for_stmt(AstFile *f) {
|
||||||
if (f->curr_proc == NULL) {
|
if (f->curr_proc == NULL) {
|
||||||
syntax_error(f->curr_token, "You cannot use a for statement in the file scope");
|
syntax_error(f->curr_token, "You cannot use a for statement in the file scope");
|
||||||
return make_bad_stmt(f, f->curr_token, f->curr_token);
|
return make_bad_stmt(f, f->curr_token, f->curr_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token token = expect_token(f, Token_for);
|
||||||
|
|
||||||
|
AstNode *init = NULL;
|
||||||
|
AstNode *cond = NULL;
|
||||||
|
AstNode *post = NULL;
|
||||||
|
AstNode *body = NULL;
|
||||||
|
bool is_range = false;
|
||||||
|
|
||||||
|
if (f->curr_token.kind != Token_OpenBrace) {
|
||||||
|
isize prev_level = f->expr_level;
|
||||||
|
f->expr_level = -1;
|
||||||
|
if (f->curr_token.kind != Token_Semicolon) {
|
||||||
|
cond = parse_simple_stmt(f, true);
|
||||||
|
if (cond->kind == AstNode_AssignStmt &&
|
||||||
|
cond->AssignStmt.op.kind == Token_in) {
|
||||||
|
is_range = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_range && f->curr_token.kind == Token_Semicolon) {
|
||||||
|
next_token(f);
|
||||||
|
init = cond;
|
||||||
|
cond = NULL;
|
||||||
|
if (f->curr_token.kind != Token_Semicolon) {
|
||||||
|
cond = parse_simple_stmt(f, false);
|
||||||
|
}
|
||||||
|
expect_semicolon(f, cond);
|
||||||
|
if (f->curr_token.kind != Token_OpenBrace) {
|
||||||
|
post = parse_simple_stmt(f, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f->expr_level = prev_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
body = parse_block_stmt(f, false);
|
||||||
|
|
||||||
|
if (is_range) {
|
||||||
|
GB_ASSERT(cond->kind == AstNode_AssignStmt);
|
||||||
|
Token in_token = cond->AssignStmt.op;
|
||||||
|
AstNode *value = NULL;
|
||||||
|
AstNode *index = NULL;
|
||||||
|
switch (cond->AssignStmt.lhs.count) {
|
||||||
|
case 1:
|
||||||
|
value = cond->AssignStmt.lhs.e[0];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value = cond->AssignStmt.lhs.e[0];
|
||||||
|
index = cond->AssignStmt.lhs.e[1];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error_node(cond, "Expected at 1 or 2 identifiers");
|
||||||
|
return make_bad_stmt(f, token, f->curr_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode *rhs = NULL;
|
||||||
|
if (cond->AssignStmt.rhs.count > 0) {
|
||||||
|
rhs = cond->AssignStmt.rhs.e[0];
|
||||||
|
}
|
||||||
|
return make_range_stmt(f, token, value, index, in_token, rhs, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
cond = convert_stmt_to_expr(f, cond, str_lit("boolean expression"));
|
||||||
|
return make_for_stmt(f, token, init, cond, post, body);
|
||||||
|
|
||||||
|
#if 0
|
||||||
Token token = expect_token(f, Token_for);
|
Token token = expect_token(f, Token_for);
|
||||||
AstNodeArray names = parse_ident_list(f);
|
AstNodeArray names = parse_ident_list(f);
|
||||||
parse_check_name_list_for_reserves(f, names);
|
parse_check_name_list_for_reserves(f, names);
|
||||||
@@ -2977,7 +3038,8 @@ AstNode *parse_for_stmt(AstFile *f) {
|
|||||||
return make_bad_stmt(f, token, f->curr_token);
|
return make_bad_stmt(f, token, f->curr_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
return make_for_stmt(f, token, value, index, expr, body);
|
return make_range_stmt(f, token, value, index, expr, body);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *parse_case_clause(AstFile *f) {
|
AstNode *parse_case_clause(AstFile *f) {
|
||||||
@@ -3030,7 +3092,7 @@ AstNode *parse_match_stmt(AstFile *f) {
|
|||||||
|
|
||||||
AstNode *var = parse_identifier(f);
|
AstNode *var = parse_identifier(f);
|
||||||
expect_token_after(f, Token_in, "match type name");
|
expect_token_after(f, Token_in, "match type name");
|
||||||
tag = parse_simple_stmt(f);
|
tag = parse_simple_stmt(f, false);
|
||||||
|
|
||||||
f->expr_level = prev_level;
|
f->expr_level = prev_level;
|
||||||
|
|
||||||
@@ -3052,13 +3114,13 @@ AstNode *parse_match_stmt(AstFile *f) {
|
|||||||
isize prev_level = f->expr_level;
|
isize prev_level = f->expr_level;
|
||||||
f->expr_level = -1;
|
f->expr_level = -1;
|
||||||
if (f->curr_token.kind != Token_Semicolon) {
|
if (f->curr_token.kind != Token_Semicolon) {
|
||||||
tag = parse_simple_stmt(f);
|
tag = parse_simple_stmt(f, false);
|
||||||
}
|
}
|
||||||
if (allow_token(f, Token_Semicolon)) {
|
if (allow_token(f, Token_Semicolon)) {
|
||||||
init = tag;
|
init = tag;
|
||||||
tag = NULL;
|
tag = NULL;
|
||||||
if (f->curr_token.kind != Token_OpenBrace) {
|
if (f->curr_token.kind != Token_OpenBrace) {
|
||||||
tag = parse_simple_stmt(f);
|
tag = parse_simple_stmt(f, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3151,13 +3213,12 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
case Token_Sub:
|
case Token_Sub:
|
||||||
case Token_Xor:
|
case Token_Xor:
|
||||||
case Token_Not:
|
case Token_Not:
|
||||||
s = parse_simple_stmt(f);
|
s = parse_simple_stmt(f, false);
|
||||||
expect_semicolon(f, s);
|
expect_semicolon(f, s);
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
case Token_if: return parse_if_stmt(f);
|
case Token_if: return parse_if_stmt(f);
|
||||||
case Token_when: return parse_when_stmt(f);
|
case Token_when: return parse_when_stmt(f);
|
||||||
case Token_while: return parse_while_stmt(f);
|
|
||||||
case Token_for: return parse_for_stmt(f);
|
case Token_for: return parse_for_stmt(f);
|
||||||
case Token_match: return parse_match_stmt(f);
|
case Token_match: return parse_match_stmt(f);
|
||||||
case Token_defer: return parse_defer_stmt(f);
|
case Token_defer: return parse_defer_stmt(f);
|
||||||
|
|||||||
@@ -92,7 +92,6 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
|||||||
TOKEN_KIND(Token_then, "then"), \
|
TOKEN_KIND(Token_then, "then"), \
|
||||||
TOKEN_KIND(Token_if, "if"), \
|
TOKEN_KIND(Token_if, "if"), \
|
||||||
TOKEN_KIND(Token_else, "else"), \
|
TOKEN_KIND(Token_else, "else"), \
|
||||||
TOKEN_KIND(Token_while, "while"), \
|
|
||||||
TOKEN_KIND(Token_for, "for"), \
|
TOKEN_KIND(Token_for, "for"), \
|
||||||
TOKEN_KIND(Token_in, "in"), \
|
TOKEN_KIND(Token_in, "in"), \
|
||||||
TOKEN_KIND(Token_when, "when"), \
|
TOKEN_KIND(Token_when, "when"), \
|
||||||
|
|||||||
Reference in New Issue
Block a user