Next: Poking Structs, Previous: Defining Types, Up: Structuring Data [Contents][Index]
In Nomenclature we mentioned that poke, the program, implements a domain specific programming language called Poke, with a big p. In the examples so far we have already used the Poke language, quite extensively, while interacting with the program using the REPL.
For example, in:
(poke) 10 + 2 12
We are giving poke a Poke expression 10 + 2
to be
evaluated. Once the expression is evaluated, the REPL prints the
resulting value for us.
Similarly, when we define a variable or a type with defvar
and
deftype
respectively, we are providing poke definitions to be
evaluated. When we assign a value to a variable we are actually
providing a Poke statement to be executed.
So the REPL accepts poke commands, some of which happen to be
Poke expressions, definitions or statements. But we also have used
dot-commands like .file
or .info
, that are not part of
the Poke programming language.
Every time we insert a line in the REPL and hit enter, poke recognizes the nature of the line, and then does the right thing. If the line is recognized as a Poke expression, for example, the Poke compiler is used to compile the statement into a routine, that is executed by the Poke Virtual Machine. The resulting value is then printed for the benefit of the user.
Poke programs are basically a collection of definitions and statements, which most often are stored in files. By convention, we use the .pk file extension when naming files containing Poke programs.
Remember how we defined the foreground and background pixels for
p.sbm
in the REPL?
(poke) defvar bga = [255UB, 255UB, 255UB] (poke) defvar fga = [255UB, 99UB, 71UB]
Where bga
is a white pixel and fga
is a tomato colored
pixel. We could write these definitions in a file colors.pk
like this:
defvar white = [255UB, 255UB, 255UB]; defvar tomato = [255UB, 99UB, 71UB];
Note that variable definitions in Poke are finished with a semicolon
(;
) character, whereas we didn’t need to specify them when we
issued the definitions in the REPL. This is because poke adds the
trailing semicolon for you when it detects a Poke construction
requiring it is introduced in the REPL.
Another difference is that Poke constructions can span for multiple lines, like in most programming languages. For example, we could have the following variable definition in a file:
defvar matrix = [[10, 20, 30], [40, 50, 60], [70, 80, 90]];
Once we have written our colors.pk file, how can we make poke
aware of it? A possibility is to use the load
construction:
(poke) load colors
Assuming a file named colors.pk exists in the current working directory, poke will load it and evaluate its contents. After this, we can use the colors:
(poke) tomato [0xffUB,0x63UB,0x47UB]
Before, we would need to define these colors every time we would like to poke SBM files or, in fact, any RGB24 data. Now we just have to load our colors.pk and use the variables defined there.
If you try to load a file whose name contains a dash character
(-
) you will get an error message:
(poke) load my-colors <stdin>:1:8: error: syntax error, unexpected '-', expecting ';' load my-colors; ^
This is because the argument to load
is interpreted as a Poke
identifier, where -
is not allowed. To alleviate this problem,
you can also specify a string to load
, like in:
(poke) load "my-colors.pk"
If you use this form of load
, however, you have to specify the
complete name of the file, including the .pk file extension.
Since loading files is such a common operation, poke provides a
dot-command .load
that does auto-completion:
(poke) .load my-colors.pk
Which is equivalent to load "my-colors.pk"
.
Since load
is part of the Poke language, it can also be used in
Poke programs stored in files. We will explore this later.
In the last section we defined a couple of RGB colors white
and
tomato
in a file called colors.pk. If we keep adding
colors to the file, we may end with a nice collection of colors that
we can use by just loading the file.
Since there are many ways to understand the notion of “color”, and also many ways to implement these many notions, it would be better to be more precise and call our file rgb24.pk, since the notion of color we are using is of that RGB24. While doing so, let’s also rename the variables to reflect the fact they denote not just any kind of colors, but RGB24 colors:
defvar rgb24_white = [255UB, 255UB, 255UB]; defvar rgb24_tomato = [255UB, 99UB, 71UB];
At this point, we can also add the definitions of a couple of types to our rgb24.pk:
deftype RGB_Color_Beam = byte; deftype RGB24_Color = RGB_Color_Beam[3]; defvar rgb24_white = [255UB, 255UB, 255UB]; defvar rgb24_tomato = [255UB, 99UB, 71UB];
Any time we want to manipulate RGB24 colors we can just load the file rgb24.pk and use these types and variables.
In poke parlance we call files like the above, that contain definitions of conceptually related entities, pickles. Pickles can be very simple, like the rgb24.pk sketched above, or fairly complicated like dwarf.pk.
It is common for pickles to load
other pickles. For example,
if we were to write a SBM pickle, we would load the RGB24 pikle from
it:
load rgb24; [… SBM definitions …]
This way, when we load sbm
from the repl, the dependencies
get loaded as well.
GNU poke includes several already written pickles for commonly used
file formats, and other domains. The load
construction knows
where these pickles are installed, so in order to load the pickle to
manipulate ELF files, for example, all you have to do is to:
(poke) load elf
When poke starts it loads the file .pokerc located in our home directory, if it exists. This initialization file contains poke commands, one per line.
If we wanted to get some Poke file loaded at startup, we could do it
by adding a load command to our .pokerc
. For example:
# My poke configuration - jemarch […] .load ~/.poke.d/mydefs.pk
Next: Poking Structs, Previous: Defining Types, Up: Structuring Data [Contents][Index]