poke-devel
[Top][All Lists]
Advanced

[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!



reply via email to

[Prev in Thread] Current Thread [Next in Thread]