🐛 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) {
dump_indent();
if (node->is_definition()) {
std::cout << "iterator_definition";
} else {
std::cout << "iterator";
}
std::cout << format_location(node->get_location());
push_indent();
set_last();

View File

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

View File

@ -89,7 +89,7 @@ void codegen::find_symbol(code_block* node) {
experimental_namespace[i.location.file] = {};
}
// 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)) {
scope.insert(i.name);
}
@ -835,13 +835,18 @@ void codegen::forei_gen(forei_expr* node) {
} else {
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
auto name_node = node->get_iterator()->get_name();
const auto name_node = iterator_node->get_name();
const auto& str = name_node->get_name();
local.empty()?
emit(op_loadg, global_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 {
// use exist variable as the iterator
mcall(node->get_iterator()->get_call());

View File

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

View File

@ -111,7 +111,10 @@ void repl::execute() {
info::instance()->in_repl_mode = true;
std::cout << "[nasal-repl] Initializating enviroment...\n";
// 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
runtime.set_allow_repl_output_flag(true);
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) {
if (node->get_name()) {
if (node->is_definition() && node->get_name()) {
symbols.push_back({
node->get_name()->get_name(),
node->get_name()->get_location()

View File

@ -237,3 +237,16 @@ print([0, 1, 2]~[3, 4, 5], "\n");
print(num("1.79769313486231570814527423731704357e+308"), "\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);
}