Pacioli Manual
Manual for Pacioli 0.4
Contents
Pacioli
A Paciolo program consists of definitions organized in modules.
Program
A program is a file containing a collection of definitions. A program can
include other programs with an include
and libraries with an import
.
A line comment starts with an #
# This is an example program
import si;
import geometry;
include some_dir/some_file;
define ...
A module provides namespaces for
- values and functions
- index sets
- units and unit vectors
- types
After the definitions have been processed, the toplevel expressions in a module are evaluated in the order they appear in the file.
Toplevel Definitions
Definitions
A definition starts with keyword define
followed by a name, the
equal sign, and an expression. A value is
defined like
define x = expression;
and a function like
define f(x, y, ..., z) = expression;
Declarations
A definition can be accompanied by a type declaration. A declaration
starts with keyword declare
followed by a name, a pair of colons,
and a type.
declare x :: type;
Declarations are optional, except for recursive functions. If a type is declared then it is checked against the definition's infered type. A declaration may restrict the type, but not generalize or contradict it.
Matrix Definitions
Syntax is
defmatrix x :: type = { foo, bar -> 123, ... };
A matrix of the declared type with the given numbers is defined.
Conversion Definitions
Syntax is same as declaration
defconv foo :: matrix type;
A conversion matrix of the declared type is defined as value. The type's row and column dimension must be the same.
Index Definitions
An index set definition starts with keyword defindex
followed by a
name, the equal sign, and a set of names.
defindex Foo = {foo, bar, baz};
The defined name is used in matrix types.
Unit Definitions
A unit definition starts with keyword defunit
and can define a base
unit, a derived unit, or a unit vector.
A base unit definition requires a name and a string to be used in output.
defunit metre "m";
A derived unit requires an additonal unit expression. This is an
expression with operators *
, /
and ^
on base units or other
derived units.
defunit knot "kn" = 0.51444444*metre/second;
A unit vector is defined for an index set by specifying a unit for each index key. An exclamation mark seperates the index set name from the unit vector name.
defunit Foo!unit = {foo: metre, bar: knot, ...};
Unit vectors are used in matrix types.
Type Definitions
Syntax is
The defined type must be a parametric type.
The Type System
A type judgement states that an expression is of some type. It is of the form
expression :: schema
Type judgements are used as input in definitions and declarations to declare a type, and as output by the compiler when the inferred types are displayed.
The type schema introduces type variables. A type schema is can introduce ordinary type varibles, index variables, or unit varibles.
for_type a,b,...: type
for_index P,Q,...: type
for_unit u,v,...: type
Index variables are written in uppercase by convention.
A type is one of the two special types for functions and matrices, or the generic parametric type. The function and matrix type are described in the next section. A parametric type is of the form
Built in types List, Tuple and Boole are parametric types.
Values
Pacioli supports numbers, booleans, lists, tuples, functions and incides.
Matrices
Any numerical value is a matrix. A scalar is a 1x1 matrix. A vector is a 1xN or a Nx1 matrix.
The type of a matrix is of the form dim per
dim
. The row and column types are expressions on units and unit
vectors with operators *
, /
, ^
and %
. The grammar of the matrix
type's dimensions is
dim ::= dim * dim dimensional multiplication
| dim / dim dimensional division
| dim ^ integer dimensional power
| dim % dim dimensional Kronecker
| term matrix type terminal
term ::= identifier ! identifier dimensioned vector
| identifier ! dimensionless vector
| identifier dimensioned number
| 1 dimensionless number
A terminal in a row or column type expression is the name of a scalar
unit or the name of a dimensioned vector space. A unit scalar is the
dimensionless 1 or a unit like a gram
or a metre
. A dimensioned
vector space is distinguished from a scalar by an exclamation
mark. The exclamation mark indicates a vector space and is always
preceded by the name of the space's index set.
The matrix type is interpreted at runtime as a unit matrix. For each dimensioned vector space the representative unit vector is assumed to be available. Each entry in a matrix type is then given by
(x per y)[i,j] = x[i] / y[j]
The runtime contents of non-terminals is defined inductively, starting
from the contents of the unit vector terminals. Let v
and w
be
unit vectors
(v * w)[i] = v[i] * w[i]
(v / w)[i] = v[i] / w[i]
(v^n)[i] = v[i]^n
(v % w)[i%j] = v[i] * v[j]
The pair i%j
in the last rule is a compound index. Tensors are
matricized with the Kronecker product. This makes multi-dimensional
data transparent for matrices and addresses the issue in the
indices. Multi-dimensional data is indexed with compound indices
instead of multiple row or column indices. See Indices.
Indices
Matrices in Pacioli are indexed by general index sets, not necessarily
integers. Indices are first class language members. They are
accessible via functions row_domain
and column_domain
or via
literal syntax x@
y, with x an index set and y an index
key. For example Foo@key13
or Bar@item42
.
A consequence of the matricization of tensors is that a matrix can
have any number of row indices and any number of column indices. A
row key or column key is a combination of items from possibly multiple
index sets. Compound literal indices are constructed with the %
symbol. For example Foo@key13%Bar@item42
. The index type lists all
index sets. In this case:
Index(Foo, Bar)
Special key _
is the only element of the index of zero index sets:
_ :: Index()
It is used to index the empty row and column domains of scalars and vectors.
Booleans
A Boolean is one of the logical values true
or false
.
The type of a boolean is Boole()
.
Tuples
A tuple is a fixed set of values of various types. Functions in Pacioli expect a tuple of values as argument.
Use function tuple
to create a tuple. It returns the tuple of
arguments. Use destructuring in a let or comprehension or use function
apply
to retreive the elements of a tuple.
The type of a tuple is
Lists
A list is a varying set of values of the same type.
The type of a list is
List(type)
Functions
Functions are first class values. Functions are globally defined in a module or anonymous lambdas.
The type of a function is
Expressions
Constants
Literal constants are numbers, or the Boolean values true
or false
.
Variables
A variable is an identifier built from alphanumeric characters and undercores. A variable can be local or it can refer to a defined value or function.
Unit Expressions
A matrix type surrounded by pipes is a unit expression. For example
|metre|
or |Foo!unit per Foo!|
.
Operators
Operators grouped by precedence
- negative
^T transpose
^R reciprocal
^D dim_inv
'^' mexpt
^ expt
per dim_div
'.*' scale
'*.' rscale
'/.' scale_down
'./' lscale_down
* multiply
/ divide
\ left_divide
'*' mmult
'/' right_division
'\' left_division
+ sum
- minus
< less
<= less_eq
> greater
>= greater_eq
= equal
!= not_equal
and and
or or
<=> equal
==> implies
<== follows_from
Function Application
A function application is of the form
foo(expression, expression, ... )
Lambda
An anonymous function is of the form
lambda (x, y, ... ) expression end
If
An if is of the form
if expression then
expression
else if expression then
expression
...
else
expression
end
Let
A let is of the form
let
foo = expression,
bar = expression,
...
in
expression
end
Each variable can also be a list of variables surrounded by parenthesis to destructure a tuple.
Comprehensions
A list comprehension is of the form
[ expression | clause, clause, ... ]
where each clause is
a generator
var <- expression
a filter
expression
or an assignment
var := expression
Each var can also be a list of variables surrounded by parenthesis to destructure a tuple.
Statements
A statement is of the form
begin
statement
statement
...
end
A return leaves the block prematurely.
Assignment
An assignment is of the form
var := expression;
The value stored by variable var
is changed to the value of the
expression. The variable can also be a list of variables surrounded by
parenthesis to destructure a tuple.
Return
A return statement is of the form
return expression;
Execution of the surrounding begin
end
block is halted and the
returned value becomes the value of the block. The expression is
optional.
While
A while statement is of the form
while expression do
statement
end
The body of the while loop is executed as long the expression is true.
If
An if statement is of the form
if expression then
statement
else if expression then
statement
...
else
statement
end
The else
and elseif
are optional.