Port the duskscript language into the engine as src/dusk/script + duskscriptcc
Brings over the duskscript VM and compiler from dusk-vm: the runtime (core/vm) lives under src/dusk/script, gated by DUSK_SCRIPT and wired into the engine lifecycle with print()/consolePrint() routed to the console; the standalone duskscriptcc compiler stays a lean host tool (linux/knulli only). Collapses int/fixed/bignum into a single float-backed SCRIPT_VALUE_NUMBER throughout the lexer, compiler, bytecode format and VM, removing the old int16-rollover fast paths and the type-conversion builtins they needed. Fixes a real big-endian bug in the bytecode's 32-bit number reader (found while adding GameCube/Wii endian support via util/endian.h) and converts src/dusk/script and duskscriptcc to dusk's memory/string/assert utilities, which surfaced two more latent bugs: a conservative GC stack scan reading its own local variable's address, and an uninitialized path buffer in scriptReadScript when the caller path has no directory component. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
1 parent
3948607b1e
commit
c1d6a97293
323 files changed
+18389
No files matched your search
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "util/memory.h"
|
||||
#include "scriptcompiletypes.h"
|
||||
#include "expression/scriptcompileliteral.h"
|
||||
#include "builder/scriptbuilderemit.h"
|
||||
#include "builder/scriptbuilderstring.h"
|
||||
#include "builder/scriptbuilderlocal.h"
|
||||
#include "builder/scriptbuildernative.h"
|
||||
#include <string.h>
|
||||
|
||||
void scriptCompileLiteral(scriptbuilder_t *builder, const scriptnode_t *node) {
|
||||
uint16_t name;
|
||||
uint8_t slot;
|
||||
const scriptnativeconstant_t *constant;
|
||||
int32_t bits;
|
||||
|
||||
switch(node->kind) {
|
||||
case SCRIPT_NODE_NUMBER:
|
||||
if(node->numberValue == (float)(int16_t)node->numberValue) {
|
||||
scriptBuilderOp(builder, SCRIPT_BC_PUSH_INT, 1);
|
||||
scriptBuilderU16(builder, (uint16_t)(int16_t)node->numberValue);
|
||||
} else {
|
||||
memoryCopy(&bits, &node->numberValue, sizeof(bits));
|
||||
scriptBuilderOp(builder, SCRIPT_BC_PUSH_NUMBER, 1);
|
||||
scriptBuilderI32(builder, bits);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCRIPT_NODE_BOOL:
|
||||
scriptBuilderOp(builder, node->number != 0 ? SCRIPT_BC_PUSH_TRUE : SCRIPT_BC_PUSH_FALSE, 1);
|
||||
break;
|
||||
|
||||
case SCRIPT_NODE_NULL:
|
||||
scriptBuilderOp(builder, SCRIPT_BC_PUSH_NULL, 1);
|
||||
break;
|
||||
|
||||
case SCRIPT_NODE_UNDEFINED:
|
||||
scriptBuilderOp(builder, SCRIPT_BC_PUSH_UNDEFINED, 1);
|
||||
break;
|
||||
|
||||
case SCRIPT_NODE_STRING:
|
||||
scriptBuilderOpFailing(builder, SCRIPT_BC_PUSH_STRING, 1);
|
||||
scriptBuilderU16(builder, scriptBuilderString(builder, node->text, node->length));
|
||||
break;
|
||||
|
||||
case SCRIPT_NODE_IDENT:
|
||||
constant = scriptBuilderConstantFind(builder, node);
|
||||
if(constant) {
|
||||
scriptBuilderOp(builder, SCRIPT_BC_PUSH_INT, 1);
|
||||
scriptBuilderU16(builder, (uint16_t)constant->value);
|
||||
break;
|
||||
}
|
||||
name = scriptBuilderName(builder, node->text);
|
||||
slot = scriptBuilderResolve(builder, name);
|
||||
if(slot == SCRIPT_COMPILE_BY_NAME) {
|
||||
scriptBuilderOp(builder, SCRIPT_BC_LOAD_VAR, 1);
|
||||
scriptBuilderU16(builder, name);
|
||||
} else {
|
||||
scriptBuilderOp(builder, SCRIPT_BC_LOAD_LOCAL, 1);
|
||||
scriptBuilderByte(builder, slot);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user