wasmpascal v1.1.3: The Compiler Learns to Complain, maybe a bit too much...

12-09-2026



I spent the last week checking every program I have in the examples to find out where the compiler was swallowing errors and warnings. Programs that had syntax issues compiled with exit code 0 — some even produced a .wasm binary that would fail at runtime.

Along the way, I updated wasmpascal to say where and why a program breaks. Warnings won't stop the compilation process, but they are pretty handy to help clean up your code. Error reporting is a bit better now, with clearer error messages for some common issues.


1. Stop compiling broken code

There were quite a few examples of code that seemed to compile, but that should not have, like:

P();                   // one-param P called with no params at all
P(1, 2);               // or called with too many
x := s;                // s is a String, x is an Integer
x := rec;              // rec is a record, x is an Integer
writeln('a')           // no ';' before the next statement
            

All of them are rejected now, with better error descriptions in most instances:

error: wrong number of parameters in call to 'P': expected 2, got 1
error: type mismatch: cannot assign String to Integer
error: missing ';' between statements (found 'writeln')
error: unexpected end of file: the source must end with 'end.'
            

2. Builtins ignored arguments

Builtins, the functions and procedures the runtime provides, would silently fail and leaving no clue that there's a problem, as with:

GotoXY(5);            // the console call was emitted as NOTHING
ArcTan2(y);           // emitted ArcTan2(0, 0) -> always returned 0.0
GetMem(a);            // no allocation, no error
FillChar(ar2, 8);     // the array was left untouched
Move(arr[0], arr[4]); // the copy was silently skipped
            

This has now been addressed and should no longer just silently cause issues. Instead, a proper error is issued by the compiler for these as well.


3. Conditional compilation

The preprocessor had faulty logic that would compile BOTH the branches, irrespective of the boolean check:

{$IF 1}
const WHICH = 'TRUEBRANCH';
{$ELSE}
const WHICH = 'ELSEBRANCH';
{$ENDIF}
            

Though not often used, this is clearly a problem so I reworked the logic so it only bothers to compile the actual block it should and not both.


4. A unit's begin ... end. is also code

Pascal units can have an initialisation section — a begin ... end. at the end that runs before the program body. Wasmpascal previously happily ignored this code, so you could not initialise variables as one would have expected to be possible.

unit u_counter;
interface
var counter: Integer;
implementation
begin
  counter := 42;   // nobody parsed this
end.
            

This has been fixed, so units can now also assign values like one would expect.


5. Diagnostic messages are clearer now

Not much to say other than I've cleaned up messages a bit to be less cryptic and add more context and information where it's available.


6. The compiler has warnings now

Warnings will not fail your build, but the compiler emits them anyway. Sometimes an unused variable warning can tell you where you made a logic error in your code, so I find these pretty handy to have around.


Try it out

Everything is live at https://wasmpascal.com/. Write a deliberate typo, call GotoXY with one argument, or drop a semicolon, and watch the compiler tell you exactly what it thinks. Then select one of the examples — Flight Leader, Pascaloids, Xonix, Minesweeper, Pong — hit Run, and have some fun with Pascal in your browser.

The examples and tutorials live in the wasmpascal_examples repository, and earlier writing about the project is on the blog:



Return to the blog index