hare

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

commit 554a40c042084f92da0d91913466c64c125cd546
parent c8d66f11253d86b2264a19075143cfa5aa4d451e
Author: Drew DeVault <sir@cmpwn.com>
Date:   Tue,  6 Sep 2022 11:51:50 +0200

hare::module: incorporate tags into manifest

This makes cross-compilation work more reliably.

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mhare/module/manifest.ha | 47+++++++++++++++++++++++++++++++++++++++++++++--
Mhare/module/scan.ha | 16+++++++++-------
Mhare/module/types.ha | 1+
3 files changed, 55 insertions(+), 9 deletions(-)

diff --git a/hare/module/manifest.ha b/hare/module/manifest.ha @@ -24,13 +24,14 @@ use temp; // The manifest file format is a series of line-oriented records. Lines starting // with # are ignored. // -// - "version" indicates the manifest format version, currently 1. +// - "version" indicates the manifest format version, currently 2. // - "input" is an input file, and its fields are the file hash, path, inode, // and mtime as a Unix timestamp. // - "module" is a version of a module, and includes the module hash and the set // of input hashes which produce it. +// - "tags" is a list of tags associated with a module version -def VERSION: int = 1; +def VERSION: int = 2; fn getinput(in: []input, hash: []u8) nullable *input = { for (let i = 0z; i < len(in); i += 1) { @@ -226,6 +227,33 @@ export fn manifest_load(ctx: *context, ident: ast::ident) (manifest | error) = { inputs = minputs, ... }); + case "tags" => + let modhash = match (strings::next_token(&tok)) { + case void => + return manifest; + case let s: str => + yield s; + }; + let modhash = match (hex::decodestr(modhash)) { + case let b: []u8 => + yield b; + case => + return manifest; + }; + + const tags = strings::remaining_tokens(&tok); + const tags = parsetags(tags) as []tag; + let found = false; + for (let i = 0z; i < len(versions); i += 1) { + if (bytes::equal(versions[i].hash, modhash)) { + versions[i].tags = tags; + found = true; + break; + }; + }; + // Implementation detail: tags always follows module + // directive for a given module version + assert(found); case => return manifest; }; @@ -331,6 +359,20 @@ export fn manifest_write(ctx: *context, man: *manifest) (void | error) = { }; fmt::fprintln(file)?; + + fmt::fprintf(file, "tags {} ", hash)?; + for (let i = 0z; i < len(ver.tags); i += 1) { + const tag = &ver.tags[i]; + fmt::fprintf(file, "{}{}", + switch (tag.mode) { + case tag_mode::INCLUSIVE => + yield "+"; + case tag_mode::EXCLUSIVE => + yield "-"; + }, + tag.name)?; + }; + fmt::fprintln(file)!; }; fs::move(ctx.fs, name, mpath)?; @@ -351,5 +393,6 @@ export fn manifest_finish(m: *manifest) void = { for (let i = 0z; i < len(m.versions); i += 1) { free(m.versions[i].inputs); + tags_free(m.versions[i].tags); }; }; diff --git a/hare/module/scan.ha b/hare/module/scan.ha @@ -25,15 +25,15 @@ def ABI_VERSION: u8 = 4; export fn scan(ctx: *context, path: str) (version | error) = { // TODO: Incorporate defines into the hash let sha = sha256::sha256(); - let found = false; for (let i = 0z; i < len(ctx.tags); i += 1) { - if (ctx.tags[i].mode == tag_mode::INCLUSIVE - && ctx.tags[i].name == "test") { - found = true; - break; - }; + const tag = &ctx.tags[i]; + hash::write(&sha, if (tag.mode == tag_mode::INCLUSIVE) { + yield [1]; + } else { + yield [0]; + }); + hash::write(&sha, strings::toutf8(tag.name)); }; - hash::write(&sha, [if (found) 1 else 0]); let iter = match (fs::iter(ctx.fs, path)) { case fs::wrongtype => // Single file case @@ -65,6 +65,7 @@ export fn scan(ctx: *context, path: str) (version | error) = { basedir = strings::dup(path::dirname(path)), depends = deps, inputs = inputs, + tags = tags_dup(ctx.tags), ... }; case let err: fs::error => @@ -75,6 +76,7 @@ export fn scan(ctx: *context, path: str) (version | error) = { defer fs::finish(iter); let ver = version { basedir = strings::dup(path), + tags = tags_dup(ctx.tags), ... }; scan_directory(ctx, &ver, &sha, path, iter)?; diff --git a/hare/module/types.ha b/hare/module/types.ha @@ -34,6 +34,7 @@ export type version = struct { depends: []ast::ident, inputs: []input, subdirs: []str, + tags: []tag, }; // The filetype of a file within a module.