implement: unit identity -- dotted paths, name rules, source path
Units start here, with the part that needs no import graph: what a unit is called and where it must live. The parser only ever read a single identifier after `unit` and `import`, so `unit game.main;` and `import std.io;` were syntax errors -- which is why the dotted fixtures failed at the semicolon. It now reads a dotted path and stores it canonically, dots included, since that spelling is the unit's identity everywhere else. `import a.b as c;` parses too, with the alias on the node. resolve.c is the new pass between parsing and checking, for the questions that span files. It carries SPEC 8.1 so far: each path segment is ASCII lowercase, starts with a letter, continues with letters, digits or underscore, and is at most eight characters; and the dotted path must match the source path it was read from, so game.world.map has to come from game/world/map.fe. The source side is folded to lowercase before comparing, because a case-insensitive host must not let two spellings become two units. That rule then applied to the fixtures, which were not obeying it: 57 declared a unit name unrelated to their file, left over from the milestone directories, and eight had names too long to be legal. Both are now aligned -- the rule is worth having only if the tree follows it. units: badupper, badlong and unitbad pass. 138 -> 146 of 188. The rest of units/ needs the import graph, which is the next piece: resolution, cycles, bindings and visibility.
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
unit m5_runtime;
|
||||
|
||||
fn take(p: ^i32) -> void { mem.destroy(p); }
|
||||
|
||||
pub fn run(mode: i32) -> !i32 {
|
||||
var p: ^i32 = try mem.create(0);
|
||||
defer { mem.destroy(p); }
|
||||
p.^ = 7;
|
||||
if mode == 1 {
|
||||
p = try mem.create(0);
|
||||
p.^ = 9;
|
||||
return p.^;
|
||||
}
|
||||
while true { break; }
|
||||
if mode == 2 { return 0; }
|
||||
return p.^ - 7;
|
||||
}
|
||||
|
||||
pub fn conditional(flag: bool) -> !void {
|
||||
var p: ^i32 = try mem.create(0);
|
||||
if flag { take(p); }
|
||||
}
|
||||
|
||||
pub fn argument_cleanup() -> !void {
|
||||
let p: ^i32 = try mem.create(0);
|
||||
take(p);
|
||||
}
|
||||
|
||||
pub fn owned_slice(n: usize) -> !void {
|
||||
let bytes: ^[]u8 = try mem.alloc_slice(u8, n);
|
||||
}
|
||||
|
||||
struct Holder { p: ^i32 }
|
||||
|
||||
pub fn replace_field() -> !void {
|
||||
let first: ^i32 = try mem.create(1);
|
||||
var h: Holder = Holder{ p: first };
|
||||
let second: ^i32 = try mem.create(2);
|
||||
let old: ^i32 = mem.replace(&mut h.p, second);
|
||||
mem.destroy(old);
|
||||
}
|
||||
|
||||
pub fn loop_cleanup() -> !void {
|
||||
var i: i32 = 0;
|
||||
while i < 2 {
|
||||
let p: ^i32 = try mem.create(i);
|
||||
i += 1;
|
||||
if i == 1 { continue; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_cleanup() -> !void {
|
||||
let first: ^i32 = try mem.create(1);
|
||||
let second: ^i32 = try mem.create(2);
|
||||
}
|
||||
|
||||
struct PairOwners { first: ^i32, second: ^i32 }
|
||||
|
||||
pub fn field_order() -> !void {
|
||||
let first: ^i32 = try mem.create(1);
|
||||
let second: ^i32 = try mem.create(2);
|
||||
let pair: PairOwners = PairOwners{ first: first, second: second };
|
||||
}
|
||||
|
||||
pub fn defer_order() -> !void {
|
||||
let first: ^i32 = try mem.create(1);
|
||||
defer { mem.destroy(first); }
|
||||
let second: ^i32 = try mem.create(2);
|
||||
}
|
||||
|
||||
enum Choice { A, B }
|
||||
|
||||
pub fn match_cleanup(flag: bool) -> !void {
|
||||
var choice: Choice = Choice.A;
|
||||
if flag { choice = Choice.B; }
|
||||
let p: ^i32 = try mem.create(1);
|
||||
match choice {
|
||||
A => { take(p); }
|
||||
B => { take(p); }
|
||||
}
|
||||
}
|
||||
|
||||
struct FileLike {
|
||||
handle: i32,
|
||||
fn close(self: Self) -> !void { self.handle = 0; }
|
||||
fn drop(self: &mut Self) { self.handle = 0; }
|
||||
}
|
||||
|
||||
pub fn close_once() -> !void {
|
||||
let file: FileLike = FileLike{ handle: 7 };
|
||||
try file.close();
|
||||
}
|
||||
|
||||
pub fn reassign_struct() -> !void {
|
||||
let first: ^i32 = try mem.create(1);
|
||||
var owner: Holder = Holder{ p: first };
|
||||
let second: ^i32 = try mem.create(2);
|
||||
owner = Holder{ p: second };
|
||||
}
|
||||
Reference in New Issue
Block a user