Skip to content

Commit

Permalink
feat: add no_stdlib directive
Browse files Browse the repository at this point in the history
  • Loading branch information
JaDogg committed Mar 17, 2024
1 parent 9c669c0 commit bbd6994
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 18 deletions.
2 changes: 1 addition & 1 deletion compiler/src/ast/codefiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ namespace yaksha {
// Flags
bool no_main_{false};
bool apply_native_define_{false};
bool no_libs_{false};
bool no_stdlib_{false};
// Conditional directives
std::vector<directive_stmt *> include_paths_{};
std::vector<directive_stmt *> library_paths_{};
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/ast/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ stmt *parser::import_statement() {
}
// We can see if we encountered this in pre_parsing
// If we did, then we can use the pre-parsed data
// during preparsing, this section will do nothing as there are no pre_parse stuff
// during preparsing, this section will do nothing if there are no pre_parse stuff
if (pre_parse_import_stmts_alias_.find(name_token->token_) !=
pre_parse_import_stmts_alias_.end()) {
auto pre_parse_import = pre_parse_import_stmts_alias_[name_token->token_];
Expand Down
1 change: 1 addition & 0 deletions compiler/src/builtins/builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
namespace yaksha {
struct builtin {
virtual ~builtin() = default;
virtual bool require_stdlib() = 0;
virtual ykobject
verify(const std::vector<ykobject> &args,
const std::vector<expr *> &arg_expressions,
Expand Down
41 changes: 36 additions & 5 deletions compiler/src/builtins/builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ struct builtin_arrput : builtin {
}
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┌─┐┬─┐┬─┐┌─┐┌─┐┌─┐
Expand Down Expand Up @@ -141,6 +142,7 @@ struct builtin_arrpop : builtin {
code << "yk__arrpop(" << args[0].first << ")";
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┌─┐┬─┐┬─┐┌─┐┌─┐┌┬┐┌─┐┌─┐┌─┐
Expand Down Expand Up @@ -192,7 +194,7 @@ struct builtin_arrsetlencap : builtin {
<< ")";
return {code.str(), o};
}

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

bool require_stdlib() override { return true; }
private:
std::string func_name_;
};
Expand Down Expand Up @@ -342,6 +344,7 @@ struct builtin_len : builtin {
o = ykobject(dt_pool->create("int"));
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┌─┐┬ ┬┌─┐┬─┐┌─┐┌┬┐
Expand Down Expand Up @@ -389,6 +392,7 @@ struct builtin_charat : builtin {
o = ykobject(dt_pool->create("int"));
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┌─┐┌─┐┌┬┐┬─┐┌─┐┌─┐
Expand Down Expand Up @@ -432,6 +436,7 @@ struct builtin_getref : builtin {
o = ykobject(dt);
return {code.str(), o};
}
bool require_stdlib() override { return false; }
};
//
// ┬ ┬┌┐┌┬─┐┌─┐┌─┐
Expand Down Expand Up @@ -471,6 +476,7 @@ struct builtin_unref : builtin {
o = ykobject(args[0].second.datatype_->args_[0]);
return {code.str(), o};
}
bool require_stdlib() override { return false; }
};
//
// ┌─┐┬ ┬┌┐┌┌─┐┬ ┬
Expand Down Expand Up @@ -510,6 +516,7 @@ struct builtin_shnew : builtin {
code << "yk__sh_new_strdup(" << args[0].first << ")";
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┌─┐┬ ┬┌─┐┌─┐┌┬┐
Expand Down Expand Up @@ -557,6 +564,7 @@ struct builtin_shget : builtin {
o = ykobject(args[0].second.datatype_->args_[0]->args_[0]);
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┌─┐┬ ┬┌─┐┌─┐┌┬┐┬
Expand Down Expand Up @@ -604,6 +612,7 @@ struct builtin_shgeti : builtin {
o = ykobject(dt_pool->create("int"));
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┌─┐┬ ┬┌─┐┬ ┬┌┬┐
Expand Down Expand Up @@ -653,6 +662,7 @@ struct builtin_shput : builtin {
code << ", " << args[2].first << ")";
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┌─┐┌─┐┌─┐┌┬┐
Expand Down Expand Up @@ -718,6 +728,7 @@ struct builtin_cast : builtin {
o = ykobject(out_dt);
return {code.str(), o};
}
bool require_stdlib() override { return false; }
};
//
// ┬ ┬┌┬┐┌┐┌┌─┐┬ ┬
Expand Down Expand Up @@ -755,6 +766,7 @@ struct builtin_hmnew : builtin {
auto o = ykobject(dt_pool);
return {"", o};
}
bool require_stdlib() override { return true; }
};
//
// ┬ ┬┌┬┐┌─┐┌─┐┌┬┐
Expand Down Expand Up @@ -800,6 +812,7 @@ struct builtin_hmget : builtin {
o = ykobject(args[0].second.datatype_->args_[0]->args_[0]);
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┬ ┬┌┬┐┌─┐┌─┐┌┬┐┬
Expand Down Expand Up @@ -845,6 +858,7 @@ struct builtin_hmgeti : builtin {
o = ykobject(dt_pool->create("int"));
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┬ ┬┌┬┐┌─┐┬ ┬┌┬┐
Expand Down Expand Up @@ -894,6 +908,7 @@ struct builtin_hmput : builtin {
<< args[2].first << ")";
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┌─┐ ┌─┐┌─┐┬─┐┌┬┐
Expand Down Expand Up @@ -965,6 +980,7 @@ struct builtin_qsort : builtin {
<< ") == 0)";
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┌─┐┬─┐┬─┐┌┐┌┌─┐┬ ┬
Expand Down Expand Up @@ -1033,6 +1049,7 @@ struct builtin_arrnew : builtin {
o = ykobject(array_dt);
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┌─┐┬ ┐ ┬┌─┐┌┬┐┌─┐┬─┐┬─┐
Expand Down Expand Up @@ -1120,6 +1137,7 @@ struct builtin_fixed_arr : builtin {
o = ykobject(array_dt);
return {code.str(), o};
}
bool require_stdlib() override { return false; }
};
//
// ┌─┐┬─┐┬─┐┌─┐┬ ┬
Expand Down Expand Up @@ -1208,6 +1226,7 @@ struct builtin_array : builtin {
o = ykobject(array_dt);
return {code.str(), o};
}
bool require_stdlib() override { return true; }
};
//
// ┬┬┌─┐
Expand Down Expand Up @@ -1275,6 +1294,7 @@ struct builtin_iif : builtin {
}
return {code.str(), o};
}
bool require_stdlib() override { return false; }
};
//
// ┌─┐┌─┐┬─┐┌─┐┌─┐┌─┐┬ ┬
Expand Down Expand Up @@ -1442,7 +1462,7 @@ struct builtin_functional : builtin {
code << return_temp;
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 Down Expand Up @@ -1546,6 +1566,7 @@ struct builtin_binarydata : builtin {
dt_parser->parse("Const[Ptr[Const[u8]]]", import_aliases, filepath));
return {esc->compile_binary_data(raw_string), o};
}
bool require_stdlib() override { return false; }
};
//
// ┌┬┐┌─┐┬┌─┌─┐
Expand Down Expand Up @@ -1620,6 +1641,7 @@ struct builtin_make : builtin {
o.datatype_ = dt;
return {code.str(), o};
}
bool require_stdlib() override { return false; }
};
//
// ┬┌┐┌┬ ┬┌┐┌┌─┐┌─┐
Expand Down Expand Up @@ -1683,6 +1705,7 @@ struct builtin_inlinec : builtin {
o.datatype_ = parsed_dt;
return {string_utils::unescape(code->literal_token_->token_), o};
}
bool require_stdlib() override { return false; }
};
//=======================================
builtins::builtins(ykdt_pool *dt_pool, gc_pool<token> *token_pool)
Expand Down Expand Up @@ -1736,8 +1759,16 @@ ykobject builtins::verify(
const std::string &name, const std::vector<ykobject> &args,
const std::vector<expr *> &arg_expressions,
const std::unordered_map<std::string, import_stmt *> &import_aliases,
const std::string &filepath, slot_matcher *dt_slot_matcher) {
return builtins_[name]->verify(args, arg_expressions, this, dt_pool_,
const std::string &filepath, slot_matcher *dt_slot_matcher,
bool no_stdlib) {
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.object_type_ = object_type::ERROR_DETECTED;
return o;
}
return builtin_object->verify(args, arg_expressions, this, dt_pool_,
import_aliases, filepath, dt_slot_matcher);
}
std::pair<std::string, ykobject> builtins::compile(
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/builtins/builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ namespace yaksha {
verify(const std::string &name, const std::vector<ykobject> &args,
const std::vector<expr *> &arg_expressions,
const std::unordered_map<std::string, import_stmt *> &import_aliases,
const std::string &filepath, slot_matcher *dt_slot_matcher);
const std::string &filepath, slot_matcher *dt_slot_matcher,
bool no_stdlib);
/**
* Compile a builtin function call.
* This assumes verify and has builtin is called.
Expand Down
16 changes: 12 additions & 4 deletions compiler/src/compiler/codegen_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,11 @@ comp_result codegen_c::emit(codefiles *cf, gc_pool<token> *token_pool,
}
c_code << "#";
}
c_code << "\n#include \"yk__lib.h\"\n";
c_code << "\n";
if (!cf->directives_.no_stdlib_) {
LOG_COMP("no_stdlib mode");
c_code << "#include \"yk__lib.h\"\n";
}
c_code << "// --forward declarations-- \n";
c_code << global_consts.str();
if (cf->esc_->has_bin_data()) { cf->esc_->compile_binary_data_to(c_code); }
Expand All @@ -122,9 +126,13 @@ comp_result codegen_c::emit(codefiles *cf, gc_pool<token> *token_pool,
if (cf->esc_->has_structures()) { cf->esc_->compile_structures(c_code); }
c_code << "// --functions-- \n";
c_code << function_body.str();
c_code << "#if defined(YK__MINIMAL_MAIN)\n";
c_code << "int main(void) { return yy__main(); }\n";
c_code << "#endif";
if (!cf->directives_.no_main_) {
LOG_COMP("no_main directive is set, no need add the minimal main to the "
"generated code.");
c_code << "#if defined(YK__MINIMAL_MAIN)\n";
c_code << "int main(void) { return yy__main(); }\n";
c_code << "#endif";
}
LOG_COMP("c code generated");
return {false, c_code.str()};
}
11 changes: 6 additions & 5 deletions compiler/src/compiler/def_class_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,20 +360,21 @@ bool def_class_visitor::has_zero_arg_directive(directive_stmt *obj) {
auto directive_type = obj->directive_type_->token_;
/* these must have no STR argument */
bool zero_arg_directive = false;
// (Global flag) No need to check for main() 🔴
// (Global flag) No need to check for main() 🟡
if (directive_type == "no_main") {
// TODO verify parameter count is zero
zero_arg_directive = true;
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;
}
// (Global flag) no yaksha runtime / libs, 🔴
if (directive_type == "no_libs") {
// (Global flag) no yaksha runtime / libs, 🟡
if (directive_type == "no_stdlib") {
zero_arg_directive = true;
cf_->directives_.no_libs_ = true;
cf_->directives_.no_stdlib_ = true;
}
return zero_arg_directive;
}
30 changes: 30 additions & 0 deletions compiler/src/compiler/multifile_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@ comp_result multifile_compiler::compile_all(codegen *code_generator) {
}
delete builtins_obj;
}
has_errors |= has_not_allowed_imports_for_no_std_lib();
if (has_errors) { return {true, ""}; }
if (cf_->directives_.no_main_ || !this->main_required_) {
LOG_COMP("main is not required");
this->main_required_ = false;
cf_->directives_.no_main_ = true;
}
LOG_COMP("post loop");
has_errors |= has_invalid_main_func(main_file_info);
if (has_errors) {
Expand Down Expand Up @@ -353,6 +360,29 @@ bool multifile_compiler::has_invalid_main_func(
}
multifile_compiler::~multifile_compiler() { delete cf_; }
codefiles &multifile_compiler::get_codefiles() const { return *cf_; }
bool multifile_compiler::has_not_allowed_imports_for_no_std_lib() {
if (!cf_->directives_.no_stdlib_) {
LOG_COMP("stdlib is allowed");
return false;
}
for (auto f : cf_->files_) {
for (auto imp : f->data_->parser_->import_stmts_) {
// allow for imports 'libs', 'w4', 'libs.c'
if (!imp->import_names_.empty() &&
imp->import_names_[0]->token_ == "raylib") {
LOG_COMP("in nostdlib mode - raylib is not allowed");
return true;
}
if (imp->import_names_.size() > 1 &&
imp->import_names_[0]->token_ == "libs" &&
imp->import_names_[1]->token_ != "c") {
LOG_COMP("in nostdlib mode only libs,w4,libs.c are allowed")
return true;
}
}
}
return false;
}
comp_result do_nothing_codegen::emit(codefiles *cf, gc_pool<token> *token_pool,
errors::error_printer *ep) {
return comp_result{false, ""};
Expand Down
1 change: 1 addition & 0 deletions compiler/src/compiler/multifile_compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ namespace yaksha {
[[nodiscard]] bool has_invalid_main_func(file_info *main_file_info) const;
[[nodiscard]] bool all_success() const;
codefiles *cf_{nullptr};
bool has_not_allowed_imports_for_no_std_lib();
};
}// namespace yaksha
#endif
Loading

0 comments on commit bbd6994

Please sign in to comment.