File: 23-errors.ha

package info (click to toggle)
harec 0.26.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,480 kB
  • sloc: ansic: 20,054; asm: 335; makefile: 116; lisp: 80; sh: 45
file content (133 lines) | stat: -rw-r--r-- 3,185 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use rt::{compile, status};

type err_int = !int;
type err_recur = !*err_recur;

fn assignability() void = {
	// Error and non-error types are interchangable:
	let a: !int = 10;
	let b: int = a;
	assert(a == b);

	compile(status::CHECK, `
		type err = !void;

		fn reterr() (int | err) = {
			return err;
		};

		fn properr() void = {
			reterr()?;
		};

		export fn main() void = void;
	`)!; // error types cannot be assigned to void
};

type error = !void;

fn err_if_false(in: bool) (error | int) = {
	if (in) {
		return 1337;
	};
	return error;
};

fn indirect(in: bool) (error | int) = {
	let x = err_if_false(in)?;
	return x;
};

fn propagate() void = {
	assert(indirect(true) as int == 1337);
	assert(indirect(false) is error);
};

fn cannotignore() void = {
	compile(status::CHECK, "
		type error = !void;

		export fn main() void = {
			error;
		};
	")!;
	compile(status::CHECK, "
		type error = !int;

		export fn main() void = {
			let x: error = 0;
			x;
		};
	")!;
	compile(status::CHECK, "
		type error = !int;

		export fn main() void = {
			let x: (error | void) = void;
			x;
		};
	")!;
	err_if_false(true)!;
};

fn discard() void = {
	let x: error = error;
	let x: (int | error) = error;
	let x = err_if_false(false);
	x = error;
	x = err_if_false(false);

	// XXX: type inference currently doesn't work because of the temporary
	// fix for https://todo.sr.ht/~sircmpwn/hare/951. once that ticket is
	// actually fixed, the explicit type here can be removed
	let _: error = error;
	let _ = err_if_false(false);
	_ = error;
	_ = err_if_false(false);

	for (let x => done: (int | done | !void)) void;
	for (let _ => done: (int | done | !void)) void;
	compile(status::CHECK, `fn f() void = for (let x => done: (int | done | !void)) x;`)!;
};

fn measurements() void = {
	assert(size(!int) == size(int));
	assert(size(!f64) == size(f64));
	assert(size(!(int | void)) == size((int | void)));
	assert(size(!(i8, rune)) == size((i8, rune)));
	assert(size(!struct { x: int, y: str }) == size(struct { x: int, y: str }));
	assert(size(!union { x: int, y: str }) == size(union { x: int, y: str }));
	assert(size(![2]int) == size([2]int));
	assert(size(![]int) == size([]int));
	assert(size(!*size) == size(*size));

	assert(align(!int) == align(int));
	assert(align(!f64) == align(f64));
	assert(align(!(int | void)) == align((int | void)));
	assert(align(!(i8, rune)) == align((i8, rune)));
	assert(align(!struct { x: int, y: str }) == align(struct { x: int, y: str }));
	assert(align(!union { x: int, y: str }) == align(union { x: int, y: str }));
	assert(align(![2]int) == align([2]int));
	assert(align(![*]int) == align([*]int));
	assert(align(![]int) == align([]int));
	assert(align(!*size) == align(*size));
};

type err_done_tagged_union = !(int | done);
type done_tagged_union = (int | done);
type err_done_tagged_union_alias = !done_tagged_union;

fn disallowed_types() void = {
	compile(status::CHECK, `type t = !done;`)!;
	compile(status::CHECK, `type t = done; type u = t; type v = !u;`)!;
	compile(status::CHECK, `fn f() !never;`)!;
};

export fn main() void = {
	assignability();
	propagate();
	cannotignore();
	discard();
	measurements();
	disallowed_types();
};