When we designed the X# compile and X# Runtime we had a few focus points in mind:

  • The language and runtime should be VO compatible whenever possible. We know that the Vulcan devteam made some decisions not to support certain features from VO, but we decided that we would like to be as compatible as technically possible.
  • We want our runtime to be fully Unicode and AnyCPU. It should run on any platform and also both in x86 and x64 mode.  That has caused some challenges because VO is Ansi (and not Unicode) and also X86. In VO you can cast a LONG to a PTR. That will not work in X64 mode because a LONG is 32 bits and a PTR 64 bits
  • We want the code to compile in "Safe" mode. No unsafe code when not strictly needed. The biggest problem / challenge here is the PTR type. With a PTR you can access memory directly and read/write from memory, even if you don't "own" that memory. However the same PTR type is also used as "unique identifier" for example in the low level file i/o and in the GUI classes for Window and Control handles. These PTR values are never used to read/write memory but are like object references. We have decided to use the .Net IntPtr type for this kind of handles. Of course the compiler can transparently convert between PTR and IntPtr.
  • We want to prove that the X# language is a first class .Net development language. That is why we decided to write the X# runtime in X#. By doing that we also create a large codebase to test the compiler. So that is a win - win situation.
  • We want the runtime to be thread safe. Each thread has its own "global" state and its own list of open workareas. When a new thread is started it will inherit the state of the main thread but will not inherit the workareas from the main thread
  • At this moment the X# Runtime is compiled against .Net Framework 4.6.

Assemblies in the X# Runtime

If you want to know in which Assembly a function or type is defined then your "best friend" is the documentation. We are using a tool to generate the documentation, so this is always correct.
Some subsystems have functions XSharp.Core DLL and in XSharp.VO.DLL as well.

Component

Description

Language / dialect used

Framework Version

XSharp.Core.DLL

This is the base DLL of the X# Runtime.

X# Core

4.6

XSharp.VO.DLL

This DLL adds features to the runtime that are needed for the VO dialect.

X# VO

4.6

XSharp.Macrocompiler.DLL

This DLL is the X# "full" macro compiler.

X# Core

4.6

XSharp.RDD.DLL

This will contain the various RDDs implemented for X#. It is not included yet.

X# Core

4.6

VO SDK Class libraries

These are  not included.

Beta 2 will include a tool that will read the registration information from your VO installation and will then create a project on your machine to compile the SDK against the X# runtime

X# VO

4.6

Known Issues

  • Some of the string conversion functions such as Str() and NTrim() do not always return the same string as VO . In VO the return value of these functions heavily depends on state settings such as SetFixed, SetDecimals, SetScience and more. This will be most likely fixed in Beta 2
  • Some of the TransForm() pictures also depend on the same settings as Str() and NTrim() and have the same problems
  • The macro compiler in this release is fully functional but not as fast as we'd like. We are working on a smaller and faster macro compiler.
  • The RDD system as well as the Db..() and VoDb..() functions are missing

Missing or incomplete Features

Feature

Description

Expected when

RDD system

There are some helper classes, defines etc  already defined in the runtime but the RDD system is not complete. You will NOT find the familiar Db functions and VoDb functions. Also functions like BOF(), EOF(), RecNo() and Found() are not included yet.

Beta 2 will include the Db.. and VoDb functions and will most likely contain one of more RDDs

MemVar support

There are already some statements in the language (like MEMVAR, PRIVATE etc) but the underlying runtime support and compiler support is not ready

Beta 3 will most likely contain the MEMVAR support

Some runtime functions are not supported yet:
Crypt functions (Crypt(), CryptA())
Encoding functions (B64Enc.., UUEnc.., GetChunkBase64 etc)
 

These functions will most likely be added in one of the next betas. For now they will throw a notimplementedexception when you use them

Beta 2 and Beta 3

Fast Macro compiler

We are not happy with the speed of the current macro compiler. It is very powerful but compiling a macro simply takes too much time. We are working on a replacement for this. To help increase performance we are caching compiled macros at this moment, so the second time you compile the same macro you will get the same codeblock back as the first time. That helps but is not enough.

September 2018.

Description of Various Subsystems

Subsystem

Remarks

Low Level File IO

These functions are implemented in XSharp.Core.
There is an important difference between the implementation in XSharp.Core when compared to VO.
In VO the file handles returned from functions such as FCreate() and FOpen() are OS file handles. That means that you can also pass them directly to Win32 API Functions. In the X# Runtime that is no longer possible.
We use .Net FileStream objects for the File IO. The File handler returned (which is of the IntPtr type) is a unique key into a table where we are storing these File IO objects. The keys are generated from random numbering. You can't and shouldn't rely on the values of these keys.

Static Memory IO

The static memory subsystem allocates memory using the Marshal.AllocHGlobal functionality. Each memory block has 2 guard blocks that contain information about the group number, size and a magic number. We have also implemented memory groups.
Unlike in VO you cannot release all blocks in a group by simply closing the Memory Group.
If you want to enumerate allocated blocks you should first call MemTrace(TRUE) to enable block tracing.
Then create a function with the following prototype

 
FUNCTION MyMemWalker(pMem AS IntPtr, nSize AS DWORD) AS LOGIC

Then call MemWalk and pass your function as parameter. The runtime will call your function and will pass in all memory blocks that have been allocated and not released yet.

 

Late Binding Support

The Runtime fully supports late binding. The late binding support still needs some optimizations.
We recommend to only use this when necessary. New code should either use the DYNAMIC type or try to use early bound code as much as possible.

 

Combining the X# Runtime and Vulcan Runtime

Technically it is possible to include both the X# and the Vulcan runtime libraries in your application. When you do so then the compiler will assume that you want to use the X# implementations for the XBase types such as USUAL and DATE. If the compiler does not find the XSharp.Core and XSharp.VO assemblies then it will assume you want to map these types to the Vulcan runtime types.

So you can mix things. However if you want to call code in the Vulcan runtime DLLs you may have to use the fully qualified classnames or typenames.

And remember: there is no automatic translation between the X# types and Vulcan types.

If you want to convert an X# variable to a Vulcan variable you may have to cast it to an intermediate type  first.

Call Vulcans implementation of Left()

LOCAL cValue as STRING
cValue := VulcanRTFuncs.Functions.Left("abcdefg",2)

If you want to convert an X# usual to a Vulcan usual, cast to OBJECT

LOCAL xUsual as USUAL
LOCAL vUsual as Vulcan.__Usual
xUsual := 10
vUsual := (OBJECT) xUsual

For dates you can do something similar. In that case you should cast the X# date to a DateTime.

LOCAL xDate as DATE
LOCAL vDate as Vulcan.__VODate
xDate := ToDay()                        // will call the X# implementation of ToDay()
vDate := (System.DateTime) xDate

 

 

Comments   

#1 Johan Nel 2018-06-14 07:56
Well done guys,
There is no stopping this team from capturing the XBase world!
Johan

You need to login to post comments on this website.