main.zig 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. const std = @import("std") ;
  2. const expect = std.testing.expect;
  3. // By specifying explicitly.
  4. const constant: i32 = 5 ;
  5. var variable : u32 = 5000 ;
  6. // From right value type.
  7. const inferred_constant = @as(i32, 5) ;
  8. var inferred_variable = @as(i32, 5000) ;
  9. const a1 = [5]u8{'h', 'e', 'l', 'l', 'o'} ;
  10. const a2 = [5]u8{'w', 'o', 'r', 'l', 'd'} ;
  11. const a2_length = a2.len ;
  12. pub fn main() void {
  13. std.debug.print("Hello, {s}!\n", .{"World"});
  14. }
  15. test "always succeeds" {
  16. std.debug.print("value\n", .{});
  17. try expect(true);
  18. }
  19. test "if statement" {
  20. const a = true ;
  21. var x: u16 = 0 ;
  22. if (a) {
  23. x += 1 ;
  24. } else {
  25. x += 2 ;
  26. }
  27. try expect(x == 1) ;
  28. }
  29. test "if statement expression" {
  30. const a = true ;
  31. var x: u16 = 0 ;
  32. x += if (a) 1 else 2 ;
  33. try expect(x == 1) ;
  34. }
  35. test "while" {
  36. var i: u8 = 2 ;
  37. while (i < 100) {
  38. i *= 2 ;
  39. }
  40. try expect(i == 128) ;
  41. }
  42. test "while with continue expression" {
  43. var sum: u8 = 0 ;
  44. var i: u8 = 1 ;
  45. while (i <= 10) : (i +=1) {
  46. sum += i ;
  47. }
  48. try expect(sum == 55) ;
  49. }
  50. test "while with continue" {
  51. var sum: u8 = 0 ;
  52. var i: u8 = 0 ;
  53. while (i <= 3) : (i += 1) {
  54. if (i == 2) continue ;
  55. sum += i ;
  56. }
  57. try expect(sum == 4) ;
  58. }
  59. test "while with break" {
  60. var sum: u8 = 0 ;
  61. var i: u8 = 0 ;
  62. while (i <= 3) : (i += 1) {
  63. if (i == 2) break ;
  64. sum += i ;
  65. }
  66. try expect(sum == 1) ;
  67. }
  68. test "for" {
  69. const string = [_]u8{'a', 'b', 'c'} ;
  70. for (string, 0..) |character, index| {
  71. _ = character ;
  72. _ = index ;
  73. }
  74. for (string) |character| {
  75. _ = character ;
  76. }
  77. for (string, 0..) |_, index| {
  78. _ = index ;
  79. }
  80. for (string) |_| {
  81. }
  82. }
  83. fn addFive(x : u32) u32 {
  84. return x + 5 ;
  85. }
  86. test "function" {
  87. const y = addFive(0) ;
  88. try expect(@TypeOf(y) == u32) ;
  89. std.debug.print("{d}\n", .{y});
  90. try expect(y == 5) ;
  91. }
  92. fn fibo(n: u16) u16 {
  93. if (n == 0 or n == 1) return n ;
  94. return fibo(n-1) + fibo(n - 2) ;
  95. }
  96. test "function recursion" {
  97. const x = fibo(10) ;
  98. try expect(x == 55) ;
  99. }
  100. test "defer" {
  101. var x: f32 = 5 ;
  102. {
  103. defer x += 2 ;
  104. try expect(x == 5) ;
  105. }
  106. try expect(x == 7) ;
  107. }
  108. test "multi defer" {
  109. var x: f32 = 5 ;
  110. {
  111. defer x += 2 ;
  112. defer x /= 2 ;
  113. }
  114. try expect(x == 4.5) ;
  115. }
  116. const FileOpenError = error{
  117. AccessDenied,
  118. OutOfMemory,
  119. FileNotFond,
  120. };
  121. const AllocationError = error{OutOfMemory} ;
  122. test "coerce error from a subset to a superset" {
  123. const err: FileOpenError = AllocationError.OutOfMemory;
  124. try expect(err == FileOpenError.OutOfMemory) ;
  125. }
  126. test "error union" {
  127. const maybe_error: AllocationError!u16 = 10 ;
  128. const no_error = maybe_error catch 0 ;
  129. try expect(@TypeOf(no_error) == u16) ;
  130. try expect(no_error == 10) ;
  131. }
  132. fn failingFunction() error{Oops}!void {
  133. return error.Oops ;
  134. }
  135. test "returning an error" {
  136. failingFunction() catch |err| {
  137. try expect(err == error.Oops) ;
  138. return;
  139. } ;
  140. }
  141. fn failFn() error{Oops}!i32 {
  142. try failingFunction() ;
  143. return 12 ;
  144. }
  145. test "try" {
  146. const v = failFn() catch |err| {
  147. try expect(err == error.Oops);
  148. return;
  149. };
  150. try expect(v == 12) ;
  151. }
  152. var problems: u32 = 98 ;
  153. fn failFnCounter() error{Oops}!void {
  154. errdefer problems += 1 ;
  155. try failingFunction();
  156. }
  157. test "errdefer" {
  158. failFnCounter() catch |err| {
  159. try expect(err == error.Oops) ;
  160. try expect(problems == 99);
  161. return;
  162. };
  163. }
  164. fn createFile() !void {
  165. return error.AccessDenied ;
  166. }
  167. test "inferred error set" {
  168. const x: error{AccessDenied}!void = createFile() ;
  169. _ = x catch {} ;
  170. }
  171. const a_err = error{NotDir, PathNotFound} ;
  172. const b_err = error{ OutOfMemory, PathNotFound} ;
  173. const c_err = a_err || b_err ;
  174. test "switch statement" {
  175. var x: i8 = 10 ;
  176. switch (x) {
  177. -1...1 => {
  178. x = -x ;
  179. },
  180. 10, 100 => {
  181. // Check out special
  182. // requirements when dividing signed
  183. // integers.
  184. x = @divExact(x, 10) ;
  185. },
  186. else => {},
  187. }
  188. try expect(x == 1) ;
  189. }
  190. test "switch expression" {
  191. var x: i8 = 10 ;
  192. x = switch(x) {
  193. -1...1 => -x,
  194. 10, 100 => @divExact(x, 10),
  195. else => x,
  196. };
  197. try expect(x == 1) ;
  198. }
  199. test "out of bounds" {
  200. //const a = [3]u8{ 1, 2, 3 } ;
  201. //var index: u8 = 5 ;
  202. //index = index ;
  203. // The code below will call ""index out of bounds" error.
  204. // const b = a[index] ;
  205. // _ = b ;
  206. }
  207. test "out of bounds, no safety" {
  208. @setRuntimeSafety(false);
  209. const a = [3]u8{ 1, 2, 3 } ;
  210. var index: u8 = 5 ;
  211. index = index ;
  212. // The code below will call ""index out of bounds" error.
  213. const b = a[index] ;
  214. _ = b ;
  215. }
  216. test "unreachable" {
  217. //const x: i32 = 1 ;
  218. // The code below will cause the "reached unreachable code".
  219. //const y: u32 = if (x == 2) 5 else unreachable ;
  220. //_ = y ;
  221. }
  222. fn asciiToUpper(x: u8) u8 {
  223. return switch (x) {
  224. 'a'...'z' => x + 'A' - 'a',
  225. 'A'...'Z' => x,
  226. else => unreachable,
  227. } ;
  228. }
  229. test "unreachable switch" {
  230. try expect(asciiToUpper('a') == 'A') ;
  231. try expect(asciiToUpper('A') == 'A') ;
  232. }
  233. fn increment(num: *u8) void {
  234. num.* += 1 ;
  235. }
  236. test "pointers" {
  237. var x: u8 = 1 ;
  238. increment(&x);
  239. try expect(x == 2) ;
  240. }
  241. test "naughty pointer" {
  242. const x: u8 = 1 ;
  243. const y: *u8 = @ptrFromInt(x);
  244. _ = y ;
  245. }
  246. test "constant pointers" {
  247. //const x: u8 = 1 ;
  248. // does not work for now.
  249. //var y = &x ;
  250. //y.* += 1 ;
  251. }
  252. test "usize" {
  253. try expect(@sizeOf(usize) == @sizeOf(*u8)) ;
  254. try expect(@sizeOf(isize) == @sizeOf(*u8)) ;
  255. }
  256. fn total(values: []const u8) usize {
  257. var sum: usize = 0 ;
  258. for (values) |v|
  259. sum += v ;
  260. return sum ;
  261. }
  262. test "slices" {
  263. const array = [_]u8{ 1, 2, 3, 4, 5 } ;
  264. const slice = array[0..3] ;
  265. try expect(total(slice) == 6) ;
  266. }
  267. test "slices 2" {
  268. const array = [_]u8{ 1, 2, 3, 4, 5 } ;
  269. const slice = array[0..3] ;
  270. try expect(@TypeOf(slice) == *const [3]u8) ;
  271. }
  272. test "slices 3" {
  273. var array = [_]u8{ 1, 2, 3, 4, 5 } ;
  274. const slice = array[0..] ;
  275. _ = slice ;
  276. }
  277. const Direction = enum{
  278. north,
  279. south,
  280. east,
  281. west,
  282. } ;
  283. const Value = enum(u2) {zero, one, two} ;
  284. test "enum ordinal value" {
  285. try expect(@intFromEnum(Value.zero) == 0) ;
  286. try expect(@intFromEnum(Value.one) == 1) ;
  287. try expect(@intFromEnum(Value.two) == 2) ;
  288. }
  289. const Value2 = enum(u32) {
  290. hundred = 100,
  291. thousand = 1000,
  292. million = 1000000,
  293. next,
  294. } ;
  295. test "set enum ordinal value" {
  296. try expect(@intFromEnum(Value2.hundred) == 100) ;
  297. try expect(@intFromEnum(Value2.thousand) == 1000) ;
  298. try expect(@intFromEnum(Value2.million) == 1000000) ;
  299. }
  300. const Suit = enum {
  301. clubs,
  302. spades,
  303. diamonds,
  304. hearts,
  305. pub fn isClubs(self: Suit) bool {
  306. return self == Suit.clubs ;
  307. }
  308. } ;
  309. test "enum method" {
  310. try expect(
  311. Suit.spades.isClubs() ==
  312. Suit.isClubs(.spades),
  313. ) ;
  314. }
  315. const Mode = enum {
  316. var count: u32 = 0 ;
  317. on,
  318. off,
  319. };
  320. test "hmm" {
  321. Mode.count += 1 ;
  322. try expect(Mode.count == 1) ;
  323. }
  324. // Structs.
  325. const Vec3 = struct{
  326. x : f32,
  327. y : f32,
  328. z : f32,
  329. } ;
  330. test "struct usage" {
  331. const my_vector = Vec3{
  332. .x = 0,
  333. .y = 100,
  334. .z = 50,
  335. } ;
  336. _ = my_vector ;
  337. }
  338. test "missing struct field" {
  339. //const my_vector = Vec3{
  340. //.x = 0,
  341. //.z = 50,
  342. //} ;
  343. //_ = my_vector ;
  344. }
  345. const Vec2 = struct{
  346. x: i32 = 0,
  347. y: i32 = 0,
  348. } ;
  349. test "struct defaults" {
  350. const my_vector = Vec2{
  351. .x = 25,
  352. } ;
  353. try expect(my_vector.y == 0) ;
  354. }
  355. const Stuff = struct{
  356. x: i32,
  357. y: i32,
  358. fn swap(self: *Stuff) void {
  359. const tmp = self.x;
  360. self.x = self.y ;
  361. self.y = tmp ;
  362. }
  363. } ;
  364. test "automatic dereference" {
  365. var thing = Stuff{
  366. .x = 10,
  367. .y = 20,
  368. } ;
  369. thing.swap();
  370. try expect(
  371. thing.x == 20 and
  372. thing.y == 10,
  373. ) ;
  374. }
  375. const Result = union{
  376. int: i64,
  377. float: f64,
  378. bool: bool,
  379. } ;
  380. test "simple union" {
  381. const result = Result{
  382. .int = 1234,
  383. } ;
  384. // error
  385. //result.float = 12.34 ;
  386. _ = result ;
  387. }
  388. const Tag = enum{a, b, c} ;
  389. const Tagged = union(Tag){
  390. a: u8,
  391. b: f32,
  392. c: bool,
  393. } ;
  394. test "switch on tagged union" {
  395. var value = Tagged{ .b = 1.5} ;
  396. switch (value) {
  397. .a => |*byte| byte.* += 1,
  398. .b => |*float| float.* *= 2,
  399. .c => |*b| b.* = !(b.*),
  400. }
  401. try expect(value.b == 3) ;
  402. }
  403. test "labeled blocks" {
  404. const count = blk: {
  405. var sum: u32 = 0 ;
  406. var i: u32 = 0 ;
  407. while (i < 10) : ({
  408. i += 1;
  409. }) {
  410. sum += i ;
  411. }
  412. break :blk sum ;
  413. } ;
  414. try expect(count == 45) ;
  415. try expect(@TypeOf(count) == u32) ;
  416. }
  417. test "nested continue" {
  418. var count: usize = 0;
  419. outer: for ([_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }) |_| {
  420. for ([_]i32{ 1, 2, 3, 4, 5 }) |_| {
  421. count += 1;
  422. continue :outer;
  423. }
  424. }
  425. try expect(count == 8);
  426. }
  427. fn rangeHasNumber(begin: usize, end: usize, number: usize) bool {
  428. var i = begin;
  429. return while (i < end) : (i += 1) {
  430. if (i == number) {
  431. break true;
  432. }
  433. } else false;
  434. }
  435. test "while loop expression" {
  436. try expect(rangeHasNumber(0, 10, 3));
  437. }
  438. test "if optional payload capture" {
  439. const a: ?i32 = 5;
  440. if (a != null) {
  441. const value = a.?;
  442. _ = value;
  443. }
  444. var b: ?i32 = 5;
  445. if (b) |*value| {
  446. value.* += 1;
  447. }
  448. try expect(b.? == 6);
  449. }
  450. var numbers_left: u32 = 4;
  451. fn eventuallyNullSequence() ?u32 {
  452. if (numbers_left == 0) return null;
  453. numbers_left -= 1;
  454. return numbers_left;
  455. }
  456. test "while null capture" {
  457. var sum: u32 = 0;
  458. while (eventuallyNullSequence()) |value| {
  459. sum += value;
  460. }
  461. try expect(sum == 6); // 3 + 2 + 1
  462. }