AddExpression << AddExpression
AddExpression >> AddExpression
AddExpression >>> AddExpression
The operands must be integral types, and undergo the usual integral promotions. The result type is the type of the left operand after the promotions. The result value is the result of shifting the bits by the right operand's value.
<< is a left shift. >> is a signed right shift. >>> is an unsigned right shift.
It's illegal to shift by more bits than the size of the quantity being shifted:
int c;
c << 33; error
Add Expressions
MulExpression + MulExpression
MulExpression - MulExpression
If the operands are of integral types, they undergo integral promotions, and then are brought to a common type using the usual arithmetic conversions.
If either operand is a floating point type, the other is implicitly converted to floating point and they are brought to a common type via the usual arithmetic conversions.
If the first operand is a pointer, and the second is an integral type, the resulting type is the type of the first operand, and the resulting value is the pointer plus (or minus) the second operand multiplied by the size of the type pointed to by the first operand.
For the + operator, if both operands are arrays of a compatible type, the resulting type is an array of that compatible type, and the resulting value is the concatenation of the two arrays.
UnaryExpression * UnaryExpression
UnaryExpression / UnaryExpression
UnaryExpression % UnaryExpression
The operands must be arithmetic types. They undergo integral promotions, and then are brought to a common type using the usual arithmetic conversions.
For integral operands, the *, /, and % correspond to multiply, divide, and modulus operations. For multiply, overflows are ignored and simply chopped to fit into the integral type. If the right operand of divide or modulus operators is 0, a DivideByZeroException is thrown.
For floating point operands, the operations correspond to the IEEE 754 floating point equivalents. The modulus operator only works with reals, it is illegal to use it with imaginary or complex operands.
Unary Expressions
& UnaryExpression
++ UnaryExpression
-- UnaryExpression
* UnaryExpression
- UnaryExpression
+ UnaryExpression
! UnaryExpression
~ UnaryExpression
delete UnaryExpression
NewExpression
( Type ) UnaryExpression
( Type ) . Identifier
New Expressions
New expressions are used to allocate memory on the garbage collected heap (default) or using a class specific allocator.
To allocate multidimensional arrays, the declaration reads in the same order as the prefix array declaration order.
char[][] foo; // dynamic array of strings
...
foo = new char[][30]; // allocate 30 arrays of strings
Cast Expressions
In C and C++, cast expressions are of the form:
(type) unaryexpression
There is an ambiguity in the grammar, however. Consider:
(foo) - p;
Is this a cast of a dereference of negated p to type foo, or is it p being subtracted from foo? This cannot be resolved without looking up foo in the symbol table to see if it is a type or a variable. But D's design goal is to have the syntax be context free - it needs to be able to parse the syntax without reference to the symbol table. So, in order to distinguish a cast from a parenthesized subexpression, a different syntax is necessary.
C++ does this by introducing:
dynamic_cast(expression)
which is ugly and clumsy to type. D introduces the cast keyword:
cast(foo) -p; cast (-p) to type foo
(foo) - p; subtract p from foo
cast has the nice characteristic that it is easy to do a textual search for it, and takes some of the burden off of the relentlessly overloaded () operator.
D differs from C/C++ in another aspect of casts. Any casting of a class reference to a derived class reference is done with a runtime check to make sure it really is a proper downcast. This means that it is equivalent to the behavior of the dynamic_cast operator in C++.
class A { ... }
class B : A { ... }
void test(A a, B b)
{
B bx = a; error, need cast
B bx = cast(B) a; bx is null if a is not a B
A ax = b; no cast needed
A ax = cast(A) b; no runtime check needed for upcast
}
D does not have a Java style instanceof operator, because the cast operator performs the same function:
Java:
if (a instanceof B)
D:
if ((B) a)
Postfix Expressions
PostfixExpression . Identifier
PostfixExpression -> Identifier
PostfixExpression ++
PostfixExpression --
PostfixExpression ( ArgumentList )
PostfixExpression [ Expression ]
Primary Expressions
Identifier
this
super
null
true
false
NumericLiteral
StringLiteral
FunctionLiteral
AssertExpression
Type . Identifier
this
Within a non-static member function, this resolves to a reference to the object that called the function.
super
Within a non-static member function, super resolves to a reference to the object that called the function, cast to its base class. It is an error if there is no base class. super is not allowed in struct member functions.
null
The keyword null represents the null pointer value; technically it is of type (void *). It can be implicitly cast to any pointer type. The integer 0 cannot be cast to the null pointer. Nulls are also used for empty arrays.
true, false
These are of type bit and resolve to values 1 and 0, respectively.
Function Literals
FunctionLiteral
function ( ParameterList ) FunctionBody
function Type ( ParameterList ) FunctionBody
delegate ( ParameterList ) FunctionBody
delegate Type ( ParameterList ) FunctionBody
FunctionLiterals enable embedding anonymous functions directly into expressions. For example:
int function(char c) fp;
void test()
{
static int foo(char c) { return 6; }
fp = foo;
}
is exactly equivalent to:
int function(char c) fp;
void test()
{
fp = function int(char c) { return 6;};
}
And:
int abc(int delegate(long i));
void test()
{ int b = 3;
int foo(long c) { return 6 + b; }
abc(foo);
}
is exactly equivalent to:
int abc(int delegate(long i));
void test()
{ int b = 3;
abc(delegate int(long c) { return 6 + b; });
}
If the Type is omitted, it is treated as void. When comparing with nested functions, the function form is analogous to static or non-nested functions, and the delegate form is analogous to non-static nested functions.
Assert Expressions
AssertExpression:
assert ( Expression )
Asserts evaluate the expression. If the result is false, an AssertException is thrown. If the result is true, then no exception is thrown. It is an error if the expression contains any side effects that the program depends on. The compiler may optionally not evaluate assert expressions at all. The result type of an assert expression is void. Asserts are a fundamental part of the Design by Contract support in D.
Share with your friends: |