hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit b030669fdd8ad27aa84cbaf769e12109d7deff02
parent ac3222b2e1fd0e94b4b1483df5b3db06b9c8edca
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 10 Mar 2021 10:16:17 -0500

Update stdlib and schedule more tasks

Diffstat:
Mgen-stdlib | 3+--
Mmain.ha | 15+++++++++++----
Mmk/stdlib.mk | 6++----
Mplan.ha | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
4 files changed, 103 insertions(+), 26 deletions(-)

diff --git a/gen-stdlib b/gen-stdlib @@ -353,7 +353,7 @@ os_exec() { 'process$(PLATFORM).ha' \ 'cmd$(PLATFORM).ha' \ cmd.ha - gen_ssa os::exec os strings fmt + gen_ssa os::exec os strings fmt bytes path } path() { @@ -362,7 +362,6 @@ path() { '$(PLATFORM).ha' \ util.ha \ join.ha \ - norm.ha \ names.ha \ iter.ha gen_ssa path strings bufio bytes diff --git a/main.ha b/main.ha @@ -19,7 +19,6 @@ export fn main() void = { ... }; defer os::rmdirall(plan.workdir); - defer path::path_free(plan.workdir); let ctx = module::context_init([module::tag { name = os::machine(), mode = module::tag_mode::INCLUSIVE, @@ -29,6 +28,13 @@ export fn main() void = { mode = module::tag_mode::INCLUSIVE, }]); + const rtdir = match (module::lookup(&ctx, ["rt"])) { + err: module::error => fmt::fatal("Error resolving rt: {}", + module::errstr(err)), + ver: module::version => ver.basedir, + }; + plan.script = path::join(rtdir, "hare.sc"); + let ver = match (module::scan(&ctx, os::args[1])) { ver: module::version => ver, err: module::error => fmt::fatal("Error scanning module: {}", @@ -48,14 +54,14 @@ export fn main() void = { fmt::errorfln("{}: selecting version {}", ident, hash); for (let i = 0z; i < len(ver.inputs); i += 1) { - fmt::errorfln("\t{}", - ver.inputs[i].path as str); + fmt::errorfln("\t{}", ver.inputs[i].path); }; }, }; }; - sched_hare_exe(&plan, ver.inputs, "hare.ssa", []); + // TODO: Choose less stupid output name + sched_hare_exe(&plan, ver.inputs, "a.out"); for (len(plan.scheduled) != 0) { let next: nullable *task = null; @@ -81,6 +87,7 @@ export fn main() void = { }; task.status = status::COMPLETE; + delete(plan.scheduled[i]); append(plan.complete, task); }; diff --git a/mk/stdlib.mk b/mk/stdlib.mk @@ -419,7 +419,7 @@ stdlib_os_exec_srcs= \ $(STDLIB)/os/exec/cmd$(PLATFORM).ha \ $(STDLIB)/os/exec/cmd.ha -$(HARECACHE)/os/exec/os.exec.ssa: $(stdlib_os_exec_srcs) $(stdlib_rt) $(stdlib_os) $(stdlib_strings) $(stdlib_fmt) +$(HARECACHE)/os/exec/os.exec.ssa: $(stdlib_os_exec_srcs) $(stdlib_rt) $(stdlib_os) $(stdlib_strings) $(stdlib_fmt) $(stdlib_bytes) $(stdlib_path) @printf 'HAREC \t$@\n' @mkdir -p $(HARECACHE)/os/exec @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nos::exec \ @@ -430,7 +430,6 @@ stdlib_path_srcs= \ $(STDLIB)/path/$(PLATFORM).ha \ $(STDLIB)/path/util.ha \ $(STDLIB)/path/join.ha \ - $(STDLIB)/path/norm.ha \ $(STDLIB)/path/names.ha \ $(STDLIB)/path/iter.ha @@ -955,7 +954,7 @@ testlib_os_exec_srcs= \ $(STDLIB)/os/exec/cmd$(PLATFORM).ha \ $(STDLIB)/os/exec/cmd.ha -$(TESTCACHE)/os/exec/os.exec.ssa: $(testlib_os_exec_srcs) $(testlib_rt) $(testlib_os) $(testlib_strings) $(testlib_fmt) +$(TESTCACHE)/os/exec/os.exec.ssa: $(testlib_os_exec_srcs) $(testlib_rt) $(testlib_os) $(testlib_strings) $(testlib_fmt) $(testlib_bytes) $(testlib_path) @printf 'HAREC \t$@\n' @mkdir -p $(TESTCACHE)/os/exec @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nos::exec \ @@ -966,7 +965,6 @@ testlib_path_srcs= \ $(STDLIB)/path/$(PLATFORM).ha \ $(STDLIB)/path/util.ha \ $(STDLIB)/path/join.ha \ - $(STDLIB)/path/norm.ha \ $(STDLIB)/path/names.ha \ $(STDLIB)/path/iter.ha diff --git a/plan.ha b/plan.ha @@ -11,38 +11,96 @@ type status = enum { type task = struct { status: status, - inputs: []module::input, depend: []*task, - output: path::path, + output: str, cmd: []str, }; type plan = struct { - workdir: path::path, + workdir: str, + counter: uint, scheduled: []*task, complete: []*task, + script: str, +}; + +// Schedules a task which compiles objects into an executable. +fn sched_ld(plan: *plan, output: str, depend: *task...) *task = { + let task = alloc(task { + status = status::SCHEDULED, + output = output, + depend = mkdepends(depend...), + cmd = alloc([ + os::tryenv("LD", "ld"), + "-T", plan.script, + "-o", output, + ]), + }); + for (let i = 0z; i < len(depend); i += 1) { + append(task.cmd, depend[i].output); + }; + append(plan.scheduled, task); + return task; +}; + +// Schedules a task which compiles assembly into an object. +fn sched_as(plan: *plan, output: str, depend: *task) *task = { + let task = alloc(task { + status = status::SCHEDULED, + output = output, + depend = mkdepends(depend), + cmd = alloc([ + os::tryenv("AS", "as"), "-o", output, depend.output, + ]), + }); + append(plan.scheduled, task); + return task; +}; + +// Schedules a task which compiles an SSA file into assembly. +fn sched_qbe(plan: *plan, output: str, depend: *task) *task = { + let task = alloc(task { + status = status::SCHEDULED, + output = output, + depend = mkdepends(depend), + cmd = alloc([ + os::tryenv("QBE", "qbe"), "-o", output, depend.output, + ]), + }); + append(plan.scheduled, task); + return task; }; +// Schedules tasks which compiles hare sources into an executable. fn sched_hare_exe( plan: *plan, inputs: []module::input, - output: path::path, - depend: []*task, + output: str, + depend: *task... ) *task = { - // TODO: Schedule the qbe, as, and ld tasks - let task = alloc(task { + // TODO: Handle mixed sources + let ssa = mkfile(plan, "ssa"); + let s = mkfile(plan, "s"); + let o = mkfile(plan, "o"); + + let harec = alloc(task { status = status::SCHEDULED, - inputs = inputs, - output = output, - depend = depend, - cmd = alloc([os::tryenv("HAREC", "harec"), "-o", output as str]), + output = ssa, + depend = mkdepends(depend...), + cmd = alloc([ + os::tryenv("HAREC", "harec"), "-o", ssa, + ]), }); + for (let i = 0z; i < len(inputs); i += 1) { - let path = inputs[i].path as str; - append(task.cmd, path); + let path = inputs[i].path; + append(harec.cmd, path); }; - append(plan.scheduled, task); - return task; + append(plan.scheduled, harec); + + let qbe = sched_qbe(plan, s, harec); + let asm = sched_as(plan, o, qbe); + return sched_ld(plan, output, asm); }; fn execute( @@ -55,9 +113,24 @@ fn execute( fmt::errorln(); let cmd = exec::cmd(task.cmd[0], task.cmd[1..]...)?; - exec::setenv(&cmd, "HARECACHE", ctx.cache as str); + exec::setenv(&cmd, "HARECACHE", ctx.cache); let proc = exec::start(&cmd)?; let st = exec::wait(&proc)?; return exec::check(&st)?; }; + +fn mkfile(plan: *plan, ext: str) str = { + static let namebuf: [32]u8 = [0...]; + const name = fmt::bsprintf(namebuf, "temp.{}.{}", + plan.counter, ext); + plan.counter += 1; + return path::join(plan.workdir, name); +}; + +fn mkdepends(t: *task...) []*task = { + // XXX: This should just be one alloc call + let deps: []*task = alloc([], len(t)); + append(deps, ...t); + return deps; +};