🎨 fix complext generic type generation

This commit is contained in:
ValKmjolnir 2024-11-20 00:41:08 +08:00
parent 55211ee666
commit 0b85f5ca51
6 changed files with 72 additions and 11 deletions

View File

@ -6,8 +6,6 @@
#include "sema/semantic.h" #include "sema/semantic.h"
#include "mir/ast2mir.h" #include "mir/ast2mir.h"
#include "ast/dumper.h"
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
@ -16,13 +14,40 @@
namespace colgm { namespace colgm {
ast::type_def* type_replace_pass::generate_generic_type(const type& t,
const span& loc) {
auto new_def = new type_def(loc);
new_def->set_name(new identifier(loc, t.name));
new_def->get_name()->set_redirect_location(ctx.this_file);
new_def->set_redirect_location(ctx.this_file);
if (t.is_immutable) {
new_def->set_constant();
}
for(i64 i = 0; i < t.pointer_depth; ++i) {
new_def->add_pointer_level();
}
if (!t.generics.empty()) {
new_def->set_generic_types(new generic_type_list(loc));
for(const auto& i : t.generics) {
new_def->get_generic_types()->add_type(
generate_generic_type(i, loc)
);
}
}
return new_def;
}
bool type_replace_pass::visit_type_def(type_def* node) { bool type_replace_pass::visit_type_def(type_def* node) {
const auto name = node->get_name()->get_name(); const auto name = node->get_name()->get_name();
if (g_data.types.count(name)) { if (g_data.types.count(name)) {
// FIXME: if embedded generics like A<T<K>>, this will be wrong
node->get_name()->reset_name(g_data.types.at(name).name); node->get_name()->reset_name(g_data.types.at(name).name);
node->get_name()->set_redirect_location(ctx.this_file);
node->set_redirect_location(ctx.this_file); node->set_redirect_location(ctx.this_file);
for (i64 i = 0; i < g_data.types.at(name).pointer_depth; ++i) {
node->add_pointer_level();
}
if (!g_data.types.at(name).generics.empty() && if (!g_data.types.at(name).generics.empty() &&
node->get_generic_types()) { node->get_generic_types()) {
err.err(node->get_location(), err.err(node->get_location(),
@ -31,6 +56,15 @@ bool type_replace_pass::visit_type_def(type_def* node) {
"but more generic types are specified in this node." "but more generic types are specified in this node."
); );
} }
if (!g_data.types.at(name).generics.empty() &&
!node->get_generic_types()) {
node->set_generic_types(new generic_type_list(node->get_location()));
for(const auto& i : g_data.types.at(name).generics) {
node->get_generic_types()->add_type(
generate_generic_type(i, node->get_location())
);
}
}
} }
if (node->get_generic_types()) { if (node->get_generic_types()) {
node->get_generic_types()->accept(this); node->get_generic_types()->accept(this);
@ -41,10 +75,17 @@ bool type_replace_pass::visit_type_def(type_def* node) {
bool type_replace_pass::visit_call_id(ast::call_id* node) { bool type_replace_pass::visit_call_id(ast::call_id* node) {
const auto name = node->get_id()->get_name(); const auto name = node->get_id()->get_name();
if (g_data.types.count(name)) { if (g_data.types.count(name)) {
// FIXME: if embedded generics like A<T<K>>, this will be wrong
node->get_id()->set_name(g_data.types.at(name).name); node->get_id()->set_name(g_data.types.at(name).name);
node->get_id()->set_redirect_location(ctx.this_file);
node->set_redirect_location(ctx.this_file); node->set_redirect_location(ctx.this_file);
if (g_data.types.at(name).pointer_depth) {
err.err(node->get_location(),
"replace type \"" + g_data.types.at(name).full_path_name() +
"\" is a pointer type, which is not allowed here."
);
}
if (!g_data.types.at(name).generics.empty() && if (!g_data.types.at(name).generics.empty() &&
node->get_generic_types()) { node->get_generic_types()) {
err.err(node->get_location(), err.err(node->get_location(),
@ -53,6 +94,15 @@ bool type_replace_pass::visit_call_id(ast::call_id* node) {
"but more generic types are specified in this node." "but more generic types are specified in this node."
); );
} }
if (!g_data.types.at(name).generics.empty() &&
!node->get_generic_types()) {
node->set_generic_types(new generic_type_list(node->get_location()));
for(const auto& i : g_data.types.at(name).generics) {
node->get_generic_types()->add_type(
generate_generic_type(i, node->get_location())
);
}
}
} }
if (node->get_generic_types()) { if (node->get_generic_types()) {
node->get_generic_types()->accept(this); node->get_generic_types()->accept(this);
@ -62,7 +112,9 @@ bool type_replace_pass::visit_call_id(ast::call_id* node) {
void generic_visitor::scan_generic_type(type_def* type_node) { void generic_visitor::scan_generic_type(type_def* type_node) {
const auto& type_name = type_node->get_name()->get_name(); const auto& type_name = type_node->get_name()->get_name();
const auto& dm = ctx.global.domain.at(type_node->get_file()); const auto& dm = type_node->is_redirected()
? ctx.global.domain.at(type_node->get_redirect_location())
: ctx.global.domain.at(type_node->get_file());
if (!dm.global_symbol.count(type_name)) { if (!dm.global_symbol.count(type_name)) {
rp.report(type_node, "unknown type \"" + type_name + "\"."); rp.report(type_node, "unknown type \"" + type_name + "\".");
@ -180,7 +232,9 @@ bool generic_visitor::visit_call_id(ast::call_id* node) {
} }
const auto& type_name = node->get_id()->get_name(); const auto& type_name = node->get_id()->get_name();
const auto& dm = ctx.global.domain.at(node->get_file()); const auto& dm = node->is_redirected()
? ctx.global.domain.at(node->get_redirect_location())
: ctx.global.domain.at(node->get_file());
if (!dm.global_symbol.count(type_name)) { if (!dm.global_symbol.count(type_name)) {
rp.report(node, "unknown type \"" + type_name + "\"."); rp.report(node, "unknown type \"" + type_name + "\".");
return true; return true;

View File

@ -25,6 +25,9 @@ private:
sema_context& ctx; sema_context& ctx;
generic_data g_data; generic_data g_data;
private:
ast::type_def* generate_generic_type(const type&, const span&);
private: private:
bool visit_type_def(ast::type_def*) override; bool visit_type_def(ast::type_def*) override;
bool visit_call_id(ast::call_id*) override; bool visit_call_id(ast::call_id*) override;

View File

@ -390,7 +390,9 @@ type semantic::resolve_identifier(identifier* node) {
return ctx.get_local(name); return ctx.get_local(name);
} }
const auto& dm = ctx.get_domain(node->get_file()); const auto& dm = node->is_redirected()
? ctx.get_domain(node->get_redirect_location())
: ctx.get_domain(node->get_file());
if (dm.global_symbol.count(name)) { if (dm.global_symbol.count(name)) {
const auto& sym = dm.global_symbol.at(name); const auto& sym = dm.global_symbol.at(name);
if (!sym.is_public) { if (!sym.is_public) {

View File

@ -12,7 +12,7 @@ test: $(COLGMCC) test/*
@ $(COLGMCC) test/bitwise.colgm $(TEST_LIB) && lli out.ll @ $(COLGMCC) test/bitwise.colgm $(TEST_LIB) && lli out.ll
@ $(COLGMCC) test/branch.colgm $(TEST_LIB) && lli out.ll @ $(COLGMCC) test/branch.colgm $(TEST_LIB) && lli out.ll
@ $(COLGMCC) test/cmpnot.colgm $(TEST_LIB) && lli out.ll @ $(COLGMCC) test/cmpnot.colgm $(TEST_LIB) && lli out.ll
-@ $(COLGMCC) test/complex_generics.colgm $(TEST_LIB) && lli out.ll @ $(COLGMCC) test/complex_generics.colgm $(TEST_LIB) && lli out.ll
@ $(COLGMCC) test/continue_break.colgm $(TEST_LIB) && lli out.ll @ $(COLGMCC) test/continue_break.colgm $(TEST_LIB) && lli out.ll
@ $(COLGMCC) test/enum_test.colgm $(TEST_LIB) && lli out.ll @ $(COLGMCC) test/enum_test.colgm $(TEST_LIB) && lli out.ll
@ $(COLGMCC) test/for_test.colgm $(TEST_LIB) && lli out.ll @ $(COLGMCC) test/for_test.colgm $(TEST_LIB) && lli out.ll

View File

@ -35,7 +35,9 @@ pub func version() -> i8* {
} }
pub func print_version() { pub func print_version() {
io::stdout().out("colgm compiler version ").out(version()).out("\n"); io::stdout().out("colgm compiler version ").out(version());
io::stdout().out(" ").out(get_platform()).out(" ").out(get_arch());
io::stdout().out("\n");
} }
pub func help() { pub func help() {

View File

@ -6,7 +6,7 @@ struct B<T> {
b: T b: T
} }
func main() -> u64 { func main() -> i64 {
var aptr = Aptr<i32*> { var aptr = Aptr<i32*> {
a: nil => i32* a: nil => i32*
}; };
@ -15,5 +15,5 @@ func main() -> u64 {
a: nil => B<i32*>* a: nil => B<i32*>*
}; };
return i32::__size__(); return 0;
} }