scripting engine add list literals

This commit is contained in:
nakst 2022-01-29 12:01:11 +00:00
parent f14586d2fa
commit cbb303c1e3
3 changed files with 155 additions and 117 deletions

View File

@ -182,121 +182,41 @@ void Start() {
// Set environment variables to force configure scripts to assume the unrecognised cross-compile target is okay.
if !buildCross {
SystemSetEnvironmentVariable("ac_cv_func_calloc_0_nonnull", "yes");
SystemSetEnvironmentVariable("ac_cv_func_chown_works", "yes");
SystemSetEnvironmentVariable("ac_cv_func_getgroups_works", "yes");
SystemSetEnvironmentVariable("ac_cv_func_malloc_0_nonnull", "yes");
SystemSetEnvironmentVariable("gl_cv_func_cbrtl_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_ceil_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_ceilf_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_ceill_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_chown_ctime_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_chown_slash_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_exp2l_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_expm1_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_fcntl_f_dupfd_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_fdopendir_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_floorf_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_fma_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_fmaf_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_fmal_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_fmod_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_fmodf_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_fmodl_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_fpurge_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_futimens_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_futimesat_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_getgroups_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_gettimeofday_clobber", "yes");
SystemSetEnvironmentVariable("gl_cv_func_hypot_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_hypotf_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_hypotl_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_isfinitel_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_isnanl_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_link_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_linkat_slash", "yes");
SystemSetEnvironmentVariable("gl_cv_func_log10_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_log10f_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_log1p_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_log1pf_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_log1pl_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_log2_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_log2f_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_log_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_logf_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_lstat_dereferences_slashed_symlink", "yes");
SystemSetEnvironmentVariable("gl_cv_func_mbrlen_empty_input", "yes");
SystemSetEnvironmentVariable("gl_cv_func_mbrtowc_empty_input", "yes");
SystemSetEnvironmentVariable("gl_cv_func_memchr_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_memmem_works_fast", "yes");
SystemSetEnvironmentVariable("gl_cv_func_mkdir_trailing_dot_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_mkdir_trailing_slash_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_mkfifo_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_mknod_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_modf_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_modff_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_modfl_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_nanosleep", "yes");
SystemSetEnvironmentVariable("gl_cv_func_open_directory_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_perror_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_printf_directive_a", "yes");
SystemSetEnvironmentVariable("gl_cv_func_printf_directive_f", "yes");
SystemSetEnvironmentVariable("gl_cv_func_printf_directive_n", "yes");
SystemSetEnvironmentVariable("gl_cv_func_printf_enomem", "yes");
SystemSetEnvironmentVariable("gl_cv_func_printf_flag_zero", "yes");
SystemSetEnvironmentVariable("gl_cv_func_printf_infinite", "yes");
SystemSetEnvironmentVariable("gl_cv_func_printf_infinite_long_double", "yes");
SystemSetEnvironmentVariable("gl_cv_func_printf_sizes_c99", "yes");
SystemSetEnvironmentVariable("gl_cv_func_pselect_detects_ebadf", "yes");
SystemSetEnvironmentVariable("gl_cv_func_ptsname_sets_errno", "yes");
SystemSetEnvironmentVariable("gl_cv_func_readlink_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_realpath_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_remainder_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_remainderf_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_remainderl_iee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_rename_dest_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_rename_link_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_rename_slash_dst_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_rename_slash_src_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_rmdir_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_round_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_roundf_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_select_detects_ebadf", "yes");
SystemSetEnvironmentVariable("gl_cv_func_setenv_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_signbit", "yes");
SystemSetEnvironmentVariable("gl_cv_func_signbit_gcc", "yes");
SystemSetEnvironmentVariable("gl_cv_func_sleep_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_snprintf_directive_n", "yes");
SystemSetEnvironmentVariable("gl_cv_func_snprintf_retval_c99", "yes");
SystemSetEnvironmentVariable("gl_cv_func_snprintf_truncation_c99", "yes");
SystemSetEnvironmentVariable("gl_cv_func_stat_dir_slash", "yes");
SystemSetEnvironmentVariable("gl_cv_func_stat_file_slash", "yes");
SystemSetEnvironmentVariable("gl_cv_func_stpncpy", "yes");
SystemSetEnvironmentVariable("gl_cv_func_strcasestr_linear", "yes");
SystemSetEnvironmentVariable("gl_cv_func_strchrnul_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_strerror_0_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_strstr_linear", "yes");
SystemSetEnvironmentVariable("gl_cv_func_strtod_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_svid_putenv", "yes");
SystemSetEnvironmentVariable("gl_cv_func_symlink_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_tdelete_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_trunc_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_truncf_ieee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_truncl_iee", "yes");
SystemSetEnvironmentVariable("gl_cv_func_tzset_clobber", "yes");
SystemSetEnvironmentVariable("gl_cv_func_ungetc_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_unlink_honors_slashes", "yes");
SystemSetEnvironmentVariable("gl_cv_func_unsetenv_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_usleep_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_utimensat_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_vsnprintf_posix", "yes");
SystemSetEnvironmentVariable("gl_cv_func_vsnprintf_zerosize_c99", "yes");
SystemSetEnvironmentVariable("gl_cv_func_vsprintf_posix", "yes");
SystemSetEnvironmentVariable("gl_cv_func_wcwidth_works", "yes");
SystemSetEnvironmentVariable("gl_cv_func_working_getdelim", "yes");
SystemSetEnvironmentVariable("gl_cv_func_working_mkstemp", "yes");
SystemSetEnvironmentVariable("gl_cv_func_working_mktime", "yes");
SystemSetEnvironmentVariable("gl_cv_func_working_strerror", "yes");
str[] variables = [
"ac_cv_func_calloc_0_nonnull", "ac_cv_func_chown_works", "ac_cv_func_getgroups_works", "ac_cv_func_malloc_0_nonnull",
"gl_cv_func_cbrtl_ieee", "gl_cv_func_ceil_ieee", "gl_cv_func_ceilf_ieee", "gl_cv_func_ceill_ieee",
"gl_cv_func_chown_ctime_works", "gl_cv_func_chown_slash_works", "gl_cv_func_exp2l_ieee", "gl_cv_func_expm1_ieee",
"gl_cv_func_fcntl_f_dupfd_works", "gl_cv_func_fdopendir_works", "gl_cv_func_floorf_ieee", "gl_cv_func_fma_works",
"gl_cv_func_fmaf_works", "gl_cv_func_fmal_works", "gl_cv_func_fmod_ieee", "gl_cv_func_fmodf_ieee",
"gl_cv_func_fmodl_ieee", "gl_cv_func_fpurge_works", "gl_cv_func_futimens_works", "gl_cv_func_futimesat_works",
"gl_cv_func_getgroups_works", "gl_cv_func_gettimeofday_clobber", "gl_cv_func_hypot_ieee", "gl_cv_func_hypotf_ieee",
"gl_cv_func_hypotl_ieee", "gl_cv_func_isfinitel_works", "gl_cv_func_isnanl_works", "gl_cv_func_link_works",
"gl_cv_func_linkat_slash", "gl_cv_func_log10_ieee", "gl_cv_func_log10f_ieee", "gl_cv_func_log1p_ieee",
"gl_cv_func_log1pf_ieee", "gl_cv_func_log1pl_ieee", "gl_cv_func_log2_ieee", "gl_cv_func_log2f_ieee",
"gl_cv_func_log_ieee", "gl_cv_func_logf_ieee", "gl_cv_func_lstat_dereferences_slashed_symlink", "gl_cv_func_mbrlen_empty_input",
"gl_cv_func_mbrtowc_empty_input", "gl_cv_func_memchr_works", "gl_cv_func_memmem_works_fast", "gl_cv_func_mkdir_trailing_dot_works",
"gl_cv_func_mkdir_trailing_slash_works", "gl_cv_func_mkfifo_works", "gl_cv_func_mknod_works", "gl_cv_func_modf_ieee",
"gl_cv_func_modff_ieee", "gl_cv_func_modfl_ieee", "gl_cv_func_nanosleep", "gl_cv_func_open_directory_works",
"gl_cv_func_perror_works", "gl_cv_func_printf_directive_a", "gl_cv_func_printf_directive_f", "gl_cv_func_printf_directive_n",
"gl_cv_func_printf_enomem", "gl_cv_func_printf_flag_zero", "gl_cv_func_printf_infinite", "gl_cv_func_printf_infinite_long_double",
"gl_cv_func_printf_sizes_c99", "gl_cv_func_pselect_detects_ebadf", "gl_cv_func_ptsname_sets_errno", "gl_cv_func_readlink_works",
"gl_cv_func_realpath_works", "gl_cv_func_remainder_ieee", "gl_cv_func_remainderf_ieee", "gl_cv_func_remainderl_iee",
"gl_cv_func_rename_dest_works", "gl_cv_func_rename_link_works", "gl_cv_func_rename_slash_dst_works", "gl_cv_func_rename_slash_src_works",
"gl_cv_func_rmdir_works", "gl_cv_func_round_ieee", "gl_cv_func_roundf_ieee", "gl_cv_func_select_detects_ebadf",
"gl_cv_func_setenv_works", "gl_cv_func_signbit", "gl_cv_func_signbit_gcc", "gl_cv_func_sleep_works",
"gl_cv_func_snprintf_directive_n", "gl_cv_func_snprintf_retval_c99", "gl_cv_func_snprintf_truncation_c99", "gl_cv_func_stat_dir_slash",
"gl_cv_func_stat_file_slash", "gl_cv_func_stpncpy", "gl_cv_func_strcasestr_linear", "gl_cv_func_strchrnul_works",
"gl_cv_func_strerror_0_works", "gl_cv_func_strstr_linear", "gl_cv_func_strtod_works", "gl_cv_func_svid_putenv",
"gl_cv_func_symlink_works", "gl_cv_func_tdelete_works", "gl_cv_func_trunc_ieee", "gl_cv_func_truncf_ieee",
"gl_cv_func_truncl_iee", "gl_cv_func_tzset_clobber", "gl_cv_func_ungetc_works", "gl_cv_func_unlink_honors_slashes",
"gl_cv_func_unsetenv_works", "gl_cv_func_usleep_works", "gl_cv_func_utimensat_works", "gl_cv_func_vsnprintf_posix",
"gl_cv_func_vsnprintf_zerosize_c99", "gl_cv_func_vsprintf_posix", "gl_cv_func_wcwidth_works", "gl_cv_func_working_getdelim",
"gl_cv_func_working_mkstemp", "gl_cv_func_working_mktime", "gl_cv_func_working_strerror"
];
for int i = 0; i < variables:len(); i += 1 {
SystemSetEnvironmentVariable(variables[i], "yes");
}
}
// Build libraries.

View File

@ -69,7 +69,7 @@ if [ $? -ne 0 ]; then
fi
# Compile the scripting engine.
gcc -o bin/script util/script.c -g -Wall -Wextra -fsanitize=address
gcc -o bin/script util/script.c -g -Wall -Wextra -O2
# Compile and run Build.
gcc -o bin/build -g util/build.c -pthread -DPARALLEL_BUILD -D${ES_TARGET-TARGET_X86_64} \

View File

@ -82,6 +82,7 @@
#define T_INDEX (91)
#define T_LIST (92)
#define T_IMPORT_PATH (93)
#define T_LIST_LITERAL (94)
#define T_EXIT_SCOPE (100)
#define T_END_FUNCTION (101)
@ -92,6 +93,8 @@
#define T_INTERPOLATE_BOOL (106)
#define T_INTERPOLATE_INT (107)
#define T_INTERPOLATE_FLOAT (108)
#define T_DUP (109)
#define T_SWAP (110)
#define T_FLOAT_ADD (120)
#define T_FLOAT_MINUS (121)
@ -837,9 +840,39 @@ Node *ParseExpression(Tokenizer *tokenizer, bool allowAssignment, uint8_t preced
node->firstChild = ParseType(tokenizer, false, false);
node->expressionType = node->firstChild;
if (!node->firstChild) return NULL;
} else if (node->token.type == T_LEFT_SQUARE) {
node->type = T_LIST_LITERAL;
Node **link = &node->firstChild;
bool needComma = false;
while (true) {
Token peek = TokenPeek(tokenizer);
if (peek.type == T_ERROR) {
return NULL;
} else if (peek.type == T_RIGHT_SQUARE) {
TokenNext(tokenizer);
break;
}
if (needComma) {
if (peek.type != T_COMMA) {
PrintError(tokenizer, "Expected a comma between list literal items.\n");
return NULL;
} else {
TokenNext(tokenizer);
}
}
Node *item = ParseExpression(tokenizer, false, 0);
if (!item) return NULL;
*link = item;
link = &item->sibling;
needComma = true;
}
} else {
PrintError2(tokenizer, node, "Expected an expression. "
"Expressions can start with a variable identifier, a string literal, a number, 'len', 'new', '!' or '('.\n");
"Expressions can start with a variable identifier, a string literal, a number, 'len', 'new', '!', '[' or '('.\n");
return NULL;
}
@ -2098,6 +2131,26 @@ bool ASTSetTypes(Tokenizer *tokenizer, Node *node) {
}
node->expressionType = &globalExpressionTypeBool;
} else if (node->type == T_LIST_LITERAL) {
if (!node->firstChild) {
// TODO Support empty list literals?
PrintError2(tokenizer, node, "Empty list literals are not allowed. Instead, put 'new T[]' where 'T' is the item type.\n");
return false;
}
Node *item = node->firstChild;
node->expressionType = (Node *) AllocateFixed(sizeof(Node));
node->expressionType->type = T_LIST;
node->expressionType->firstChild = item->expressionType;
while (item) {
if (!ASTMatching(node->expressionType->firstChild, item->expressionType)) {
PrintError2(tokenizer, item, "The type of this item is different to the ones before it in the list.\n");
return false;
}
item = item->sibling;
}
} else {
PrintDebug("ASTSetTypes %d\n", node->type);
Assert(false);
@ -2454,6 +2507,49 @@ bool FunctionBuilderRecurse(Tokenizer *tokenizer, Node *node, FunctionBuilder *b
FunctionBuilderAddLineNumber(builder, node);
FunctionBuilderAppend(builder, &node->operationType, sizeof(node->operationType));
return true;
} else if (node->type == T_LIST_LITERAL) {
// Step 1: Create the list.
uint8_t b = T_NEW;
int16_t isManaged = ASTIsManagedType(node->expressionType->firstChild) ? -2 : -1;
FunctionBuilderAddLineNumber(builder, node);
FunctionBuilderAppend(builder, &b, sizeof(b));
FunctionBuilderAppend(builder, &isManaged, sizeof(isManaged));
// Step 2: Resize the list.
uint32_t size = 0;
Node *item = node->firstChild;
while (item) { size++; item = item->sibling; }
b = T_DUP;
FunctionBuilderAppend(builder, &b, sizeof(b));
b = T_NUMERIC_LITERAL;
FunctionBuilderAppend(builder, &b, sizeof(b));
Value v;
v.i = size;
FunctionBuilderAppend(builder, &v, sizeof(v));
b = T_OP_RESIZE;
FunctionBuilderAppend(builder, &b, sizeof(b));
// Step 3: Populate the list.
item = node->firstChild;
uint32_t i = 0;
while (item) {
b = T_DUP;
FunctionBuilderAppend(builder, &b, sizeof(b));
FunctionBuilderRecurse(tokenizer, item, builder, false);
b = T_SWAP;
FunctionBuilderAppend(builder, &b, sizeof(b));
b = T_NUMERIC_LITERAL;
FunctionBuilderAppend(builder, &b, sizeof(b));
Value v;
v.i = i++;
FunctionBuilderAppend(builder, &v, sizeof(v));
b = T_EQUALS_LIST;
FunctionBuilderAppend(builder, &b, sizeof(b));
item = item->sibling;
}
return true;
}
@ -2825,6 +2921,7 @@ int ScriptExecuteFunction(uintptr_t instructionPointer, ExecutionContext *contex
while (true) {
uint8_t command = functionData[instructionPointer++];
// PrintDebug("--> %d\n", command);
if (command == T_BLOCK || command == T_FUNCBODY) {
uint16_t newVariableCount = functionData[instructionPointer + 0] + (functionData[instructionPointer + 1] << 8);
@ -3359,6 +3456,27 @@ int ScriptExecuteFunction(uintptr_t instructionPointer, ExecutionContext *contex
} else if (command == T_POP) {
if (context->stackPointer < 1) return -1;
context->stackPointer--;
} else if (command == T_DUP) {
if (context->stackPointer < 1) return -1;
if (context->stackPointer == context->stackEntriesAllocated) {
PrintError4(context, instructionPointer - 1, "Stack overflow.\n");
return 0;
}
context->stack[context->stackPointer] = context->stack[context->stackPointer - 1];
context->stackIsManaged[context->stackPointer] = context->stackIsManaged[context->stackPointer - 1];
context->stackPointer++;
} else if (command == T_SWAP) {
if (context->stackPointer < 2) return -1;
Value v1 = context->stack[context->stackPointer - 1];
Value v2 = context->stack[context->stackPointer - 2];
bool m1 = context->stackIsManaged[context->stackPointer - 1];
bool m2 = context->stackIsManaged[context->stackPointer - 2];
context->stack[context->stackPointer - 1] = v2;
context->stack[context->stackPointer - 2] = v1;
context->stackIsManaged[context->stackPointer - 1] = m2;
context->stackIsManaged[context->stackPointer - 2] = m1;
} else if (command == T_ASSERT) {
if (context->stackPointer < 1) return -1;
Value condition = context->stack[--context->stackPointer];