Smart Mobile Studio
  • News
  • Forums
  • Download
  • Store
  • Showcases
    • Featured demos
    • The Smart Contest 2013, Round 1 – Graphics
  • Documentation
    • Get the book
    • System requirements
    • Prerequisites
    • Getting started
      • Introduction
      • Application architecture
      • The application object
      • Forms and navigation
      • Message dialogs
      • Themes and styles
    • Project types
      • Visual project
      • Game project
      • Console project
    • Layout manager
    • Networking
      • TW3HttpRequest
      • TW3JSONP
      • Loading files
  • About

Differences between Delphi and Smart

Note: The project codenamed “OP4JS” is now officially called Smart Mobile Studio.

The Smart Pascal dialect is more or less identical to Delphi 7, so if you are familiar with either FreePascal or Delphi then learning Smart will be a breeze. This document will outline the differences and features of Smart compared to classical Object Pascal. Unlike other products we have gone to great lengths to keep the source-format as close to Delphi 7 as possible. We believe the wast majority of Delphi developers will feel right at home with Smart and enjoy the opportunities our product delivers.

If you are new to Object Pascal we highly recommend the website Delphi Basics to help you get started.

Character case and syntax

Smart follows the standard Object Pascal text formatting, which is not case sensitive. Your procedure, variable, class and type names can be defined in any case your wish.

Unit variables

This is fully supported, however object instances must be initiated from an existing instance (TApplication being the obvious initiator).

Unit initialization and finalization

Under Delphi and free pascal these two procedures are typically used to initialize unit variables, they are not supported at this time

Generics and RTTI

Some aspects of generics are on the drawing board, but as of writing this is not something we support. But TObject does have a classtype property and you can also use the IS keyword:

if (someobject is TMyObject) then
begin
  //do something
end;

Exceptions

Smart has full support for exceptions. JavaScript exceptions will surface as ordinary Object Pascal exceptions and can be handled the exact same way. There is one small difference however, the CreateFmt() constructor is implemented in EW3Exception.

Data-types

Smart supports the following data-types and arrays of these. The range of types is limited by JavaScript.

  • TObject
  • Boolean
  • Integer
  • String
  • Float
  • Variant

Note: JavaScript automatically decides if an integer is 8, 16, 32 or 64 bit in size. Operations like bit shifting only affects the least significant 32 bits. Also The default size of an integer depends on the operative system (32 bits on iOS, 64 bit on a modern iMac).

Interfaces

Smart fully supports interfaces. There is no need for TInterfacedObject, interfaces can be applied directly to TObject since JavaScript does not have a mechanism for observing reference counts.

type
  IMyInterface = interface
    procedure myInternalMethod;
  end;

  TMyObject = class(TObject, IMyInterface)
  private
    { IMyInterface Implementation }
    procedure myInternalMethod;
  end;

Constructors and destructors

These are supported as normal (a part of TObject). It must be underlined that when writing components (derived from TW3CustomControl, TW3GraphicControl or TW3Component) you rarely override these directly like under Delphi or Free Pascal, instead you override the protected methods InitializeObject and FinalizeObject. This is to compensate for the lack of BeforeDestruction and AfterConstruction in our object model.

Type casting

Normal typecasting is fully supported. Normal rules apply (you can only cast an object reference to it’s native type or an ancestor).

Var parameters

Smart supports var parameters

Records and composite types

Smart supports records and also arrays of records, both dynamic and static

Variants

Variants are supported as a data-type, but can only be used as containers. The compiler has no operators that deals with them (so you cannot write: A:=1 + myVariant, because there is no way to predict the resulting type without considerable overhead and loss of performance). Under Smart variants are used to transport information between raw JavaScript methods. You can however have variant parameters and function results, but these can only be accessed by methods using ASM sections (see ASM sections below). To force a variant cast explicitly, you can use the following functions from the RTL (W3System.pas):

  • function VarAsString(aValue: Variant): String;
  • function VarAsInt(aValue: Variant): Integer;
  • function VarAsFloat(aValue: Variant): Float;
  • function VarAsObj(aValue: Variant): TObject;
  • function VarAsBool(aValue: Variant): Boolean;

Dynamic Arrays

Smart supports dynamic arrays in the form of objects (which in reality maps directly to JavaScript arrays). You allocate dynamic arrays using the classical “new” keyword, as such:

type
  TIntArray = array of Integer;

procedure TestArray;
var
  myData: TIntArray;
begin
  myData := new TIntArray[10];
  // myData supports:
  // .length = returns length of array
  // .push(value) = adds a new item to it
  // .delete(index,count) = deletes X number of entries
  // And more. Please see documentation on arrays for more info
end;

Events and event handlers

Since everything is an object in the JavaScript world, the “of object” ending for procedure references is not needed (and not supported). So where you under FreePascal or Delphi would write:

type
  TMyCleverEvent = procedure (Sender: TObject) of object;

Smart demands that you write:

type
  TMyCleverEvent = procedure (Sender: TObject);

Pointers

JavaScript does not support pointers but deals exclusively with references , as such the pointer data-type serves no function and does not exist in our flavour of Object Pascal.  In short we can say that JavaScript deals with references and values in 3 ways:

  • references to native objects provided by the browser
  • variables holding data structures created by JavaScript (including JavaScript prototype objects)
  • references to JavaScript values or functions (functions can return functions in JavaScript)

What we have done to clean up this mess – is to map our rigid Object Pascal terminology onto the unstructured and colorful JavaScript mesh. Our goal has not been to make Object Pascal look like JavaScript, but rather to force JavaScript to abide by our rules. This is much more elegant than trying to mimic or fake a datatype that doesnt exist:

  • You handle object references with TObject
  • you handle data structures with records or variants
  • you handle values using normal variable types
  • You handle function references with procedural types (see events and event handlers above)

We have true object inheritance

JavaScript does not support true OOP in the ordinary sense of the word, which makes it exceedingly difficult for classical web-designers to create reusable components or manage large scale projects. But Smart delivers full OOP running under JavaScript (!). Our compiler technology generates a real-life VMT (virtual method table) in JavaScript, which means that you can write objects and inherit from them just like you do in Delphi. This gives you a tremendous advantage over classical web developers that must rely on a wide scope of JavaScript libraries, libraries that rarely co-exist without causing browser instabilities. With Smart this is not the case – here you can enjoy the same freedom of rapid, object oriented software architecture as you would under Delphi or Visual Studio.

ASM blocks

In the world of Delphi or free pascal, it’s quite rare to find people that write assembler side by side with their pascal code anymore. Real assembler is complex, error prone and tricky to master (which is why so few people are good at it). But under Smart assembler is pure fun – because to a browser assembler is JavaScript! Unlike x86 assembler, JavaScript is reasonably easy to work with (although abhorrently difficult to get right beyond 20.000 lines) and if you want to interface more closely with the browser – you have no other option but to use an ASM section. So ASM sections contain normal JavaScript, not machine instructions. Let us have a look at the ground rules:

procedure TMyObject.Testing;
var
  mRef: TObject;
begin
  mRef := tagRef;
  asm
    (@mRef).style.width=100 + "px";
  end;
end;

What we do here is to first get a handle to the our tag (the tagRef is a public property of TW3TagObject, the base class for all our controls and components). We then enter the ASM section, use that reference to access and alter the width style property of our control. Of-course you don’t have to do things this way, our RTL is quite rich in functions to deal with such simple tasks. But learning how to benefit from your JavaScript skills is a great bonus. You get the best of both worlds. The same could easily be achieved with a function from our W3Systems.pas RTL unit:

procedure TMyObject.Testing;
asm
  w3_setStyle(tagRef, 'width', w3_intToPxStr(100));
end;

There is one important rule when mixing raw JavaScript with Object Pascal code though, and that is that you must prefix any variables comming from the pascal side with the @ character. The reason is that when our obfuscator (a process that makes the generated sourcecode “unreadable” to human eyes) examines your code, all the names, variables and tokens are altered. As such, the compiler needs something extra to distinguish pascal symbols from raw JavaScript symbols. So all Object Pascal variables (or references) must be prefixed. Due to the nature of JavaScript, in some cases you also have to isolate references inside a ( .. ) block, like this:

procedure TMyObject.Testing;
asm
  (@self.FWidth) = parseInt( (@mRef).style.width );
end;

Of-course, you can use functions in W3System.pas to achieve the exact same thing:

procedure TMyObject.Testing;
begin
  Self.width := w3_getStyleAsInt(tagRef, 'width');
end;

Note: The above is not an example of how to size a control. TW3CustomControl have ample properties and methods for moving and resizing, just like TCustomControl have in Delphi.

Common RTL units

Smart does not try to mimic the Delphi unit names, although the list of functionality and component architecture share many similarities. The Smart RTL is in constant growth but as of writing the following units can be concidered “standard”. There are ofcourse more units in our runtime library, but these units represent the central hub of our system

  • W3System.pas – Low level function, procedures and types
  • W3Components.pas – Class hierarchy, from TW3TagObj to TW3CustomControl
  • W3Storage.pas – Wrappers for the JavaScript storage API
  • W3Ctrls.pas – Common controls like TW3Button, TW3Panel, TW3Checkbox and more
  • W3Time.pas – Timer and callback objects
  • W3Lists.pas – TW3StringList, TW3IntList and TW3ObjectList
  • W3Forms.pas – TW3CustomForm and associated information
  • W3Application.pas – The central objects that all programs build on
  • W3Effects.pas – Webkit animation objects
  • W3Graphics.pas – Full implementation of HTML5 canvas objects
  • W3Buffers.pas – Memory access and allocation objects
  • W3Inet.pas – Ajax and XML http objects
  • W3Touch.pas – Touch, multi-touch and gesture object
  • W3Fonts.pas – Objects for making fonts management more palatable
  • W3Styles.pas – Dynamic creation and management of styles and stylesheets

8 thoughts on “Differences between Delphi and Smart”

  1. Jose Torres says:
    01.02.2012 at 16:37

    Can I use a JavaScript library, like jQuery or Qooxdoo?

    Log in to Reply
    • Jon Lennart Aasenden says:
      01.02.2012 at 17:24

      Sure. Just add it to the “lib” folder and wrap it. You can access native JS through an ASM section, create an instance of it to a variant, and then access it’s methods directly. Take a look at some of the articles under “documentation” and also the developer’s log and you will examples for it 🙂
      You can also reference functions through the external keyword:

      function someNativeJSFunction:String;external;

      .. then you can call it just like any pascal method

      There is also a “add script” button in the IDE

      Log in to Reply
  2. hvassbotn says:
    01.06.2012 at 11:35

    > the “of object” ending for procedure references is not needed (and not supported)

    What is the rationale behind this (the not supported bit)?

    This makes it harder to share core code between native Delphi and Smart without using IFDEFs…?

    Log in to Reply
    • Jørn E. Angeltveit says:
      01.06.2012 at 14:13

      This feature was added just to annoy you, Hallvard 😉
      We knew that some smart guy would drop by one of these days and pick on this.
      —

      To be honest, I’m not sure. It’s been like this in DWS forever. The scripting engine doesn’t need to differentiate between function pointers, closures and procedure references.

      As long as the parameters (and result type) match, the declaration will accept standalone functions, object methods, interface methods, anonymous methods and record methods.

      It could, of course, be possible to accept the construct (both “reference to” and “of object”) and just let the compiler ignore it. Perhaps produce a hint during compilation.

      —

      UPDATE:
      I just received an answer from Eric on this, and there is no particular reason.

      “At the time I was unsure if introducing ‘of object’ or ‘reference to’ without enforcing them (ie. just having the parser ignore them) would be good or bad.

      We can add the support with a ‘pedantic’ hint, if there ain’t any argument against it.”

      Log in to Reply
    • Jon Lennart says:
      01.06.2012 at 17:53

      We added support for that today 🙂 Will be in the first hotfix!

      Log in to Reply
      • hvassbotn says:
        21.06.2012 at 08:44

        Cool! 🙂

        This might make it slightly more realistic to share some core / business logic code between a Smart and a Delphi project.

        Log in to Reply
  3. softwarex says:
    13.06.2012 at 20:23

    It would be awesome if someone could make a step by step tutorial (howto) on using external javascript like jQuery or Qooxdoo.
    Not everybody is an expert on both js and sms or delphi.
    So a step by step would be amazing. Not just general hints.

    Log in to Reply
    • Jon Lennart says:
      14.06.2012 at 00:49

      Unless you need something very, very spesific, you dont really need jquery under smart. But i do understand that other libraries can (and will) be absorbed by smart – so documentation is vital. Working with low-level stuff is something that will be best covered in the upcomming smart book (that can be bought now), but i’ll also write some articles on the subject over the holiday. Having said that, in order to absorb a javascript library – you will need at least some understanding of how javascript works, and also how smart creates controls and keeps track of them via handles (which is more or less identical to how delphi does it with windows handles).

      Log in to Reply

Leave a comment Cancel reply

You must be logged in to post a comment.

Pages

  • About
  • Feature Matrix
  • Forums
  • News
  • Release History
  • Download
  • Showcases
    • The Smart Contest 2013, Round 1 – Graphics
  • Store
  • Documentation
    • Creating your own controls
    • Debugging, exceptions and error handling
    • Differences between Delphi and Smart
    • Get the book
    • Getting started
      • Introduction
      • Local storage, session storage and global storage
      • Application architecture
      • The application object
      • Forms and navigation
      • Message dialogs
      • pmSmart Box Model
      • Themes and styles
    • Layout manager
    • Networking
      • Loading files
      • TW3HttpRequest
      • TW3JSONP
    • Prerequisites
    • Real data, talking to sqLite
    • System requirements
    • Project types
      • Visual project
      • Game project
      • Console project

Archives

  • December 2019
  • December 2018
  • November 2018
  • July 2018
  • June 2018
  • February 2018
  • September 2017
  • April 2017
  • November 2016
  • October 2016
  • September 2016
  • April 2016
  • March 2016
  • January 2016
  • October 2015
  • September 2015
  • July 2015
  • April 2015
  • January 2015
  • December 2014
  • October 2014
  • September 2014
  • August 2014
  • July 2014
  • June 2014
  • March 2014
  • February 2014
  • January 2014
  • December 2013
  • November 2013
  • October 2013
  • August 2013
  • July 2013
  • June 2013
  • May 2013
  • April 2013
  • March 2013
  • February 2013
  • January 2013
  • December 2012
  • November 2012
  • August 2012
  • July 2012
  • June 2012
  • May 2012
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • November 2011
  • October 2011
  • September 2011

Categories

  • Announcements (25)
  • Developers log (119)
  • Documentation (26)
  • News (104)
  • News and articles (16)

WordPress

  • Register
  • Log in
  • WordPress

Subscribe

  • Entries (RSS)
  • Comments (RSS)
© Optimale Systemer AS