mirror of https://github.com/colgm/colgm.git
🎨 fix complext generic type generation
This commit is contained in:
parent
55211ee666
commit
0b85f5ca51
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
2
makefile
2
makefile
|
@ -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
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
Loading…
Reference in New Issue