🎨 support primitive ::__size__ function

This commit is contained in:
ValKmjolnir 2024-10-25 00:57:05 +08:00
parent 616ebb216a
commit c082f63afd
11 changed files with 137 additions and 28 deletions

View File

@ -44,6 +44,32 @@ void add_default_func::add_main_impl() {
ctx->impls.push_back(default_main);
}
void add_default_func::add_primitive_size() {
struct prm_pair { const char* name; const char* size; };
const prm_pair pairs[] = {
{"i64", "8"}, {"i32", "4"}, {"i16", "2"}, {"i8", "1"},
{"u64", "8"}, {"u32", "4"}, {"u16", "2"}, {"u8", "1"},
{"f32", "4"}, {"f64", "8"}, {"bool", "1"}
};
for(auto i : pairs) {
const auto name = "@" + std::string(i.name) + ".__size__";
if (used_funcs.count(name)) {
continue;
}
auto size_impl = new mir_func;
size_impl->name = name;
size_impl->return_type = type::u64_type();
size_impl->block = new mir_block(span::null());
auto return_stmt = new mir_return(span::null(), new mir_block(span::null()));
return_stmt->get_value()->add_content(
new mir_number(span::null(), i.size, type::u64_type())
);
size_impl->block->add_content(return_stmt);
ctx->impls.push_back(size_impl);
}
}
bool add_default_func::run(mir_context* c) {
ctx = c;
for(auto i : ctx->decls) {
@ -55,6 +81,8 @@ bool add_default_func::run(mir_context* c) {
add_malloc_decl();
add_free_decl();
add_primitive_size();
add_main_impl();
return true;
}

View File

@ -17,6 +17,7 @@ private:
void add_malloc_decl();
void add_free_decl();
void add_main_impl();
void add_primitive_size();
public:
~add_default_func() override = default;

View File

@ -625,6 +625,12 @@ void mir2sir::visit_mir_call_id(mir_call_id* node) {
// get full path
switch(ctx.search_symbol_kind(node->get_type())) {
case sym_kind::basic_kind:
value_stack.push_back(mir_value_t::primitive(
node->get_type().full_path_name(),
node->get_type()
));
break;
case sym_kind::func_kind:
push_global_func(node->get_type());
break;
@ -780,6 +786,7 @@ void mir2sir::visit_mir_get_path(mir_get_path* node) {
value_stack.pop_back();
switch(prev.value_kind) {
case mir_value_t::kind::primitive:
case mir_value_t::kind::struct_symbol:
value_stack.push_back(mir_value_t::func_kind(
prev.resolve_type.full_path_name() + "." + node->get_name(),

View File

@ -53,6 +53,7 @@ public:
nil,
variable,
literal,
primitive,
func_symbol,
method,
struct_symbol,
@ -98,6 +99,13 @@ public:
.resolve_type = ty
};
}
static auto primitive(const std::string& value, const type& ty) {
return mir_value_t {
.value_kind = mir_value_t::kind::primitive,
.content = value,
.resolve_type = ty
};
}
static auto func_kind(const std::string& full_name, const type& ty) {
return mir_value_t {
.value_kind = mir_value_t::kind::func_symbol,

View File

@ -73,6 +73,9 @@ public:
public:
sym_kind search_symbol_kind(const type& t) const {
if (primitives.count(t.name_for_search())) {
return sym_kind::basic_kind;
}
if (!global.domain.count(t.loc_file)) {
return sym_kind::error_kind;
}

View File

@ -10,8 +10,8 @@ namespace colgm {
struct colgm_primitive {
std::string name;
std::unordered_map<std::string, colgm_func> static_method;
std::unordered_map<std::string, colgm_func> method;
std::unordered_map<std::string, colgm_func> static_methods;
std::unordered_map<std::string, colgm_func> methods;
};
}

View File

@ -428,21 +428,43 @@ colgm_func regist_pass::builtin_struct_alloc(const span& loc, const type& ty) {
return func;
}
void regist_pass::regist_basic_types() {
ctx.global_symbol = {
{"i64", {sym_kind::basic_kind, "", true}},
{"i32", {sym_kind::basic_kind, "", true}},
{"i16", {sym_kind::basic_kind, "", true}},
{"i8", {sym_kind::basic_kind, "", true}},
{"u64", {sym_kind::basic_kind, "", true}},
{"u32", {sym_kind::basic_kind, "", true}},
{"u16", {sym_kind::basic_kind, "", true}},
{"u8", {sym_kind::basic_kind, "", true}},
{"f32", {sym_kind::basic_kind, "", true}},
{"f64", {sym_kind::basic_kind, "", true}},
{"void", {sym_kind::basic_kind, "", true}},
{"bool", {sym_kind::basic_kind, "", true}}
void regist_pass::regist_primitive_types() {
const char* primitives[] = {
"i64", "i32", "i16", "i8",
"u64", "u32", "u16", "u8",
"f32", "f64", "void", "bool"
};
// do clear, so this process should be called first
ctx.global_symbol.clear();
// load symbol info
for(auto i : primitives) {
ctx.global_symbol.insert({i, {sym_kind::basic_kind, "", true}});
}
// load default methods
for(auto i : primitives) {
if (std::string(i) == "void") {
continue;
}
ctx.primitives.insert({i, colgm_primitive()});
auto& cp = ctx.primitives.at(i);
cp.name = i;
cp.static_methods.insert({
"__size__",
generate_primitive_size_method(i)
});
}
}
colgm_func regist_pass::generate_primitive_size_method(const char* name) {
auto func = colgm_func();
func.name = "__size__";
func.location = span::null();
func.return_type = type::u64_type();
func.is_public = true;
return func;
}
void regist_pass::regist_single_import(ast::use_stmt* node) {
@ -1111,7 +1133,7 @@ void regist_pass::generate_method_parameter_list(param_list* node,
}
void regist_pass::run(ast::root* ast_root) {
regist_basic_types();
regist_primitive_types();
regist_imported_types(ast_root);
if (err.geterr()) {
return;

View File

@ -111,10 +111,11 @@ private:
colgm_func builtin_struct_size(const span&);
colgm_func builtin_struct_alloc(const span&, const type&);
private: // basic types
// basic types, now support:
private: // primitive types
// primitive types, now support:
// bool, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, void
void regist_basic_types();
void regist_primitive_types();
colgm_func generate_primitive_size_method(const char*);
private: // import symbols
void regist_single_import(ast::use_stmt*);

View File

@ -621,6 +621,21 @@ type semantic::resolve_call_func_args(const type& prev, call_func_args* node) {
node->set_resolve_type(func.return_type);
return func.return_type;
}
// static method call of primitive type
if (prev.prm_info.flag_is_static) {
if (!ctx.primitives.count(prev.name_for_search())) {
rp.report(node,
"cannot call static method of primitive type \"" +
prev.name_for_search() + "\"."
);
return type::error_type();
}
const auto& p = ctx.primitives.at(prev.name_for_search());
const auto& method = p.static_methods.at(prev.prm_info.method_name);
check_static_call_args(method, node);
node->set_resolve_type(method.return_type);
return method.return_type;
}
// static method call of struct
if (prev.stm_info.flag_is_static) {
const auto& domain = ctx.global.domain.at(prev.loc_file);
@ -736,11 +751,30 @@ type semantic::resolve_call_path(const type& prev, call_path* node) {
// prev resolved type is a primitive type
if (prev.loc_file.empty()) {
rp.report(node,
"cannot get static method \"" + node->get_name() +
"\" from \"" + prev.to_string() + "\"."
);
return type::error_type();
if (!ctx.primitives.count(prev.name_for_search())) {
rp.report(node,
"cannot get static method \"" + node->get_name() +
"\" from \"" + prev.to_string() + "\"."
);
return type::error_type();
}
const auto& p = ctx.primitives.at(prev.name_for_search());
if (!p.static_methods.count(node->get_name())) {
rp.report(node,
"cannot get static method \"" + node->get_name() +
"\" from \"" + prev.to_string() + "\"."
);
return type::error_type();
}
auto infer = prev;
infer.pointer_depth = 0;
infer.is_global = true;
infer.prm_info = {
.flag_is_static = true,
.flag_is_normal = false,
.method_name = node->get_name()
};
return infer;
}
const auto& domain = ctx.global.domain.at(prev.loc_file);

View File

@ -40,7 +40,8 @@ struct type {
bool is_constant_type = false;
bool is_generic_placeholder = false;
struct_method_info stm_info;
struct_method_info stm_info; // struct methods
struct_method_info prm_info; // primitive methods
std::vector<type> generics = {};
private:

View File

@ -85,11 +85,15 @@ func main() -> i64 {
a.get();
b.get();
# var c = Vec<i32>::create();
var c = Vec<i32>::create();
puts("[generic.colgm] Vec<i32>::create success");
var d = Vec<A>::create();
puts("[generic.colgm] Vec<A>::create success");
var e = Vec<B>::create();
puts("[generic.colgm] Vec<B>::create success");
a.a = 2;
# c.__data[0] = b.a;
c.__data[0] = b.a;
d.__data[0] = A {a: 1, b: 2 => i32};
e.__data[0] = B {a: 3 => i32, b: 4};
var f = new<A>(1024);