FoxDev StudioFor Visual FoxPro 9 applications

FoxPro webassembly runtime + IDE

A Love letter to FoxPro

CustomerCompanyWestern Trading Co.Credit limit25,000.00Save

What it looks like

The goal is to have feature parity with the good ol FoxPro

By leveraging golden tests against vfp9 we aim at having 100% compatibility. That is the mission.

1,722elements of the Visual FoxPro 9 language reference known to the runtime
1,534of them exercised by a test that compares the answer with the product's
3names it has not met yet; everything else runs, is ignored on purpose, or is refused by name

What Visual FoxPro 10 would have been

Visual FoxPro stopped at version 9, and at 32 bits. This is the same language, rebuilt on a web foundation that brings the fox to the next level. Four pieces are what make that possible.

Where a call goes/and where the 32-bit world stops
64-BIT32-BITThe form on screenReact, drawing straight from the tree belowrepaints one control, not the formThe live object treeevery control, with its properties and its eventsTHISFORM.lblGreeting.Caption = cMsgThe virtual machineyour code, compiled to bytecode, run in WebAssemblyyields a request, never blocksThe hostfiles, tables, COM, and 64-bit libraries in processSET LIBRARY TOfllhost.exea 32-bit process, holding your .fll
64-bit, end to end

Using Nodejs as host give us 64 bit offsets for the DBF, lifting the 2 GB limit

There are really good projects, battle tested that brings vfp9 to 64 bits. We aim at something much bigger, an open runtime capable of loading 64 bit libraries and going above and beyond the closed source vfp9 limitations.

The offset/and what it reaches
Visual FoxPro2,147,483,647bytes: the table stops at 2 GBthe leading bit carries the sign, which is why it is 2 GB and not 4FoxDev Studio9,223,372,036,854,775,807bytes: the offset is never what stopsevery byte of every read and write is addressed this wayWhat that buys one tableEvery square below is 2 GB: the whole of what a Visual FoxPro table could hold.2 GB279 squares: one FoxDev table of 130-byte records, 558 GB.At 1 KB records it reaches 4.4 TB, which is 2,200 of them.what stops it now is the DBF header's own record count
The virtual machine

A compiler, and a machine built to run what it makes

Visual FoxPro compiled your program to p-code and shipped a runtime to execute it. This is the same arrangement, made again: a compiler and a bytecode interpreter written in Rust and compiled to WebAssembly, so one machine runs your code wherever the application runs. The editor checks what you type through that very compiler, so what it underlines and what the runtime refuses cannot drift apart.

A running program is a fiber. When it needs something from the world outside (a message box, a modal form, the next record) it does not call out and block; it yields, the work is done while the machine is off the stack, and the answer is handed back. That is why MESSAGEBOX() stops your program without freezing the window behind it, why READ EVENTS waits without spinning, and whySetFocus can fire GotFocus, and Init can run while a form is still being built, in the order FoxPro always did it.

How the machine works and what it runs.

The screen

Forms rendered using React and a custom DOM tree

A running form is a live tree of objects with the properties you would expect, and the interface is drawn straight from that tree by React. Each object watches only itself, so THISFORM.lblGreeting.Caption = cMsg repaints one label rather than the whole form. On a dense screen that is the difference between instant and sluggish.

The 32-bit bridge

Old libraries are battle tested, we support them

An .fll is a 32-bit image, and every process in a 64-bit application is 64-bit, so nothing inside the application itself could ever open one. Rather than tell you it is impossible, SET LIBRARY TO starts a small 32-bit process whose only job is to hold your library, and the runtime talks to it. The calls are synchronous, because a program may call into a library halfway through an expression, and an answer that arrived later would not be an answer. It is measured against real libraries: the encryption library, FoxTools, and libraries built from Microsoft's own API samples.

Nothing 64-bit needs the bridge: DECLARE ... DLL reaches a modern library in the same process, and automation objects are reached the way they always were. The old road stays open; it just is not the only one any more.

FoxScript: the same language, with more room

Everything you have written still means what it always meant. FoxScript only adds on top: a block you can hand to something else to run later, and a way to answer a web request from the code that already knows your business.

server.prg/FoxScript
&& your old add-in libraries load just as before
SET LIBRARY TO "vfpencryption71.fll" ADDITIVE

LOCAL oServer
oServer = FoxScript.Http.CreateServer()

oServer.Get("/api/v1/customers/:id", LAMBDA(req, res)
    LOCAL lnId
    lnId = VAL(req.Params("id"))

    SELECT * FROM customer WHERE cust_id = lnId INTO CURSOR c_cust

    IF RECCOUNT("c_cust") > 0
        res.Status(200).Json(FoxScript.Data.CursorToJson("c_cust"))
    ELSE
        res.Status(404).Json('{"error": "Not found"}')
    ENDIF

    USE IN c_cust
ENDLAMBDA)

oServer.Listen(8080)
READ EVENTS

Every line of that runs on the same runtime your forms do. The queries, the cursor and the library call are ordinary FoxPro; the lambda and the server are what FoxScript adds: no second language, no service to stand up beside it.The keywords and the HTTP APIare each written down in full.

Download

The nightly is rebuilt from every push to main and published as a pre-release on GitHub. Unsigned, so the first launch asks you to confirm.

Read the documentation

Each part of the product is written down, including the parts that are not there yet.

What is coming

Work already mapped out, roughly in the order it is being built.

The last of the languageA short list of corners is still open, each one checked against the original as it closes.
ReportsThe report designer and the report engine, band by band, measured the same way the rest was.
Tables past two gigabytes, as a format of their ownThe 64-bit offsets are there today; a container that is honest about the DBF header's limits comes next.
An installer for what you shipYour application handed to the people who use it as a single thing they can run, with nothing to set up first.