From e3cea9d3b0c482edb0ad194b392d3fde84e09950 Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Wed, 5 May 2021 22:12:37 +0200 Subject: [PATCH] [FEAT] Implemented 'for'. More tests needed --- parser.cpp | 62 ++++++++++++++++++++++++++++-------------------------- test.vb | 3 +++ 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/parser.cpp b/parser.cpp index b45a2f8..d5d3758 100644 --- a/parser.cpp +++ b/parser.cpp @@ -642,53 +642,53 @@ static const bool parse_if() { if (!else_visited) error_raise("Expected 'ELSE', 'END' or a statement"); else error_raise("Expected 'END' or a statement"); return false; } -/* -static void parse_for() { - char* previous_breaklabel = breaklabel; - char* previous_contlabel = contlabel; - EXPECT(TOKEN_IDENTIFIER, "Expected variable"); - int ivar = get_variable_index(tkn_get_string()); - tkn_next(); - EXPECT(TOKEN_EQ, "Expected '='"); + +static const bool parse_for() { + const std::string previous_breaklabel = breaklabel; + const std::string previous_contlabel = contlabel; + EXPECT2(TOKEN_IDENTIFIER, "Expected variable"); + if (scope_variable_exists(tkn_get_string(), true)) HALT2("Identifier already used"); + const uint32_t var_address = scope_declare_variable(tkn_get_string(), 0, 0); + tkn_next(); EXPECT2(TOKEN_EQ, "Expected '='"); tkn_next(); parse_expression(); - emmit(OP_STORE); - emmit_w(ivar); - char forlabel[8]; - generate_anonymous_labelname(forlabel); - char endlabel[8]; - generate_anonymous_labelname(endlabel); - char continuelabel[8]; - generate_anonymous_labelname(continuelabel); + emmit(OP_STL); + emmit_dw(var_address); + const std::string forlabel = generate_anonymous_labelname(); + const std::string endlabel = generate_anonymous_labelname(); + const std::string continuelabel = generate_anonymous_labelname(); breaklabel = endlabel; contlabel = continuelabel; register_label_address(forlabel); - EXPECT(TOKEN_TO, "Expected 'TO'"); + EXPECT2(TOKEN_TO, "Expected 'TO'"); tkn_next(); parse_expression(); - emmit(OP_LOAD); - emmit_w(ivar); + emmit(OP_LDL); + emmit_dw(var_address); emmit(OP_EQ); emmit(OP_JTR); - emmit_w(get_label_address(endlabel)); + emmit_dw(get_label_address(endlabel)); //int endLabel = GetCurrentAddress(); - parse_statements(); - EXPECT(TOKEN_END, "Expected 'END'"); + scope_open_block(); + const bool ret_called = parse_statements(); + scope_close_block(); + EXPECT2(TOKEN_END, "Expected 'END'"); tkn_next(); register_label_address(continuelabel); - emmit(OP_LOAD); - emmit_w(ivar); + emmit(OP_LDL); + emmit_dw(var_address); emmit(OP_INC); - emmit(OP_STORE); - emmit_w(ivar); + emmit(OP_STL); + emmit_dw(var_address); emmit(OP_JMP); - emmit_w(get_label_address(forlabel)); + emmit_dw(get_label_address(forlabel)); register_label_address(endlabel); //Patch(endLabel, GetCurrentAddress()); breaklabel = previous_breaklabel; contlabel = previous_contlabel; + return ret_called; } - +/* static void parse_break() { if (breaklabel == nullptr) { parser_finished = true; error_raise("Can't break outside of a loop or condition"); return; } emmit(OP_JMP); @@ -780,9 +780,11 @@ static const bool parse_statements() { tkn_next(); if (local_return && !already_warned) { error_warning("Unreachable code"); already_warned = true; } if (parse_if()) { return_called = true; } break; -/* case TOKEN_FOR: - tkn_next(); parse_for(); break; + tkn_next(); + if (local_return && !already_warned) { error_warning("Unreachable code"); already_warned = true; } + if (parse_for()) { return_called = true; } break; +/* case TOKEN_BREAK: tkn_next(); parse_break(); break; case TOKEN_CONTINUE: diff --git a/test.vb b/test.vb index b73a963..8d1560d 100644 --- a/test.vb +++ b/test.vb @@ -17,6 +17,9 @@ function tarari(a as number, b as number) as number var local1 as number if local1 > 0 then var local1 as number = 1 + for i = 0 to 10 + var local1 as number = local1 + 1 + end return local1 else var local3 as number = 2