1 /// Copyright: Copyright (c) 2017-2020 Andrey Penechko.
2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
3 /// Authors: Andrey Penechko.
4 module tests.ctfe;
5 
6 import tester;
7 
8 Test[] ctfeTests() { return collectTests!(tests.ctfe)(); }
9 
10 
11 @TestInfo(&tester1)
12 immutable ctfe1 = q{--- ctfe1
13 	// Simplest case
14 	i32 func() { return 42; }
15 	enum i32 val = func(); // CTFE is performed at IR gen of `run`, `func` already has IR
16 	i32 run() {
17 		return val; // returns 42
18 	}
19 };
20 void tester1(ref TestContext ctx) {
21 	assert(ctx.getFunctionPtr!(int)("run")() == 42);
22 }
23 
24 
25 @TestInfo(&tester2)
26 immutable ctfe2 = q{--- ctfe2
27 	// Parameter and vreg
28 	i32 func(i32 param) { return param; }
29 	enum i32 val = func(42); // CTFE
30 	i32 run() {
31 		return val; // returns 42
32 	}
33 };
34 void tester2(ref TestContext ctx) {
35 	assert(ctx.getFunctionPtr!(int)("run")() == 42);
36 }
37 
38 
39 @TestInfo(&tester3)
40 immutable ctfe3 = q{--- ctfe3
41 	// add
42 	i32 func(i32 param) { return param + param; }
43 	enum i32 val = func(42); // CTFE
44 	i32 run() {
45 		return val; // returns 84
46 	}
47 };
48 void tester3(ref TestContext ctx) {
49 	assert(ctx.getFunctionPtr!(int)("run")() == 84);
50 }
51 
52 
53 @TestInfo(&tester4)
54 immutable ctfe4 = q{--- ctfe4
55 	// control flow
56 	i32 sign(i32 number) {
57 		i32 result;
58 		if (number < 0) result = -1;
59 		else if (number > 0) result = 1;
60 		else result = 0;
61 		return result;
62 	}
63 	enum i32 val0 = sign(-1); // CTFE
64 	enum i32 val1 = sign( 0); // CTFE
65 	enum i32 val2 = sign( 1); // CTFE
66 	i32 get_val0() { return val0; } // -1
67 	i32 get_val1() { return val1; } //  0
68 	i32 get_val2() { return val2; } //  1
69 };
70 void tester4(ref TestContext ctx) {
71 	assert(ctx.getFunctionPtr!(int)("get_val0")() == -1);
72 	assert(ctx.getFunctionPtr!(int)("get_val1")() ==  0);
73 	assert(ctx.getFunctionPtr!(int)("get_val2")() ==  1);
74 }
75 
76 
77 @TestInfo(&tester5)
78 immutable ctfe5 = q{--- ctfe5
79 	// call
80 	i32 fib(i32 number) {
81 		if (number < 1) return 0;
82 		if (number < 3) return 1;
83 		return fib(number-1) + fib(number-2);
84 	}
85 	// loop
86 	i32 fib2(i32 number) {
87 		i32 lo = 0;
88 		i32 hi = 1;
89 		for (i32 i = 0; i < number; ++i) {
90 			hi = hi + lo;
91 			lo = hi - lo;
92 		}
93 		return lo;
94 	}
95 
96 	i32 get() {
97 		enum i32 val = fib(6); // CTFE
98 		return val; // 8
99 	}
100 
101 	i32 get2() {
102 		enum i32 val = fib2(30); // CTFE
103 		return val; // 8
104 	}
105 };
106 void tester5(ref TestContext ctx) {
107 	assert(ctx.getFunctionPtr!(int)("get")() == 8);
108 	assert(ctx.getFunctionPtr!(int)("get2")() == 832040);
109 }
110 
111 @TestInfo(&tester6)
112 immutable ctfe6 = q{--- ctfe6
113 	i64 fib(i64 number) {
114 		i64 lo = 0;
115 		i64 hi = 1;
116 		for (i64 i = 0; i < number; ++i) {
117 			hi = hi + lo;
118 			lo = hi - lo;
119 		}
120 		return lo;
121 	}
122 	enum i64 val = fib(62); // CTFE
123 	i64 get() { return val; }
124 };
125 void tester6(ref TestContext ctx) {
126 	assert(ctx.getFunctionPtr!(long)("get")() == 4052739537881UL);
127 }