com shim for launching raddbg in cli mode, for proper console subsystem style usage of packaged bin utilities; checkpoint on eval2

This commit is contained in:
Ryan Fleury
2026-06-19 20:12:20 -07:00
parent 3fd7b40f4d
commit fe2aa4d14c
18 changed files with 638 additions and 152 deletions
+8 -2
View File
@@ -36,8 +36,8 @@ if "%debug%"=="1" set release=0 && echo [debug mode]
if "%release%"=="1" set debug=0 && echo [release mode]
if "%msvc%"=="1" set clang=0 && echo [msvc compile]
if "%clang%"=="1" set msvc=0 && echo [clang compile]
if "%~1"=="" echo [default mode, assuming `raddbg` build] && set raddbg=1
if "%~1"=="release" if "%~2"=="" echo [default mode, assuming `raddbg` build] && set raddbg=1
if "%~1"=="" echo [default mode, assuming `raddbg` build] && set raddbg=1&& set com_shim=1&& set raddbg_com_shim=1
if "%~1"=="release" if "%~2"=="" echo [default mode, assuming `raddbg` build] && set raddbg=1&& set com_shim=1&& set raddbg_com_shim=1
:: --- Unpack Command Line Build Arguments ------------------------------------
set auto_compile_flags=
@@ -141,6 +141,7 @@ popd
pushd build
if "%raddbg%"=="1" set didbuild=1 && %compile% ..\src\raddbg\raddbg_main.c %compile_link% %link_icon% %out%raddbg.exe || exit /b 1
if "%raddbg_non_graphical%"=="1" set didbuild=1 && %compile% -DWM_STUB=1 -DR_BACKEND=R_BACKEND_STUB ..\src\raddbg\raddbg_main.c %compile_link% %link_icon% %out%raddbg_non_graphical.exe || exit /b 1
if "%com_shim%"=="1" set didbuild=1 && %compile% ..\src\com_shim\com_shim_main.c %compile_link% %out%com_shim.exe || exit /b 1
if "%radlink%"=="1" set didbuild=1 && %compile% ..\src\linker\lnk.c %compile_link% %linker% /NOIMPLIB %linker% /NATVIS:"%~dp0\src\linker\linker.natvis" %out%radlink.exe || exit /b 1
if "%radbin%"=="1" set didbuild=1 && %compile% ..\src\radbin\radbin_main.c %compile_link% %out%radbin.exe || exit /b 1
if "%raddump%"=="1" set didbuild=1 && %compile% ..\src\raddump\raddump_main.c %compile_link% %out%raddump.exe || exit /b 1
@@ -166,6 +167,11 @@ if "%mule_peb_trample%"=="1" (
)
popd
:: --- Set Up Debugger Com Shim -----------------------------------------------
pushd build
if "%raddbg_com_shim%"=="1" copy /y com_shim.exe raddbg.com
popd
:: --- Warn On No Builds ------------------------------------------------------
if "%didbuild%"=="" (
echo [WARNING] no valid build target specified; must use build target names as arguments to this script, like `build raddbg` or `build rdi_from_pdb`.
+1 -1
View File
@@ -49,7 +49,7 @@ commands =
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.f1 = { .win = "raddbg_stable --ipc kill_all && build radbin no_meta", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.f1 = { .win = "raddbg_stable --ipc kill_all && build ryan_scratch && pushd build && ryan_scratch.exe", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//- rjf: [raddbg wsl]
// .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
+1 -1
View File
@@ -7,7 +7,6 @@ target:
working_directory: "../raddebugger"
arguments: "--user:C:/devel/raddebugger/build/raddbg_test.user"
debug_subprocesses: 0
enabled: 1
}
target:
{
@@ -35,4 +34,5 @@ target:
{
executable: "build/ryan_scratch.exe"
working_directory: build
enabled: 1
}
+1 -1
View File
@@ -70,7 +70,7 @@ internal Process launch_cmd_linef(char *fmt, ...);
////////////////////////////////
//~ rjf: @per_os_impl Aborting
internal void abort_self(S32 exit_code);
internal void abort_self(U64 exit_code);
////////////////////////////////
//~ rjf: @per_os_impl Process Info
+64
View File
@@ -0,0 +1,64 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#define NO_ASYNC 1
#define BUILD_CONSOLE_INTERFACE 1
#define BUILD_TITLE "The RAD Debugger (Command Line Launcher)"
#include "base/base_inc.h"
#include "base/base_inc.c"
internal void
entry_point(CmdLine *cmd_line)
{
Temp scratch = scratch_begin(0, 0);
B32 wait_for_process = cmd_line_has_flag(cmd_line, s("cli")) || cmd_line_has_flag(cmd_line, s("bin"));
String8List command_parts = {0};
String8 exe_name = str8f(scratch.arena, "%S.exe", str8_chop_last_dot(cmd_line->exe_name));
if(str8_match(exe_name, cmd_line->exe_name, 0))
{
fprintf(stderr,
"ERROR: Attempting to launch %.*s recursively.\n"
"\n"
"This executable needs to be used with a .com extension next to the real target\n"
"executable, with the same name, but with a .exe extension. This guarantees that\n"
"cmd.exe will prefer launching this .com file when the executable name is used,\n"
"allowing the same executable to be used in the Windows command-line subsystem\n"
"style when launched from the command line, but used graphically when launched\n"
"via Explorer.\n\n", str8_varg(exe_name));
fflush(stderr);
}
else
{
// NOTE(rjf): sub-processes must be killed if the parent process
// is killed, if we're waiting for it
if(wait_for_process)
{
#if OS_WINDOWS
HANDLE job_handle = CreateJobObjectA(0, 0);
JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info = { .BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE };
SetInformationJobObject(job_handle, JobObjectExtendedLimitInformation, &job_info, sizeof(job_info));
AssignProcessToJobObject(job_handle, GetCurrentProcess());
#endif
}
str8_list_push(scratch.arena, &command_parts, exe_name);
for EachIndex(idx, cmd_line->argc)
{
String8 arg = str8_cstring(cmd_line->argv[idx]);
str8_list_push(scratch.arena, &command_parts, arg);
}
StringJoin join = {.sep = s(" ")};
String8 command = str8_list_join(scratch.arena, &command_parts, &join);
Process process = launch_cmd_line(command);
if(wait_for_process)
{
U64 exit_code = 0;
process_join(process, max_U64, &exit_code);
abort_self(exit_code);
}
else
{
process_detach(process);
}
}
scratch_end(scratch);
}
+2
View File
@@ -693,6 +693,7 @@ di_async_tick(void)
B32 og_is_downloading = 0;
if(og_path.size != 0)
{
#if defined(SYMBOL_SERVER_H)
B32 file_is_present = (properties_from_file_path(og_path).modified != 0);
if(!file_is_present)
{
@@ -715,6 +716,7 @@ di_async_tick(void)
}
}
}
#endif
}
//- rjf: analyze O.G. debug info
+368 -53
View File
@@ -95,6 +95,8 @@ internal E2_Expr *
e2_expr_from_name(E2_ExprMap *map, String8 name)
{
E2_Expr *expr = &e2_expr_nil;
if(map->slots_count != 0)
{
U64 hash = u64_hash_from_str8(name);
U64 slot_idx = hash%map->slots_count;
E2_ExprMapNode *node = 0;
@@ -110,6 +112,7 @@ e2_expr_from_name(E2_ExprMap *map, String8 name)
{
expr = node->expr;
}
}
return expr;
}
@@ -765,6 +768,8 @@ e2_expr_unary_op(Arena *arena, E2_TypeKey type_key, RDI_EvalOp op, E2_Expr *oper
e->type_key = type_key;
e->op = op;
e->mode = E2_Mode_Value;
e->val.u512.u8[0] = e2_type_group_from_kind(e2_type_kind_from_key(type_key));
e->val.u512.u8[1] = 8*e2_byte_size_from_type_key(type_key);
e2_expr_push_child(e, operand);
return e;
}
@@ -1125,21 +1130,40 @@ e2_try_token(String8 string, E2_TokenKind kind, String8 expected_string, U64 *of
}
internal E2_Parse
e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, String8 string)
e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, E2_Expr *access_result, String8 string)
{
U64 off = state->string_off;
E2_Parse parse = {E2_Status_Error, .expr = &e2_expr_nil, .access_expr = &e2_expr_nil};
E2_Parse parse = {E2_ParseStatus_Error, .expr = &e2_expr_nil, .params_expr = &e2_expr_nil};
E2_Expr *next_access_result = access_result;
//- rjf: parse & attach to top parsing task - if we don't have a top task
// then it is just the result
E2_Expr *expr = &e2_expr_nil;
for(B32 done = 0; !done;)
{
U64 start_off = off;
S64 max_precedence = state->top_task ? state->top_task->max_precedence : max_S64;
B32 need_new_expr = (expr == &e2_expr_nil && !state->caller_info_completes_task);
E2_Token token = {0};
//- rjf: skip leading whitespace / comments
for(;;)
{
E2_Token next_token = {0};
U64 next_off = off + e2_read_token(string, off, &next_token);
if(next_token.kind == E2_TokenKind_Whitespace ||
next_token.kind == E2_TokenKind_Comment)
{
off = next_off;
}
else
{
break;
}
}
//- rjf: nested sub-expressions
if(expr == &e2_expr_nil && e2_try_token(string, E2_TokenKind_Symbol, s("("), &off, &token))
if(need_new_expr && e2_try_token(string, E2_TokenKind_Symbol, s("("), &off, &token))
{
E2_ParseTask *task = state->free_task;
if(task != 0)
@@ -1158,11 +1182,12 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, S
SLLStackPush(state->top_task, task);
}
//- rjf: prefix unaries
else if(expr == &e2_expr_nil && e2_try_token(string, E2_TokenKind_Symbol, s(""), &off, &token))
//- rjf: symbols (possible prefix unaries, *or* unexpected)
else if(need_new_expr && e2_try_token(string, E2_TokenKind_Symbol, s(""), &off, &token))
{
// rjf: string -> operator kind
E2_OpKind op_kind = E2_OpKind_Null;
String8 closer = {0};
{
String8 token_string = str8_substr(string, token.range);
for EachNonZeroEnumVal(E2_OpKind, k)
@@ -1172,6 +1197,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, S
str8_match(token_string, e2_op_kind_info_table[k].pre, 0))
{
op_kind = k;
closer = e2_op_kind_info_table[k].post;
break;
}
}
@@ -1180,6 +1206,83 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, S
// rjf: push task for operand
if(op_kind != E2_OpKind_Null)
{
E2_ParseTask *task = state->free_task;
if(task != 0)
{
SLLStackPop(state->free_task);
}
else
{
task = push_array_no_zero(arena, E2_ParseTask, 1);
}
MemoryZeroStruct(task);
task->src_range = token.range;
task->child_count_target = 1;
task->op_kind = op_kind;
task->max_precedence = e2_op_kind_info_table[op_kind].precedence;
task->expected_closer = closer;
SLLStackPush(state->top_task, task);
}
// rjf: report unexpected symbols
if(op_kind == E2_OpKind_Null)
{
String8 token_string = str8_substr(string, token.range);
e2_msgf(arena, &parse.msgs, token.range, "Unexpected `%S`.", token_string);
}
}
//- rjf: identifiers with an active dot op kind -> member access
else if(need_new_expr && state->top_task != 0 && state->top_task->op_kind == E2_OpKind_Dot && e2_try_token(string, E2_TokenKind_Identifier, s(""), &off, &token))
{
// rjf: if we have a caller-provided access result, use that as our new expression
if(next_access_result != &e2_expr_nil)
{
expr = next_access_result;
next_access_result = &e2_expr_nil;
}
// rjf: if we don't, ask for it - reset the offset to before this token
else
{
done = 1;
parse.status = E2_ParseStatus_MemberAccess;
parse.expr = state->top_task->first_child ? state->top_task->first_child->v : &e2_expr_nil;
parse.member_name = str8_substr(string, token.range);
state->last_requested_member_name = parse.member_name;
off = start_off;
}
}
//- rjf: standalone identifiers (also could be operator keyword)
else if(need_new_expr && e2_try_token(string, E2_TokenKind_Identifier, s(""), &off, &token))
{
String8 identifier = str8_substr(string, token.range);
B32 identifier_mapped = 0;
// rjf: first try to resolve as an operator name
if(!identifier_mapped)
{
// rjf: string -> op kind
E2_OpKind op_kind = E2_OpKind_Null;
{
String8 token_string = str8_substr(string, token.range);
for EachNonZeroEnumVal(E2_OpKind, k)
{
if(e2_op_kind_info_table[k].parse_kind == E2_OpParseKind_UnaryPrefix &&
e2_op_kind_info_table[k].precedence <= max_precedence &&
str8_match(token_string, str8_skip_chop_whitespace(e2_op_kind_info_table[k].pre), 0))
{
op_kind = k;
break;
}
}
}
// rjf: push task for operand
if(op_kind != E2_OpKind_Null)
{
identifier_mapped = 1;
E2_ParseTask *task = state->free_task;
if(task != 0)
{
@@ -1198,21 +1301,25 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, S
}
}
//- rjf: leaf identifiers
else if(expr == &e2_expr_nil && e2_try_token(string, E2_TokenKind_Identifier, s(""), &off, &token))
// rjf: try to resolve via caller-provided named expressions
if(!identifier_mapped)
{
String8 identifier = str8_substr(string, token.range);
expr = e2_expr_from_name(expr_map, identifier);
if(expr == &e2_expr_nil)
identifier_mapped = (expr != &e2_expr_nil);
}
// rjf: couldn't map -> ask caller to resolve it
if(!identifier_mapped)
{
done = 1;
parse.status = E2_Status_MissedIdentifierResolution;
parse.status = E2_ParseStatus_MissedIdentifierResolution;
parse.missed_identifier = identifier;
off = start_off;
}
}
//- rjf: leaf numerics
else if(expr == &e2_expr_nil && e2_try_token(string, E2_TokenKind_Numeric, s(""), &off, &token))
else if(need_new_expr && e2_try_token(string, E2_TokenKind_Numeric, s(""), &off, &token))
{
U64 u64_val = 0;
String8 numeric_string = str8_substr(string, token.range);
@@ -1261,22 +1368,34 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, S
}
}
//- rjf: extend parsed expression tree with trailing binary operators
if(expr != &e2_expr_nil)
//- rjf: extend parsed expression tree with trailing operators
if(!state->caller_info_completes_task && expr != &e2_expr_nil)
{
U64 trailing_symbol_off = off;
if(e2_try_token(string, E2_TokenKind_Symbol, s(""), &trailing_symbol_off, &token))
{
// rjf: token string -> operator kind
E2_OpKind op_kind = E2_OpKind_Null;
U64 child_count_target = 2;
String8 splitter = {0};
String8 closer = {0};
B32 splitter_is_required = 0;
{
String8 token_string = str8_substr(string, token.range);
for EachNonZeroEnumVal(E2_OpKind, k)
{
if(e2_op_kind_info_table[k].parse_kind == E2_OpParseKind_Binary &&
e2_op_kind_info_table[k].precedence <= max_precedence &&
str8_match(token_string, e2_op_kind_info_table[k].sep, 0))
E2_OpInfo *op_info = &e2_op_kind_info_table[k];
if(op_info->precedence <= max_precedence && str8_match(token_string, op_info->sep, 0))
{
switch(op_info->parse_kind)
{
default:{}break;
case E2_OpParseKind_Binary: {child_count_target = 2;}break;
case E2_OpParseKind_Ternary: {child_count_target = 3; splitter_is_required = 1;}break;
case E2_OpParseKind_Call: {child_count_target = max_U64;}break;
}
splitter = op_info->chain;
closer = op_info->post;
op_kind = k;
break;
}
@@ -1298,9 +1417,12 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, S
MemoryZeroStruct(task);
task->src_range = token.range;
task->child_count = 0;
task->child_count_target = 2;
task->child_count_target = child_count_target;
task->op_kind = op_kind;
task->max_precedence = e2_op_kind_info_table[op_kind].precedence;
task->expected_splitter = splitter;
task->expected_closer = closer;
task->splitter_is_required = splitter_is_required;
SLLStackPush(state->top_task, task);
off = trailing_symbol_off;
}
@@ -1309,29 +1431,52 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, S
//- rjf: attach formed expressions to parent task exprs; pop tasks when they're done.
// if we have no parent task, then we just fill the result, and we're done with the parse.
if(expr != &e2_expr_nil)
if(state->caller_info_completes_task || expr != &e2_expr_nil)
{
//- rjf: pop finished expressions
for(;state->top_task != 0;)
for(;state->top_task != 0 && !done;)
{
//- rjf: gather finished expression to current task; increase task child count
if(!state->caller_info_completes_task)
{
E2_ExprNode *n = push_array(arena, E2_ExprNode, 1);
SLLQueuePush(state->top_task->first_child, state->top_task->last_child, n);
n->v = expr;
state->top_task->child_count += 1;
}
//- rjf: task child count hits limit -> complete this subtree
if(state->top_task->child_count >= state->top_task->child_count_target)
//- rjf: consume expected splitters
if(!state->caller_info_completes_task &&
state->top_task->child_count > 1 &&
state->top_task->expected_splitter.size != 0 &&
state->top_task->child_count < state->top_task->child_count_target)
{
//- rjf: release task
if(!e2_try_token(string, E2_TokenKind_Symbol, state->top_task->expected_splitter, &off, 0) && state->top_task->splitter_is_required)
{
e2_msgf(arena, &parse.msgs, r1u64(off, off), "Expected `%S`.", state->top_task->expected_splitter);
}
}
//- rjf: consume expected closers - can terminate a child list early
B32 closer_found = 0;
if(!state->caller_info_completes_task && state->top_task->expected_closer.size != 0)
{
closer_found = e2_try_token(string, E2_TokenKind_Symbol, state->top_task->expected_closer, &off, 0);
}
//- rjf: caller-provided info completes a task, *or* closer found,
// *or* task child count hits limit -> complete this subtree
if(state->caller_info_completes_task || closer_found || state->top_task->child_count >= state->top_task->child_count_target)
{
B32 completed_with_caller_info = state->caller_info_completes_task;
state->caller_info_completes_task = 0;
E2_ParseTask *completed_task = state->top_task;
SLLStackPop(state->top_task);
SLLStackPush(state->free_task, completed_task);
//- rjf: produced finished expression tree, given all children
E2_Expr *finished_root = &e2_expr_nil;
E2_Expr *lhs = completed_task->first_child ? completed_task->first_child->v : &e2_expr_nil;
E2_Expr *rhs = completed_task->last_child ? completed_task->last_child->v : &e2_expr_nil;
E2_Expr *mhs = completed_task->child_count == 3 ? lhs->next : &e2_expr_nil;
{
RDI_EvalOp op = RDI_EvalOp_Stop;
E2_TypeKey dst_type_key = {E2_TypeKeyKind_Null};
@@ -1354,8 +1499,77 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, S
}
}break;
//- rjf: dereference
//- rjf: member accesses -> at this point we should have a resolved access
// expression submitted to us by the user (the parser reports it first)
// stored as the second child in the list. we just want to use the
// second expression - the initial child was just the accessed evaluation.
case E2_OpKind_Dot:
{
finished_root = rhs;
}break;
//- rjf: indexes
case E2_OpKind_Index:
{
E2_TypeKey lhs_type_key = e2_type_key_undecorate(lhs->type_key);
E2_TypeKind lhs_type_kind = e2_type_kind_from_key(lhs_type_key);
// rjf: array/pointer *address* indexes
if(lhs_type_kind == E2_TypeKind_Ptr || lhs_type_kind == E2_TypeKind_Array)
{
E2_TypeKey element_type_key = e2_type_key_direct(lhs_type_key);
U64 element_byte_size = e2_byte_size_from_type_key(element_type_key);
E2_Expr *base_addr_value_expr = e2_expr_resolve_to_value(arena, lhs);
E2_Expr *index_value_expr = e2_expr_resolve_to_value(arena, rhs);
E2_Expr *offset_value_expr = index_value_expr;
if(element_byte_size != 1)
{
E2_Expr *element_size_value_expr = e2_expr_const_u64_or_smaller(arena, element_byte_size);
offset_value_expr = e2_expr_binary_op(arena, e2_type_key_basic(E2_TypeKind_U64), RDI_EvalOp_Mul, index_value_expr, element_size_value_expr);
}
E2_Expr *element_addr_value_expr = e2_expr_binary_op(arena, e2_type_key_basic(E2_TypeKind_U64), RDI_EvalOp_Add, base_addr_value_expr, offset_value_expr);
element_addr_value_expr->type_key = element_type_key;
element_addr_value_expr->mode = E2_Mode_Address;
finished_root = element_addr_value_expr;
}
// rjf: fallback case: ask the caller for fancy indexing operations
else
{
if(next_access_result != &e2_expr_nil)
{
finished_root = next_access_result;
next_access_result = &e2_expr_nil;
}
else
{
done = 1;
parse.status = E2_ParseStatus_IndexAccess;
parse.expr = lhs;
parse.params_expr = rhs;
state->caller_info_completes_task = 1;
}
}
}break;
//- rjf: calls
case E2_OpKind_Call:
{
// TODO(rjf)
}break;
//- rjf: sizeof
case E2_OpKind_SizeOf:
{
E2_TypeKey rhs_type_key = e2_type_key_unwrap(rhs->type_key, E2_TypeUnwrapFlag_AllDecorative & ~E2_TypeUnwrapFlag_Enums);
U64 rhs_size = e2_byte_size_from_type_key(rhs_type_key);
finished_root = e2_expr_const_u64_or_smaller(arena, rhs_size);
finished_root->type_key = e2_type_key_basic(E2_TypeKind_U64);
}break;
//- rjf: dereferences
case E2_OpKind_Deref:
case E2_OpKind_DerefAsm:
{
// rjf: unpack operand
E2_TypeKey rhs_type_key = e2_type_key_unwrap(rhs->type_key, E2_TypeUnwrapFlag_AllDecorative & ~E2_TypeUnwrapFlag_Enums);
@@ -1375,12 +1589,26 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, S
malformed = 1;
e2_msgf(arena, &parse.msgs, completed_task->src_range, "Cannot dereference arrays of zero-sized types.");
}
else if(!e2_type_kind_is_ptr_or_ref(rhs_type_kind) && rhs_type_kind != E2_TypeKind_Array)
else if(!e2_type_kind_is_ptr_or_ref(rhs_type_kind) && rhs_type_kind != E2_TypeKind_Array &&
completed_task->op_kind != E2_OpKind_DerefAsm)
{
malformed = 1;
e2_msgf(arena, &parse.msgs, completed_task->src_range, "Cannot dereference this type.");
}
// rjf: asm-style deref -> go to u64 if the address expression isn't
// an array or pointer
//
// TODO(rjf): probably we should get an absolute-fallback-architecture here,
// which ultimately is sourced by the selected thread, to choose an address-sized
// integer type.
//
if(!e2_type_kind_is_ptr_or_ref(rhs_type_kind) && rhs_type_kind != E2_TypeKind_Array &&
completed_task->op_kind == E2_OpKind_DerefAsm)
{
dereferenced_type = e2_type_key_basic(E2_TypeKind_U64);
}
// rjf: not malformed -> equip info
if(!malformed)
{
@@ -1597,20 +1825,30 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, S
//- rjf: definitions (TODO(rjf): tricky with the 'user resolves expressions' model - let's figure it out once basics are in)
case E2_OpKind_Define:{}break;
//- rjf: conditionals
case E2_OpKind_Cond:
{
// TODO(rjf)
}break;
}
}
//- rjf: consume expected closers
if(completed_task->expected_closer.size != 0)
{
if(!e2_try_token(string, E2_TokenKind_Symbol, completed_task->expected_closer, &off, 0))
//- rjf: report missing closers
if(!completed_with_caller_info && completed_task->expected_closer.size != 0 && !closer_found)
{
e2_msgf(arena, &parse.msgs, r1u64(off, off), "Expected `%S`.", completed_task->expected_closer);
}
}
//- rjf: work on the parent of the finished expression next
expr = finished_root;
//- rjf: release task
if(!done)
{
SLLStackPop(state->top_task);
SLLStackPush(state->free_task, completed_task);
}
}
//- rjf: if the top task is not done -> break & continue - reset expression, because we need to parse another.
@@ -1626,20 +1864,70 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, S
if(state->top_task == 0 && off >= string.size)
{
parse.expr = expr;
if(parse.status == E2_Status_Error)
if(parse.status == E2_ParseStatus_Error)
{
parse.status = E2_Status_Good;
parse.status = E2_ParseStatus_Good;
}
break;
}
}
//- rjf: we're always done if there's nothing left to parse
if(off >= string.size)
{
done = 1;
}
}
//- rjf: advance offset if successful
if(parse.status == E2_Status_Good || parse.status == E2_Status_Error)
//- rjf: asking caller for info? -> if we already did this at this offset,
// the user couldn't provide the info, so we just fail out.
if(e2_parse_status_is_caller_request(parse.status))
{
if(state->caller_request_count > 0 && state->last_caller_request_string_off == state->string_off)
{
if(parse.status == E2_ParseStatus_MissedIdentifierResolution)
{
e2_msgf(arena, &parse.msgs, r1u64(state->string_off, state->string_off + parse.missed_identifier.size), "`%S` couldn't be resolved.", parse.missed_identifier);
}
parse.status = E2_ParseStatus_Error;
}
state->caller_request_count += 1;
state->last_caller_request_string_off = state->string_off;
}
//- rjf: report incomplete tasks
if(off >= string.size && !e2_parse_status_is_caller_request(parse.status))
{
for(E2_ParseTask *t = state->top_task; t != 0; t = t->next)
{
if(t->child_count == 1 && t->child_count_target == 2 && t->op_kind == E2_OpKind_Dot)
{
e2_msgf(arena, &parse.msgs, t->src_range, "Couldn't access member `%S`.", state->last_requested_member_name);
}
else if(t->child_count == 2 && t->child_count_target == 2 && t->op_kind == E2_OpKind_Index)
{
e2_msgf(arena, &parse.msgs, t->src_range, "Couldn't index into this type.");
}
else if(t->child_count == 1 && t->child_count_target == 2 && t->op_kind != E2_OpKind_Null)
{
e2_msgf(arena, &parse.msgs, t->src_range, "Expected expression after binary operator `%S`.", e2_op_kind_info_table[t->op_kind].sep);
}
else if(t->child_count == 0 && t->child_count_target == 1 && t->op_kind != E2_OpKind_Null)
{
e2_msgf(arena, &parse.msgs, t->src_range, "Expected expression after unary operator `%S`.", e2_op_kind_info_table[t->op_kind].pre);
}
else
{
e2_msgf(arena, &parse.msgs, t->src_range, "Expected expression.");
}
}
}
//- rjf: commit offset
{
state->string_off = off;
}
return parse;
}
@@ -1724,12 +2012,14 @@ e2_bytecode_from_expr(Arena *arena, E2_Expr *expr)
internal E2_Interp
e2_interp_from_bytecode(Arena *arena, E2_InterpState *state, E2_SpaceMap *space_map, String8 bytecode)
{
E2_Interp interp = {E2_Status_Error};
E2_Interp interp = {E2_InterpStatus_Error};
{
U64 off = state->bytecode_off;
U64 off_opl = bytecode.size;
B32 done = 0;
B32 good = 1;
//- rjf: execute bytecode
for(;off < off_opl && !done && good;)
{
Temp scratch = scratch_begin(&arena, 1);
@@ -1784,7 +2074,7 @@ e2_interp_from_bytecode(Arena *arena, E2_InterpState *state, E2_SpaceMap *space_
case E2_EvalOp_SetCtxID:
{
interp.status = E2_Status_NewCtxID;
interp.status = E2_InterpStatus_NewCtxID;
interp.ctx_id = decode_val.u64;
}break;
@@ -1818,7 +2108,7 @@ e2_interp_from_bytecode(Arena *arena, E2_InterpState *state, E2_SpaceMap *space_
if(read_size != size)
{
good = 0;
interp.status = E2_Status_MissedSpaceRead;
interp.status = E2_InterpStatus_MissedSpaceRead;
interp.missed_read_space_addr_range = space_addr_range;
}
}break;
@@ -1840,14 +2130,14 @@ e2_interp_from_bytecode(Arena *arena, E2_InterpState *state, E2_SpaceMap *space_
if(read_size != size)
{
good = 0;
interp.status = E2_Status_MissedSpaceRead;
interp.status = E2_InterpStatus_MissedSpaceRead;
interp.missed_read_space_addr_range = space_addr_range;
}
}
else
{
good = 0;
interp.status = E2_Status_BadRegCode;
interp.status = E2_InterpStatus_BadRegCode;
}
}break;
case RDI_EvalOp_FrameOff: {ctx_flags = E2_CtxFlag_HasFrameBase; ctx_base_addr = state->selected_ctx.frame_base_addr;}goto optional_base_off;
@@ -1863,7 +2153,7 @@ e2_interp_from_bytecode(Arena *arena, E2_InterpState *state, E2_SpaceMap *space_
else
{
good = 0;
interp.status = E2_Status_MissingCtxFlag;
interp.status = E2_InterpStatus_MissingCtxFlag;
interp.missing_ctx_flags |= ctx_flags;
}
}break;
@@ -1919,9 +2209,9 @@ e2_interp_from_bytecode(Arena *arena, E2_InterpState *state, E2_SpaceMap *space_
#define BinOp(target_type_group, dst_type, src_type, symbol) else if(type_group == (RDI_EvalTypeGroup_##target_type_group)) do{push_vals[0].dst_type = popped_vals[1].src_type symbol popped_vals[0].src_type;}while(0)
#define SizedBinOp(target_type_group, size, dst_type, src_type, symbol) else if(type_group == (RDI_EvalTypeGroup_##target_type_group) && op_arithmetic_size == (size)) do{push_vals[0].dst_type = popped_vals[1].src_type symbol popped_vals[0].src_type;}while(0)
#define BinOpDiv(target_type_group, dst_type, src_type, symbol) else if(type_group == (RDI_EvalTypeGroup_##target_type_group)) do{if(popped_vals[0].src_type != 0) { push_vals[0].dst_type = popped_vals[1].src_type symbol popped_vals[0].src_type; } else {interp.status = E2_Status_DivideByZero; good = 0;} }while(0)
#define SizedBinOpDiv(target_type_group, size, dst_type, src_type, symbol) else if(type_group == (RDI_EvalTypeGroup_##target_type_group) && op_arithmetic_size == (size)) do{if(popped_vals[0].src_type != 0) { push_vals[0].dst_type = popped_vals[1].src_type symbol popped_vals[0].src_type; } else {interp.status = E2_Status_DivideByZero; good = 0;} }while(0)
#define BinOpDivFn(target_type_group, dst_type, src_type, fn) else if(type_group == (RDI_EvalTypeGroup_##target_type_group)) do{if(popped_vals[0].src_type != 0) { push_vals[0].dst_type = fn(popped_vals[1].src_type, popped_vals[0].src_type); } else {interp.status = E2_Status_DivideByZero; good = 0;} }while(0)
#define BinOpDiv(target_type_group, dst_type, src_type, symbol) else if(type_group == (RDI_EvalTypeGroup_##target_type_group)) do{if(popped_vals[0].src_type != 0) { push_vals[0].dst_type = popped_vals[1].src_type symbol popped_vals[0].src_type; } else {interp.status = E2_InterpStatus_DivideByZero; good = 0;} }while(0)
#define SizedBinOpDiv(target_type_group, size, dst_type, src_type, symbol) else if(type_group == (RDI_EvalTypeGroup_##target_type_group) && op_arithmetic_size == (size)) do{if(popped_vals[0].src_type != 0) { push_vals[0].dst_type = popped_vals[1].src_type symbol popped_vals[0].src_type; } else {interp.status = E2_InterpStatus_DivideByZero; good = 0;} }while(0)
#define BinOpDivFn(target_type_group, dst_type, src_type, fn) else if(type_group == (RDI_EvalTypeGroup_##target_type_group)) do{if(popped_vals[0].src_type != 0) { push_vals[0].dst_type = fn(popped_vals[1].src_type, popped_vals[0].src_type); } else {interp.status = E2_InterpStatus_DivideByZero; good = 0;} }while(0)
#define ArithTypeCasesInt(symbol)\
SizedBinOp(S, 8, s8, s8, symbol);\
SizedBinOp(S, 16, s16, s16, symbol);\
@@ -1955,7 +2245,7 @@ ArithTypeCasesIntDiv(symbol)
#define ArithTypeCasesIntAllU64(symbol)\
BinOp(S, u64, u64, symbol);\
BinOp(U, u64, u64, symbol);
#define Case(name, ...) case RDI_EvalOp_##name:{if(0){} __VA_ARGS__ else {interp.status = E2_Status_BadOpTypes; good = 0;}}break
#define Case(name, ...) case RDI_EvalOp_##name:{if(0){} __VA_ARGS__ else {interp.status = E2_InterpStatus_BadOpTypes; good = 0;}}break
Case(Add, ArithTypeCases(+));
Case(Sub, ArithTypeCases(-));
Case(Mul, ArithTypeCases(*));
@@ -2049,7 +2339,7 @@ BinOp(U, u64, u64, symbol);
{
switch(in + out*RDI_EvalTypeGroup_COUNT)
{
default:{good = 0; interp.status = E2_Status_BadOpTypes;}break;
default:{good = 0; interp.status = E2_InterpStatus_BadOpTypes;}break;
#define Case(dst_tg, dst_slot, dst_type, src_tg, src_slot) case RDI_EvalTypeGroup_##src_tg + RDI_EvalTypeGroup_##dst_tg*RDI_EvalTypeGroup_COUNT:{push_vals[0].dst_slot = (dst_type)popped_vals[0].src_slot;}break
Case(U, u64, U64, F32, f32);
Case(U, u64, U64, F64, f64);
@@ -2083,7 +2373,7 @@ BinOp(U, u64, u64, symbol);
if(!found)
{
good = 0;
interp.status = E2_Status_InsufficientStackSpace;
interp.status = E2_InterpStatus_InsufficientStackSpace;
}
}break;
@@ -2106,7 +2396,7 @@ BinOp(U, u64, u64, symbol);
else
{
good = 0;
interp.status = E2_Status_BadOffset;
interp.status = E2_InterpStatus_BadOffset;
}
}break;
@@ -2118,7 +2408,7 @@ BinOp(U, u64, u64, symbol);
default:
{
good = 0;
interp.status = E2_Status_UnsupportedOp;
interp.status = E2_InterpStatus_UnsupportedOp;
}break;
case 2:{push_vals[0].u16 = bswap_u16(popped_vals[0].u16);}break;
case 4:{push_vals[0].u32 = bswap_u32(popped_vals[0].u32);}break;
@@ -2136,7 +2426,7 @@ BinOp(U, u64, u64, symbol);
// skip past the embedded sub-bytecode in the outer stream so the
// bytes are not interpreted as outer ops on resume.
good = 0;
interp.status = E2_Status_UnsupportedOp;
interp.status = E2_InterpStatus_UnsupportedOp;
}break;
case RDI_EvalOp_PartialValue:
@@ -2146,14 +2436,14 @@ BinOp(U, u64, u64, symbol);
// value already on the stack is the result. for multi-piece, only
// the first piece is returned (stack[0] is the final result).
good = 0;
interp.status = E2_Status_UnsupportedOp;
interp.status = E2_InterpStatus_UnsupportedOp;
}break;
case RDI_EvalOp_PartialValueBit:
{
// DW_OP_bit_piece marker. same caveat as PartialValue.
good = 0;
interp.status = E2_Status_UnsupportedOp;
interp.status = E2_InterpStatus_UnsupportedOp;
}break;
}
@@ -2200,9 +2490,34 @@ BinOp(U, u64, u64, symbol);
break;
}
}
//- rjf: asking caller for info? -> if we already did this at this offset,
// the user couldn't provide the info, so we just fail out.
if(e2_interp_status_is_caller_request(interp.status))
{
if(state->caller_request_count > 0 && state->last_caller_request_bytecode_off == state->bytecode_off)
{
switch(interp.status)
{
default:{}break;
case E2_InterpStatus_MissedSpaceRead:
{
e2_msgf(arena, &interp.msgs, r1u64(state->bytecode_off, state->bytecode_off+1), "Couldn't read address range [0x%I64x, 0x%I64x) in space 0x%I64x.",
interp.missed_read_space_addr_range.min,
interp.missed_read_space_addr_range.max,
interp.space_id);
}break;
}
interp.status = E2_InterpStatus_Error;
}
state->caller_request_count += 1;
state->last_caller_request_bytecode_off = state->bytecode_off;
}
//- rjf: if we're done with the bytecode stream, report success / value
if(off == off_opl && good)
{
interp.status = E2_Status_Good;
interp.status = E2_InterpStatus_Good;
if(state->top_val != 0)
{
interp.val = state->top_val->val;
+63 -26
View File
@@ -12,7 +12,8 @@ typedef enum E2_OpParseKind
E2_OpParseKind_Null,
E2_OpParseKind_UnaryPrefix,
E2_OpParseKind_Binary,
E2_OpParseKind_UnaryPostfix,
E2_OpParseKind_Ternary,
E2_OpParseKind_Call,
}
E2_OpParseKind;
@@ -41,31 +42,57 @@ enum
};
////////////////////////////////
//~ rjf: Compilation Statuses
//~ rjf: Parse Statuses
typedef enum E2_Status
typedef enum E2_ParseStatus
{
E2_Status_Good,
//- rjf: terminals
E2_ParseStatus_Good,
E2_ParseStatus_Error,
E2_ParseStatus_FirstTerminal = E2_ParseStatus_Good,
E2_ParseStatus_LastTerminal = E2_ParseStatus_Error,
//- rjf: need caller-provided info
E2_Status_MissedSpaceRead,
E2_Status_MissedIdentifierResolution,
E2_Status_Access,
E2_Status_NewCtxID,
//- rjf: unrecoverable errors
E2_Status_BadRegCode,
E2_Status_MissingCtxFlag,
E2_Status_DivideByZero,
E2_Status_InsufficientStackSpace,
E2_Status_BadOpTypes,
E2_Status_UnsupportedOp,
E2_Status_BadOffset,
E2_Status_Error,
E2_Status_FirstError = E2_Status_BadRegCode,
E2_Status_LastError = E2_Status_Error,
//- rjf: caller-provided info
E2_ParseStatus_MissedIdentifierResolution,
E2_ParseStatus_MemberAccess,
E2_ParseStatus_IndexAccess,
E2_ParseStatus_Call,
E2_ParseStatus_FirstCallerRequest = E2_ParseStatus_MissedIdentifierResolution,
E2_ParseStatus_LastCallerRequest = E2_ParseStatus_Call,
}
E2_Status;
E2_ParseStatus;
#define e2_parse_status_is_terminal(s) (E2_ParseStatus_FirstTerminal <= (s) && (s) <= E2_ParseStatus_LastTerminal)
#define e2_parse_status_is_caller_request(s) (E2_ParseStatus_FirstCallerRequest <= (s) && (s) <= E2_ParseStatus_LastCallerRequest)
////////////////////////////////
//~ rjf: Interpretation Statuses
typedef enum E2_InterpStatus
{
//- rjf: terminals
E2_InterpStatus_Good,
E2_InterpStatus_BadRegCode,
E2_InterpStatus_MissingCtxFlag,
E2_InterpStatus_DivideByZero,
E2_InterpStatus_InsufficientStackSpace,
E2_InterpStatus_BadOpTypes,
E2_InterpStatus_UnsupportedOp,
E2_InterpStatus_BadOffset,
E2_InterpStatus_Error,
E2_InterpStatus_FirstTerminal = E2_InterpStatus_Good,
E2_InterpStatus_LastTerminal = E2_InterpStatus_Error,
//- rjf: caller-provided info
E2_InterpStatus_MissedSpaceRead,
E2_InterpStatus_NewCtxID,
E2_InterpStatus_FirstCallerRequest = E2_InterpStatus_MissedSpaceRead,
E2_InterpStatus_LastCallerRequest = E2_InterpStatus_NewCtxID,
}
E2_InterpStatus;
#define e2_interp_status_is_terminal(s) (E2_InterpStatus_FirstTerminal <= (s) && (s) <= E2_InterpStatus_LastTerminal)
#define e2_interp_status_is_caller_request(s) (E2_InterpStatus_FirstCallerRequest <= (s) && (s) <= E2_InterpStatus_LastCallerRequest)
////////////////////////////////
//~ rjf: Type Keys
@@ -330,6 +357,8 @@ struct E2_ParseTask
S64 max_precedence;
E2_OpKind op_kind;
String8 expected_closer;
String8 expected_splitter;
B32 splitter_is_required;
};
typedef struct E2_ParseState E2_ParseState;
@@ -338,6 +367,10 @@ struct E2_ParseState
U64 string_off;
E2_ParseTask *top_task;
E2_ParseTask *free_task;
U64 last_caller_request_string_off;
U64 caller_request_count;
String8 last_requested_member_name;
B32 caller_info_completes_task;
};
typedef struct E2_Msg E2_Msg;
@@ -359,10 +392,11 @@ struct E2_MsgList
typedef struct E2_Parse E2_Parse;
struct E2_Parse
{
E2_Status status;
E2_ParseStatus status;
String8 missed_identifier;
E2_Expr *expr;
E2_Expr *access_expr;
String8 member_name;
E2_Expr *params_expr;
E2_MsgList msgs;
};
@@ -398,17 +432,20 @@ struct E2_InterpState
E2_Ctx selected_ctx;
E2_InterpStackValNode *top_val;
E2_InterpStackValNode *free_val;
U64 last_caller_request_bytecode_off;
U64 caller_request_count;
};
typedef struct E2_Interp E2_Interp;
struct E2_Interp
{
E2_Status status;
E2_InterpStatus status;
E2_SpaceID space_id;
Rng1U64 missed_read_space_addr_range;
E2_CtxID ctx_id;
E2_CtxFlags missing_ctx_flags;
E2_Val val;
E2_MsgList msgs;
};
////////////////////////////////
@@ -537,7 +574,7 @@ internal void e2_expr_push_child(E2_Expr *parent, E2_Expr *expr);
internal E2_Token e2_token_from_string_off(String8 string, U64 start_off);
internal U64 e2_read_token(String8 string, U64 off, E2_Token *token_out);
internal B32 e2_try_token(String8 string, E2_TokenKind kind, String8 expected_string, U64 *off_out, E2_Token *token_out);
internal E2_Parse e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, String8 string);
internal E2_Parse e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, E2_Expr *access_result, String8 string);
////////////////////////////////
//~ rjf: Expression -> Bytecode
+6
View File
@@ -4,6 +4,11 @@
@table(name parse_kind precedence pre sep pos chain)
E2_OpTable:
{
{Dot Binary 1 "" "." "" "" }
{Index Binary 1 "" "[" "]" "" }
{Call Call 1 "" "(" ")" ","}
{DerefAsm UnaryPrefix 1 "[" "" "]" "" }
{SizeOf UnaryPrefix 1 "sizeof " "" "" "" }
{Deref UnaryPrefix 2 "*" "" "" "" }
{Address UnaryPrefix 2 "&" "" "" "" }
{Pos UnaryPrefix 2 "+" "" "" "" }
@@ -29,6 +34,7 @@ E2_OpTable:
{LogAnd Binary 11 "" "&&" "" "" }
{LogOr Binary 12 "" "||" "" "" }
{Define Binary 13 "" "=" "" "" }
{Cond Ternary 14 "" "?" "" ":"}
}
@enum E2_OpKind:
+7 -1
View File
@@ -4,9 +4,14 @@
//- GENERATED CODE
C_LINKAGE_BEGIN
E2_OpInfo e2_op_kind_info_table[26] =
E2_OpInfo e2_op_kind_info_table[32] =
{
{0},
{E2_OpParseKind_Binary, 1, str8_lit_comp(""), str8_lit_comp("."), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_Binary, 1, str8_lit_comp(""), str8_lit_comp("["), str8_lit_comp("]"), str8_lit_comp("")},
{E2_OpParseKind_Call, 1, str8_lit_comp(""), str8_lit_comp("("), str8_lit_comp(")"), str8_lit_comp(",")},
{E2_OpParseKind_UnaryPrefix, 1, str8_lit_comp("["), str8_lit_comp(""), str8_lit_comp("]"), str8_lit_comp("")},
{E2_OpParseKind_UnaryPrefix, 1, str8_lit_comp("sizeof "), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_UnaryPrefix, 2, str8_lit_comp("*"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_UnaryPrefix, 2, str8_lit_comp("&"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_UnaryPrefix, 2, str8_lit_comp("+"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
@@ -32,6 +37,7 @@ E2_OpInfo e2_op_kind_info_table[26] =
{E2_OpParseKind_Binary, 11, str8_lit_comp(""), str8_lit_comp("&&"), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_Binary, 12, str8_lit_comp(""), str8_lit_comp("||"), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_Binary, 13, str8_lit_comp(""), str8_lit_comp("="), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_Ternary, 14, str8_lit_comp(""), str8_lit_comp("?"), str8_lit_comp(""), str8_lit_comp(":")},
};
U8 e2_type_kind_basic_byte_size_table[61] =
+7 -1
View File
@@ -9,6 +9,11 @@
typedef enum E2_OpKind
{
E2_OpKind_Null,
E2_OpKind_Dot,
E2_OpKind_Index,
E2_OpKind_Call,
E2_OpKind_DerefAsm,
E2_OpKind_SizeOf,
E2_OpKind_Deref,
E2_OpKind_Address,
E2_OpKind_Pos,
@@ -34,6 +39,7 @@ E2_OpKind_BitOr,
E2_OpKind_LogAnd,
E2_OpKind_LogOr,
E2_OpKind_Define,
E2_OpKind_Cond,
E2_OpKind_COUNT,
} E2_OpKind;
@@ -116,7 +122,7 @@ E2_TypeKind_LastMeta = E2_TypeKind_MetaDescription,
} E2_TypeKind;
C_LINKAGE_BEGIN
extern E2_OpInfo e2_op_kind_info_table[26];
extern E2_OpInfo e2_op_kind_info_table[32];
extern U8 e2_type_kind_basic_byte_size_table[61];
extern String8 e2_type_kind_basic_string_table[61];
+2 -2
View File
@@ -79,8 +79,8 @@ RDI_EVAL_CTRLBITS(16, 0, 1),
RDI_EVAL_CTRLBITS(32, 0, 1),
RDI_EVAL_CTRLBITS(64, 0, 1),
RDI_EVAL_CTRLBITS(1, 0, 1),
RDI_EVAL_CTRLBITS(1, 1, 1),
RDI_EVAL_CTRLBITS(1, 1, 1),
RDI_EVAL_CTRLBITS(2, 1, 1),
RDI_EVAL_CTRLBITS(2, 1, 1),
RDI_EVAL_CTRLBITS(2, 2, 1),
RDI_EVAL_CTRLBITS(2, 2, 1),
RDI_EVAL_CTRLBITS(2, 2, 1),
+2 -2
View File
@@ -1187,9 +1187,9 @@ make_directory(String8 path)
//~ rjf: @per_os_impl Aborting
internal void
abort_self(S32 exit_code)
abort_self(U64 exit_code)
{
exit(exit_code);
exit((int)exit_code);
}
////////////////////////////////
+10
View File
@@ -586,6 +586,16 @@ entry_point(CmdLine *cmd_line)
{
Temp scratch = scratch_begin(0, 0);
//- rjf: re-open stdout handles if cli
#if OS_WINDOWS
if(cmd_line_has_flag(cmd_line, s("bin")))
{
AttachConsole(ATTACH_PARENT_PROCESS);
freopen("CONOUT$", "wt", stdout);
freopen("CONOUT$", "wt", stderr);
}
#endif
//- rjf: unpack command line arguments
ExecMode exec_mode = ExecMode_Normal;
B32 auto_run = 0;
+2 -2
View File
@@ -1214,8 +1214,8 @@ RDI_EvalOpTable:
{ConstU256 16 32 0 1}
{ConstU512 17 64 0 1}
{ConstString 18 1 0 1}
{Abs 19 1 1 1}
{Neg 20 1 1 1}
{Abs 19 2 1 1}
{Neg 20 2 1 1}
{Add 21 2 2 1}
{Sub 22 2 2 1}
{Mul 23 2 2 1}
+1 -1
View File
@@ -422,7 +422,7 @@ p2r_convert2(Arena *arena, P2R_ConvertParams *params)
}
else
{
cv2r_comp_units[idx].obj_name = s("*global");
cv2r_comp_units[idx].obj_name = s("*global*");
}
cv2r_comp_units[idx].ranges = unit_ranges[idx];
cv2r_comp_units[idx].sym = all_syms[idx];
+47 -13
View File
@@ -13,9 +13,7 @@
//- rjf: [h]
#include "base/base_inc.h"
#include "x64/x64.h"
#include "http/http_inc.h"
#include "artifact_cache/artifact_cache.h"
#include "symbol_server/symbol_server_inc.h"
#include "rdi/rdi_local.h"
#include "dbg_info/dbg_info.h"
#include "arch/arch_inc.h"
@@ -24,9 +22,7 @@
//- rjf: [c]
#include "base/base_inc.c"
#include "x64/x64.c"
#include "http/http_inc.c"
#include "artifact_cache/artifact_cache.c"
#include "symbol_server/symbol_server_inc.c"
#include "rdi/rdi_local.c"
#include "dbg_info/dbg_info.c"
#include "arch/arch_inc.c"
@@ -40,6 +36,10 @@ entry_point(CmdLine *cmdline)
{
String8 strings[] =
{
s("[123]"),
s("foo"),
s("foo.bar"),
s("123[456]"),
s("123"),
s("123 + 456"),
s("!1"),
@@ -50,22 +50,47 @@ entry_point(CmdLine *cmdline)
s("3 * 4 + 2"),
s("(3 * 4) + 2"),
s("2 + (3 * 4)"),
s("123 | 456"),
s("123 + "),
s("-123"),
s("sizeof 123"),
s("1 ? 123 : 456"),
s("123(1, 2, 3)"),
};
for EachElement(idx, strings)
{
Temp scratch = scratch_begin(0, 0);
String8List msgs = {0};
// rjf: string -> expr
E2_Expr *expr = &e2_expr_nil;
{
E2_ParseState state = {0};
E2_ExprMap expr_map = {0};
E2_Expr *access_expr = &e2_expr_nil;
for(;;)
{
E2_Parse parse = e2_parse_from_string(scratch.arena, &state, &expr_map, strings[idx]);
if(parse.status == E2_Status_Good)
{
E2_Parse parse = e2_parse_from_string(scratch.arena, &state, &expr_map, access_expr, strings[idx]);
expr = parse.expr;
access_expr = &e2_expr_nil;
for EachNode(n, E2_Msg, parse.msgs.first)
{
str8_list_push(scratch.arena, &msgs, n->string);
}
if(parse.status == E2_ParseStatus_MissedIdentifierResolution)
{
e2_expr_map_push(scratch.arena, &expr_map, parse.missed_identifier, e2_expr_const_u64_or_smaller(scratch.arena, 123));
}
if(parse.status == E2_ParseStatus_IndexAccess)
{
access_expr = e2_expr_const_u64_or_smaller(scratch.arena, 111);
}
if(parse.status == E2_ParseStatus_MemberAccess)
{
access_expr = e2_expr_const_u64_or_smaller(scratch.arena, 456);
}
if(e2_parse_status_is_terminal(parse.status))
{
break;
}
}
@@ -82,20 +107,29 @@ entry_point(CmdLine *cmdline)
for(;;)
{
E2_Interp interp = e2_interp_from_bytecode(scratch.arena, &state, &space_map, bytecode);
if(interp.status == E2_Status_Good)
{
val = interp.val;
break;
}
else if(E2_Status_FirstError <= interp.status <= E2_Status_LastError)
if(e2_interp_status_is_terminal(interp.status))
{
if(interp.status != E2_InterpStatus_Good)
{
str8_list_pushf(scratch.arena, &msgs, "Interpretation error (%i).", interp.status);
}
break;
}
}
}
// rjf: message string list -> string
StringJoin join = {.sep = s(" ")};
String8 msgs_string = str8_list_join(scratch.arena, &msgs, &join);
// rjf: log
printf("%.*s -> %I64u\n", str8_varg(strings[idx]), val.u64);
printf("%.*s -> %I64d *%s* %s%.*s\n", str8_varg(strings[idx]),
val.s64,
expr->mode == E2_Mode_Type ? "type" :
expr->mode == E2_Mode_Value ? "value" :
"address",
msgs_string.size != 0 ? " // " : "", str8_varg(msgs_string));
fflush(stdout);
scratch_end(scratch);
+2 -2
View File
@@ -1276,9 +1276,9 @@ make_directory(String8 path)
//~ rjf: @per_os_impl Aborting
internal void
abort_self(S32 exit_code)
abort_self(U64 exit_code)
{
ExitProcess(exit_code);
ExitProcess((int)exit_code);
}
////////////////////////////////