🐛 fix error codegen in foreach/forindex loop

undefined symbol was recognized as defined in symbol_finder, now it is
fixed :)
This commit is contained in:
ValKmjolnir 2023-10-26 22:40:20 +08:00
parent bbed29eb65
commit ef4af8f195
7 changed files with 43 additions and 8 deletions

View File

@ -386,7 +386,11 @@ bool ast_dumper::visit_for_expr(for_expr* node) {
bool ast_dumper::visit_iter_expr(iter_expr* node) { bool ast_dumper::visit_iter_expr(iter_expr* node) {
dump_indent(); dump_indent();
std::cout << "iterator"; if (node->is_definition()) {
std::cout << "iterator_definition";
} else {
std::cout << "iterator";
}
std::cout << format_location(node->get_location()); std::cout << format_location(node->get_location());
push_indent(); push_indent();
set_last(); set_last();

View File

@ -560,18 +560,22 @@ public:
class iter_expr: public expr { class iter_expr: public expr {
private: private:
bool is_iterator_definition;
identifier* name; identifier* name;
call_expr* call; call_expr* call;
public: public:
iter_expr(const span& location): iter_expr(const span& location):
expr(location, expr_type::ast_iter), expr(location, expr_type::ast_iter),
is_iterator_definition(false),
name(nullptr), call(nullptr) {} name(nullptr), call(nullptr) {}
~iter_expr() override; ~iter_expr() override;
void set_name(identifier* node) {name = node;} void set_name(identifier* node) {name = node;}
void set_call(call_expr* node) {call = node;} void set_call(call_expr* node) {call = node;}
void set_is_definition(bool flag) {is_iterator_definition = flag;}
identifier* get_name() {return name;} identifier* get_name() {return name;}
call_expr* get_call() {return call;} call_expr* get_call() {return call;}
bool is_definition() const {return is_iterator_definition;}
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };

View File

@ -89,7 +89,7 @@ void codegen::find_symbol(code_block* node) {
experimental_namespace[i.location.file] = {}; experimental_namespace[i.location.file] = {};
} }
// if in global scope, load global symbol into this namespace // if in global scope, load global symbol into this namespace
auto scope = experimental_namespace.at(i.location.file); auto& scope = experimental_namespace.at(i.location.file);
if (local.empty() && !scope.count(i.name)) { if (local.empty() && !scope.count(i.name)) {
scope.insert(i.name); scope.insert(i.name);
} }
@ -835,13 +835,18 @@ void codegen::forei_gen(forei_expr* node) {
} else { } else {
emit(op_feach, 0, node->get_location()); emit(op_feach, 0, node->get_location());
} }
if (node->get_iterator()->get_name()) {
auto iterator_node = node->get_iterator();
if (iterator_node->is_definition()) {
// define a new iterator // define a new iterator
auto name_node = node->get_iterator()->get_name(); const auto name_node = iterator_node->get_name();
const auto& str = name_node->get_name(); const auto& str = name_node->get_name();
local.empty()? local.empty()?
emit(op_loadg, global_symbol_find(str), name_node->get_location()): emit(op_loadg, global_symbol_find(str), name_node->get_location()):
emit(op_loadl, local_symbol_find(str), name_node->get_location()); emit(op_loadl, local_symbol_find(str), name_node->get_location());
} else if (!iterator_node->is_definition() && iterator_node->get_name()) {
mcall(node->get_iterator()->get_name());
replace_left_assignment_with_load(node->get_iterator()->get_location());
} else { } else {
// use exist variable as the iterator // use exist variable as the iterator
mcall(node->get_iterator()->get_call()); mcall(node->get_iterator()->get_call());

View File

@ -971,20 +971,26 @@ forei_expr* parse::forei_loop() {
iter_expr* parse::iter_gen() { iter_expr* parse::iter_gen() {
auto node = new iter_expr(toks[ptr].loc); auto node = new iter_expr(toks[ptr].loc);
// definition
if (lookahead(tok::var)) { if (lookahead(tok::var)) {
match(tok::var); match(tok::var);
node->set_name(id()); node->set_name(id());
node->set_is_definition(true);
update_location(node); update_location(node);
return node; return node;
} }
// single symbol call
auto id_node = id(); auto id_node = id();
if (!is_call(toks[ptr].type)) { if (!is_call(toks[ptr].type)) {
node->set_name(id_node); node->set_name(id_node);
update_location(node); update_location(node);
return node; return node;
} }
// call expression
auto tmp = new call_expr(id_node->get_location()); auto tmp = new call_expr(id_node->get_location());
tmp->set_first(id()); tmp->set_first(id_node);
while(is_call(toks[ptr].type)) { while(is_call(toks[ptr].type)) {
tmp->add_call(call_scalar()); tmp->add_call(call_scalar());
} }

View File

@ -111,7 +111,10 @@ void repl::execute() {
info::instance()->in_repl_mode = true; info::instance()->in_repl_mode = true;
std::cout << "[nasal-repl] Initializating enviroment...\n"; std::cout << "[nasal-repl] Initializating enviroment...\n";
// run on pass for initializing basic modules, without output // run on pass for initializing basic modules, without output
run(); if (!run()) {
std::cout << "[nasal-repl] Initialization failed.\n\n";
std::exit(-1);
}
// allow output now // allow output now
runtime.set_allow_repl_output_flag(true); runtime.set_allow_repl_output_flag(true);
std::cout << "[nasal-repl] Initialization complete.\n\n"; std::cout << "[nasal-repl] Initialization complete.\n\n";

View File

@ -29,7 +29,7 @@ bool symbol_finder::visit_function(function* node) {
} }
bool symbol_finder::visit_iter_expr(iter_expr* node) { bool symbol_finder::visit_iter_expr(iter_expr* node) {
if (node->get_name()) { if (node->is_definition() && node->get_name()) {
symbols.push_back({ symbols.push_back({
node->get_name()->get_name(), node->get_name()->get_name(),
node->get_name()->get_location() node->get_name()->get_location()

View File

@ -236,4 +236,17 @@ for(var a=0;a<16;a+=1) {
print([0, 1, 2]~[3, 4, 5], "\n"); print([0, 1, 2]~[3, 4, 5], "\n");
print(num("1.79769313486231570814527423731704357e+308"), "\n"); print(num("1.79769313486231570814527423731704357e+308"), "\n");
print(num("4.94065645841246544176568792868e-324"), "\n"); print(num("4.94065645841246544176568792868e-324"), "\n");
var test_call_iterator = {iter: 0};
foreach(test_call_iterator.iter; [0, 1, 2, 3]) {
println(test_call_iterator);
}
var test_single_id_iterator = 0;
foreach(test_single_id_iterator; [0, 1, 2, 3]) {
println(test_single_id_iterator);
}