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
@@ -7,6 +7,12 @@ add_subdirectory(animation)
|
||||
add_subdirectory(assert)
|
||||
add_subdirectory(asset)
|
||||
add_subdirectory(console)
|
||||
if(
|
||||
DUSK_SCRIPT AND
|
||||
(DUSK_TARGET_SYSTEM STREQUAL "linux" OR DUSK_TARGET_SYSTEM STREQUAL "knulli")
|
||||
)
|
||||
add_subdirectory(duskscript)
|
||||
endif()
|
||||
add_subdirectory(error)
|
||||
add_subdirectory(thread)
|
||||
add_subdirectory(display)
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# Copyright (c) 2026 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
include(dusktest)
|
||||
|
||||
dusktest(test_duskscript.c)
|
||||
|
||||
# Compile the fixture scripts to bytecode with duskscriptcc at build time, so
|
||||
# the test exercises the real compiler -> runtime -> consolePrint pipeline.
|
||||
set(DUSKSCRIPT_TEST_FIXTURE_DS ${CMAKE_CURRENT_LIST_DIR}/fixture.ds)
|
||||
set(DUSKSCRIPT_TEST_FIXTURE_DSB ${CMAKE_CURRENT_BINARY_DIR}/fixture.dsb)
|
||||
set(DUSKSCRIPT_TEST_NUMBERS_DS ${CMAKE_CURRENT_LIST_DIR}/fixture_numbers.ds)
|
||||
set(DUSKSCRIPT_TEST_NUMBERS_DSB ${CMAKE_CURRENT_BINARY_DIR}/fixture_numbers.dsb)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${DUSKSCRIPT_TEST_FIXTURE_DSB}
|
||||
COMMAND duskscriptcc ${DUSKSCRIPT_TEST_FIXTURE_DS} -o ${DUSKSCRIPT_TEST_FIXTURE_DSB}
|
||||
DEPENDS duskscriptcc ${DUSKSCRIPT_TEST_FIXTURE_DS}
|
||||
COMMENT "Compiling duskscript test fixture"
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT ${DUSKSCRIPT_TEST_NUMBERS_DSB}
|
||||
COMMAND duskscriptcc ${DUSKSCRIPT_TEST_NUMBERS_DS} -o ${DUSKSCRIPT_TEST_NUMBERS_DSB}
|
||||
DEPENDS duskscriptcc ${DUSKSCRIPT_TEST_NUMBERS_DS}
|
||||
COMMENT "Compiling duskscript numbers test fixture"
|
||||
)
|
||||
add_custom_target(duskscript_test_fixture DEPENDS ${DUSKSCRIPT_TEST_FIXTURE_DSB} ${DUSKSCRIPT_TEST_NUMBERS_DSB})
|
||||
add_dependencies(test_duskscript duskscript_test_fixture)
|
||||
|
||||
target_compile_definitions(test_duskscript PRIVATE
|
||||
DUSKSCRIPT_TEST_FIXTURE="${DUSKSCRIPT_TEST_FIXTURE_DSB}"
|
||||
DUSKSCRIPT_TEST_NUMBERS="${DUSKSCRIPT_TEST_NUMBERS_DSB}"
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
print("print hello");
|
||||
consolePrint("consolePrint hello");
|
||||
@@ -0,0 +1,20 @@
|
||||
consolePrint(tostr(3 + 2));
|
||||
consolePrint(tostr(1.5 + 2.25));
|
||||
consolePrint(tostr(10 / 4));
|
||||
consolePrint(tostr(3 < 2));
|
||||
|
||||
var i = 0;
|
||||
var sum = 0;
|
||||
while(i < 5) {
|
||||
sum = sum + i;
|
||||
i = i + 1;
|
||||
}
|
||||
consolePrint(tostr(sum));
|
||||
|
||||
var arr = [10, 20, 30];
|
||||
consolePrint(tostr(arr[1]));
|
||||
|
||||
consolePrint(tostr(5 & 3));
|
||||
consolePrint(tostr(1 << 4));
|
||||
consolePrint(tostr(floor(3.7)));
|
||||
consolePrint(tostr(tonum("3.5")));
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "dusktest.h"
|
||||
#include "script/script.h"
|
||||
#include "console/console.h"
|
||||
|
||||
static void test_scriptRunsAndPrintsToConsole(void **state) {
|
||||
scripterror_t error;
|
||||
scriptresult_t result;
|
||||
|
||||
consoleInit();
|
||||
assert_int_equal(errorIsOk(scriptInit()), true);
|
||||
|
||||
result = scriptRuntimeRunFile(SCRIPT.runtime, DUSKSCRIPT_TEST_FIXTURE, true, &error);
|
||||
assert_int_equal(result, SCRIPT_OK);
|
||||
|
||||
// print() reaches the console through scriptPrintHandler.
|
||||
assert_string_equal(CONSOLE.line[CONSOLE_HISTORY_MAX - 2], "print hello");
|
||||
// consolePrint(text), the native, writes directly.
|
||||
assert_string_equal(CONSOLE.line[CONSOLE_HISTORY_MAX - 1], "consolePrint hello");
|
||||
|
||||
assert_int_equal(errorIsOk(scriptDispose()), true);
|
||||
consoleDispose();
|
||||
}
|
||||
|
||||
static void test_scriptNumbersAreAllFloats(void **state) {
|
||||
scripterror_t error;
|
||||
scriptresult_t result;
|
||||
// In the order fixture_numbers.ds prints them.
|
||||
const char_t *expected[] = {
|
||||
"5", "3.75", "2.5", "false", "10", "20", "1", "16", "3", "3.5"
|
||||
};
|
||||
const int32_t count = (int32_t)(sizeof(expected) / sizeof(expected[0]));
|
||||
int32_t i;
|
||||
|
||||
consoleInit();
|
||||
assert_int_equal(errorIsOk(scriptInit()), true);
|
||||
|
||||
result = scriptRuntimeRunFile(SCRIPT.runtime, DUSKSCRIPT_TEST_NUMBERS, true, &error);
|
||||
assert_int_equal(result, SCRIPT_OK);
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
assert_string_equal(CONSOLE.line[CONSOLE_HISTORY_MAX - count + i], expected[i]);
|
||||
}
|
||||
|
||||
assert_int_equal(errorIsOk(scriptDispose()), true);
|
||||
consoleDispose();
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_scriptRunsAndPrintsToConsole),
|
||||
cmocka_unit_test(test_scriptNumbersAreAllFloats),
|
||||
};
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
Reference in new issue
Block a user