mirror of https://github.com/colgm/colgm.git
🎨 support primitive ::__size__ function
This commit is contained in:
parent
616ebb216a
commit
c082f63afd
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue