Cone Language Reference

Expressions

On this page

Note: All of this capability is implemented except the special my name.

Now that we have literals and variables, we can construct more complex expressions that use operators, methods and functions calls to calculate new values. Although the expression examples on this page work with integer and floating point values, similar expressions can be formulated that manipulate values of other types.

Arithmetic expressions#

Arithmetic Operators#

Integer and floating point numbers may be computed using arithmetic operators:

'+'
Add
'-'
Subtract (or negate when used as a prefix operator)
'*'
Multiply
'/'
Divide
'%'
Modulo (remainder)

Thus:

-12 + 14    // 2
6 / 5       // 1
-4 % 3      // -1 (where -4/3 --> -1, truncating towards zero)
2*2 + 2*3   // 10 (standard algebraic operator precedence)
2 * (4 + 1) // 10 (parentheses override operator precedence)

Method Calls#

Additional calculations can be performed using method calls. The name of the desired method follows the object value, separated by the dot operator ('.'):

(-1).abs    // 1 (the absolute value, making a number positive)
(pi/2).sin  // 1.0 (trigonometric sine function)

Sometimes, a method may require additional values. These argument values are specified within parentheses following the method's name.

4.max(5)    // 5 (returns the larger of the two numbers)

Method calls are very common and convenient. It is helpful to know that:

  • The logic a method performs depends on the type of the value it is applied to. Thus, a method named 'max' applied to an integer is actually a different method than when 'max' is applied to a floating point number. Every type defines the names and logic for all methods it supports. An error results when trying to use a method not implemented by the value's type.
  • The arithmetic operators introduced earlier (e.g., + for add) are implemented under the covers using number type methods:
    // The method name equivalent for the + operator is `+`
    // The method name is enclosed in backticks since it includes punctuation
    3+4 // is actually the same as: 3 .`+`(4)
    // The space between 3 and . is needed here, otherwise 3. would be parsed as the float 3.0
    // When using a variable this space is not needed: n.`+`(4)
    

Note: The arguments to a function or method call are evaluated in left-to-right order. This is also true for tuples.

Note: Inside any argument on a method call, the special name my may be used. Its value is the same as the object of the method call. This can be helpful to call helper methods on the object to prepare other argument values.

Function calls#

Function calls are very much like method calls, except they are not applied to a value in the same way. Instead of specifying a value, dot operator, and a method name, one simply specifies the function name followed by any comma-separated arguments in parentheses.

pow(10f, 2f)

Numeric conversions#

To convert a number from one type to another, call the intended type's method from with the number:

imm six = i32.from(6u8);    // Converts 8-bit unsigned integer to 32-bit signed integer
imm sixf = f64.from(six);   // Converts 32-bit signed integer to 64-bit floating point number

If the receiving number type is a smaller size, numeric information may be lost. Explicit Conversion gives what each conversion does.

Bitwise expressions#

The bitwise operators operate on true/false values:

'|'
Or
'&'
And
'^'
Xor
'~'
Not

For example:

true | (false & true) // true
true ^ ~true          // true

These bitwise operators may also be used on unsigned integers, as they are viewed as a collection of true/false bits.

0xE0u | 0xB8u  // 0xF8u

Shift operators#

The shifting of an integer's bits is accomplished using the << and >> operators:

0x0Cu << 1    // 0x18, after shifting bits left once

The amount to shift by is a value of the same integer type. << fills the bits it vacates with zeros, and the bits shifted past the top are gone. >> on an unsigned integer fills with zeros; on a signed integer it fills with copies of the sign bit, so a negative value stays negative.

Every amount gives an answer, the same in every build. An amount of the integer's width or more shifts every bit out: << gives 0, as does >> on an unsigned integer, and >> on a signed integer gives the sign in every bit, 0 or -1. The amount is read as an unsigned number of its own width, so a negative amount of a signed type is past the width too:

imm n = 64u64;
255u64 >> n         // 0
(1u64 << n) - 1u64  // all ones: 1 << 64 is 0
-8i32 >> 40i32      // -1, at run time

In a constant expression, such as a const's value, a shift by the width or more, or by a negative amount, is an error.

An amount taken modulo the width is asked for by name: the integer methods shlMasked and shrMasked, the processor's one-instruction shift, and rotateLeft and rotateRight (An integer's bits).

Lval-based Expressions#

An 'lval'-based expression is one where the expression to the "left" represents a memory "container" which holds a value. Lval-based expressions will change the stored value. The assignment expression introduced on the previous page is lval-based, as examples specified a variable to the left of the =.

Parallel Assignment#

Parallel assignment makes it possible to simultaneously assign multiple values to multiple variables. This can be convenient when swapping the values held by two variables:

// Swap the variable values for a and b
a,b = b,a;

This is also useful for capturing multiple values returned by a function or method call:

min, max = minmax(5, 4);

Increment/decrement Operators#

When used to the left of an lval, ++ will increment the number and -- will decrement it.

mut cnt = 10;
++cnt;          // 11
--cnt;          // 10

When used to the right of an lval, it will still increment and decrement, but the expression will return the original value.

mut cnt = 10;
imm x = cnt++;  // x is 10, cnt is 11

Arithmetic Assignment#

The arithmetic assignment operators (e.g., '+=', '-=', '*=', '/=') offer a convenient way to update an existing stored value:

counter = 3;
counter += 1;  // 4. Equivalent to: counter = counter + 1

Logical assignment operators#

These work similarly to the arithmetic assignment operators:

mut flags = 0xC0u;
flags |= 0x01u;   // 0xC1u
flags >>= 1;      // 0x60u

Other Expression Operators#

Cone supports several more expression operators. Descriptions may be found in the chapters relevant to their common use: