Property expressions and statements

Object Pascal does allow binding a property to a field for direct read/writer, but we all have seen properties that required a slightly more complex getter or setter, and that usually meant a method for both. DWScript (svn trunk) & Smart Pascal (1.1) now support property expressions and statements, so the syntax is extended to allow:

property Name : Type read (expression) write (expression|statement)

Under the hood, the compiler will generate an unnamed getter or setter method when appropriate.

Let’s take f.i. a class that exposes an internal list, you can now use just

TMyClass = class
   private
      FList : array of TElement;
   public
      property Items[i: Integer] : TElement read (FList[i]) 
                                            write (FList[i]); default;
      property Count : Integer read (FList.Length);
end;

Look Ma! No implementation and no constructor needed for trivial properties!
The astute reader will quickly notice how much shorter this is compared to doing it with a TList<T> and classic properties instead.

And for an hypothetical angle value types that accepts both radians and degrees you could have

TMyAngle = record
   private
      FAngle : Float;
   public
      property Radians : Float read FAngle write FAngle;
      property Degrees : Float read (RadToDeg(FAngle)) 
                               write (FAngle:=DegToRad(Value));
end;

In the setter statement, there is a special value creatively named… “Value” which holds the value assigned to the property.

In addition to expressions and statements, you can also if specify a property name as getter or setter, this will create an alias (no under-the-hood getter or setter method will be created):

TAncestor = class
   private
      FHidden : Integer;
      procedure SetSecret(v : Integer);
   protected
      property Hidden : Integer read FHidden write FHidden;
      property Secret : Integer write SetSecret;
end;

TSubClass = class (TAncestor)
   public
      property Revealed : Integer read Hidden write Secret;
      property OldReveal : Integer read Revealed write Revealed; deprecated;
end;

Which can be of use when you want to make public a protected property under a different name in a subclass, and the underlying field or method being private wasn’t visible. It can also be helpful if you want to rename a property in a migration-friendly way, with the old name deprecated.

So to summarize:

  • read now accepts expressions and properties, in addition to field names and methods names
  • write now accepts writable expressions (the left-side of an assignment), statements (an assignment or a method call) and properties in addition to field names and method names. “Value” contains the value assigned to the property.
  • property expressions are supported for classes, records, helpers and interfaces.

As we weren’t sure of the potential ambiguity, the compiler currently requires the presence of brackets ( ) before the new expressions and statements are allowed, this requirement might be lifted in the future, or maybe not, as it makes such expressions stand out more.
This is an open question, Oxygen accepts read expressions without brackets (but doesn’t have write expressions or statements), so feedback on this aspect is welcome.

Thanks go to Primoz Gabrielcic for providing the unit tests for the above feature!

11 thoughts on “Property expressions and statements

  1. That’s great!
    little offtop and some questons:
    1) What about to full support xe3 and lazarus for dws? Some time ago i tryed to compile dws under xe3 upd2 – not success. Just want to move my project to smartmobile studio for web, and to dwscript for all the rest: win, linux – lazarus, mac osx – delphi. On your opinion – is that possible? How speed will slow down in comparison whith delphi – or maybe conversely, will up?
    2) How difficult it will be to me to add support for llvm for dws, could you provide some help with it: short tutorial?

  2. Sergionn :

    That’s great!
    little offtop and some questons:
    1) What about to full support xe3 and lazarus for dws?
    2) How difficult it will be to me to add support for llvm for dws, could you provide some help with it: short tutorial?

    1) Some workarounds for the XE3 compiler bugs were contributed, though I don’t have means of testing XE3, and I don’t know if the latest XE3 fixed the compiler.
    For Lazarus, the situation is a bit similar, I had made the port to fpc 2.7, but it has since disappeared from the Lazarus daily snapshots (2.7 is required for generics and Unicode)
    2) I’m not sure about llvm port complexity, I had only made some tests to use for Delphi integration, and the major roadblock was that it’s designed for C++, is constantly evolving and there were no good and maintained interfacing libraries for Delphi. Using LLVM for a full-blown compiler might paradoxically be simpler. Compiling the DWScript AST to llvm may not be too hard, though the devil will be the debugger and everything that goes around.

  3. Ok thanks for answer, just wait for freepascal 2.7, then try….
    And then the other question: is that possible to make dws produce c++ code, like it was for done for js code generation? could you point me to tutorial and samples?

  4. That’s VERY cool. The only problem with seeing this sort of stuff happening with DWS is that it simply serves to reinforce just how LITTLE truly useful stuff is coming out of Embarcadero themselves.

    I have been expecting this sort of change ever since I saw the similar feature/syntax in Chrome a.k.a Oxygene a.k.a Prism. It was such an obvious and seemingly simple addition that would made Delphi developer’s lives so much easier and was TRULY in the “Spirit of Delphi”.

    But no, instead we got an abortion of a generics implementation and ever since then, whenever anyone asks for or suggests this sort of condensed/simplified syntax feature, they are told they can just do it with generics or anonymous methods or both.

    It’s as if Embarcadero WANT us to all drop Delphi and go use C/C++ like languages instead.

  5. DWS is fine with XE3 but you will have to checkout from the SVN. I’ve contributed the (very basic) IDE that is in the tools sub folder and I use XE3 to manage it. Eric is so busy creating and testing that DWS lacks a slick installer but after you’ve checked out the latest source you will find that compiling the DPK is about all you need to do.

  6. Sergionn :

    And then the other question: is that possible to make dws produce c++ code, like it was for done for js code generation?

    In some ways it would be simpler to generate C++ than JS, as C++ has similar scoping rules and similar classes/struct, but on the other DWScript code typically assumes either a GC (as in JS) or a ARC+GC hybrid (as in the DWS engine).
    A lot of the complexity in the JS codegen is disambiguation of the variables and recreating a class model with virtual methods, interfaces, records, since JS scoping is different.
    However the hard part won’t be the C++ generation, but if you want to debug the outcome whole looking at the Pascal source (which I don’t know how/if it can be done, given that the code would go through an intermediate C compiler)

  7. Ok, thanks, just leave the idea of c++(llvm) output for now.
    Began to explore the possibilities of my application to transfer to dws-smart, and found it don’t support “set of” structures, will it be soon, or abandon remove from my code) such structures in general as the outdated?

  8. @Jolyon Smith
    >and ever since then, whenever anyone asks for or suggests this sort of
    >condensed/simplified syntax feature, they are told they can just do it
    >with generics or anonymous methods or both.

    It’s sometimes worse… now in the forum Rudy is telling me that if you don’t want super-strict typing 100% of the time (C# has a “dynamic” keyword to turn off compiler type checking for a variable so you can do things like duck typing on a specific object) then you should just use another language instead of Delphi. 🙁 Jacinto Franca and I were working out a way for Delphi to return multiple values from a function via returning a record and having automatic unpacking of values, but Rudy’s not keen on that one either.

    >It’s as if Embarcadero WANT us to all drop Delphi and go use C/C++
    >like languages instead.

    Apparently they want us to go use dynamically typed languages like Python and Ruby, functional languages like Haskell, etc. too because the reception to features from those languages is just as chilly.

    Anyway, I agree that this getter/setter enhancement would be a great addition to the language. I’ve been annoying Delphi fanboys lately by suggesting that while VCL was RAD for GUI, Pascal was never designed as a RAD language nor was it chosen for its RAD abilities. Honestly, it’s somewhat the opposite of RAD. In the meantime, languages that can truly be called RAD languages have shown up and there’s a great deal Delphi could learn from them. DWScript already seems to understand that and has no problem adding features to make development truly more rapid. It seems there’s more innovation going on here and with FreePascal then there has been with Embarcadero for many years now.

  9. Sergionn :
    it don’t support “set of” structures, will it be soon, or abandon remove from my code, such structures in general as the outdated?

    I haven’t gotten around to writing a complete set of of units tests for it, and there are some issues to figure out wrt to the syntax, as it overlaps with that of array comprehension in the language, and I want to have more of it. Current plan would be to have the sets be a form of “unique array of”, and let the compiler figure out the optimizations.
    Ad interim you can use the “flags” enums (http://delphitools.info/2012/03/30/explicitly-scoped-enums/) or plain arrays if set unicity and set operations aren’t required (arrays support in/not in operators)

  10. Jolyon Smith :

    I have been expecting this sort of change ever since I saw the similar feature/syntax in Chrome a.k.a Oxygene a.k.a Prism.

    Initially I forged on both for useful stuff, and as a counter point to naysayers that were whining the language couldn’t evolve while retaining backward compatibility, yada yada yada.

    Interestingly enough, DWScript has become more compatible with old Delphi code, while syntax extensions were added, compatibility with Oxygene got improved, it can be used in a “consolidated unit” form familiar to Java & C# users, and can do PHP-like web page generation as well with the “HTML Filter” component.

    If rumors about Delphi NextGen are true, it could be more compatible with both old Delphi and NextGen than NextGen will be compatible with old Delphi, which is kinda sad tbh.

Comments are closed.