Skip to content

Commit bb29615

Browse files
committed
add NEXT statement
1 parent cd6357a commit bb29615

7 files changed

Lines changed: 93 additions & 14 deletions

File tree

ast.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,20 @@ class ExitStatement: public Statement {
10831083
ExitStatement &operator=(const ExitStatement &);
10841084
};
10851085

1086+
class NextStatement: public Statement {
1087+
public:
1088+
NextStatement(int line, unsigned int loop_id): Statement(line), loop_id(loop_id) {}
1089+
1090+
const unsigned int loop_id;
1091+
1092+
virtual void generate_code(Emitter &emitter) const;
1093+
1094+
virtual std::string text() const { return "NextStatement(...)"; }
1095+
private:
1096+
NextStatement(const NextStatement &);
1097+
NextStatement &operator=(const NextStatement &);
1098+
};
1099+
10861100
class Function: public Variable {
10871101
public:
10881102
Function(const std::string &name, const Type *returntype, Scope *scope, const std::vector<FunctionParameter *> &params): Variable(name, makeFunctionType(returntype, params)), scope(scope), params(params), entry_label(UINT_MAX), statements() {}

compiler.cpp

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,15 @@ class Emitter {
1616
std::vector<unsigned int> fixups;
1717
unsigned int target;
1818
};
19+
class LoopLabels {
20+
public:
21+
LoopLabels(): exit(nullptr), next(nullptr) {}
22+
LoopLabels(Label *exit, Label *next): exit(exit), next(next) {}
23+
Label *exit;
24+
Label *next;
25+
};
1926
public:
20-
Emitter(DebugInfo *debug): code(), strings(), globals(), functions(), exit_label(), debug_info(debug) {}
27+
Emitter(DebugInfo *debug): code(), strings(), globals(), functions(), loop_labels(), debug_info(debug) {}
2128
void emit(unsigned char b);
2229
void emit_uint32(uint32_t value);
2330
void emit(unsigned char b, uint32_t value);
@@ -31,16 +38,17 @@ class Emitter {
3138
Label create_label();
3239
void emit_jump(unsigned char b, Label &label);
3340
void jump_target(Label &label);
34-
void add_exit_label(unsigned int loop_id, Label &label);
35-
void remove_exit_label(unsigned int loop_id);
41+
void add_loop_labels(unsigned int loop_id, Label &exit, Label &next);
42+
void remove_loop_labels(unsigned int loop_id);
3643
Label &get_exit_label(unsigned int loop_id);
44+
Label &get_next_label(unsigned int loop_id);
3745
void debug_line(int line);
3846
private:
3947
std::vector<unsigned char> code;
4048
std::vector<std::string> strings;
4149
std::vector<std::string> globals;
4250
std::vector<Label> functions;
43-
std::map<size_t, Label *> exit_label;
51+
std::map<size_t, LoopLabels> loop_labels;
4452
DebugInfo *debug_info;
4553
private:
4654
Emitter(const Emitter &);
@@ -156,22 +164,30 @@ void Emitter::jump_target(Label &label)
156164
}
157165
}
158166

159-
void Emitter::add_exit_label(unsigned int loop_id, Label &label)
167+
void Emitter::add_loop_labels(unsigned int loop_id, Label &exit, Label &next)
160168
{
161-
exit_label[loop_id] = &label;
169+
loop_labels[loop_id] = LoopLabels(&exit, &next);
162170
}
163171

164-
void Emitter::remove_exit_label(unsigned int loop_id)
172+
void Emitter::remove_loop_labels(unsigned int loop_id)
165173
{
166-
exit_label.erase(loop_id);
174+
loop_labels.erase(loop_id);
167175
}
168176

169177
Emitter::Label &Emitter::get_exit_label(unsigned int loop_id)
170178
{
171-
if (exit_label.find(loop_id) == exit_label.end()) {
179+
if (loop_labels.find(loop_id) == loop_labels.end()) {
180+
internal_error("loop_id not found");
181+
}
182+
return *loop_labels[loop_id].exit;
183+
}
184+
185+
Emitter::Label &Emitter::get_next_label(unsigned int loop_id)
186+
{
187+
if (loop_labels.find(loop_id) == loop_labels.end()) {
172188
internal_error("loop_id not found");
173189
}
174-
return *exit_label[loop_id];
190+
return *loop_labels[loop_id].next;
175191
}
176192

177193
void Emitter::debug_line(int line)
@@ -740,14 +756,14 @@ void WhileStatement::generate_code(Emitter &emitter) const
740756
emitter.jump_target(top);
741757
condition->generate(emitter);
742758
auto skip = emitter.create_label();
743-
emitter.add_exit_label(loop_id, skip);
744759
emitter.emit_jump(JF, skip);
760+
emitter.add_loop_labels(loop_id, skip, top);
745761
for (auto stmt: statements) {
746762
stmt->generate(emitter);
747763
}
748764
emitter.emit_jump(JUMP, top);
749765
emitter.jump_target(skip);
750-
emitter.remove_exit_label(loop_id);
766+
emitter.remove_loop_labels(loop_id);
751767
}
752768

753769
void CaseStatement::generate_code(Emitter &emitter) const
@@ -824,8 +840,8 @@ void CaseStatement::RangeWhenCondition::generate(Emitter &emitter) const
824840
void ForStatement::generate_code(Emitter &emitter) const
825841
{
826842
auto skip = emitter.create_label();
827-
emitter.add_exit_label(loop_id, skip);
828843
auto loop = emitter.create_label();
844+
auto next = emitter.create_label();
829845

830846
start->generate(emitter);
831847
var->generate_store(emitter);
@@ -836,25 +852,33 @@ void ForStatement::generate_code(Emitter &emitter) const
836852
emitter.emit(GEN);
837853
emitter.emit_jump(JF, skip);
838854

855+
emitter.add_loop_labels(loop_id, skip, next);
856+
839857
for (auto stmt: statements) {
840858
stmt->generate(emitter);
841859
}
842860

861+
emitter.jump_target(next);
843862
emitter.emit(PUSHN, number_from_uint32(1));
844863
var->generate_load(emitter);
845864
emitter.emit(ADDN);
846865
var->generate_store(emitter);
847866
emitter.emit_jump(JUMP, loop);
848867

849868
emitter.jump_target(skip);
850-
emitter.remove_exit_label(loop_id);
869+
emitter.remove_loop_labels(loop_id);
851870
}
852871

853872
void ExitStatement::generate_code(Emitter &emitter) const
854873
{
855874
emitter.emit_jump(JUMP, emitter.get_exit_label(loop_id));
856875
}
857876

877+
void NextStatement::generate_code(Emitter &emitter) const
878+
{
879+
emitter.emit_jump(JUMP, emitter.get_next_label(loop_id));
880+
}
881+
858882
void Scope::predeclare(Emitter &emitter) const
859883
{
860884
for (auto n: names) {

lexer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ std::string Token::tostring() const
7272
case DOTDOT: s << "DOTDOT"; break;
7373
case EXTERNAL: s << "EXTERNAL"; break;
7474
case EXIT: s << "EXIT"; break;
75+
case NEXT: s << "NEXT"; break;
7576
}
7677
s << ">";
7778
return s.str();
@@ -192,6 +193,7 @@ std::vector<Token> tokenize(const std::string &source)
192193
else if (t.text == "WHEN") t.type = WHEN;
193194
else if (t.text == "EXTERNAL") t.type = EXTERNAL;
194195
else if (t.text == "EXIT") t.type = EXIT;
196+
else if (t.text == "NEXT") t.type = NEXT;
195197
} else if (isdigit(c)) {
196198
t.type = NUMBER;
197199
if (c == '0' && (i+1 < source.length()) && source.at(i+1) != '.' && tolower(source.at(i+1)) != 'e' && not isdigit(source.at(i+1))) {

lexer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ enum TokenType {
6666
DOTDOT,
6767
EXTERNAL,
6868
EXIT,
69+
NEXT,
6970
};
7071

7172
class Token {

parser.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class Parser {
5252
const Statement *parseCaseStatement(Scope *scope, int line);
5353
const Statement *parseForStatement(Scope *scope, int line);
5454
const Statement *parseExitStatement(Scope *scope, int line);
55+
const Statement *parseNextStatement(Scope *scope, int line);
5556
const Statement *parseImport(Scope *scope);
5657
const Statement *parseStatement(Scope *scope);
5758
const Program *parse();
@@ -1386,6 +1387,25 @@ const Statement *Parser::parseExitStatement(Scope *, int line)
13861387
error(2137, tokens[i-1], "no matching loop found in current scope");
13871388
}
13881389

1390+
const Statement *Parser::parseNextStatement(Scope *, int line)
1391+
{
1392+
++i;
1393+
if (tokens[i].type != WHILE
1394+
&& tokens[i].type != FOR) {
1395+
error(2144, tokens[i], "loop type expected");
1396+
}
1397+
TokenType type = tokens[i].type;
1398+
++i;
1399+
if (not loops.empty()) {
1400+
for (auto j = loops.top().rbegin(); j != loops.top().rend(); ++j) {
1401+
if (j->first == type) {
1402+
return new NextStatement(line, j->second);
1403+
}
1404+
}
1405+
}
1406+
error(2145, tokens[i-1], "no matching loop found in current scope");
1407+
}
1408+
13891409
const Statement *Parser::parseImport(Scope *scope)
13901410
{
13911411
++i;
@@ -1424,6 +1444,8 @@ const Statement *Parser::parseStatement(Scope *scope)
14241444
return parseForStatement(scope, line);
14251445
} else if (tokens[i].type == EXIT) {
14261446
return parseExitStatement(scope, line);
1447+
} else if (tokens[i].type == NEXT) {
1448+
return parseNextStatement(scope, line);
14271449
} else if (tokens[i].type == IDENTIFIER) {
14281450
const VariableReference *ref = parseVariableReference(scope);
14291451
if (tokens[i].type == ASSIGN) {

t/errors/S2144.simple

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
VAR a: Number
2+
3+
FOR a IN 1 TO 10 DO
4+
print(str(a))
5+
IF ((a MOD 5) = 0) THEN
6+
NEXT
7+
END IF
8+
NEXT

t/errors/S2145.simple

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
VAR a: Number
2+
3+
FOR a IN 1 TO 10 DO
4+
print(str(a))
5+
IF ((a MOD 5) = 0) THEN
6+
NEXT WHILE
7+
END IF
8+
NEXT

0 commit comments

Comments
 (0)