Skip to content

Commit 427700d

Browse files
committed
Added IO functions to the Basil prelude.
1 parent 66c3666 commit 427700d

File tree

23 files changed

+721
-437
lines changed

23 files changed

+721
-437
lines changed

build.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,19 +136,21 @@ def cmd_exists(cmd): # see if a given command is available on the system PATH
136136
"-Wall", "-Wno-unused", "-Wno-comment"
137137
]
138138
if OS == "Linux":
139-
CXXFLAGS.append("-DINCLUDE_UTF8_LOOKUP_TABLE")
139+
if "librt" not in TARGET: CXXFLAGS.append("-DINCLUDE_UTF8_LOOKUP_TABLE")
140140
LDFLAGS += ["-Wl,--gc-sections"]
141141
LDLIBS += ["-lc"]
142142
if CXXTYPE == "intel": LDLIBS += ["-limf", "-lirc"]
143143
elif OS == "Darwin":
144-
CXXFLAGS.append("-DINCLUDE_UTF8_LOOKUP_TABLE")
144+
if "librt" not in TARGET: CXXFLAGS.append("-DINCLUDE_UTF8_LOOKUP_TABLE")
145145
LDFLAGS += ["-nodefaultlibs", "-Wl,--gc-sections"]
146146
LDLIBS += ["-lc"]
147147
if CXXTYPE == "intel": LDLIBS += ["-limf", "-lirc"]
148148
if "release" in TARGET:
149149
CXXFLAGS += ["-fno-unwind-tables", "-fno-asynchronous-unwind-tables", "-Os", "-DBASIL_RELEASE"]
150150
elif "debug" in TARGET:
151151
CXXFLAGS += ["-g3", "-O0"]
152+
elif "librt" in TARGET:
153+
CXXFLAGS += ["-nostdlib", "-fno-builtin", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables", "-Os", "-DBASIL_RELEASE"]
152154
if TARGET == "librt-dynamic":
153155
LDFLAGS.append("-shared")
154156
elif CXXTYPE == "msvc":
@@ -375,6 +377,7 @@ def strip_cmd(target):
375377
TASKS.append(strip_cmd(PRODUCT))
376378

377379
if TARGET == "librt-static":
380+
if os.path.exists(PRODUCT): os.remove(PRODUCT)
378381
TASKS.append(ar_lib_cmd(OBJS.values(), PRODUCT))
379382

380383
if TARGET in {"test"}:

compiler/builtin.cpp

Lines changed: 201 additions & 28 deletions
Large diffs are not rendered by default.

compiler/driver.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
#include "stdlib.h"
1919
#include "time.h"
2020
#include "jasmine/jobj.h"
21+
#include "runtime/sys.h"
2122
#include "runtime/core.h"
2223

2324
namespace basil {
2425
void init() {
2526
init_types_and_symbols();
27+
sys::init_io();
2628
}
2729

2830
void deinit() {
@@ -31,7 +33,17 @@ namespace basil {
3133
}
3234

3335
void init_rt(jasmine::Object& obj) {
34-
// obj.define_native(jasmine::global("print_i"), (void*)print_i);
36+
obj.define_native(jasmine::global("write_N6Streamii"), (void*)write_N6Streamii);
37+
obj.define_native(jasmine::global("write_N6Streamif"), (void*)write_N6Streamif);
38+
obj.define_native(jasmine::global("write_N6Streamid"), (void*)write_N6Streamid);
39+
obj.define_native(jasmine::global("write_N6Streamic"), (void*)write_N6Streamic);
40+
obj.define_native(jasmine::global("write_N6Streamib"), (void*)write_N6Streamib);
41+
obj.define_native(jasmine::global("write_N6Streamis"), (void*)write_N6Streamis);
42+
obj.define_native(jasmine::global("write_N6Streamiv"), (void*)write_N6Streamiv);
43+
obj.define_native(jasmine::global("init_v"), (void*)init_v);
44+
obj.define_native(jasmine::global("exit_i"), (void*)exit_i);
45+
obj.define_native(jasmine::global("open_si"), (void*)open_si);
46+
obj.define_native(jasmine::global("close_N6Streami"), (void*)close_N6Streami);
3547
}
3648

3749
static bool repl_mode = false;
@@ -165,12 +177,23 @@ namespace basil {
165177
rc<IRFunction> main_ir = ref<IRFunction>(symbol_from(".basil_main"), t_func(T_VOID, T_INT));
166178
main_ir->finish(T_INT, main->gen_ssa(env, main_ir));
167179

180+
rc<IRFunction> entry = ref<IRFunction>(symbol_from("_start"), t_func(T_VOID, T_VOID));
181+
entry->add_insn(ir_call(entry, t_func(T_VOID, T_VOID),
182+
ir_label(symbol_from("init_v")), vector_of<IRParam>()));
183+
IRParam ret = entry->add_insn(ir_call(entry, t_func(T_VOID, T_INT),
184+
ir_label(symbol_from(".basil_main")), vector_of<IRParam>()));
185+
entry->add_insn(ir_call(entry, t_func(T_INT, T_VOID),
186+
ir_label(symbol_from("exit_i")), vector_of<IRParam>(ret)));
187+
entry->finish(T_VOID, ir_int(0));
188+
168189
map<Symbol, rc<IRFunction>> ir_functions;
169190
for (auto& [k, v] : functions) {
170191
v->gen_ssa(root_env(), main_ir);
171192
if (v->kind() == AST_FUNCTION) ir_functions[k] = get_ssa_function(v);
172193
}
173194

195+
ir_functions[symbol_from("_start")] = entry;
196+
174197
if (error_count()) {
175198
print_errors(_stdout, nullptr);
176199
discard_errors();
@@ -379,7 +402,8 @@ namespace basil {
379402
else return false;
380403
}
381404

382-
void write_asm(bytebuf buf, stream& io) {
405+
void write_asm(void* base, bytebuf buf, stream& io) {
406+
writeln(io, BOLDCYAN, "#", u64(base), RESET, ":");
383407
while (buf.size()) {
384408
u8 byte = buf.read();
385409
u8 upper = byte >> 4, lower = byte & 15;
@@ -474,7 +498,8 @@ namespace basil {
474498
// native.writeELF("out.o");
475499
init_rt(native);
476500
native.load();
477-
// write_asm(native.code(), _stdout);
501+
// write_asm(native.get_loaded(jasmine::OS_CODE), native.code(), _stdout);
502+
// write_asm(native.get_loaded(jasmine::OS_DATA), native.data(), _stdout);
478503
auto main = (i64(*)())native.find(jasmine::global(".basil_main"));
479504
i64 main_result = main();
480505
if (ast->type(global) != T_VOID) {
@@ -504,9 +529,11 @@ namespace basil {
504529
rc<jasmine::Object> native = native_from_section(obj->sections[*obj->main_section]);
505530
init_rt(*native);
506531
native->load();
507-
// write_asm(native->code(), _stdout);
532+
// write_asm(native->get_loaded(jasmine::OS_CODE), native->code(), _stdout);
533+
// write_asm(native->get_loaded(jasmine::OS_DATA), native->data(), _stdout);
508534
auto main = (i64(*)())native->find(jasmine::global(".basil_main"));
509535
main();
536+
exit(0);
510537
// println("= ", BOLD, ITALICBLUE, main(), RESET);
511538
}
512539

@@ -560,7 +587,7 @@ namespace basil {
560587
case NT_EXECUTABLE: {
561588
ustring obj = compute_object_name(filename, OBJ_FILE_EXT);
562589
native->writeObj(obj.raw());
563-
ustring cmd = format<ustring>("gcc -nostdlib ", obj, " -Wl,-e.basil_main -o ", compute_object_name(obj.raw(), ""));
590+
ustring cmd = format<ustring>("gcc -nostdlib ", obj, " -o ", compute_object_name(obj.raw(), ""));
564591
for (const char* arg : args) cmd += " ", cmd += arg; // add linker args
565592
// println(cmd);
566593
system(cmd.raw());

compiler/eval.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,7 @@ namespace basil {
887887

888888
Value call(rc<Env> env, Value call_term, Value func, const Value& args_in) {
889889
if ((perfinfo.current_count() >= perfinfo.max_count || perfinfo.counts.size() >= perfinfo.max_depth)
890-
&& !perfinfo.is_instantiating() && !perfinfo.is_comptime()) {
890+
&& !perfinfo.is_instantiating() && !perfinfo.is_comptime() && !v_head(call_term).form->is_macro) {
891891
return v_error({}); // return error value if current function is too expensive
892892
}
893893

@@ -1099,6 +1099,8 @@ namespace basil {
10991099
Value result;
11001100
rc<InstTable> fn_body = v_resolve_body(*func.data.fn, orig_args); // resolve function body
11011101
perfinfo.begin_call(call_term, fn_body, 1); // user-defined functions are considered more expensive
1102+
if (t_is_macro(func.type)) is_runtime = false;
1103+
perfinfo.make_comptime();
11021104
if (!is_runtime) {
11031105
if (func.type.of(K_RUNTIME)) // check just in case
11041106
panic("Somehow got runtime function in compile-time function call!");

compiler/forms.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,11 @@ namespace basil {
498498
return form;
499499
}
500500

501+
rc<Form> f_as_macro(rc<Form> form) {
502+
form->make_macro();
503+
return form;
504+
}
505+
501506
const char* FK_NAMES[NUM_FORM_KINDS] = {
502507
"term",
503508
"callable",

compiler/forms.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,9 @@ namespace basil {
339339
// Constructs a compound form from the provided subform mapping information.
340340
// Compound forms are not applicable, so no associativity or precedence is necessary.
341341
rc<Form> f_compound(const map<Value, rc<Form>>& members);
342+
343+
// Applicative alternative to Form::make_macro().
344+
rc<Form> f_as_macro(rc<Form> form);
342345
}
343346

344347
void write(stream& io, const basil::Param& param);

0 commit comments

Comments
 (0)