This repository has been archived on 2024-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
pacciani/README.md

431 lines
13 KiB
Markdown
Raw Normal View History

2023-04-18 22:55:48 +02:00
# The Pacciani programming language
2014-11-29 00:47:58 +01:00
2023-04-18 22:55:48 +02:00
Pacciani is an esoteric language largely based on the [Monicelli Programming Language](https://github.com/esseks/monicelli), which you should definitely check out!
2014-11-29 00:47:58 +01:00
2023-04-18 22:55:48 +02:00
# What's Pacciani anyway?
2023-04-18 22:55:48 +02:00
Pacciani is an esoterical programming language based on the so-called
"compagni di merende" from the Italian [Monster of Florence](https://en.wikipedia.org/wiki/Monster_of_Florence) trial.
2015-03-08 13:56:06 +01:00
2014-12-14 14:24:48 +01:00
2017-10-12 22:36:56 +02:00
# Compilation
2023-04-18 22:55:48 +02:00
A part of the Pacciani compiler (the lexer) is generated using `ragel`, which
2017-10-12 22:36:56 +02:00
you will need to have installed. If this is not the case, the configuration
2023-04-18 22:55:48 +02:00
script will warn you. Pacciani is developed with version 6.8, but any
2017-10-12 22:36:56 +02:00
sufficiently recent release should do just fine.
2015-03-08 13:56:06 +01:00
2023-01-04 19:24:51 +01:00
You will also need to have LLVM development libraries installed, version 14.
Newer versions might or might not work. CMake looks for version 14 by default, you
2023-04-18 22:55:48 +02:00
can override this by setting the `PACCIANI_LLVM_VERSION` variable:
2015-03-08 13:56:06 +01:00
2023-04-18 22:55:48 +02:00
$ cmake -DPACCIANI_LLVM_VERSION=15
Finally, you will need CMake, version 3.14 or higher.
2015-03-08 13:56:06 +01:00
2017-10-12 22:36:56 +02:00
A typical Makefile-based build workflow would be:
2023-04-18 22:55:48 +02:00
$ cd pacciani/
2017-10-12 22:36:56 +02:00
$ mkdir build/
$ cd build/
2023-04-18 22:55:48 +02:00
$ cmake .. -DCMAKE_INSTALL_PREFIX="$HOME/pcc"
2017-10-12 22:36:56 +02:00
$ make all install
If your tools are installed in non-standard locations
(e.g. Homebrew on Mac OS X), you can alter the search path with:
2014-11-29 00:47:58 +01:00
2017-10-12 22:36:56 +02:00
$ PATH=/path/to/ragel cmake ..
2015-03-08 13:56:06 +01:00
2023-04-18 22:55:48 +02:00
`pcc` statically links LLVM, once compiled it will only depend on the C++
2017-10-12 22:36:56 +02:00
runtime and on `libz`.
2015-03-08 13:56:06 +01:00
2017-10-12 22:36:56 +02:00
## Note for non-POSIX platforms (like Windows)
2015-03-08 13:56:06 +01:00
2017-10-12 22:36:56 +02:00
The external linker is called using fork+exec for simplicity. This means that
this part of the workflow will **not** work on non-POSIX systems, such as
Windows. There, you will need to disable this feature at build time. You will
only get object files (.o) that you will have to link, including a C runtime
library, by yourself.
2023-04-18 22:55:48 +02:00
You can disable the invocation of an external linker and make `pcc` compilable
2017-10-12 22:36:56 +02:00
on Windows during CMake configuration by forcing the appropriate flag to OFF:
2023-04-18 22:55:48 +02:00
$ cmake .. -DPACCIANI_LINKER=OFF
2015-03-08 13:56:06 +01:00
2017-10-12 22:36:56 +02:00
## Tested platforms
2015-03-08 13:56:06 +01:00
2023-04-18 22:55:48 +02:00
The reference OS for building and testing Pacciani is the most recent Ubuntu LTS.
If the build is broken there, then it's a bug. It _should_ also compile on Windows, as
well as many more POSIX systems, including Mac OS X. If you needed a patch to compile
2023-04-18 22:55:48 +02:00
Pacciani on your favourite platform, please send us a pull request!
2015-03-08 13:56:06 +01:00
2017-10-12 22:36:56 +02:00
# Usage
2015-03-08 13:56:06 +01:00
2023-04-18 22:55:48 +02:00
Pacciani build an executable by default on POSIX systems
2017-10-12 22:36:56 +02:00
(such as Linux, Mac OS X). Linking requires an external C compiler, anything
decently modern and standard-conformant should do.
2014-11-29 00:47:58 +01:00
2017-10-12 22:36:56 +02:00
A typical invocation is very similar to what you would expect from your C
compiler:
2014-11-29 00:47:58 +01:00
2023-04-18 22:55:48 +02:00
$ pcc example.pc -o example
2017-10-12 22:36:56 +02:00
$ ./example
2014-11-29 00:47:58 +01:00
2023-04-18 22:55:48 +02:00
Please be aware that the Pacciani compiler depends on the availability of a C
2017-10-12 22:36:56 +02:00
compiler and stdlib, although this dependency should be available on virtually
2023-04-18 22:55:48 +02:00
all platforms where you might think to run `pcc`.
2014-11-29 00:47:58 +01:00
2017-10-12 22:36:56 +02:00
# Language overview
2014-11-29 00:47:58 +01:00
Statements have no terminator, i.e. no semicolon `;` or the like. A single
statement can be split across multiple lines and multiple statements can be
grouped on the same line. However, keywords consisting of multiple space-separed
words **cannot** be split on multiple lines.
2014-11-29 01:04:56 +01:00
A comma might be inserted after each statement, if it fits the sentence ;)
Accented letters can be replaced by the non-accented letter followed by a
backtick `` ` ``, although the use of the correct Italian spelling is strongly
2023-04-18 22:55:48 +02:00
encouraged for maximizing the firenze effect.
2017-10-12 22:36:56 +02:00
## Getting started real quick
2015-03-08 13:56:06 +01:00
For those of you who want to get to the code ASAP, the `examples/`
folder contains a set of programs covering most of the features of the language.
2017-10-12 22:36:56 +02:00
## Main
2014-11-29 00:47:58 +01:00
The entry point of the program (the "main") is identified by the phrase:
2023-04-18 22:55:48 +02:00
Tutti in piedi
2014-11-29 00:47:58 +01:00
2023-04-18 22:55:48 +02:00
which marks the beginning of the _processo_ (i.e. of the program).
2014-11-29 00:47:58 +01:00
A value can be returned by using the the following statement:
2023-04-18 22:55:48 +02:00
seduti <expression>!
2014-11-29 00:47:58 +01:00
optionally, no value might be returned with:
2023-04-18 22:55:48 +02:00
seduti!
2014-11-29 00:47:58 +01:00
2017-10-12 22:36:56 +02:00
## Expressions
2014-11-29 00:47:58 +01:00
The usual operators are given, but spelled as words to best fit in sentences.
They are directly mapped on usual operators as follows:
| Form | Maps to |
|----------------------|---------|
2014-11-29 00:58:27 +01:00
| più | `+` |
| meno | `-` |
| per | `*` |
| diviso | `/` |
| maggiore di | `>` |
| minore di | `<` |
| maggiore uguale a/di | `>=` |
| minore uguale a/di | `<=` |
2014-11-29 00:47:58 +01:00
So `2 più 4` means `2 + 4`. `maggiore o uguale` is admitted as alternate
form of the >= operator, same for `minore o uguale`.
2014-11-29 00:47:58 +01:00
2015-03-08 13:56:06 +01:00
When evaluating binary expressions whose operands have different types,
the type of the result will be the less restrictive between the two.
This ensures that no loss takes place when evaluating an expression.
2017-10-12 22:36:56 +02:00
## Binary shift
2014-11-29 00:47:58 +01:00
Binary shift operators have a slighly different
syntax:
2023-04-18 22:55:48 +02:00
<what> con saluto romano a <direction> per <bits>
2014-11-29 00:47:58 +01:00
which is equivalent to `what >> bits` or `what << bits`, depending on the
direction, which is specified as follows:
| Phrase | Direction |
|----------|-----------|
| destra | right |
| sinistra | left |
as you might have noticed, those are simply the translation in Italian of
"left" and "right". For instance:
2023-04-18 22:55:48 +02:00
testimone con saluto romano a sinistra per 2
2014-11-29 00:47:58 +01:00
2023-04-18 22:55:48 +02:00
maps to `testimone << 2`.
2014-11-29 00:47:58 +01:00
It goes without saying, other expression can be used instead of numbers.
2014-11-29 18:26:06 +01:00
Also, the usual precedence rules apply.
2014-11-29 00:47:58 +01:00
2023-04-18 22:55:48 +02:00
**There is no syntax for braces in Pacciani**.
2014-11-29 00:47:58 +01:00
2017-10-12 22:36:56 +02:00
## Variables
2014-11-29 00:47:58 +01:00
A variable name can contain numbers, upper and lower case character and must
not start with a number (the usual rules, that's it).
A variable might be prefixed with an article to fit a sentence. The
compiler does not check concordance with the following name, but accepts any
article of the Italian language: `il`, `lo`, `la`, `i`, `gli`, `le`, `un`, `una`
2014-11-29 18:26:25 +01:00
`dei`, `delle`, `l'`, `un'`. For instance, `cappello` and `il cappello` refer
to the same variable.
2014-11-29 00:47:58 +01:00
Consequently, the articles above cannot be used as variable names.
2017-10-12 22:36:56 +02:00
## Assignment
2014-11-29 00:47:58 +01:00
A value can be assigned to a variable with the following statement:
2023-04-18 22:55:48 +02:00
<varname> è amico di <expression>
2014-11-29 00:47:58 +01:00
2015-03-08 13:56:06 +01:00
The `<expression>` initializer is casted to the declared type of the variable,
even if the cast will cause some loss. This feature can be (ab)used to introduce
C-style casts too.
2017-10-12 22:36:56 +02:00
## Declaration
2014-11-29 00:47:58 +01:00
Variables can be declared in any scope. There are 5 variable types, which are
directly mapped on C++/C99 types as follows:
2015-03-08 13:56:06 +01:00
| Type name | Mapped C type | Size |
|-----------|---------------|-------|
2023-04-18 22:55:48 +02:00
| Pacciani | `int` | 64bit |
| Vanni | `char` | 8bit |
| Pucci | `float` | 32bit |
| Lotti | `bool` | - |
| Canessa | `double` | 64bit |
2014-11-29 00:47:58 +01:00
A variable is declared with the following statement:
2023-04-18 22:55:48 +02:00
venga <varname>, <type>
2014-11-29 00:47:58 +01:00
an initialization value can be provided:
2023-04-18 22:55:48 +02:00
venga <varname>, <type> è amico di <expression>
2014-11-29 00:47:58 +01:00
for instance:
2023-04-18 22:55:48 +02:00
venga l'imputato, Pacciani è amico di 4
2014-11-29 00:47:58 +01:00
2023-04-18 22:55:48 +02:00
declares a variables called `testimone` of type `Pacciani` (`int`) and initializes
2014-11-29 00:47:58 +01:00
it to 4.
2017-10-12 22:36:56 +02:00
## Input/Output
2014-11-29 00:47:58 +01:00
Variables and expressions can be printed with the statement:
2023-04-18 22:55:48 +02:00
<expression> è espulso dall'aula
2014-11-29 00:47:58 +01:00
Conversely, a variable might be read from input using:
2023-04-18 22:55:48 +02:00
chiamo a testimoniare <varname>
2014-11-29 00:47:58 +01:00
2017-10-12 22:36:56 +02:00
## Loop
2014-11-29 00:47:58 +01:00
There is only one loop construct, equivalent to a C `do {} while();`, which is
defined as follows:
2023-04-18 22:55:48 +02:00
allora
2014-11-29 00:47:58 +01:00
<statements>
2023-04-18 22:55:48 +02:00
si calmi, se <condition>
2014-11-29 00:47:58 +01:00
2014-11-29 01:08:12 +01:00
For example:
2023-04-18 22:55:48 +02:00
venga il mostro, Pacciani è amico di 10
allora
il mostro è amico di mostro meno 1
si calmi, se il mostro è maggiore di 0
2014-11-29 01:08:12 +01:00
maps to:
2023-04-18 22:55:48 +02:00
int mostro = 10;
2014-11-29 01:08:12 +01:00
do {
2023-04-18 22:55:48 +02:00
mostro = mostro - 1;
} while (mostro > 0);
2014-11-29 01:08:12 +01:00
2023-04-18 22:55:48 +02:00
`si calmi` might be replaced by its alternate form `perfavore`
2017-10-12 22:36:56 +02:00
## Branch
2014-11-29 00:47:58 +01:00
2014-11-29 01:17:07 +01:00
The branch construct encompasses both the features of an `if` and a `switch`.
2014-11-29 00:47:58 +01:00
The best way to explain it is by comparing its various forms to the corresponding
C translation.
This is the general form:
2023-04-18 22:55:48 +02:00
lei conosce <variable>?
2014-11-29 00:47:58 +01:00
<condition>:
<statements>
2023-04-18 22:55:48 +02:00
o merenda <condition>:
2014-11-29 00:47:58 +01:00
<statements>
2023-04-18 22:55:48 +02:00
insomma:
2014-11-29 00:47:58 +01:00
<statement>
2023-04-18 22:55:48 +02:00
e facevate le merende insieme
2014-11-29 00:47:58 +01:00
where `<condition>` might be either a value or a semi-expression, that is an
operator followed by any expression. For instance:
2023-04-18 22:55:48 +02:00
lei conosce il testimone?
giulio:
testimone è amico di testimone meno 1
o merenda giulio diviso 2:
testimone è amico di testimone più 1
o merenda maggiore di mobiletto per due:
testimone è amico di testimone per 2
insomma:
testimone è amico di 2
e facevate le merende insieme
2014-11-29 00:47:58 +01:00
maps to:
2023-04-18 22:55:48 +02:00
if (testimone == giulio) {
testimone = testimone - 1;
} else if (testimone == (giulio / 2)) {
testimone = testimone + 1;
} else if (testimone > (mobiletto * 2)) {
testimone = testimone * 2;
2014-11-29 00:47:58 +01:00
} else {
2023-04-18 22:55:48 +02:00
testimone = 2;
2014-11-29 00:47:58 +01:00
}
The statement can emulate an `if () {} else {}`:
2023-04-18 22:55:48 +02:00
lei conosce il genio?
2014-11-29 00:47:58 +01:00
maggiore di mobiletto:
2023-04-18 22:55:48 +02:00
genio è amico di 2
insomma:
genio è amico di 0
e facevate le merende insieme
2014-11-29 00:47:58 +01:00
Placing multiple `o <condition>:` block is similar to a chain of `else if` in C.
2023-04-18 22:55:48 +02:00
The `insomma` block can be omitted:
2014-11-29 01:18:29 +01:00
2023-04-18 22:55:48 +02:00
lei conosce il genio?
2014-11-29 01:18:29 +01:00
maggiore di mobiletto:
2023-04-18 22:55:48 +02:00
genio è amico di 2
e facevate le merende insieme
2014-11-29 01:18:29 +01:00
Finally, here is the equivalent of a `switch () {}`:
2014-11-29 00:47:58 +01:00
2023-04-18 22:55:48 +02:00
lei conosce il genio?
2014-11-29 00:47:58 +01:00
1:
2023-04-18 22:55:48 +02:00
genio è amico di 2
o merenda 2:
genio è amico di 7
insomma:
genio è amico di 9
e facevate le merende insieme
2014-11-29 00:47:58 +01:00
2023-04-18 22:55:48 +02:00
where the `insomma` part is like the `default` block.
2014-11-29 00:47:58 +01:00
2017-10-12 22:36:56 +02:00
## Functions
2014-11-29 01:13:01 +01:00
2017-10-12 22:36:56 +02:00
## Declaration
2023-04-18 22:55:48 +02:00
A function is declared with the `idromassaggiatore` statement:
2023-04-18 22:55:48 +02:00
idromassaggiatore [<type>] <name> [con <param> <type>[, <param> <type>...]] innocente
<statements>
Where `<type>` can be omitted for a void function. For instance:
2023-04-18 22:55:48 +02:00
idromassaggiatore Pacciani merendivoro con mario Vanni innocente
seduti mario meno 2!
2023-04-18 22:55:48 +02:00
is a function of type `Pacciani`, taking one argument of type `Vanni`.
Multiple arguments must be comma-separed, like in:
2023-04-18 22:55:48 +02:00
idromassaggiatore Pacciani merendivoro con mario Vanni, barilotto Pacciani innocente
seduti mario meno 2!
2023-04-18 22:55:48 +02:00
which is a function of type `Pacciani`, taking two arguments of type `Vanni`
and `Pacciani`. It maps to:
2023-04-18 22:55:48 +02:00
int merendivoro(char mario, int barilotto) {
return mario - 2;
}
Finally, this:
2023-04-18 22:55:48 +02:00
idromassaggiatore merendivoro innocente
seduti!
is a `void` function taking no arguments and becomes:
2023-04-18 22:55:48 +02:00
void merendivoro() {
return;
}
Functions cannot be nested and can be declared before or after the main in any
2023-04-18 22:55:48 +02:00
order. `pcc` will not check that a return statement is always reachable inside
a non-void function. Failing to return a value leads to undefined behaviour.
2017-10-12 22:36:56 +02:00
A function might be declared with no body, in which case it's treated as a
prototype. A prototype makes the function signature known to the compiler, and
it signals that the function is implemented in another file.
## Invocation
2023-04-18 22:55:48 +02:00
A function is called with the `noi condividiamo` statement:
2023-04-18 22:55:48 +02:00
noi condividiamo <name> [con <expression>[, <expression>...] innocente
Functions might be called inside expressions. For instance, this:
2023-04-18 22:55:48 +02:00
il giudice è amico di noi condividiamo poeticamente con merende diviso 3 innocente per 2
maps to:
2014-11-29 01:13:01 +01:00
2023-04-18 22:55:48 +02:00
giudice = poeticamente(merende / 3) * 2;
2014-11-29 01:13:01 +01:00
2017-10-12 22:36:56 +02:00
## Exceptions
2014-11-29 00:47:58 +01:00
The program might be aborted immediately with the statement:
2023-04-18 22:55:48 +02:00
viva idduce
2014-11-29 00:47:58 +01:00
there are no arguments.
2017-10-12 22:36:56 +02:00
## Assertions
2014-11-29 00:47:58 +01:00
An assertion block will evaluate its expression and trigger an error message
if it is found to be 0 (logical false). An assertion is stated as:
2023-04-18 22:55:48 +02:00
ma cosa dice <expression>!
2014-11-29 00:47:58 +01:00
2017-10-12 22:36:56 +02:00
## Comments
2014-11-29 00:47:58 +01:00
2023-04-18 22:55:48 +02:00
Any character after `il nostro signore Gesù` is ignored until a line break is encountered. For
instance, in:
2014-11-29 00:47:58 +01:00
2023-04-18 22:55:48 +02:00
il testimone è amico di 4 il nostro signore Gesù è mio amico
2023-04-18 22:55:48 +02:00
`il nostro signore Gesù` is ignored.
2014-11-29 00:47:58 +01:00
Comments are useful to fill the "supercazzola" and make it more readable, since
any word (including reserved words) can be inserted into it.
2017-10-12 22:36:56 +02:00
## Meta comments
2014-11-29 00:47:58 +01:00
In addition to line comments, there are meta comments. A meta comment starts
with an hash sign `#` and continues until a line break is encountered, as an
ordinary comment.
They have a different graphical symbol, which can be immediately spotted inside
2023-04-18 22:55:48 +02:00
a long "processo". Also, ordinary comments can and should be used in an
2014-11-29 00:47:58 +01:00
improper way to fill the sentence, meta comments provide a mechanism for
distiguishing "real" comments.
2017-10-12 22:36:56 +02:00
## Reserved words and phrases
2014-12-16 16:53:27 +01:00
2017-10-12 22:36:56 +02:00
The following phrases are currently reserved with no assigned usage. They cannot
be used as variable identifiers, even if they do not serve any other purpose in
the current language revision.
2014-12-16 16:53:27 +01:00
2023-04-18 22:55:48 +02:00
* `lei la picchiava`