Here’s Danny‘s session, “What’s New in the Delphi Compiler”. At this point, I am actually caught up on my conference blogging. (Caught up on the first day. Will wonders never cease?)
What’s New in the
- Major Win32 compiler work
- Records with Methods
- Operator Overloading
- Class vars (per-type global storage)
- Unit initialization consolidation
- Large app, lots of units, lots of initialization -> loaded lots of pages from disk to run all those initialization sections.
- When the linker does smart linking and assigning addresses, now it puts all those initializations together in one clump of code pages. Result: faster startup (on the order of 2-5%), and significant reduction in working set.
- Next step is to put them in a separate segment, so they can be purged from the working set after startup. Not done yet.
- Finalizations are also clumped together.
- Inline-able magic functions (string Length(), etc.)
- Minor .NET compiler work
- Minor bug fixes, metadata improvements
- .NET Compact Frameworks Enablement
- Soften error checking for missing CLR stuff
- Beef up class helpers
Records with Methods
type TBlock = record procedure Foo(I: Integer); function Bar: TBlock; private Data: Integer; public property Color: Integer … end;
- In old-style objects, virtual methods were optional, so the VMT could be at a different offset in different types (if it was there at all). Difficult to work with.
- In the
Delphilanguage, “class” is always a reference type, for simplicity.
- Value types: If they’re small, allocating them is fast.
- Yes, you can reference the type within itself (see the declaration of Bar, above).
- Private, protected, public. Probably has strict private and strict protected as well.
- No inheritance. (So protected really doesn’t mean anything. Maybe it isn’t there after all.)
- Default scope is public.
- Can implement interfaces in .NET, but not in Win32
- No published. Records have no VMT so they can’t have RTTI.
- Can still have variant sections in the record, but they have to be at the end. May not be able to put visibility specifiers after you’ve started a variant section. Cannot put methods inside a variant section.
- Assigning the record will copy everything regardless of visibility.
- Note: if you put compiler-managed types in a record (string, interface, dynamic array, Variant), the compiler will generate try..finally code all over the place for you. (This is the same rules as before.)
Operator Overloading (Win32)
- Requires value semantics. “A + B” must return a new instance. (Otherwise, who’s going to clean them up?)
- Supported on record types only (see previous point)
- Same syntax & rules as
- class operator Add(A, B: TQuark): TQuark;
- class operator Add(A: TQuark; B: Byte): TQuark;
- class operator Implicit(A: Integer): TQuark;
- class operator Explicit(A: TQuark): Integer;
- class operator Explicit(A: TQuark): string;
- Implicitly overloaded, so you don’t have to use the “overload;” directive.
- Can’t define new operators, but you can override all of the standard ones (except assignment and pointer dereferencing).
- If you want to support all the different integer types, you have to do it yourself.
- Commutativity is not assumed. So if you want both TQuark + Byte and Byte + TQuark, you have to define it. (Not a big deal – have one call the other, and get it inlined.)
- Operator Explicit is the only place you’re allowed to overload on result type.
- If TFoo defines Add(TFoo, TBar), and TBar defines Add(TFoo, TBar), the compiler will pick one. Don’t do this.
- Implicit conversion happens when:
- A := B;
- Passing parameters
- Don’t define an implicit conversion if you will lose information.
- Will not do long-trip conversions. If A can be implicitly converted to B, and B to C, and you try to go straight from A to C,
Delphiwill say “Bad programmer!”
- Explicit is for explicit casts, like TFoo(5), or Integer(MyFoo).
- These are allowed to lose data, e.g., going from a LongInt to a Byte.
- If two types both define the same implicit or explicit conversion (like TFoo to TBar), you will get a compiler error (ambiguous overload, or some such) at the point where you try to do the cast.
- You cannot call TQuark.Add directly. It doesn’t exist.
- Operators are implicitly static.
- WriteLn(Q) uses Explicit(Quark): string
- If you do a hard typecast on something that supports that as an implicit typecast, it’ll work. You don’t have to declare the same thing as both implicit and explicit.
- Cast operators: Implicit, Explicit
- Unary: Positive, Negative, Inc, Dec, LogicalNot, BitwiseNot, Trunc, Round
- Comparison: Equal, NotEqual, GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual
- Binary: Add, Subtract, Multiply, Divide, IntDivide, Modulus, ShiftLeft, ShiftRight, LogicalAnd, LogicalOr, LogicalXor, BitwiseAnd, BitwiseOr, BitwiseXor
- If you define both LogicalOr and BinaryOr, the compiler will pick one. Don’t do that.
- You can have an operator called Divide and a method called Divide. They won’t collide.
- Operators should always create and return a new value, not modify the inputs. (Yes, this applies to operator Inc and Dec as well.)
- Expression: A + B
- Types: TA, TB
- Add operator is selected from the Add operators on TA and TB only, not from other classes. (Again, it’s not automatically transitive.)
- If TA is convertible from TB, but not the other way around, TA is considered narrower, or more specific. This affects overloaded method calls.
- Global storage for a field within your type
- Descendants share ancestor’s class vars
- Not separate storage for each derived type
TMyClass = class private class var SharedStuff: Integer; public ... end;
- Cannot initialize these in Win32, yet. (No class constructors in Win32.) But you could initialize it from a unit initialization section.
- Accessible from class functions
- Same default initialization rules as globals: initialized to zero.
- “class var” starts a new section. So do “var” and “type”. (“Var” and “class var” are there because of nested types in Delphi 2005 – “type” introduces a section, so you need “var” to get back out of that mode.)
- Can have class constants as well (but not typed class constants).
- These are objectives, not guaranteed feature lists
- “Highlander” (calendar 2006)
- Full .NET 2.0 support & integration
Delphigenerics, class fragments, and more
- Full .NET Compact Framework support, including VCL.NET for CF
- Support .NET 2.0 64-bit app development
- “Delphi Longhorn” (not the actual codename) (sometime after Highlander)
- Win32 & .NET development for Windows Vista OS
- Avalon (WPF)
- Closest logical evolution of Win32
- Same shortcomings as Win32 (DLLs, APIs, security)
- Unicode VCL
- Company green light, just needs time & resources