Skip to content

Commit

Permalink
feat: directives to use minimal mode
Browse files Browse the repository at this point in the history
  • Loading branch information
JaDogg committed Mar 17, 2024
1 parent bbd6994 commit b60154c
Show file tree
Hide file tree
Showing 13 changed files with 117 additions and 21 deletions.
25 changes: 18 additions & 7 deletions compiler/src/builtins/builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ struct builtin_arrsetlencap : builtin {
return {code.str(), o};
}
bool require_stdlib() override { return true; }

private:
std::string func_name_;
};
Expand Down Expand Up @@ -274,6 +275,7 @@ struct builtin_print : builtin {
return {code.str(), o};
}
bool require_stdlib() override { return true; }

private:
std::string func_name_;
};
Expand Down Expand Up @@ -1249,8 +1251,10 @@ struct builtin_iif : builtin {
*args[2].datatype_->const_unwrap()) {
o.string_val_ = "Second and third argument to iif() must be of same type";
} else if (args[1].is_a_function()) {
ykdatatype *arg1_dt = dt_slot_matcher->function_to_datatype(args[1]);
ykdatatype *arg2_dt = dt_slot_matcher->function_to_datatype(args[2]);
ykdatatype *arg1_dt =
dt_slot_matcher->function_to_datatype_or_null(args[1]);
ykdatatype *arg2_dt =
dt_slot_matcher->function_to_datatype_or_null(args[2]);
if (arg1_dt != nullptr && arg2_dt != nullptr &&
*(arg1_dt->const_unwrap()) == *(arg2_dt->const_unwrap())) {
o = ykobject(arg1_dt);
Expand Down Expand Up @@ -1351,7 +1355,7 @@ struct builtin_functional : builtin {
ykdatatype *dt;
ykdatatype *return_val_type;
if (args[1].second.is_a_function()) {
dt = fnc_dt_extractor->function_to_datatype(args[1].second);
dt = fnc_dt_extractor->function_to_datatype_or_null(args[1].second);
} else {
dt = args[1].second.datatype_;
}
Expand Down Expand Up @@ -1463,6 +1467,7 @@ struct builtin_functional : builtin {
return {code.str(), ykobject(return_val_type)};
}
bool require_stdlib() override { return true; }

private:
void write_statement(std::stringstream &read_stream,
statement_writer *st_writer) {
Expand All @@ -1483,7 +1488,13 @@ struct builtin_functional : builtin {
if (function.datatype_->is_function()) {
dt = function.datatype_;
} else {
dt = dt_slot_matcher->function_to_datatype(function);
dt = dt_slot_matcher->function_to_datatype_or_null(function);
}
if (dt == nullptr) {
ykobject o = ykobject(dt_pool);
o.string_val_ = "Function argument for builtin " + name_ + " if invalid";
o.object_type_ = object_type::ERROR_DETECTED;
return o;
}
ykobject o = ykobject(dt_pool);
ykdatatype *template_dt = array.datatype_->args_[0];
Expand Down Expand Up @@ -1761,15 +1772,15 @@ ykobject builtins::verify(
const std::unordered_map<std::string, import_stmt *> &import_aliases,
const std::string &filepath, slot_matcher *dt_slot_matcher,
bool no_stdlib) {
auto& builtin_object = builtins_[name];
auto &builtin_object = builtins_[name];
if (builtin_object->require_stdlib() && no_stdlib) {
auto o = ykobject(dt_pool_);
o.string_val_ = "Builtin '" + name + "' does not work without stdlib.";
o.string_val_ = "Builtin '" + name + "' does not work without stdlib.";
o.object_type_ = object_type::ERROR_DETECTED;
return o;
}
return builtin_object->verify(args, arg_expressions, this, dt_pool_,
import_aliases, filepath, dt_slot_matcher);
import_aliases, filepath, dt_slot_matcher);
}
std::pair<std::string, ykobject> builtins::compile(
const std::string &name,
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/compiler/def_class_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ bool def_class_visitor::has_zero_arg_directive(directive_stmt *obj) {
cf_->directives_.no_main_ = true;
}
// (Global flag) Directly substitute '@nativedefine' or 'native constants'
if (directive_type == "apply_nativedefine") { // 🔴
if (directive_type == "apply_nativedefine") {// 🔴
zero_arg_directive = true;
cf_->directives_.apply_native_define_ = true;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/compiler/function_datatype_extractor.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace yaksha {
* @param arg argument
* @return nullptr if failed, else a valid datatype
*/
virtual ykdatatype *function_to_datatype(const ykobject &arg) = 0;
virtual ykdatatype *function_to_datatype_or_null(const ykobject &arg) = 0;
};
}// namespace yaksha
#endif
6 changes: 5 additions & 1 deletion compiler/src/compiler/multifile_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,11 @@ comp_result multifile_compiler::compile_all(codegen *code_generator) {
// Statement usage analysis
// So we know which 'functions / classes / consts' are actually used
usage_analyser ua{main_file_info};
ua.analyse();
if (cf_->directives_.no_main_) {
ua.analyse_no_main();
} else {
ua.analyse();
}
if (!ua.errors_.empty()) {
error_printer_.print_errors(ua.errors_);
LOG_COMP("usage analyser found errors");
Expand Down
25 changes: 21 additions & 4 deletions compiler/src/compiler/to_c_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,10 @@ void to_c_compiler::visit_fncall_expr(fncall_expr *obj) {
LOG_COMP("module function: " << name << " file=" << module_file << " fn="
<< module_fn << " prefix=" << module_prefix);
auto fndef = module_info->data_->dsv_->get_function(module_fn);
if (cf_->directives_.apply_native_define_ &&
fndef->annotations_.native_define_) {
prefixed_fn_name = fndef->annotations_.native_define_arg_;
}
auto fn_return = fndef->return_type_;
std::vector<ykdatatype *> params{};
params.reserve(fndef->params_.size());
Expand All @@ -426,12 +430,17 @@ void to_c_compiler::visit_fncall_expr(fncall_expr *obj) {
} else if (defs_classes_.has_function(name)) {
LOG_COMP("local_function: " << name);
auto fn_def = defs_classes_.get_function(name);
std::string prefixed_name = prefix(name, prefix_val_);
if (cf_->directives_.apply_native_define_ &&
fn_def->annotations_.native_define_) {
prefixed_name = fn_def->annotations_.native_define_arg_;
}
auto return_type = fn_def->return_type_;
std::vector<ykdatatype *> params{};
params.reserve(fn_def->params_.size());
for (auto &p : fn_def->params_) { params.emplace_back(p.data_type_); }
compile_function_call(obj, prefix(name, prefix_val_), code, return_type,
params, fn_def->annotations_.varargs_);
compile_function_call(obj, prefixed_name, code, return_type, params,
fn_def->annotations_.varargs_);
} else if (defs_classes_.has_class(name)) {
LOG_COMP("local_class:" << name);
auto class_ = defs_classes_.get_class(name);
Expand Down Expand Up @@ -475,6 +484,7 @@ void to_c_compiler::compile_function_call(
bool first = true;
size_t arg_size = obj->args_.size();
size_t param_size = parameters.size();
// ---
for (size_t i = 0; i < arg_size; i++) {
auto arg = obj->args_[i];
ykdatatype *param;
Expand Down Expand Up @@ -823,6 +833,9 @@ void to_c_compiler::visit_def_stmt(def_stmt *obj) {
LOG_COMP("compiling def_stmt: " << obj->name_->token_);
auto name = prefix(obj->name_->token_, prefix_val_);
if (obj->annotations_.native_define_) {
if (cf_->directives_.apply_native_define_) {
return;// no need to write native_defines
}
struct_forward_declarations_ << "#define " << name << " "
<< obj->annotations_.native_define_arg_
<< "\n";
Expand Down Expand Up @@ -1009,7 +1022,11 @@ void to_c_compiler::visit_let_stmt(let_stmt *obj) {
visited_expr = true;
resulting_pair = compile_expression(obj->expression_);
if (resulting_pair.second.is_a_function()) {
obj->data_type_ = function_to_datatype(resulting_pair.second);
obj->data_type_ = function_to_datatype_or_null(resulting_pair.second);
if (obj->data_type_ == nullptr) {
error(obj->name_, "Failed to derive data type of function pointer");
return;
}
} else {
obj->data_type_ = resulting_pair.second.datatype_
->const_unwrap(); /* set our data type here */
Expand Down Expand Up @@ -1704,7 +1721,7 @@ void to_c_compiler::write_statement_no_end(std::string code_line) {
body_ << code_line << "\n";
}
void to_c_compiler::visit_runtimefeature_stmt(runtimefeature_stmt *obj) {}
ykdatatype *to_c_compiler::function_to_datatype(const ykobject &arg) {
ykdatatype *to_c_compiler::function_to_datatype_or_null(const ykobject &arg) {
def_stmt *funct;
if (arg.object_type_ == object_type::FUNCTION) {
funct = defs_classes_.get_function(arg.string_val_);
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/compiler/to_c_compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ namespace yaksha {
entry_struct_func_compiler *esc, gc_pool<token> *token_pool);
~to_c_compiler() override;
compiler_output compile(codefiles *cf, file_info *fi);
ykdatatype *function_to_datatype(const ykobject &arg) override;
ykdatatype *function_to_datatype_or_null(const ykobject &arg) override;
void visit_assign_expr(assign_expr *obj) override;
void visit_binary_expr(binary_expr *obj) override;
void visit_fncall_expr(fncall_expr *obj) override;
Expand Down
16 changes: 12 additions & 4 deletions compiler/src/compiler/type_checker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,14 @@ void type_checker::visit_assign_expr(assign_expr *obj) {
if (scope_.is_defined(name)) {
object = scope_.get(name);
} else {
if (rhs.is_a_function()) { rhs.datatype_ = function_to_datatype(rhs); }
if (rhs.is_a_function()) {
rhs.datatype_ = function_to_datatype_or_null(rhs);
if (rhs.datatype_ == nullptr) {
error(obj->right_->locate(),
"Failed to derive data type of function pointer");
return;
}
}
if (rhs.datatype_->is_none()) {
error(obj->opr_, "Cannot infer type when RHS is None");
}
Expand Down Expand Up @@ -309,7 +316,8 @@ void type_checker::visit_fncall_expr(fncall_expr *obj) {
arguments.push_back(pop());
}
auto result = builtins_.verify(name.string_val_, arguments, obj->args_,
import_stmts_alias_, filepath_, this, cf_->directives_.no_stdlib_);
import_stmts_alias_, filepath_, this,
cf_->directives_.no_stdlib_);
// Error when calling builtin, if so return None as data type
if (result.object_type_ == object_type::ERROR_DETECTED) {
error(obj->paren_token_, result.string_val_);
Expand Down Expand Up @@ -1002,7 +1010,7 @@ void type_checker::visit_const_stmt(const_stmt *obj) {
}
bool type_checker::slot_match(const ykobject &arg, ykdatatype *datatype) {
if (arg.is_a_function() && datatype->is_function()) {
ykdatatype *arg_datatype = function_to_datatype(arg);
ykdatatype *arg_datatype = function_to_datatype_or_null(arg);
return arg_datatype != nullptr && *arg_datatype == *datatype;
}
if (arg.is_primitive_or_obj() &&
Expand All @@ -1024,7 +1032,7 @@ bool type_checker::slot_match(const ykobject &arg, ykdatatype *datatype) {
}
return false;
}
ykdatatype *type_checker::function_to_datatype(const ykobject &arg) {
ykdatatype *type_checker::function_to_datatype_or_null(const ykobject &arg) {
def_stmt *funct;
if (arg.object_type_ == object_type::FUNCTION) {
funct = defs_classes_->get_function(arg.string_val_);
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/compiler/type_checker.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ namespace yaksha {
gc_pool<token> *token_pool);
~type_checker() override;
bool slot_match(const ykobject &arg, ykdatatype *datatype) override;
ykdatatype *function_to_datatype(const ykobject &arg) override;
ykdatatype *function_to_datatype_or_null(const ykobject &arg) override;
void check(const std::vector<stmt *> &statements);
void visit_assign_expr(assign_expr *obj) override;
void visit_binary_expr(binary_expr *obj) override;
Expand Down
10 changes: 9 additions & 1 deletion compiler/src/compiler/usage_analyser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ void usage_analyser::analyse() {
import_stack_.clear();
object_stack_.clear();
}
void usage_analyser::analyse_no_main() {
for (std::string &name : main_->data_->dsv_->function_names_) {
LOG_COMP("usage analyser (no main) - found: " << name);
main_->data_->dsv_->get_function(name)->accept(this);
}
import_stack_.clear();
object_stack_.clear();
}
void usage_analyser::visit_assign_expr(assign_expr *obj) {
obj->hits_++;
obj->right_->accept(this);
Expand Down Expand Up @@ -445,4 +453,4 @@ void usage_analyser::visit_cfor_stmt(cfor_stmt *obj) {
}
void usage_analyser::visit_enum_stmt(enum_stmt *obj) { obj->hits_++; }
void usage_analyser::visit_union_stmt(union_stmt *obj) { obj->hits_++; }
void usage_analyser::visit_directive_stmt(directive_stmt *obj) {}
void usage_analyser::visit_directive_stmt(directive_stmt *obj) { obj->hits_++; }
1 change: 1 addition & 0 deletions compiler/src/compiler/usage_analyser.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ namespace yaksha {
struct usage_analyser : expr_visitor, stmt_visitor {
explicit usage_analyser(file_info *main_file_info);
void analyse();
void analyse_no_main();
void visit_assign_expr(assign_expr *obj) override;
void visit_assign_arr_expr(assign_arr_expr *obj) override;
void visit_assign_member_expr(assign_member_expr *obj) override;
Expand Down
25 changes: 25 additions & 0 deletions compiler/test_data/compiler_tests/directives/minimal_mode.yaka
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
directive no_main
directive no_stdlib
directive apply_nativedefine
directive ccode """
#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif

#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
"""

# Below wil be inlined
@nativedefine("max")
def max(a: i32, b: i32) -> i32:
pass

@nativedefine("min")
def min(a: i32, b: i32) -> i32:
pass

def add(a: i32, b: i32) -> i32:
return min(a, b) + max(a, b)

19 changes: 19 additions & 0 deletions compiler/test_data/compiler_tests/directives/minimal_mode.yaka.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// YK
// --forward declarations--
int32_t yy__add(int32_t, int32_t);
// --structs--
// --functions--

#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif

#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
;
int32_t yy__add(int32_t yy__a, int32_t yy__b)
{
int32_t t__0 = (min(yy__a, yy__b) + max(yy__a, yy__b));
return t__0;
}
3 changes: 3 additions & 0 deletions compiler/tests/test_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,4 +379,7 @@ TEST_CASE("compiler: bug-fix - access struct str member") {
}
TEST_CASE("compiler: directive - ccode") {
test_compile_yaka_file("../test_data/compiler_tests/directives/directive_ccode.yaka");
}
TEST_CASE("compiler: directive - no_main/no_stdlib") {
test_compile_yaka_file("../test_data/compiler_tests/directives/minimal_mode.yaka");
}

0 comments on commit b60154c

Please sign in to comment.