Jump to content

Oxygene (programming language)

From Wikipedia, the free encyclopedia
Oxygene
DeveloperRemObjects Software
First appeared2005;19 years ago(2005)[1]
PlatformCommon Language Infrastructure,Java,Cocoa,CPU-Native,Windows32/64 bit,Linux32/64 bit,WebAssembly
LicenseTrialware
Websiteelementscompiler/elements/oxygene/
Influenced by
Delphi'sObject Pascal,C#

Oxygene(formerly known asChrome) is aprogramming languagedeveloped byRemObjects SoftwareforMicrosoft'sCommon Language Infrastructure,theJavaPlatform andCocoa.Oxygene is based onDelphi'sObject Pascal,but also has influences fromC#,Eiffel,Java,F#and other languages.

Compared to the now deprecatedDelphi.NET,Oxygene does not emphasize total backward compatibility, but is designed to be a "reinvention" of the language, be a good citizen on the managed development platforms, and leverage all the features and technologies provided by the.NETand Java runtimes.

Oxygene is a commercial product and offers full integration intoMicrosoft'sVisual StudioIDE on Windows, as well as its own IDE called Fire for use onmacOS.Oxygene is one of six languages supported by the underlying Elements Compiler toolchain, next toC#,Swift,Java,GoandMercury(based onVisual Basic.NET).

From 2008 to 2012, RemObjects Software licensed its compiler and IDE technology toEmbarcaderoto be used in theirEmbarcadero Prismproduct.[2]Starting in the Fall of 2011, Oxygene became available in two separate editions, with the second edition adding support for the Java and Android runtimes. Starting with the release of XE4, Embarcadero Prism is no longer part of the RAD Studio SKU. Numerous support and upgrade paths for Prism customers exist to migrate to Oxygene.[3]As of 2016, there is only one edition of Oxygene, which allows development on Windows or macOS, and which can create executables for Windows, Linux, WebAssembly.NET, iOS, Android, Java and macOS.

The language[edit]

The Oxygene language has its origins in Object Pascal in general and Delphi in particular, but was designed to reflect the guidelines of.NET programming and to create fully CLR-compliant assemblies. Therefore, some minor language features known from Object Pascal / Delphi have been dropped or revised, while a slew of new and more modern features, such as Generics or Sequences and Queries have been added to the language.

Oxygene is anobject-orientedlanguage, which means it uses classes, which can hold data and execute code, to design programs.[clarification needed]Classes are "prototypes" for objects, like the idea of an apple is the prototype for the apple one can actually buy in a shop. It is known that an apple has a colour, and that it can be peeled: those are the data and executable "code" for the apple class.

Oxygene provides language-level support for some features of parallel programming. The goal is to use all cores or processors of a computer to improve performance. To reach this goal, tasks have to be distributed among several threads. The.NET Framework'sThreadPoolclass offered a way to efficiently work with several threads. TheTask Parallel Library(TPL) was introduced in.NET 4.0 to provide more features for parallel programming.

Operators can be overloaded in Oxygene using theclass operatorsyntax:

classoperatorimplicit(i:Integer):MyClass;

Note, that foroperator overloadingeach operator has a name, that has to be used in the operator overloading syntax, because for example "+" would not be a valid method name in Oxygene.[4]

Program structure[edit]

Oxygene does not use "Units" like Delphi does, but uses.NET namespaces to organize and group types. A namespace can span multiple files (and assemblies), but one file can only contain types of one namespace. This namespace is defined at the very top of the file:

namespace ConsoleApplication1;

Oxygene files are separated into an interface and an implementation section, which is the structure known from Delphi. The interface section follows the declaration of the namespace. It contains theusesclause, which in Oxygene imports types from other namespaces:

uses
System.Linq;

Imported namespaces have to be in the project itself or in referenced assemblies. Unlike in C#, in Oxygene alias names cannot be defined for namespaces, only for single type names (see below).

Following theusesclause a file contains type declarations, like they are known from Delphi:

interface

type
ConsoleApp=class
public
classmethodMain;
end;

As in C#, the Main method is the entry point for every program. It can have a parameterargs: Array of Stringfor passing command line arguments to the program.

More types can be declared without repeating thetypekeyword.

The implementation of the declared methods is placed in the implementation section:

implementation

classmethodConsoleApp.Main;
begin
// add your own code here
Console.WriteLine('Hello World.');
end;

end.

Files are always ended withend.

Types[edit]

As a.NET language, Oxygene uses the.NET type system: There are value types (like structs) and reference types (like arrays or classes).

Although it does not introduce own "pre-defined" types, Oxygene offers more "pascalish" generic names for some of them,[5]so that for example theSystem.Int32can be used asIntegerandBoolean(System.Boolean),Char(System.Char),Real(System.Double) join the family of pascal-typenames, too. The struct character of these types, which is part of.NET, is fully preserved.

As in all.NET languages types in Oxygene have a visibility. In Oxygene the default visibility isassembly,which is equivalent to theinternalvisibility in C#. The other possible type visibility ispublic.

type
MyClass=publicclass
end;

The visibility can be set for every type defined (classes, interfaces, records,...).

An alias name can be defined for types, which can be used locally or in other Oxygene assemblies.

type
IntList=publicList<Integer>;//visible in other Oxygene-assemblies
SecretEnumerable=IEnumerable<String>;//not visible in other assemblies

Public type aliases won't be visible for other languages.

Records[edit]

Records are what.NET structs are called in Oxygene. They are declared just like classes, but with therecordkeyword:

type
MyRecord=record
methodFoo;
end;

As they're just.NET structs, records can have fields, methods and properties, but do not haveinheritanceand cannot implementinterfaces.

Interfaces[edit]

Interfaces are a very important concept in the.NET world, the framework itself makes heavy use of them. Interfaces are the specification of a small set of methods, properties and events a class has to implement when implementing the interface. For example, the interfaceIEnumerable<T>specifies theGetEnumeratormethod which is used to iterate over sequences.

Interfaces are declared just like classes:

type
MyInterface=publicinterface
methodMakeItSo:IEnumerable;
propertyBar:Stringreadwrite;
end;

Please notice, that for properties the getter and setter are not explicitly specified.

Delegates[edit]

Delegates define signatures for methods, so that these methods can be passed in parameters (e.g. callbacks) or stored in variables, etc. They're the type-safe NET equivalent to function pointers. They're also used in events. When assigning a method to a delegate, one has to use the@operator, so the compiler knows, that one doesn't want to call the method but just assign it.

Oxygene can create anonymous delegates; for example methods can be passed to theInvokemethod of a control without declaring the delegate:

methodMainForm.MainForm_Load(sender:System.Object;e:System.EventArgs);
begin
Invoke(@DoSomething);
end;

An anonymous delegate with the signature of the methodDoSomethingwill be created by the compiler.

Oxygene supports polymorphic delegates, which means, that delegates which have parameters of descending types are assignment compatible. Assume two classesMyClassandMyClassEx = class(MyClass),then in the following codeBlubbExis assignment compatible toBlubb.

type
delegateBlubb(sender:Object;m:MyClass);
delegateBlubbEx(sender:Object;mx:MyClassEx);

Fields can be used to delegate the implementation of an interface, if the type they're of implements this interface:

Implementor=publicclass(IMyInterface)
//... implement interface...
end;

MyClass=publicclass(IMyInterface)
fSomeImplementor:Implementor;publicimplementsIMyInterface;//takes care of implementing the interface
end;

In this example the compiler will create public methods and properties inMyClass,which call the methods / properties offSomeImplementor,to implement the members of IMyInterface. This can be used to provide mixin-like functionality.[6]

Anonymous methods[edit]

Anonymous methods are implemented inside other methods. They are not accessible outside of the method unless stored inside a delegate field. Anonymous methods can use the local variables of the method they're implemented in and the fields of the class they belong to.

Anonymous methods are especially useful when working with code that is supposed to be executed in a GUI thread, which is done in.NET by passing a method do theInvokemethod (Control.Invokein WinForms,Dispatcher.Invokein WPF):

methodWindow1.PredictNearFuture;//declared as async in the interface
begin
//... Calculate result here, store in variable "theFuture"
Dispatcher.Invoke(DispatcherPriority.ApplicationIdle,method;begin
theFutureTextBox.Text:=theFuture;
end);
end;

Anonymous methods can have parameters, too:

methodWindow1.PredictNearFuture;//declared as async in the interface
begin
//... Calculate result here, store in variable "theFuture"
Dispatcher.Invoke(DispatcherPriority.ApplicationIdle,method(aFuture:String);begin
theFutureTextBox.Text:=aFuture;
end,theFuture);
end;

Both source codes useanonymous delegates.

Property notification[edit]

Property notification is used mainly for data binding, when theGUIhas to know when the value of a property changes. The.NET framework provides the interfacesINotifyPropertyChangedandINotifyPropertyChanging(in.NET 3.5) for this purpose. These interfaces define events which have to be fired when a property is changed / was changed.

Oxygene provides thenotifymodifier, which can be used on properties. If this modifier is used, the compiler will add the interfaces to the class, implement them and create code to raise the events when the property changes / was changed.

propertyFoo:StringreadfFoowriteSetFoo;notify;
propertyBar:String;notify'Blubb';//will notify that property "Blubb" was changed instead of "Bar"

The modifier can be used on properties which have a setter method. The code to raise the events will then be added to this method during compile time.

Code examples[edit]

Hello World[edit]

namespaceHelloWorld;

interface

type
HelloClass=class
public
classmethodMain;
end;

implementation

classmethodHelloClass.Main;
begin
writeLn('Hello World!');
end;

end.

Generic container[edit]

namespaceGenericContainer;

interface

type
TestApp=class
public
classmethodMain;
end;

Person=class
public
propertyFirstName:String;
propertyLastName:String;
end;

implementation

uses
System.Collections.Generic;

classmethodTestApp.Main;
begin
varmyList:=newList<Person>;//type inference
myList.Add(newPerson(FirstName:='John',LastName:='Doe'));
myList.Add(newPerson(FirstName:='Jane',LastName:='Doe'));
myList.Add(newPerson(FirstName:='James',LastName:='Doe'));
Console.WriteLine(myList[1].FirstName);//No casting needed
Console.ReadLine;
end;

end.

Generic method[edit]

namespaceGenericMethodTest;

interface

type
GenericMethodTest=staticclass
public
classmethodMain;
private
classmethodSwap<T>(varleft,right:T);
classmethodDoSwap<T>(left,right:T);
end;

implementation

classmethodGenericMethodTest.DoSwap<T>(left,right:T);
begin
vara:=left;
varb:=right;
Console.WriteLine('Type: {0}',typeof(T));
Console.WriteLine('-> a = {0}, b = {1}',a,b);
Swap<T>(vara,varb);
Console.WriteLine('-> a = {0}, b = {1}',a,b);
end;

classmethodGenericMethodTest.Main;
begin
vara:=23;// type inference
varb:=15;
DoSwap<Integer>(a,b);// no downcasting to Object in this method.

varaa:='abc';// type inference
varbb:='def';
DoSwap<String>(aa,bb);// no downcasting to Object in this method.

DoSwap(1.1,1.2);// type inference for generic parameters
Console.ReadLine();
end;

classmethodGenericMethodTest.Swap<T>(varleft,right:T);
begin
vartemp:=left;
left:=right;
right:=temp;
end;

end.

Program output:

Type: System.Int32
-> a = 23, b = 15
-> a = 15, b = 23
Type: System.String
-> a = abc, b = def
-> a = def, b = abc
Type: System.Double
-> a = 1,1, b = 1,2
-> a = 1,2, b = 1,1

Differences between Delphi and Oxygene[edit]

  • unit:Replaced with thenamespacekeyword. Since Oxygene doesn't compile per-file but per-project, it does not depend on the name of the file. Instead the unit or namespace keyword is used to denote the default namespace that all types are defined in for that file
  • procedureandfunction:methodis the preferred keyword, thoughprocedureandfunctionstill work.
  • overload:In Oxygene all methods are overloaded by default, so no special keyword is needed for this
  • .Create():This constructor call has been replaced by thenewkeyword. It can still be enabled in theproject optionsfor legacy reasons
  • string:Characters in strings are zero-based and read-only. Strings can have nil values, so testing against empty string is not always sufficient.

Criticism[edit]

Some people[who?]would like to port their Win32 Delphi code to Oxygene without making major changes. This is not possible because while Oxygene looks like Delphi, there are enough changes so as to make it incompatible for a simple recompile. While the name gives it the appearance of another version of Delphi, that is not completely true.[7]

On top of the language difference, theVisual Component Libraryframework is not available in Oxygene.[8]This makes porting even more difficult because classic Delphi code relies heavily on the VCL.

See also[edit]

References[edit]

  1. ^"Evolution of the Oxygene Language | Oxygene | Elements".Archivedfrom the original on 2018-01-05.Retrieved2018-01-04.
  2. ^"Embarcadero Prism page, at the bottom of the page an image stating it is powered by RemObjects Oxygene".Archivedfrom the original on 2011-12-27.Retrieved2011-12-14.
  3. ^"Prism XE4, Where Art Thou? | RemObjects Blogs".Archived fromthe originalon 2013-06-20.Retrieved2013-06-06.
  4. ^"Operator Overloading - Delphi Prism".Archived fromthe originalon 2011-07-08.Retrieved2010-01-09.
  5. ^"Built-In Types - Delphi Prism".Archived fromthe originalon 2011-07-08.Retrieved2010-01-10.
  6. ^"Provide Mixin-like functionality - Delphi Prism".Archived fromthe originalon 2011-07-08.Retrieved2010-01-17.
  7. ^"A Stack Overflow discussion where people remark that Oxygene is not Delphi Win32".Archived fromthe originalon 2012-10-25.Retrieved2016-07-25.
  8. ^"Delphi Prism 2010 review where they state in the third paragraph that VCL.net is not available".Archivedfrom the original on 2009-09-04.Retrieved2009-12-14.

External links[edit]