The clike binary compiles a C-style language and immediately executes it using the PSCAL virtual machine. Source files may omit extensions; many examples in this project do so.
From the repository root run:
cmake -B build
cmake --build build --target clikeThis generates build/bin/clike.
sudo cmake --install buildInvoke the compiler with a source file:
build/bin/clike path/to/programFor example, run the text-based Hangman game:
build/bin/clike Examples/clike/base/hangman5The compiler translates the source to VM bytecode and executes it immediately.
Additional examples live in Examples/clike/base and Examples/clike/sdl, including sdl/multibouncingballs for an SDL demo and base/hangman5 for a console game.
--dump-bytecode: compile and disassemble bytecode before execution.--dump-bytecode-only: compile and disassemble bytecode and exit without executing.
These are useful for CI or debugging compiled output.
- Logical
&&and||short-circuit like C. - Shift operators
<<and>>are supported with standard precedence (lower than+/-, left associative). ~xon integer-typed operands behaves like bitwise NOT; on non-integer types it falls back to logical NOT.
When building with -DSDL=ON, the CLike preprocessor defines SDL_ENABLED. You can guard SDL-dependent code like:
#ifdef SDL_ENABLED
// graphics/audio code here
#else
printf("SDL not available\n");
#endifFor headless environments, set SDL_VIDEODRIVER=dummy and SDL_AUDIODRIVER=dummy or leave defaults as provided by the test scripts.
CLike supports simple module imports:
import "math_utils.cl";The compiler searches in the current directory, then in CLIKE_LIB_DIR if set, and finally in the built-in default install path. For project-local modules, set:
export CLIKE_LIB_DIR=$(pwd)/Examples/clike/baseCLIKE_LIB_DIR: directory for imported.clmodules.SDL_VIDEODRIVER,SDL_AUDIODRIVER: set todummyfor headless runs. SetRUN_SDL=1to run SDL content.
- Simple Web Server (CLike):
- Source:
Examples/clike/base/simple_web_server - Quick start:
build/bin/clike Examples/clike/base/simple_web_server /path/to/htdocs 8080 - Documentation:
Docs/simple_web_server.md - A basic
htdocstree is available in the PSCAL clone atlib/misc/simple_web_server/htdocs.
- Source:
CLike maps the VM's worker-pool builtins to lowercase helpers:
thread_spawn_named(target, name, ...)– launches an allow-listed builtin on a worker thread, returning aThreadhandle. Additional arguments are forwarded to the builtin before an options record that sets the thread name.thread_pool_submit(target, name, ...)– queues work on the shared pool without stealing the worker from the caller. The returned handle can be joined withWaitForThread.WaitForThread(handle)– joins the worker, returning0when it reported success and consuming the cached status flag so the slot can be reused immediately if no result value is pending.thread_set_name(handle, name)/thread_lookup(nameOrId)– rename handles or resolve them by name.thread_pause,thread_resume, andthread_cancelmirror the VM control operations; the helpers return1on success and0otherwise.thread_get_result(handle, consumeStatus)andthread_get_status(handle, dropResult)surface the stored payloads and success flags. Pass a non-zero second argument to release the slot after reading when you bypassedWaitForThreador still need to drop a cached result value.thread_stats()returns an array of records describing each worker participating in the pool so scripts can report metrics or feed dashboards.
The CLike front end can call VM HTTP builtins directly. Common helpers:
httpsession(): int– create a session; returns session id or -1 on error.httpclose(s)– free session.httpsetheader(s, name, value)– set request header.httpclearheaders(s)– clear accumulated headers.httpsetoption(s, key, value)– set options; supported keys include:timeout_ms(int),follow_redirects(int 0/1),user_agent(string)ca_path,client_cert,client_key,proxy(strings)verify_peer(0/1),verify_host(0/1),http2(0/1)basic_auth(stringuser:pass),out_file(string path)
httprequest(s, method, url, bodyStr|mstream|null, outMStream): int– perform request.httprequesttofile(s, method, url, body, outPath): int– stream response to file.httpgetlastheaders(s): string– raw response headers for last request.httpgetheader(s, name): string– convenience header lookup.httperrorcode(s): int– VM error class (0 none; 1 generic; 2 I/O; 3 timeout; 4 SSL; 5 resolve; 6 connect).httplasterror(s): string– last libcurl error message if any.
Notes:
file://URLs are supported without libcurl; the runtime reads the file and synthesizes basic headers.- If
out_fileis set viahttpsetoption,httprequesttees the response to both memory and the file.
Per-session options configured with httpsetoption:
- TLS:
tls_min/tls_max: 10, 11, 12, 13 map to TLSv1.0–TLSv1.3 (min and max).alpn: 0/1 toggles ALPN when available.ciphers: set cipher list (OpenSSL format).pin_sha256: pinned public key forCURLOPT_PINNEDPUBLICKEY(sha256//BASE64or file path).
- Proxies:
proxy: proxy URL (e.g.,http://proxy:8080).proxy_userpwd:user:passcredentials.proxy_type:http,https(if supported),socks5,socks4.
- DNS overrides:
resolve_add: addhost:port:addressmapping.resolve_clear: clear overrides.
Example (guarded by RUN_NET_TESTS):
int main() {
if (getenv("RUN_NET_TESTS") == NULL || strcmp(getenv("RUN_NET_TESTS"), "1") != 0) {
printf("Set RUN_NET_TESTS=1 to run this demo.\n");
return 0;
}
const char* url = getenv("URL"); if (!url) url = "https://example.com";
const char* pin = getenv("PIN_SHA256");
int s = httpsession();
httpsetoption(s, "tls_min", 12);
httpsetoption(s, "alpn", 1);
if (pin && pin[0]) httpsetoption(s, "pin_sha256", pin);
mstream out = mstreamcreate();
int code = httprequest(s, "GET", url, NULL, out);
printf("status=%d err=%d msg=%s\n", code, httperrorcode(s), httplasterror(s));
mstreamfree(&out);
httpclose(s);
return 0;
}Example:
int main() {
int s = httpsession();
httpsetheader(s, "Accept", "text/html");
httpsetoption(s, "timeout_ms", 5000);
mstream out = mstreamcreate();
int code = httprequest(s, "GET", "https://example.com", NULL, out);
printf("status=%d, ctype=%s\n", code, httpgetheader(s, "Content-Type"));
mstreamfree(&out);
httpclose(s);
return 0;
}The VM also exposes thin wrappers over BSD sockets:
socketcreate(type[, family])– create TCP (0) or UDP (1) sockets. Pass6(or anAF_INET6constant) for IPv6 sockets; the default is IPv4.socketconnect(s, host, port)– connect to a remote host/port.socketbind(s, port),socketlisten(s, backlog),socketaccept(s)– server helpers.socketsend(s, data)andsocketreceive(s, maxlen)– send or receive strings or memory streams.socketsetblocking(s, bool)toggles blocking mode;socketpoll(s, timeout_ms, flags)polls for read (1) or write (2).socketlasterror()returns the last error code anddnslookup(host)resolves hostnames.
See Examples/clike/base/SocketEchoDemo for a complete echo server/client demo.