Expressions and operators
PPL provides the following operators:
Category | Operators |
---|---|
Arithmetic |
|
Append |
|
Boolean |
|
Comparison |
|
Value equality/inequality |
|
Reference equality/inequality |
|
Feature access |
|
if expression |
|
Null alternative |
|
Error alternative |
|
Common precedence rules are built into PPL (e.g. multiplication before addition).
Operator overloading is supported in the following way: Some operators are implemented by a function with a defined name. For example, the compiler applies function multiply
for operator *
. Thus 3 * 4
is translated by the compiler to 3.multiply(4)
.
Therefore you can use these operators for your own types. For example, if you create a new type complex_number
with functions add
and multiply
, you can use the operators +
and *
and benefit from the built-in operator precedence rules. Instead of writing …
c4 = c2.multiply(c3).add(c1)
... you can simply write:
c4 = c1 + c2 * c3
The following table shows the built-in function names for operators that can be used in any type:
Operator | Function name |
---|---|
+ |
add |
- |
subtract |
* |
multiply |
/ |
divide |
& |
append |
and |
and |
or |
or |
xor |
xor |
not |
not |
=v, #v |
is_equal_to |
>#, >=, <#, <= |
compare_to |
Examples of expressions and operators:
-
arithmetic operators
// addition const a = 3 + 4 // with '+' operator assert a =v 7 // check result const b = 3.add(4) // same with function call assert b =v 7 // operator precedence assert 1 + 2 * 3 =v 7 // multiplication before additon assert (1 + 2) * 3 =v 9 // parenthesis used to change precedence assert 1 + 2 * 3 =v 1.add(2.multiply(3)) assert (1 + 2) * 3 =v 1.add(2).multiply(3)
-
append operator
const foo = "foo" const bar = "bar" const fb1 = foo & bar // concatenation using '&' operator const fb2 = foo.append(bar) // using function call const fb3 = """{{foo}}{{bar}}""" // using string interpolation assert \ fb1 =v "foobar" and \ fb2 =v "foobar" and \ fb3 =v "foobar" const message = "Current time: " & local_time.now.to_string write_line ( message )
-
boolean operators
const the_sun_shines = yes const it_rains = no const weather_is_fine = the_sun_shines and not it_rains assert weather_is_fine
-
comparison operators
assert 7 =v 7 and 7 ># 6 and 7 >= 7 and 7 <# 8 and 7 <= 7 const seven1 = 7 const seven2 = 6 + 1 assert seven1 =v seven2 // values are equal assert not ( seven1 #v seven2 ) assert seven1 #r seven2 // but references are not assert not ( seven1 =r seven2 )
-
accessing an object’s feature (i.e. an attribute or a function)
-
without
null
orerror
check// function 'first' of type 'string' returns a character assert "abc".first =v 'a' assert "abc".first.to_string =v "a" assert "123456".substring ( from = 3, to = 4 ) =v "34" assert "12ab56".substring ( from = 3, to = 4 ).to_upper_case =v "AB"
-
with
null
checkconst index_1 = "abc".find_first ( "b" ) assert index_1 is not null assert index_1 =v 2 const index_2 = "abc".find_first ( "z" ) // function 'find_first' returns null assert index_2 is null // following instruction is not allowed because function 'find_first' can return null, // which would cause a null pointer error // const index_as_string = "abc".find_first ( "b" ).to_string // we have to check for null with the '.null?' operator const index_as_string = "abc".find_first ( "b" ).null?.to_string assert index_as_string is not null assert index_as_string =v "2" /// In the following instruction 'to_string' is not executed, because 'find_first' returns null. No null pointer error occurs! c is simply set to 'null' ./// const c = "abc".find_first("z").null?.to_string assert c is null // We can also use an 'if null' instruction: const index_3 = "abc".find_first ( "z" ) if index_3 is not null then write_line ( "found ") else write_line ( "not found ") .
-
with
error
check// Retrieve content from URL const URL_string = "http://www.foo.com" const result = \ URL.try_parse ( URL_string ) \ .error? \ .try_read_text_content /// The type of 'result' is 'string or IO_error or null' (a union/sum type). If the URL is invalid or the URL content cannot be retrieved then result contains an 'IO_error' object else it contains a 'string' object, or 'null' if there is no content ./// // Now we can check the result case type of result when string s write_line ( """The content of {{URL_string}} is: {{s}}""" ) when error e write_line ( """Connecting to {{URL_string}} raised the following error: {{e.description}}""" ) when null write_line ( """There are no data available at {{URL_string}}""" ) .
-
-
if
expressionconst height = 10 const width = 20 const size = if height >= 10 and width >= 15 then "big" else "small" assert size =v "big"
-
if_null
operator// if 'get_name_or_null' returns null then "unknown" will be assigned to name const name = get_name_or_null if_null: "unknown" assert name is not null /// If the customer has no orders yet then - 'customer.order_list' returns null - 'size' is not executed - 0 (the expression after if_null:) is assigned to 'num_orders' else 'num_orders' contains the number of elements in customer.order_list ./// const num_orders = customer.order_list.null?.size if_null: 0 write_line ( """Number of orders: {{num_orders.to_string}}""" )
-
if_error
operator// If _any_ error occurs then "unknown" will be assigned to 'URL_content' const URL_content = \ URL.try_parse ( "http://www.foo.com" ) \ .error? \ .try_read_text_content \ if_error: "unknown"