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:
@@ -1,4 +1,4 @@
|
||||
unit m4_bad_arity;
|
||||
unit bad_ari;
|
||||
|
||||
fn main() -> i32 {
|
||||
@print("{} {}", 1);
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m4_bad_buffer_writer;
|
||||
unit bad_bufw;
|
||||
|
||||
fn main() -> void {
|
||||
var raw: [4]u8 = [0, 0, 0, 0];
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m4_bad_cls;
|
||||
unit bad_cls;
|
||||
|
||||
fn main() -> i32 {
|
||||
@print("}", 1);
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m4_bad_many;
|
||||
unit bad_many;
|
||||
|
||||
fn main() -> i32 {
|
||||
@print("{}", 1, 2);
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m4_bad_open;
|
||||
unit bad_open;
|
||||
|
||||
fn main() -> i32 {
|
||||
@print("{", 1);
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m4_bad_runtime;
|
||||
unit bad_run;
|
||||
|
||||
fn main() -> i32 {
|
||||
var fmt: str = "{}";
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m4_bad_try;
|
||||
unit bad_try;
|
||||
|
||||
fn main() -> i32 {
|
||||
try @print("nope");
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m4_bad_type;
|
||||
unit bad_type;
|
||||
|
||||
struct Point { x: i32, }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m4_bad_verb;
|
||||
unit bad_verb;
|
||||
|
||||
fn main() -> i32 {
|
||||
@print("{q}", 1);
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m4_bad_writer;
|
||||
unit bad_writ;
|
||||
|
||||
fn main() -> i32 {
|
||||
var x: i32 = 0;
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m4_format;
|
||||
unit ok_forma;
|
||||
|
||||
const FMT: str = "n={} hex={x} c={c} s={s} b={b} {{ok}}\n";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m4_prop;
|
||||
unit ok_prop;
|
||||
|
||||
pub fn propagate(w: io.Writer) -> !void {
|
||||
try @fprint(w, "a{}b", 1);
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m4_try_fprint;
|
||||
unit ok_try_f;
|
||||
|
||||
fn main() -> !void {
|
||||
var raw: [4]u8 = [0, 0, 0, 0];
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m5_bad_consuming_close;
|
||||
unit bad_clos;
|
||||
|
||||
struct FileLike {
|
||||
handle: i32,
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m5_bad_conditional;
|
||||
unit bad_cond;
|
||||
|
||||
fn take(p: ^i32) -> void { mem.destroy(p); }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m5_bad_double;
|
||||
unit bad_dbl;
|
||||
|
||||
fn bad(p: ^i32) -> void {
|
||||
mem.destroy(p);
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m5_bad_destroy;
|
||||
unit bad_dest;
|
||||
|
||||
fn bad(x: i32) -> void {
|
||||
mem.destroy(x);
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m5_bad_drop;
|
||||
unit bad_drop;
|
||||
|
||||
struct Box {
|
||||
value: i32,
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m5_bad_loop_move;
|
||||
unit bad_loop;
|
||||
|
||||
fn take(p: ^i32) -> void { mem.destroy(p); }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m5_bad_move;
|
||||
unit bad_move;
|
||||
|
||||
fn take(p: ^i32) -> void { mem.destroy(p); }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m5_bad_projection_move;
|
||||
unit bad_proj;
|
||||
|
||||
struct Holder { p: ^i32 }
|
||||
fn take(p: ^i32) -> void { mem.destroy(p); }
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m5_defer;
|
||||
unit ok_defer;
|
||||
|
||||
pub fn cleanup(p: ^i32) -> void {
|
||||
defer { mem.destroy(p); }
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m5_owned;
|
||||
unit ok_owned;
|
||||
|
||||
fn main() -> !void {
|
||||
var p: ^i32 = try mem.create(0);
|
||||
@@ -1,4 +1,4 @@
|
||||
unit keywords_and_builtins;
|
||||
unit keybuilt;
|
||||
|
||||
pub fn demo() {
|
||||
let a = true and not false;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// ERROR:logical operator
|
||||
unit old_logic;
|
||||
unit logical;
|
||||
fn main() { let x = true && false; }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// ERROR:expected ';'
|
||||
unit broken;
|
||||
unit misssemi;
|
||||
fn main() { let x: i32 = 1 }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// ERROR:unterminated block comment
|
||||
unit broken;
|
||||
unit unclcomm;
|
||||
/* no ending delimiter
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit v012_forms;
|
||||
unit v012form;
|
||||
|
||||
shared atomic var ticks: u16 = 0;
|
||||
packed struct Packet {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit bad_arity;
|
||||
unit bad_ari;
|
||||
|
||||
fn add(a: i32, b: i32) -> i32 {
|
||||
return a + b;
|
||||
@@ -1,4 +1,4 @@
|
||||
unit bad_assign;
|
||||
unit bad_asgn;
|
||||
|
||||
fn main() -> i32 {
|
||||
let value: i32 = 1;
|
||||
@@ -1,4 +1,4 @@
|
||||
unit bad_condition;
|
||||
unit bad_cond;
|
||||
|
||||
fn main() -> i32 {
|
||||
if 1 { return 0; }
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m3_bad_mut_let;
|
||||
unit bad_mlet;
|
||||
|
||||
fn bad() -> void {
|
||||
var raw: [2]u8 = [1, 2];
|
||||
@@ -1,4 +1,4 @@
|
||||
unit bad_return;
|
||||
unit bad_ret;
|
||||
|
||||
fn main() -> i32 {
|
||||
return true;
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m3_bad_shared_write;
|
||||
unit bad_shwr;
|
||||
|
||||
fn bad(s: []u8) -> void {
|
||||
s[0] = 1;
|
||||
@@ -1,4 +1,4 @@
|
||||
unit bad_types;
|
||||
unit bad_type;
|
||||
|
||||
fn add(a: i32, b: i32) -> i32 {
|
||||
return a + b;
|
||||
@@ -1,4 +1,4 @@
|
||||
unit bad_uninit;
|
||||
unit bad_unit;
|
||||
|
||||
fn main() -> i32 {
|
||||
var value: i32;
|
||||
@@ -1,4 +1,4 @@
|
||||
unit bad_unknown;
|
||||
unit bad_unk;
|
||||
|
||||
fn main() -> i32 {
|
||||
return missing_name;
|
||||
@@ -1,4 +1,4 @@
|
||||
unit fail_m3_array;
|
||||
unit badarr;
|
||||
fn main() -> i32 {
|
||||
let a: [2]i32 = [1, true, 3];
|
||||
return a[0];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit fail_m3_char;
|
||||
unit badchar;
|
||||
|
||||
fn main() -> i32 {
|
||||
let u: u8 = 'A';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit fail_m3_cycle;
|
||||
unit badcycle;
|
||||
|
||||
struct A { b: B, }
|
||||
struct B { a: A, }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit fail_m3_let_field;
|
||||
unit badfield;
|
||||
|
||||
struct Point { x: i32, y: i32, }
|
||||
fn main() -> i32 {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit fail_m3_fields;
|
||||
unit badfld;
|
||||
struct Point { x: i32, y: i32, }
|
||||
fn main() -> i32 {
|
||||
let p: Point = Point{ x: 1 };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit fail_m3_let_index;
|
||||
unit badindex;
|
||||
|
||||
fn main() -> i32 {
|
||||
let a: [2]i32 = [1, 2];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit fail_m3_match;
|
||||
unit badmat;
|
||||
enum Shape { Empty, Circle(i32), }
|
||||
fn main() -> i32 {
|
||||
match Shape.Empty { Empty => 0; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit fail_m3_str;
|
||||
unit badstr;
|
||||
fn main() -> i32 {
|
||||
var text: str = "abc";
|
||||
text[0] = 'z';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m3_arrayctx;
|
||||
unit ok_arra1;
|
||||
|
||||
fn main() -> i32 {
|
||||
let bytes: [3]u8 = [1, 2, 3];
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m3_array;
|
||||
unit ok_array;
|
||||
|
||||
fn main() -> i32 {
|
||||
let a: [3]i32 = [1, 2, 3];
|
||||
@@ -1,4 +1,4 @@
|
||||
unit cast_while;
|
||||
unit ok_castw;
|
||||
|
||||
pub fn main() -> i32 {
|
||||
var x: i16 = 0;
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m3_char;
|
||||
unit ok_char;
|
||||
|
||||
fn main() -> i32 {
|
||||
let c: char = '\u0041';
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m3_enum;
|
||||
unit ok_enum;
|
||||
|
||||
enum Shape { Empty, Circle(i32), Rect { w: i32, h: i32, }, }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m3_for;
|
||||
unit ok_for;
|
||||
|
||||
fn main() -> i32 {
|
||||
var total: i32 = 0;
|
||||
@@ -1,4 +1,4 @@
|
||||
unit hello;
|
||||
unit ok_hello;
|
||||
|
||||
fn add(a: i32, b: i32) -> i32 {
|
||||
return a + b;
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m3_mutable;
|
||||
unit ok_mutab;
|
||||
|
||||
fn takes_shared(s: []u8) -> u8 { return s[0]; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m3_nested;
|
||||
unit ok_neste;
|
||||
|
||||
struct Outer { inner: Inner, }
|
||||
struct Inner { value: i32, }
|
||||
@@ -1,4 +1,4 @@
|
||||
unit scopes;
|
||||
unit ok_scope;
|
||||
|
||||
fn register(switch: i32) -> i32 {
|
||||
let auto: i32 = switch;
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m3_str;
|
||||
unit ok_str;
|
||||
|
||||
fn main() -> i32 {
|
||||
let text: str = "abc";
|
||||
@@ -1,4 +1,4 @@
|
||||
unit m3_struct;
|
||||
unit ok_struc;
|
||||
|
||||
struct Point { x: i32, y: i32, }
|
||||
packed struct PackedPoint { x: u8, y: i32, }
|
||||
Reference in New Issue
Block a user