File: 30-reduction.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 (137 lines) | stat: -rw-r--r-- 2,475 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
134
135
136
137
use rt::{compile, status, toutf8};

fn assert_fail(expr: str) void = {
	let buf: [1024]u8 = [0...];
	let buf = buf[..0];
	static append(buf, toutf8("export fn main() void = {\n")...)!;
	static append(buf, toutf8(expr)...)!;
	static append(buf, toutf8(";\n};")...)!;
	compile(status::CHECK, *(&buf: *str))!;
};

export fn main() void = {
	// format:
	// let x = &expr;
	// let x: *type = x;

	let x = &(if (true) 0i else void);
	let x: *(int | void) = x;

	let x = &match (0u8: (u8 | u16 | u32 | u64)) {
	case u8 =>
		yield null: *int;
	case u16 =>
		yield null: nullable *int;
	case u32 =>
		yield null;
	case u64 =>
		yield;
	};
	let x: *(nullable *int | void) = x;

	let x = &switch (0) {
	case 42 =>
		yield null: *int;
	case 69 =>
		yield null: nullable *int;
	case 1337 =>
		yield null;
	case =>
		yield;
	};
	let x: *(nullable *int | void) = x;

	// if, match, and switch all use the same code for reduction, so we
	// don't need to rigorously test all three

	let x = &(if (true) null: *int else null);
	let x: *nullable *int = x;

	let x = &(if (true) null: *int else null: nullable *int);
	let x: *nullable *int = x;

	let x = &{
		if (true) yield;
		yield 0;
	};
	let x: *(int | void) = x;

	assert_fail("if (true) null "
		"else if (true) null: *int "
		"else null: *opaque");
	assert_fail("if (true) null else void");
	assert_fail("if (true) null: *int else if (true) null");

	// However, literals behave differently in if vs switch/match

	let x = &(if (true) 0 else if (true) 1 else 2);
	let x: *int = x;

	let x = &(if (true) 0 else 9223372036854775807);
	let x: *(int | i64) = x;

	let x = &(if (true) 0 else 0z);
	let x: *(int | size) = x;

	let x = &(if (true) 0 else void);
	let x: *(int | void) = x;

	let x = &switch (0) {
	case 0 =>
		yield 0;
	case 1 =>
		yield 1;
	case =>
		yield 2;
	};
	let x: *int = x;

	let x = &switch (0) {
	case 0 =>
		yield 0;
	case =>
		yield 9223372036854775807;
	};
	let x: *(int | i64) = x;

	let x = &switch (0) {
	case 0 =>
		yield 0;
	case =>
		yield 0z;
	};
	let x: *(int | size) = x;

	let x = &switch (0) {
	case 0 =>
		yield 0;
	case =>
		yield;
	};
	let x: *(int | void) = x;

	let x = &switch (0) {
	case 0 =>
		yield 0;
	case 1 =>
		yield 1z;
	case =>
		yield 2u32;
	};
	let x: *(int | size | u32) = x;

	let x = &switch (0) {
	case 0 =>
		yield 0;
	case 1 =>
		yield 1i;
	case =>
		yield 9223372036854775807;
	};
	let x: *(int | i64) = x;

	let x = &{
		for (false) yield 42;
	};
	let x: *(int | void) = x;
};