[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Documentation] Learn Poke in Y Minutes
From: |
Jose E. Marchesi |
Subject: |
Re: [Documentation] Learn Poke in Y Minutes |
Date: |
Sun, 28 Feb 2021 12:09:08 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) |
Hi Mohammad.
Fun stuff :)
Would you like to maintain this in the poke source distribution doc/
directory?
See some comments below.
> After months, my tutorial is ready (from my PoV). I'd be glad if you review
> it and if you like it, publish it on GNU poke web site.
> I think it covers all the basics of Poke.
> The emphasis of this document is not on "GNU poke", it's on the
> "Poke".
First suggestion then: what about changing the title to "Learn the Poke
lanuage in Y Minutes".
> /* Values
> *
> * Poke programming language has the following types of value:
> *
> * - Integer
> * - String
> * - Offset
> * - Array
> * - Struct
> * - Union
> * - Function (or closure)
> *
> * There are two categories of values in Poke:
> * - Simple values
> * - Integer
> * - String
> * - Offset
> * - Composite values
> * - Array
> * - Struct
> * - Union
> * - Function // FIXME not sure
That would be Closures.
> *
> * The difference lies in the semantics of copy. Consider the following `C`
> * prgoram:
program
> *
> * ```c
> * void f(int);
> * void g(int*);
> *
> * int main() {
> * int i = 10;
> *
> * f(i); // sends a copy of **value of** `i` to `f`
> * g(&i); // sends a copy of **address of** `i` to `g`
> *
> * return 0;
> * }
> * ```
> *
> * Simple values in Poke are like `int` in `C`. The copy makes a new disjoint
> * value. Changing the copied value will not change the original one.
> * And composite values are like `int*` in `C`. The new copy will also points
> * to the same data.
> */
This copy strategy is called "copying by shared value". You may want to
mention that.
>
>
> /* Integer values */
> var decimal = 10;
> var hexadecimal = 0xff;
> var binary = 0b1100;
> var octal = 0o777;
>
> var si8 = 1B; /* byte (8-bit) */
> var si16 = 2H; /* byte (16-bit) */
> var si32 = 3; /* int (32-bit) */
> var si64 = 4L; /* long (64-bit) */
>
> var ui8 = 4UB; /* unsigned byte (8-bit) */
> var ui16 = 5UH; /* unsigned int (16-bit) */
> var ui32 = 6U; /* unsigned int (32-bit) */
> var ui64 = 7UL; /* unsigned long (64-bit) */
>
> var long_decimal = 100_000_000;
> var long_hexadecimal = 0x1122_aabb_ccdd_eeff;
Maybe mention that _ can be used anywhere in an integer literal, in any
numeration base? Otherwise people may think it can only be used to
separate hexadecimal digits.
> /* Offset values
> *
> * Poke does not using integers to specify offsets in binary data, it has a
does not use
> * primitive type for that: offset!
> *
> * Offsets have two parts:
> * - magnitude (an integer)
> * - unit (b (bit), byte (B), etc.)
> *
> * Offsets are also useful for specifying the size.
specifying sizes.
> /* Offset arithmetic
> *
> * OFF +- OFF -> OFF
> * OFF * INT -> OFF
> * OFF / OFF -> INT
> * OFF /^ OFF -> INT
> * OFF % OFF -> OFF
> */
> var off_1_plus_2 = 1#B + 2#B; /* 3#B */
> var off_1_minus_2 = 1#B - 2#B; /* -1#B */
> var off_8_times_10 = 8#B * 10; /* 80#B */
> var off_10_times_8 = 10 * 8#B; /* 80#B */
> var off_7_div_1 = 7#B / 1#B; /* 7 */ /* This is an integer */
> var off_7_cdiv_2 = 7#B /^ 2#B; /* 4 */ /* This is an integer */
> var off_7_mod_3 = 7#B % 3#B; /* 1#B */
poke now also supports:
OFFSET / INT -> OFFSET
OFFSET /^ INT -> OFFSET
Also, I would probably mention that /^ is for ceil integer division?
That's an unusual operator.
> /* Array values */
> var arr1 = [1, 2, 3];
> var arr2 = [[1, 2], [3, 4]];
>
> var elem10 = arr1[0]; /* Arrays are indexed using the usual notation */
> var elem12 = arr1[2]; /* This is the last element of `arr1`: 3 */
>
> /* If you try to access elements beyond the bounds, you'll get an
> * `E_out_of_bounds` exception.
> */
> /* var elem1x = arr1[3]; */
> /* var elem1y = arr1[-1]; */
>
> /* Array trimming: Extraction of a subset of the array */
> var arr3 = arr1[0:2]; /* arr3 == [arr1[0], arr1[1]] */
> var arr4 = arr1[0:0]; /* arr4 is an empty array */
>
> /* Array is a "composite value"; It behaves like pointers on copy.
> * The underlying data is shared between `arr1` and `arr5`.
> */
> var arr5 = arr1;
> arr5[0] = -1; /* arr1 == [-1, 2, 3] */
>
> /* Array trimming *makes* a new array with *copies* of the selected data */
> var arr6 = arr1[:];
> var arr7 = arr2[:];
> arr6[0] = 1; /* arr6 == [1, 2, 3] && arr1 == [-1, 2, 3] */
> arr7[0][0] = -1; /* arr2 == [[-1, 2], [3, 4]] */
>
> /* Making array using the constructor */
> var arr8 = string[3]("Hi"); /* arr8 == ["Hi", "Hi", "Hi"] */
> var arr9 = int<32>[](); /* arr9 == arr4 */
Add this?
var arr10 = int<32>[](16#B); /* arr10 = [0, 0, 0, 0] */
> /* Offset types
> *
> * Offset types are denoted as `offset<BASE_TYPE,UNIT>`, where BASE_TYPE is
> * an integer type and UNIT the specification of an unit.
> *
> * Examples:
> *
> * offset<int<32>,B>
> * offset<uint<12>,Kb>
> */
Add this?
offset<uint<12>,1024>
> /* Integral Structs
> */
> type IntSct = struct uint<16> /* After `struct` comes an integral type */
> {
> /* bit-width of all fields == 16 */
> uint<4> x;
> uint<8> y;
> uint<4> z;
> };
> var intsct = IntSct
> {
> x = 0xa,
> y = 0xbc,
> z = 0xd,
> };
> var x = intsct.x; /* x == 0xaUN (`UN` means unsigned nibble (4-bit)) */
> var y = intsct.y; /* y == 0xbcUB */
> var z = intsct.z; /* z == 0xdUN */
> /* Compiler promotes `intsct` to integer in all contexts where an integer is
> * expected.
> * Integral struct is a struct that can be interpreted as an integer.
> */
> var intsct_as_uint16 = intsct + 0H; /* intsct_as_uint16 == 0xabcdUH */
> var intsct_as_uint16_2 = +intsct; /* intsct_as_uint16_2 == 0xabcdUH */
I would add somewhere that integral structs are stored like integers.
> var N = 10;
> fun Nsquare = int<32>: /* No input parameter */
s/parameter/argument/
What about mentioning the alternate syntax to call functions?
fun foo = (int one, int two, int three) int: { ... }
var res = foo (10, 20, 30) + 1;
var res = (foo :one 10 :two 20 :three 30) + 1;
foo :one 10 :two 20 :three 30;
> /* Casts
> */
> var num_u32 = 1;
> var num_u64 = num_u32 as uint<64>;
What about casting structs?
> /* Loops
> *
> * - while
> * - for-in
> * - try-until
> */
poke now supports FOR:
for (...;...;...)
:)
> /* `print` and `printf`
> */
>
> /* `print` accepts only one argument of type `string` and prints it in the
> * output; it's like the `puts` function of C standard library.
> */
> print ("`print` is like `puts`!\n");
Mention you can use the alternate form:
print "`print` is like `puts`!\n";
Same for printf below.
Also, it may be worth it to mention the signed arithmetic overflow
detection, which may be surprising for C programmers.
As for publishing, just let me know when you want it out and I will add
to the poke homepage, and also publish it in applied pokology :)
Thanks!