mirror of
https://codeberg.org/andyscott/ziglings.git
synced 2024-12-22 14:03:10 -05:00
commit
c7868de511
22 changed files with 46 additions and 47 deletions
|
@ -33,7 +33,7 @@ pub fn main() void {
|
||||||
// have a little preview of Zig 'for' loops instead:
|
// have a little preview of Zig 'for' loops instead:
|
||||||
//
|
//
|
||||||
// for (<item array>) |item| { <do something with item> }
|
// for (<item array>) |item| { <do something with item> }
|
||||||
//
|
//
|
||||||
// Don't worry, we'll cover looping properly in upcoming
|
// Don't worry, we'll cover looping properly in upcoming
|
||||||
// lessons.
|
// lessons.
|
||||||
//
|
//
|
||||||
|
|
|
@ -31,5 +31,5 @@ pub fn main() void {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printPhrase(part1: []u8, part2: []u8, part3: []u8) void {
|
fn printPhrase(part1: []u8, part2: []u8, part3: []u8) void {
|
||||||
std.debug.print("'{s} {s} {s}.' ", .{part1, part2, part3});
|
std.debug.print("'{s} {s} {s}.' ", .{ part1, part2, part3 });
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,6 @@ pub fn main() void {
|
||||||
0b1101000, // binary
|
0b1101000, // binary
|
||||||
0x66, // hex
|
0x66, // hex
|
||||||
};
|
};
|
||||||
|
|
||||||
print("{s} is cool.\n", .{zig});
|
print("{s} is cool.\n", .{zig});
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ pub fn main() void {
|
||||||
// | exponent significand
|
// | exponent significand
|
||||||
// |
|
// |
|
||||||
// sign
|
// sign
|
||||||
//
|
//
|
||||||
// This example is the decimal number 3.140625, which happens to
|
// This example is the decimal number 3.140625, which happens to
|
||||||
// be the closest representation of Pi we can make with an f16
|
// be the closest representation of Pi we can make with an f16
|
||||||
// due to the way IEEE-754 floating points store digits:
|
// due to the way IEEE-754 floating points store digits:
|
||||||
|
@ -86,6 +86,6 @@ pub fn main() void {
|
||||||
//
|
//
|
||||||
// Fun fact: sometimes you'll see the significand labeled as a
|
// Fun fact: sometimes you'll see the significand labeled as a
|
||||||
// "mantissa" but Donald E. Knuth says not to do that.
|
// "mantissa" but Donald E. Knuth says not to do that.
|
||||||
//
|
//
|
||||||
// C compatibility fact: There is also a Zig floating point type
|
// C compatibility fact: There is also a Zig floating point type
|
||||||
// specifically for working with C ABIs called c_longdouble.
|
// specifically for working with C ABIs called c_longdouble.
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
// const arr: [3]u8 = [3]u8{5, 6, 7};
|
// const arr: [3]u8 = [3]u8{5, 6, 7};
|
||||||
// const s: []const u8 = &arr; // to slice
|
// const s: []const u8 = &arr; // to slice
|
||||||
// const p: [*]const u8 = &arr; // to many-item pointer
|
// const p: [*]const u8 = &arr; // to many-item pointer
|
||||||
//
|
//
|
||||||
// 4. Single-item mutable pointers can coerce to single-item
|
// 4. Single-item mutable pointers can coerce to single-item
|
||||||
// pointers pointing to an array of length 1. (Interesting!)
|
// pointers pointing to an array of length 1. (Interesting!)
|
||||||
//
|
//
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// The Zig compiler provides "builtin" functions. You've already
|
// The Zig compiler provides "builtin" functions. You've already
|
||||||
// gotten used to seeing an @import() at the top of every
|
// gotten used to seeing an @import() at the top of every
|
||||||
// Ziglings exercise.
|
// Ziglings exercise.
|
||||||
//
|
//
|
||||||
// We've also seen @intCast() in "016_for2.zig", "058_quiz7.zig";
|
// We've also seen @intCast() in "016_for2.zig", "058_quiz7.zig";
|
||||||
// and @enumToInt() in "036_enums2.zig".
|
// and @enumToInt() in "036_enums2.zig".
|
||||||
|
@ -51,10 +51,10 @@ pub fn main() void {
|
||||||
// 1111 + 1 = 0000 Yes! (Real answer is 10000)
|
// 1111 + 1 = 0000 Yes! (Real answer is 10000)
|
||||||
// 0000 + 1 = 0001 Yes!
|
// 0000 + 1 = 0001 Yes!
|
||||||
// 0001 + 1 = 0010 Yes!
|
// 0001 + 1 = 0010 Yes!
|
||||||
//
|
//
|
||||||
// Also, check out our fancy formatting! b:0>4 means, "print
|
// Also, check out our fancy formatting! b:0>4 means, "print
|
||||||
// as a binary number, zero-pad right-aligned four digits."
|
// as a binary number, zero-pad right-aligned four digits."
|
||||||
print("{b:0>4} + {b:0>4} = {b:0>4} ({})", .{a, b, my_result, overflowed});
|
print("{b:0>4} + {b:0>4} = {b:0>4} ({})", .{ a, b, my_result, overflowed });
|
||||||
|
|
||||||
print(". Furthermore, ", .{});
|
print(". Furthermore, ", .{});
|
||||||
|
|
||||||
|
@ -70,5 +70,5 @@ pub fn main() void {
|
||||||
// this builtin to reverse the bits of a u8 integer.
|
// this builtin to reverse the bits of a u8 integer.
|
||||||
const input: u8 = 0b11110000;
|
const input: u8 = 0b11110000;
|
||||||
const tupni: u8 = @bitReverse(input);
|
const tupni: u8 = @bitReverse(input);
|
||||||
print("{b:0>8} backwards is {b:0>8}.\n", .{input, tupni});
|
print("{b:0>8} backwards is {b:0>8}.\n", .{ input, tupni });
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// Zig has builtins for mathematical operations such as...
|
// Zig has builtins for mathematical operations such as...
|
||||||
//
|
//
|
||||||
// @sqrt @sin @cos
|
// @sqrt @sin @cos
|
||||||
// @exp @log @floor
|
// @exp @log @floor
|
||||||
//
|
//
|
||||||
// ...and lots of type casting operations such as...
|
// ...and lots of type casting operations such as...
|
||||||
|
@ -20,18 +20,18 @@
|
||||||
// by exploring just THREE of Zig's MANY introspection abilities:
|
// by exploring just THREE of Zig's MANY introspection abilities:
|
||||||
//
|
//
|
||||||
// 1. @This() type
|
// 1. @This() type
|
||||||
//
|
//
|
||||||
// Returns the innermost struct, enum, or union that a function
|
// Returns the innermost struct, enum, or union that a function
|
||||||
// call is inside.
|
// call is inside.
|
||||||
//
|
//
|
||||||
// 2. @typeInfo(comptime T: type) @import("std").builtin.TypeInfo
|
// 2. @typeInfo(comptime T: type) @import("std").builtin.TypeInfo
|
||||||
//
|
//
|
||||||
// Returns information about any type in a TypeInfo union which
|
// Returns information about any type in a TypeInfo union which
|
||||||
// will contain different information depending on which type
|
// will contain different information depending on which type
|
||||||
// you're examining.
|
// you're examining.
|
||||||
//
|
//
|
||||||
// 3. @TypeOf(...) type
|
// 3. @TypeOf(...) type
|
||||||
//
|
//
|
||||||
// Returns the type common to all input parameters (each of which
|
// Returns the type common to all input parameters (each of which
|
||||||
// may be any expression). The type is resolved using the same
|
// may be any expression). The type is resolved using the same
|
||||||
// "peer type resolution" process the compiler itself uses when
|
// "peer type resolution" process the compiler itself uses when
|
||||||
|
@ -46,14 +46,14 @@ const Narcissus = struct {
|
||||||
me: *Narcissus = undefined,
|
me: *Narcissus = undefined,
|
||||||
myself: *Narcissus = undefined,
|
myself: *Narcissus = undefined,
|
||||||
echo: void = undefined,
|
echo: void = undefined,
|
||||||
|
|
||||||
fn fetchTheMostBeautifulType() type {
|
fn fetchTheMostBeautifulType() type {
|
||||||
return @This();
|
return @This();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() void {
|
pub fn main() void {
|
||||||
var narcissus: Narcissus = Narcissus {};
|
var narcissus: Narcissus = Narcissus{};
|
||||||
|
|
||||||
// Oops! We cannot leave the 'me' and 'myself' fields
|
// Oops! We cannot leave the 'me' and 'myself' fields
|
||||||
// undefined. Please set them here:
|
// undefined. Please set them here:
|
||||||
|
@ -70,7 +70,7 @@ pub fn main() void {
|
||||||
// fix this call:
|
// fix this call:
|
||||||
const T2 = narcissus.fetchTheMostBeautifulType();
|
const T2 = narcissus.fetchTheMostBeautifulType();
|
||||||
|
|
||||||
print("A {} loves all {}es. ", .{T1, T2});
|
print("A {} loves all {}es. ", .{ T1, T2 });
|
||||||
|
|
||||||
// His final words as he was looking in
|
// His final words as he was looking in
|
||||||
// those waters he habitually watched
|
// those waters he habitually watched
|
||||||
|
|
|
@ -27,10 +27,10 @@
|
||||||
//
|
//
|
||||||
// Zig takes these concepts further by making these optimizations
|
// Zig takes these concepts further by making these optimizations
|
||||||
// an integral part of the language itself!
|
// an integral part of the language itself!
|
||||||
//
|
//
|
||||||
const print = @import("std").debug.print;
|
const print = @import("std").debug.print;
|
||||||
|
|
||||||
pub fn main() void {
|
pub fn main() void {
|
||||||
// ALL numeric literals in Zig are of type comptime_int or
|
// ALL numeric literals in Zig are of type comptime_int or
|
||||||
// comptime_float. They are of arbitrary size (as big or
|
// comptime_float. They are of arbitrary size (as big or
|
||||||
// little as you need).
|
// little as you need).
|
||||||
|
@ -46,7 +46,7 @@ pub fn main() void {
|
||||||
const const_int = 12345;
|
const const_int = 12345;
|
||||||
const const_float = 987.654;
|
const const_float = 987.654;
|
||||||
|
|
||||||
print("Immutable: {}, {d:.3}; ", .{const_int, const_float});
|
print("Immutable: {}, {d:.3}; ", .{ const_int, const_float });
|
||||||
|
|
||||||
// But something changes when we assign the exact same values
|
// But something changes when we assign the exact same values
|
||||||
// to identifiers mutably with "var".
|
// to identifiers mutably with "var".
|
||||||
|
@ -69,7 +69,7 @@ pub fn main() void {
|
||||||
var_int = 54321;
|
var_int = 54321;
|
||||||
var_float = 456.789;
|
var_float = 456.789;
|
||||||
|
|
||||||
print("Mutable: {}, {d:.3}; ", .{var_int, var_float});
|
print("Mutable: {}, {d:.3}; ", .{ var_int, var_float });
|
||||||
|
|
||||||
// Bonus: Now that we're familiar with Zig's builtins, we can
|
// Bonus: Now that we're familiar with Zig's builtins, we can
|
||||||
// also inspect the types to see what they are, no guessing
|
// also inspect the types to see what they are, no guessing
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// --o-- comptime * | .. .
|
// --o-- comptime * | .. .
|
||||||
// * | * . . . . --*-- . * .
|
// * | * . . . . --*-- . * .
|
||||||
// . . . . . . . . . | . . .
|
// . . . . . . . . . | . . .
|
||||||
//
|
//
|
||||||
// When placed before a variable declaration, 'comptime'
|
// When placed before a variable declaration, 'comptime'
|
||||||
// guarantees that every usage of that variable will be performed
|
// guarantees that every usage of that variable will be performed
|
||||||
// at compile time.
|
// at compile time.
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
//
|
//
|
||||||
const print = @import("std").debug.print;
|
const print = @import("std").debug.print;
|
||||||
|
|
||||||
pub fn main() void {
|
pub fn main() void {
|
||||||
//
|
//
|
||||||
// In this contrived example, we've decided to allocate some
|
// In this contrived example, we've decided to allocate some
|
||||||
// arrays using a variable count! But something's missing...
|
// arrays using a variable count! But something's missing...
|
||||||
|
@ -49,7 +49,7 @@ pub fn main() void {
|
||||||
count += 1;
|
count += 1;
|
||||||
var a4: [count]u8 = .{'D'} ** count;
|
var a4: [count]u8 = .{'D'} ** count;
|
||||||
|
|
||||||
print("{s} {s} {s} {s}\n", .{a1, a2, a3, a4});
|
print("{s} {s} {s} {s}\n", .{ a1, a2, a3, a4 });
|
||||||
|
|
||||||
// Builtin BONUS!
|
// Builtin BONUS!
|
||||||
//
|
//
|
||||||
|
|
|
@ -61,10 +61,10 @@ const Schooner = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() void {
|
pub fn main() void {
|
||||||
var whale = Schooner {.name = "Whale"};
|
var whale = Schooner{ .name = "Whale" };
|
||||||
var shark = Schooner {.name = "Shark"};
|
var shark = Schooner{ .name = "Shark" };
|
||||||
var minnow = Schooner {.name = "Minnow"};
|
var minnow = Schooner{ .name = "Minnow" };
|
||||||
|
|
||||||
// Hey, we can't just pass this runtime variable as an
|
// Hey, we can't just pass this runtime variable as an
|
||||||
// argument to the scaleMe() method. What would let us do
|
// argument to the scaleMe() method. What would let us do
|
||||||
|
|
|
@ -13,14 +13,14 @@
|
||||||
//
|
//
|
||||||
const print = @import("std").debug.print;
|
const print = @import("std").debug.print;
|
||||||
|
|
||||||
pub fn main() void {
|
pub fn main() void {
|
||||||
// Here we declare arrays of three different types and sizes
|
// Here we declare arrays of three different types and sizes
|
||||||
// at compile time from a function call. Neat!
|
// at compile time from a function call. Neat!
|
||||||
const s1 = makeSequence(u8, 3); // creates a [3]u8
|
const s1 = makeSequence(u8, 3); // creates a [3]u8
|
||||||
const s2 = makeSequence(u32, 5); // creates a [5]u32
|
const s2 = makeSequence(u32, 5); // creates a [5]u32
|
||||||
const s3 = makeSequence(i64, 7); // creates a [7]i64
|
const s3 = makeSequence(i64, 7); // creates a [7]i64
|
||||||
|
|
||||||
print("s1={any}, s2={any}, s3={any}\n", .{s1, s2, s3});
|
print("s1={any}, s2={any}, s3={any}\n", .{ s1, s2, s3 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is pretty wild because it executes at runtime
|
// This function is pretty wild because it executes at runtime
|
||||||
|
@ -49,6 +49,6 @@ fn makeSequence(comptime T: type, ??? size: usize) [???]T {
|
||||||
while (i < size) : (i += 1) {
|
while (i < size) : (i += 1) {
|
||||||
sequence[i] = @intCast(T, i) + 1;
|
sequence[i] = @intCast(T, i) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sequence;
|
return sequence;
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,6 @@ fn isADuck(possible_duck: anytype) bool {
|
||||||
// error, not a runtime panic or crash!
|
// error, not a runtime panic or crash!
|
||||||
possible_duck.quack();
|
possible_duck.quack();
|
||||||
}
|
}
|
||||||
|
|
||||||
return is_duck;
|
return is_duck;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ pub fn main() void {
|
||||||
'*' => value *= digit,
|
'*' => value *= digit,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
// ...But it's quite a bit more exciting than it first appears.
|
// ...But it's quite a bit more exciting than it first appears.
|
||||||
// The 'inline while' no longer exists at runtime and neither
|
// The 'inline while' no longer exists at runtime and neither
|
||||||
// does anything else not touched directly by runtime
|
// does anything else not touched directly by runtime
|
||||||
// code. The 'instructions' string, for example, does not
|
// code. The 'instructions' string, for example, does not
|
||||||
|
@ -61,6 +61,6 @@ pub fn main() void {
|
||||||
// code at compile time. Guess we're compiler writers
|
// code at compile time. Guess we're compiler writers
|
||||||
// now. See? The wizard hat was justified after all.
|
// now. See? The wizard hat was justified after all.
|
||||||
}
|
}
|
||||||
|
|
||||||
print("{}\n", .{value});
|
print("{}\n", .{value});
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ fn getLlama(i: usize) u32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fun fact: this assert() function is identical to
|
// Fun fact: this assert() function is identical to
|
||||||
// std.debug.assert() from the Zig Standard Library.
|
// std.debug.assert() from the Zig Standard Library.
|
||||||
fn assert(ok: bool) void {
|
fn assert(ok: bool) void {
|
||||||
if (!ok) unreachable;
|
if (!ok) unreachable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,12 +54,12 @@ fn makePath(from: *Place, to: *Place, dist: u8) Path {
|
||||||
|
|
||||||
// Using our new function, these path definitions take up considerably less
|
// Using our new function, these path definitions take up considerably less
|
||||||
// space in our program now!
|
// space in our program now!
|
||||||
const a_paths = [_]Path{ makePath(&a, &b, 2) };
|
const a_paths = [_]Path{makePath(&a, &b, 2)};
|
||||||
const b_paths = [_]Path{ makePath(&b, &a, 2), makePath(&b, &d, 1) };
|
const b_paths = [_]Path{ makePath(&b, &a, 2), makePath(&b, &d, 1) };
|
||||||
const c_paths = [_]Path{ makePath(&c, &d, 3), makePath(&c, &e, 2) };
|
const c_paths = [_]Path{ makePath(&c, &d, 3), makePath(&c, &e, 2) };
|
||||||
const d_paths = [_]Path{ makePath(&d, &b, 1), makePath(&d, &c, 3), makePath(&d, &f, 7) };
|
const d_paths = [_]Path{ makePath(&d, &b, 1), makePath(&d, &c, 3), makePath(&d, &f, 7) };
|
||||||
const e_paths = [_]Path{ makePath(&e, &c, 2), makePath(&e, &f, 1) };
|
const e_paths = [_]Path{ makePath(&e, &c, 2), makePath(&e, &f, 1) };
|
||||||
const f_paths = [_]Path{ makePath(&f, &d, 7) };
|
const f_paths = [_]Path{makePath(&f, &d, 7)};
|
||||||
//
|
//
|
||||||
// But is it more readable? That could be argued either way.
|
// But is it more readable? That could be argued either way.
|
||||||
//
|
//
|
||||||
|
@ -69,7 +69,7 @@ const f_paths = [_]Path{ makePath(&f, &d, 7) };
|
||||||
//
|
//
|
||||||
// For example, we could create our own "path language" and
|
// For example, we could create our own "path language" and
|
||||||
// create Paths from that. Something like this, perhaps:
|
// create Paths from that. Something like this, perhaps:
|
||||||
//
|
//
|
||||||
// a -> (b[2])
|
// a -> (b[2])
|
||||||
// b -> (a[2] d[1])
|
// b -> (a[2] d[1])
|
||||||
// c -> (d[3] e[2])
|
// c -> (d[3] e[2])
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
// Versatility! Zig strings are compatible with C strings (which
|
// Versatility! Zig strings are compatible with C strings (which
|
||||||
// are null-terminated) AND can be coerced to a variety of other
|
// are null-terminated) AND can be coerced to a variety of other
|
||||||
// Zig types:
|
// Zig types:
|
||||||
//
|
//
|
||||||
// const a: [5]u8 = "array".*;
|
// const a: [5]u8 = "array".*;
|
||||||
// const b: *const [16]u8 = "pointer to array";
|
// const b: *const [16]u8 = "pointer to array";
|
||||||
// const c: []const u8 = "slice";
|
// const c: []const u8 = "slice";
|
||||||
|
@ -50,7 +50,7 @@ pub fn main() void {
|
||||||
//
|
//
|
||||||
// Luckily, the 'length' field makes it possible to still
|
// Luckily, the 'length' field makes it possible to still
|
||||||
// work with this value.
|
// work with this value.
|
||||||
const foo = WeirdContainer {
|
const foo = WeirdContainer{
|
||||||
.data = "Weird Data!",
|
.data = "Weird Data!",
|
||||||
.length = 11,
|
.length = 11,
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// past the authorities: the @"" identifier quoting syntax.
|
// past the authorities: the @"" identifier quoting syntax.
|
||||||
//
|
//
|
||||||
// @"foo"
|
// @"foo"
|
||||||
//
|
//
|
||||||
// Please help us safely smuggle these fugitive identifiers into
|
// Please help us safely smuggle these fugitive identifiers into
|
||||||
// our program:
|
// our program:
|
||||||
//
|
//
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
// If a .{} thing is what the print function wants, do we need to
|
// If a .{} thing is what the print function wants, do we need to
|
||||||
// break our "tuple" apart and put it in another one? No! It's
|
// break our "tuple" apart and put it in another one? No! It's
|
||||||
// redundant! This will print the same thing:
|
// redundant! This will print the same thing:
|
||||||
//
|
//
|
||||||
// print("{} {}\n", foo);
|
// print("{} {}\n", foo);
|
||||||
//
|
//
|
||||||
// Aha! So now we know that print() takes a "tuple". Things are
|
// Aha! So now we know that print() takes a "tuple". Things are
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
// fn bar() void {
|
// fn bar() void {
|
||||||
// fooThatSuspends();
|
// fooThatSuspends();
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// 6. The main() function cannot be async!
|
// 6. The main() function cannot be async!
|
||||||
//
|
//
|
||||||
// Given facts 3 and 4, how do we fix this program (broken by facts
|
// Given facts 3 and 4, how do we fix this program (broken by facts
|
||||||
|
|
|
@ -26,4 +26,3 @@ fn foo() void {
|
||||||
suspend {}
|
suspend {}
|
||||||
print("async!\n", .{});
|
print("async!\n", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ pub fn main() void {
|
||||||
var com_title = com_frame;
|
var com_title = com_frame;
|
||||||
var org_title = org_frame;
|
var org_title = org_frame;
|
||||||
|
|
||||||
print(".com: {s}, .org: {s}.\n", .{com_title, org_title});
|
print(".com: {s}, .org: {s}.\n", .{ com_title, org_title });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getPageTitle(url: []const u8) []const u8 {
|
fn getPageTitle(url: []const u8) []const u8 {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
// fn bar() void {
|
// fn bar() void {
|
||||||
// fooThatMightSuspend(true); // Now bar() is async!
|
// fooThatMightSuspend(true); // Now bar() is async!
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// But if you KNOW the function won't suspend, you can make a
|
// But if you KNOW the function won't suspend, you can make a
|
||||||
// promise to the compiler with the 'nosuspend' keyword:
|
// promise to the compiler with the 'nosuspend' keyword:
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in a new issue