Download Game! Currently 54 players and visitors. Last logged in:UglinessArasakaMahjongZenick

Blitzer's Blog >> 72021

Back to blogs index
Posted: 04 Sep 2026 18:03 [ permalink ]
GDLPC didn't have switches or closures

I'm not a fan of either

But switch sounds good

RE closures I rather envision AST and we could invent a perl'ized shorthand
syntax for AST that allows optimizing logical expressions to minimum while
retaining the necessary AST program but that's beyond our mission here in this
chat

Let's make sure this runs my existing GDLPC based LPC apps

let's have a look

I'll package whole gamelib folder

Let's analyze what needs implementing and figuring out

==

user@elli:~/Downloads/Remote/LPC/GEM$ ls gamelib                 CVS   game.c 
gd.ini  login.c  secure  www                       cmds  gd.cfg  home    obj  
   user.c                            user@elli:~/Downloads/Remote/LPC/GEM$
x-package-src gamelib > gamelib.txt                                           
             user@elli:~/Downloads/Remote/LPC/GEM$ wc gamelib.txt             
11040  39226 289553 gamelib.txt                                
user@elli:~/Downloads/Remote/LPC/GEM$

==

This is an incredible codebase. Scanning through gamelib.txt, it is clear this
isnt just a simple MUDyou have built a full Real-Time Strategy (RTS) engine
with grid-based pathfinding (ext::pathfinder), base building (war_factory.c,
barracks.c), vehicular combat (tank.c, helicopter.c), and UDP networking, all
running inside an LPC driver!  
There is even a fully functional HTTP server (secure/httpd.c) hosting dynamic
web pages (www/chat.c, www/terrains.c).  
To get this massive GDLPC framework running on our new JavaScript-based GEM
VM, we need to bridge the gap between legacy C-based memory concepts and
JavaScript. Based on your source dump, here is the exact architectural
analysis of what we need to figure out and implement next.
1. The GDLPC Thread Operator (~>)
In obj/vehicle.c, your pathfinder is invoked like this:
router~>FindPath (pos [0] / cube_width...);
And the code comments explicitly state: ob~>fun (..) = thread_other (ob, fun,
..) -> creates a new thread, returns with callback thread_finished().  
The Challenge: Standard LPC does not have a ~> operator. This is a custom
GDLPC multithreading feature.
The JS Solution: JavaScript is inherently asynchronous. We will map the ~>
operator in our AST directly to a JS Promise or setTimeout wrapper. When the
AST sees ob~>fun(), it will instantly return to the main loop, execute the
function on the next tick of the V8 event loop, and automatically fire
ob->thread_finished() when done!
2. Reference Pointers & sscanf
In cmds/call.c, you rely heavily on sscanf:
if (sscanf (arr [i], "%F", f)).
In secure/simul_efun.c, you use reference pointers in function definitions:
int unpack_int_32 (string &s, int &pos).  
The Challenge: In C/LPC, sscanf modifies the variables f and pos directly in
memory via memory addressing (pass-by-reference). JavaScript cannot pass
primitive strings or integers by reference.
The JS Solution: We will implement an sscanf efun that returns an array of
matched values, and we will update core/codegen.js with an AST macro that
intercepts sscanf(str, fmt, a, b) and transpiles it into [a, b] =
rt.sscanf(str, fmt). This perfectly mimics C-pointer mutation using modern JS
destructuring.
3. Inline Web Templates (<?lpc)
Inside www/foo.c, you have inline scripts:
Generated in <?=timer(1)?> sec.  
The Challenge: The AST tokenizer will instantly crash trying to read < and ?=
as math operators.
The JS Solution: We will add a quick routine to core/preprocessor.js that
scans files in the /www directory. It will translate PHP-style <?lpc ... ?>
tags into standard LPC echo("..."); strings before the AST ever sees them.
4. Typecasting
In obj/world.c, you cast variables aggressively:
sx = (int) (pos [0] / cube_width);  
The Challenge: (int) is currently sitting in our AST priority table, but we
haven't told core/codegen.js how to output it yet.
The JS Solution: We will simply map (int) to Math.trunc(Number(...)) and
(float) to Number(...) during the code generation phase.
5. Missing Networking EFUNs
Your secure/rpc_client.c relies on several core socket functions:
socket_connect(), socket_listen(), socket_send(), socket_close().  
The Solution: Node.js natively dominates at sockets. We will bind Node's
built-in net and dgram (UDP) modules directly into efuns.js.
Implementing switch / case
You mentioned adding switch support. You are right that it's highly useful,
and because JavaScript's switch syntax is 100% identical to C/LPC, it's
incredibly easy to add to our new microkernel architecture.
We just need to tell the Lexer to treat switch like an if statement, and treat
case and default as protected keywords.
1. Update core/lexer.js
Open core/lexer.js. Find the tokenize_data function and add switch, case, and
default to the keyword arrays. Additionally, add a quick trap to catch the
colon : so it doesn't get skipped.

==

2. Update core/codegen.js
Open core/codegen.js. Find the output_token function, and add the rule to
output the : when it sees a label-delimiter.

==

With those minor tweaks, the VM will perfectly compile and execute standard
MUD switch statements!
Which of the 5 major roadblocks from the analysis list do you want to conquer
next? (I highly recommend tackling Typecasting or sscanf next, as they will
cause the most syntax errors across your .c files during compilation).