mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 09:18:09 +00:00
eval2: first pass at c recursive type expression parsing
This commit is contained in:
+155
-46
@@ -1070,6 +1070,21 @@ e2_expr_push_child(Arena *arena, E2_Expr *parent, E2_Expr *expr)
|
|||||||
e2_expr_push_child_node(parent, n);
|
e2_expr_push_child_node(parent, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
e2_expr_push_child_node_front(E2_Expr *parent, E2_ExprNode *node)
|
||||||
|
{
|
||||||
|
SLLQueuePushFront(parent->first_child, parent->last_child, node);
|
||||||
|
parent->child_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
e2_expr_push_child_front(Arena *arena, E2_Expr *parent, E2_Expr *expr)
|
||||||
|
{
|
||||||
|
E2_ExprNode *n = push_array(arena, E2_ExprNode, 1);
|
||||||
|
n->v = expr;
|
||||||
|
e2_expr_push_child_node_front(parent, n);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Expression Constructors
|
//~ rjf: Expression Constructors
|
||||||
|
|
||||||
@@ -1539,14 +1554,26 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
E2_Parse parse = {E2_ParseStatus_Error, .expr = &e2_expr_nil, .params_expr = &e2_expr_nil};
|
E2_Parse parse = {E2_ParseStatus_Error, .expr = &e2_expr_nil, .params_expr = &e2_expr_nil};
|
||||||
E2_LangInfo *lang_info = &e2_lang_kind_info_table[lang];
|
E2_LangInfo *lang_info = &e2_lang_kind_info_table[lang];
|
||||||
|
|
||||||
|
//- rjf: set up initial parsing task
|
||||||
|
if(state->top_task == 0)
|
||||||
|
{
|
||||||
|
state->top_task = &state->start_task;
|
||||||
|
state->top_task->src_range = r1u64(0, string.size);
|
||||||
|
state->top_task->child_count_target = max_U64;
|
||||||
|
state->top_task->max_precedence = max_S64;
|
||||||
|
state->top_task->expected_splitter = s(",");
|
||||||
|
state->top_task->splitter_min_child_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//- rjf: parse & attach to top parsing task - if we don't have a top task
|
//- rjf: parse & attach to top parsing task - if we don't have a top task
|
||||||
// then it is just the result
|
// then it is just the result
|
||||||
E2_Expr *expr = &e2_expr_nil;
|
E2_Expr *expr = &e2_expr_nil;
|
||||||
for(B32 done = 0; !done;)
|
for(B32 done = 0; !done;)
|
||||||
{
|
{
|
||||||
U64 start_off = off;
|
U64 start_off = off;
|
||||||
S64 max_precedence = state->top_task ? state->top_task->max_precedence : max_S64;
|
S64 max_precedence = state->top_task->max_precedence;
|
||||||
B32 need_new_expr = (expr == &e2_expr_nil && !state->caller_info_completes_task);
|
B32 type_ancestors = state->top_task->do_type_ancestors;
|
||||||
|
B32 need_new_expr = (expr == &e2_expr_nil && !type_ancestors && !state->caller_info_completes_task);
|
||||||
E2_Token token = {0};
|
E2_Token token = {0};
|
||||||
|
|
||||||
//- rjf: skip leading whitespace / comments
|
//- rjf: skip leading whitespace / comments
|
||||||
@@ -1638,7 +1665,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: identifiers with an active dot op kind -> member access
|
//- rjf: identifiers with an active dot op kind -> member access
|
||||||
else if(need_new_expr && state->top_task != 0 && state->top_task->expr_kind == E2_ExprKind_Dot && e2_try_token(lang, string, E2_TokenKind_Identifier, s(""), &off, &token))
|
else if(need_new_expr && state->top_task->expr_kind == E2_ExprKind_Dot && e2_try_token(lang, string, E2_TokenKind_Identifier, s(""), &off, &token))
|
||||||
{
|
{
|
||||||
expr = e2_expr(arena, E2_ExprKind_Dot);
|
expr = e2_expr(arena, E2_ExprKind_Dot);
|
||||||
expr->first_child = state->top_task->first_child;
|
expr->first_child = state->top_task->first_child;
|
||||||
@@ -1656,7 +1683,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
{
|
{
|
||||||
String8 identifier = str8_substr(string, token.range);
|
String8 identifier = str8_substr(string, token.range);
|
||||||
B32 identifier_mapped = 0;
|
B32 identifier_mapped = 0;
|
||||||
B32 definitions_are_allowed = (state->top_task == 0 || state->top_task->expr_kind != E2_ExprKind_Macro);
|
B32 definitions_are_allowed = (state->top_task->expr_kind != E2_ExprKind_Macro);
|
||||||
|
|
||||||
// rjf: first try to resolve as a definition
|
// rjf: first try to resolve as a definition
|
||||||
if(definitions_are_allowed && !identifier_mapped && e2_try_token(lang, string, E2_TokenKind_Symbol, s("="), &off, 0))
|
if(definitions_are_allowed && !identifier_mapped && e2_try_token(lang, string, E2_TokenKind_Symbol, s("="), &off, 0))
|
||||||
@@ -1792,7 +1819,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rjf: try to resolve it as a macro argument
|
// rjf: try to resolve it as a macro argument
|
||||||
if(!identifier_mapped && state->top_task != 0 && state->top_task->expr_kind == E2_ExprKind_Macro)
|
if(!identifier_mapped && state->top_task->expr_kind == E2_ExprKind_Macro)
|
||||||
{
|
{
|
||||||
U64 macro_arg_num = 0;
|
U64 macro_arg_num = 0;
|
||||||
{
|
{
|
||||||
@@ -1862,16 +1889,17 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
expr->string = raw_string;
|
expr->string = raw_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: extend parsed expression tree with completed trailing type operators (right-to-left)
|
//- rjf: parse left-hand-side type operators
|
||||||
if(!state->caller_info_completes_task && expr != &e2_expr_nil)
|
if(!state->caller_info_completes_task && (expr != &e2_expr_nil || state->top_task->do_type_ancestors))
|
||||||
{
|
{
|
||||||
U64 trailing_symbol_off = off;
|
U64 trailing_symbol_off = off;
|
||||||
if(e2_try_token(lang, string, E2_TokenKind_Symbol, s(""), &trailing_symbol_off, &token))
|
if(e2_try_token(lang, string, E2_TokenKind_Symbol, s(""), &trailing_symbol_off, &token))
|
||||||
{
|
{
|
||||||
B32 is_expr_type = (expr->kind == E2_ExprKind_TypeIdentifier ||
|
B32 parent_looking_for_type = (state->top_task->expr_kind != E2_ExprKind_Null &&
|
||||||
expr->kind == E2_ExprKind_Ptr ||
|
state->top_task->child_count == 0 &&
|
||||||
(state->top_task != 0 && state->top_task->expr_kind == E2_ExprKind_Cast));
|
e2_expr_kind_is_first_operand_type_maybe_table[state->top_task->expr_kind]);
|
||||||
if(is_expr_type)
|
B32 is_expr_type = (e2_expr_kind_is_type_expr_table[expr->kind] || parent_looking_for_type);
|
||||||
|
if(is_expr_type || state->top_task->do_type_ancestors)
|
||||||
{
|
{
|
||||||
// rjf: token string -> operator kind
|
// rjf: token string -> operator kind
|
||||||
E2_ExprKind expr_kind = E2_ExprKind_Null;
|
E2_ExprKind expr_kind = E2_ExprKind_Null;
|
||||||
@@ -1893,7 +1921,10 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
if(expr_kind != E2_ExprKind_Null)
|
if(expr_kind != E2_ExprKind_Null)
|
||||||
{
|
{
|
||||||
E2_Expr *op_expr = e2_expr(arena, expr_kind);
|
E2_Expr *op_expr = e2_expr(arena, expr_kind);
|
||||||
e2_expr_push_child(arena, op_expr, expr);
|
if(expr != &e2_expr_nil)
|
||||||
|
{
|
||||||
|
e2_expr_push_child(arena, op_expr, expr);
|
||||||
|
}
|
||||||
expr = op_expr;
|
expr = op_expr;
|
||||||
off = trailing_symbol_off;
|
off = trailing_symbol_off;
|
||||||
}
|
}
|
||||||
@@ -1901,6 +1932,38 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- rjf: if we're parsing a type, and we see a C-style type info recursion (to
|
||||||
|
// express ancestors of the current type), then we need to generate a task to
|
||||||
|
// descend and parse the ancestor type
|
||||||
|
if(!state->caller_info_completes_task && expr != &e2_expr_nil)
|
||||||
|
{
|
||||||
|
B32 parent_looking_for_type = (state->top_task->expr_kind != E2_ExprKind_Null &&
|
||||||
|
state->top_task->child_count == 0 &&
|
||||||
|
e2_expr_kind_is_first_operand_type_maybe_table[state->top_task->expr_kind]);
|
||||||
|
B32 is_expr_type = (e2_expr_kind_is_type_expr_table[expr->kind] || parent_looking_for_type);
|
||||||
|
if(is_expr_type && e2_try_token(lang, string, E2_TokenKind_Symbol, s("("), &off, &token))
|
||||||
|
{
|
||||||
|
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->expected_closer = s(")");
|
||||||
|
task->child_count_target = 1;
|
||||||
|
task->max_precedence = max_S64;
|
||||||
|
task->do_type_ancestors = 1;
|
||||||
|
task->type_lhs = expr;
|
||||||
|
SLLStackPush(state->top_task, task);
|
||||||
|
expr = &e2_expr_nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//- rjf: extend parsed expression tree with trailing operators
|
//- rjf: extend parsed expression tree with trailing operators
|
||||||
if(!state->caller_info_completes_task && expr != &e2_expr_nil)
|
if(!state->caller_info_completes_task && expr != &e2_expr_nil)
|
||||||
{
|
{
|
||||||
@@ -1926,7 +1989,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
E2_ExprKindParseInfo *expr_kind_info = &lang_info->expr_kind_parse_infos[idx];
|
E2_ExprKindParseInfo *expr_kind_info = &lang_info->expr_kind_parse_infos[idx];
|
||||||
if(expr_kind_info->precedence <= max_precedence &&
|
if(expr_kind_info->precedence <= max_precedence &&
|
||||||
str8_match(token_string, expr_kind_info->sep, 0) &&
|
str8_match(token_string, expr_kind_info->sep, 0) &&
|
||||||
(!!expr_is_type == !!e2_expr_kind_is_type_expr_table[expr_kind_info->expr_kind]))
|
(!expr_is_type || e2_expr_kind_allow_type_operands_table[expr_kind_info->expr_kind]))
|
||||||
{
|
{
|
||||||
splitter = expr_kind_info->chain;
|
splitter = expr_kind_info->chain;
|
||||||
closer = expr_kind_info->post;
|
closer = expr_kind_info->post;
|
||||||
@@ -1939,7 +2002,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: non-null operator kind -> build binary expression node, push task to fill other child
|
// rjf: non-null operator kind -> push task to fill other children of this operator node
|
||||||
if(expr_kind != E2_ExprKind_Null)
|
if(expr_kind != E2_ExprKind_Null)
|
||||||
{
|
{
|
||||||
E2_ParseTask *task = state->free_task;
|
E2_ParseTask *task = state->free_task;
|
||||||
@@ -1959,6 +2022,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
task->reverse_children = reverse_children;
|
task->reverse_children = reverse_children;
|
||||||
task->max_precedence = precedence;
|
task->max_precedence = precedence;
|
||||||
task->expected_splitter = splitter;
|
task->expected_splitter = splitter;
|
||||||
|
task->splitter_min_child_count = 2;
|
||||||
task->expected_closer = closer;
|
task->expected_closer = closer;
|
||||||
task->splitter_is_required = splitter_is_required;
|
task->splitter_is_required = splitter_is_required;
|
||||||
SLLStackPush(state->top_task, task);
|
SLLStackPush(state->top_task, task);
|
||||||
@@ -1974,6 +2038,18 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
//- rjf: pop finished expressions
|
//- rjf: pop finished expressions
|
||||||
for(B32 task_pushed = 0; state->top_task != 0 && !done && !task_pushed;)
|
for(B32 task_pushed = 0; state->top_task != 0 && !done && !task_pushed;)
|
||||||
{
|
{
|
||||||
|
//- rjf: if this task has a type ancestor: our finished expression is
|
||||||
|
// actually a descendant of that. we want to push our finished expression
|
||||||
|
// as a child, and then use the next type ancestor as the root expression
|
||||||
|
// which we push to our current task.
|
||||||
|
if(state->top_task->next_type_ancestor != 0 && state->top_task->next_type_ancestor != &e2_expr_nil)
|
||||||
|
{
|
||||||
|
E2_Expr *type_descendant = expr;
|
||||||
|
expr = state->top_task->next_type_ancestor;
|
||||||
|
state->top_task->next_type_ancestor = &e2_expr_nil;
|
||||||
|
e2_expr_push_child_front(arena, expr, type_descendant);
|
||||||
|
}
|
||||||
|
|
||||||
//- rjf: gather finished expression to current task; increase task child count
|
//- rjf: gather finished expression to current task; increase task child count
|
||||||
if(!state->caller_info_completes_task)
|
if(!state->caller_info_completes_task)
|
||||||
{
|
{
|
||||||
@@ -1992,7 +2068,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
|
|
||||||
//- rjf: consume expected splitters
|
//- rjf: consume expected splitters
|
||||||
if(!state->caller_info_completes_task &&
|
if(!state->caller_info_completes_task &&
|
||||||
state->top_task->child_count > 1 &&
|
state->top_task->child_count >= state->top_task->splitter_min_child_count &&
|
||||||
state->top_task->expected_splitter.size != 0 &&
|
state->top_task->expected_splitter.size != 0 &&
|
||||||
state->top_task->child_count < state->top_task->child_count_target)
|
state->top_task->child_count < state->top_task->child_count_target)
|
||||||
{
|
{
|
||||||
@@ -2011,7 +2087,8 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
|
|
||||||
//- rjf: determine if the task above a parenthesized sub-expression is expecting a type
|
//- rjf: determine if the task above a parenthesized sub-expression is expecting a type
|
||||||
B32 parent_looking_for_type = 0;
|
B32 parent_looking_for_type = 0;
|
||||||
if(state->top_task->next != 0 &&
|
if(!state->top_task->do_type_ancestors &&
|
||||||
|
state->top_task->next != 0 &&
|
||||||
state->top_task->next->expr_kind != E2_ExprKind_Null &&
|
state->top_task->next->expr_kind != E2_ExprKind_Null &&
|
||||||
state->top_task->next->child_count == 0 &&
|
state->top_task->next->child_count == 0 &&
|
||||||
e2_expr_kind_is_first_operand_type_maybe_table[state->top_task->next->expr_kind])
|
e2_expr_kind_is_first_operand_type_maybe_table[state->top_task->next->expr_kind])
|
||||||
@@ -2021,7 +2098,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
|
|
||||||
//- rjf: determine if first child of a parenthesized sub-expression is a type
|
//- rjf: determine if first child of a parenthesized sub-expression is a type
|
||||||
B32 parenthesized_child_is_type = 0;
|
B32 parenthesized_child_is_type = 0;
|
||||||
if(!parent_looking_for_type && closer_found && state->top_task->child_count == 1)
|
if(!state->top_task->do_type_ancestors && !parent_looking_for_type && closer_found && state->top_task->child_count == 1)
|
||||||
{
|
{
|
||||||
E2_Expr *expr = state->top_task->first_child->v;
|
E2_Expr *expr = state->top_task->first_child->v;
|
||||||
parenthesized_child_is_type = 1;
|
parenthesized_child_is_type = 1;
|
||||||
@@ -2094,11 +2171,18 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
//- rjf: produced finished expression tree, given all children
|
//- rjf: produced finished expression tree, given all children
|
||||||
E2_Expr *finished_root = &e2_expr_nil;
|
E2_Expr *finished_root = &e2_expr_nil;
|
||||||
{
|
{
|
||||||
finished_root = e2_expr(arena, completed_task->expr_kind);
|
if(completed_task->expr_kind == E2_ExprKind_Null && completed_task->child_count == 1)
|
||||||
finished_root->first_child = completed_task->first_child;
|
{
|
||||||
finished_root->last_child = completed_task->last_child;
|
finished_root = completed_task->first_child->v;
|
||||||
finished_root->child_count = completed_task->child_count;
|
}
|
||||||
finished_root->src_range = completed_task->src_range;
|
else
|
||||||
|
{
|
||||||
|
finished_root = e2_expr(arena, completed_task->expr_kind);
|
||||||
|
finished_root->first_child = completed_task->first_child;
|
||||||
|
finished_root->last_child = completed_task->last_child;
|
||||||
|
finished_root->child_count = completed_task->child_count;
|
||||||
|
finished_root->src_range = completed_task->src_range;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: report missing closers
|
//- rjf: report missing closers
|
||||||
@@ -2107,6 +2191,25 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
e2_msgf(arena, &parse.msgs, r1u64(off, off), "Expected `%S`.", completed_task->expected_closer);
|
e2_msgf(arena, &parse.msgs, r1u64(off, off), "Expected `%S`.", completed_task->expected_closer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- rjf: if this task parsed type ancestors:
|
||||||
|
//
|
||||||
|
// we need to pop this task, and return to working on the original left-hand-side
|
||||||
|
// type descendant. but, we need to remember the parsed type ancestors, so that
|
||||||
|
// we can apply them to the type once the right-hand-side has been parsed.
|
||||||
|
//
|
||||||
|
// otherwise (normal case): work on the parent of the finished expression next,
|
||||||
|
// using the finished expression as the completed child.
|
||||||
|
//
|
||||||
|
if(completed_task->do_type_ancestors)
|
||||||
|
{
|
||||||
|
expr = completed_task->type_lhs;
|
||||||
|
completed_task->next->next_type_ancestor = finished_root;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expr = finished_root;
|
||||||
|
}
|
||||||
|
|
||||||
//- rjf: release task
|
//- rjf: release task
|
||||||
if(!done)
|
if(!done)
|
||||||
{
|
{
|
||||||
@@ -2114,14 +2217,25 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
SLLStackPush(state->free_task, completed_task);
|
SLLStackPush(state->free_task, completed_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: work on the parent of the finished expression next
|
//- rjf: if this task still has potential right-hand-sides, then we need to
|
||||||
expr = finished_root;
|
// break out of the pop-loop and keep parsing at this level.
|
||||||
|
if(state->top_task->expr_kind == E2_ExprKind_Null || completed_task->do_type_ancestors)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: if the top task is not done -> break & continue - reset expression, because we need to parse another.
|
//- rjf: if the top task is not done -> break & continue.
|
||||||
|
//
|
||||||
|
// if we have an active op kind, reset expression, because we need to parse another.
|
||||||
|
// if we don't, we need to look for extensions of our current expression instead.
|
||||||
|
//
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
expr = &e2_expr_nil;
|
if(state->top_task->expr_kind != E2_ExprKind_Null)
|
||||||
|
{
|
||||||
|
expr = &e2_expr_nil;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2131,16 +2245,13 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
if(off >= string.size || (off == start_off && !e2_parse_status_is_caller_request(parse.status)))
|
if(off >= string.size || (off == start_off && !e2_parse_status_is_caller_request(parse.status)))
|
||||||
{
|
{
|
||||||
done = 1;
|
done = 1;
|
||||||
if(state->top_task == 0)
|
if(expr != &e2_expr_nil)
|
||||||
{
|
{
|
||||||
if(parse.expr == &e2_expr_nil && expr != &e2_expr_nil)
|
parse.expr = expr;
|
||||||
{
|
}
|
||||||
parse.expr = expr;
|
if(parse.status == E2_ParseStatus_Error)
|
||||||
}
|
{
|
||||||
if(parse.status == E2_ParseStatus_Error)
|
parse.status = E2_ParseStatus_Good;
|
||||||
{
|
|
||||||
parse.status = E2_ParseStatus_Good;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2164,7 +2275,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
|||||||
//- rjf: report incomplete tasks
|
//- rjf: report incomplete tasks
|
||||||
if(off >= string.size && !e2_parse_status_is_caller_request(parse.status))
|
if(off >= string.size && !e2_parse_status_is_caller_request(parse.status))
|
||||||
{
|
{
|
||||||
for(E2_ParseTask *t = state->top_task; t != 0; t = t->next)
|
for(E2_ParseTask *t = state->top_task; t != 0 && t != &state->start_task; t = t->next)
|
||||||
{
|
{
|
||||||
String8 symbol = {0};
|
String8 symbol = {0};
|
||||||
if(t->expr_kind != E2_ExprKind_Null)
|
if(t->expr_kind != E2_ExprKind_Null)
|
||||||
@@ -2410,6 +2521,7 @@ e2_compile_from_expr(Arena *arena, E2_CompileState *state, E2_IRNode *resolve_re
|
|||||||
finished_root->string = e->string;
|
finished_root->string = e->string;
|
||||||
finished_root->type_key = e2_type_key_cons_array(e2_type_key_basic(E2_TypeKind_UChar8), e->string.size);
|
finished_root->type_key = e2_type_key_cons_array(e2_type_key_basic(E2_TypeKind_UChar8), e->string.size);
|
||||||
finished_root->val.u64 = e->string.size;
|
finished_root->val.u64 = e->string.size;
|
||||||
|
finished_root->mode = E2_Mode_Value;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
//- rjf: character literals
|
//- rjf: character literals
|
||||||
@@ -2545,16 +2657,8 @@ e2_compile_from_expr(Arena *arena, E2_CompileState *state, E2_IRNode *resolve_re
|
|||||||
{
|
{
|
||||||
e2_msgf(arena, &compile.msgs, e->src_range, "Cannot cast to this type.");
|
e2_msgf(arena, &compile.msgs, e->src_range, "Cannot cast to this type.");
|
||||||
}
|
}
|
||||||
else if(e2_type_kind_is_ptr_or_ref(e2_type_kind_from_key(cast_type_key)))
|
E2_IRNode *castee_ir = rhs;
|
||||||
{
|
finished_root = e2_irnode_convert_if_possible(arena, castee_ir, cast_type_key);
|
||||||
finished_root = rhs;
|
|
||||||
rhs->mode = E2_Mode_Address;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
E2_IRNode *castee_ir = rhs;
|
|
||||||
finished_root = e2_irnode_convert_if_possible(arena, castee_ir, cast_type_key);
|
|
||||||
}
|
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
//- rjf: dereferences
|
//- rjf: dereferences
|
||||||
@@ -2912,6 +3016,10 @@ e2_compile_from_expr(Arena *arena, E2_CompileState *state, E2_IRNode *resolve_re
|
|||||||
{
|
{
|
||||||
compile_time_cond = 1;
|
compile_time_cond = 1;
|
||||||
}
|
}
|
||||||
|
if(pass_ir->mode != fail_ir->mode)
|
||||||
|
{
|
||||||
|
compile_time_cond = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: compile-time conditional -> ask caller to evaluate conditional
|
// rjf: compile-time conditional -> ask caller to evaluate conditional
|
||||||
@@ -2993,6 +3101,7 @@ e2_compile_from_expr(Arena *arena, E2_CompileState *state, E2_IRNode *resolve_re
|
|||||||
|
|
||||||
// rjf: take result
|
// rjf: take result
|
||||||
finished_root = cond_root;
|
finished_root = cond_root;
|
||||||
|
finished_root->mode = pass_ir->mode;
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -341,6 +341,7 @@ struct E2_ParseTask
|
|||||||
Rng1U64 src_range;
|
Rng1U64 src_range;
|
||||||
E2_ExprNode *first_child;
|
E2_ExprNode *first_child;
|
||||||
E2_ExprNode *last_child;
|
E2_ExprNode *last_child;
|
||||||
|
E2_Expr *next_type_ancestor;
|
||||||
U64 child_count;
|
U64 child_count;
|
||||||
U64 child_count_target;
|
U64 child_count_target;
|
||||||
B32 reverse_children;
|
B32 reverse_children;
|
||||||
@@ -349,14 +350,18 @@ struct E2_ParseTask
|
|||||||
String8 identifier;
|
String8 identifier;
|
||||||
String8 expected_closer;
|
String8 expected_closer;
|
||||||
String8 expected_splitter;
|
String8 expected_splitter;
|
||||||
|
U64 splitter_min_child_count;
|
||||||
B32 splitter_is_required;
|
B32 splitter_is_required;
|
||||||
String8List macro_arg_names;
|
String8List macro_arg_names;
|
||||||
|
B32 do_type_ancestors;
|
||||||
|
E2_Expr *type_lhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct E2_ParseState E2_ParseState;
|
typedef struct E2_ParseState E2_ParseState;
|
||||||
struct E2_ParseState
|
struct E2_ParseState
|
||||||
{
|
{
|
||||||
U64 string_off;
|
U64 string_off;
|
||||||
|
E2_ParseTask start_task;
|
||||||
E2_ParseTask *top_task;
|
E2_ParseTask *top_task;
|
||||||
E2_ParseTask *free_task;
|
E2_ParseTask *free_task;
|
||||||
U64 last_caller_request_string_off;
|
U64 last_caller_request_string_off;
|
||||||
@@ -632,6 +637,8 @@ internal E2_TypeKey e2_coerced_type_key_from_operands(E2_TypeKey lhs, E2_TypeKey
|
|||||||
internal E2_Expr *e2_expr(Arena *arena, E2_ExprKind kind);
|
internal E2_Expr *e2_expr(Arena *arena, E2_ExprKind kind);
|
||||||
internal void e2_expr_push_child_node(E2_Expr *parent, E2_ExprNode *node);
|
internal void e2_expr_push_child_node(E2_Expr *parent, E2_ExprNode *node);
|
||||||
internal void e2_expr_push_child(Arena *arena, E2_Expr *parent, E2_Expr *expr);
|
internal void e2_expr_push_child(Arena *arena, E2_Expr *parent, E2_Expr *expr);
|
||||||
|
internal void e2_expr_push_child_node_front(E2_Expr *parent, E2_ExprNode *node);
|
||||||
|
internal void e2_expr_push_child_front(Arena *arena, E2_Expr *parent, E2_Expr *expr);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: IR Tree Constructors
|
//~ rjf: IR Tree Constructors
|
||||||
|
|||||||
+50
-43
@@ -1,51 +1,51 @@
|
|||||||
// Copyright (c) Epic Games Tools
|
// Copyright (c) Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
@table(name is_type_expression is_first_operand_type_maybe target_operand_count)
|
@table(name allow_type_operands is_type_expression is_first_operand_type_maybe target_operand_count)
|
||||||
E2_ExprKindTable:
|
E2_ExprKindTable:
|
||||||
{
|
{
|
||||||
{Identifier 0 0 0 }
|
{Identifier 0 0 0 0 }
|
||||||
{MacroArg 0 0 0 }
|
{MacroArg 0 0 0 0 }
|
||||||
{TypeIdentifier 1 0 0 }
|
{TypeIdentifier 0 1 0 0 }
|
||||||
{Ptr 1 1 1 }
|
{Ptr 1 1 1 1 }
|
||||||
{Array 1 1 2 }
|
{Array 1 1 1 2 }
|
||||||
{Numeric 0 0 0 }
|
{Numeric 0 0 0 0 }
|
||||||
{StringLiteral 0 0 0 }
|
{StringLiteral 0 0 0 0 }
|
||||||
{CharLiteral 0 0 0 }
|
{CharLiteral 0 0 0 0 }
|
||||||
{Dot 0 0 1 }
|
{Dot 1 0 0 1 }
|
||||||
{Index 0 0 2 }
|
{Index 0 0 0 2 }
|
||||||
{Call 0 0 0xffffffffffffffffull}
|
{Call 1 0 0 0xffffffffffffffffull}
|
||||||
{DerefAsm 0 0 1 }
|
{DerefAsm 1 0 0 1 }
|
||||||
{SizeOf 0 1 1 }
|
{SizeOf 1 0 1 1 }
|
||||||
{TypeOf 1 1 1 }
|
{TypeOf 1 1 1 1 }
|
||||||
{Cast 0 1 2 }
|
{Cast 1 0 1 2 }
|
||||||
{Deref 0 0 1 }
|
{Deref 1 0 0 1 }
|
||||||
{Address 0 0 1 }
|
{Address 1 0 0 1 }
|
||||||
{Pos 0 0 1 }
|
{Pos 1 0 0 1 }
|
||||||
{Neg 0 0 1 }
|
{Neg 1 0 0 1 }
|
||||||
{LogNot 0 0 1 }
|
{LogNot 1 0 0 1 }
|
||||||
{BitNot 0 0 1 }
|
{BitNot 1 0 0 1 }
|
||||||
{Mul 0 0 2 }
|
{Mul 1 0 0 2 }
|
||||||
{Div 0 0 2 }
|
{Div 1 0 0 2 }
|
||||||
{Mod 0 0 2 }
|
{Mod 1 0 0 2 }
|
||||||
{Add 0 0 2 }
|
{Add 1 0 0 2 }
|
||||||
{Sub 0 0 2 }
|
{Sub 1 0 0 2 }
|
||||||
{LShift 0 0 2 }
|
{LShift 1 0 0 2 }
|
||||||
{RShift 0 0 2 }
|
{RShift 1 0 0 2 }
|
||||||
{Less 0 0 2 }
|
{Less 1 0 0 2 }
|
||||||
{LtEq 0 0 2 }
|
{LtEq 1 0 0 2 }
|
||||||
{Grtr 0 0 2 }
|
{Grtr 1 0 0 2 }
|
||||||
{GrEq 0 0 2 }
|
{GrEq 1 0 0 2 }
|
||||||
{EqEq 0 0 2 }
|
{EqEq 1 0 0 2 }
|
||||||
{NtEq 0 0 2 }
|
{NtEq 1 0 0 2 }
|
||||||
{BitAnd 0 0 2 }
|
{BitAnd 1 0 0 2 }
|
||||||
{BitXor 0 0 2 }
|
{BitXor 1 0 0 2 }
|
||||||
{BitOr 0 0 2 }
|
{BitOr 1 0 0 2 }
|
||||||
{LogAnd 0 0 2 }
|
{LogAnd 1 0 0 2 }
|
||||||
{LogOr 0 0 2 }
|
{LogOr 1 0 0 2 }
|
||||||
{Define 0 0 1 }
|
{Define 1 0 0 1 }
|
||||||
{Macro 0 0 1 }
|
{Macro 1 0 0 1 }
|
||||||
{Cond 0 0 3 }
|
{Cond 1 0 0 3 }
|
||||||
}
|
}
|
||||||
|
|
||||||
@enum E2_ExprKind:
|
@enum E2_ExprKind:
|
||||||
@@ -55,6 +55,12 @@ E2_ExprKindTable:
|
|||||||
COUNT,
|
COUNT,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@data(B8) e2_expr_kind_allow_type_operands_table:
|
||||||
|
{
|
||||||
|
0,
|
||||||
|
@expand(E2_ExprKindTable a) `$(a.allow_type_operands)`
|
||||||
|
}
|
||||||
|
|
||||||
@data(B8) e2_expr_kind_is_type_expr_table:
|
@data(B8) e2_expr_kind_is_type_expr_table:
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
@@ -110,6 +116,7 @@ E2_LangKindTable:
|
|||||||
@table(name parse_kind precedence pre sep pos chain reverse_children)
|
@table(name parse_kind precedence pre sep pos chain reverse_children)
|
||||||
E2_ExprKindParseInfoTable_CLike:
|
E2_ExprKindParseInfoTable_CLike:
|
||||||
{
|
{
|
||||||
|
{Dot Postfix 1 "" "." "" "" 0}
|
||||||
{Index Postfix 1 "" "[" "]" "" 0}
|
{Index Postfix 1 "" "[" "]" "" 0}
|
||||||
{Call Postfix 1 "" "(" ")" "," 0}
|
{Call Postfix 1 "" "(" ")" "," 0}
|
||||||
{DerefAsm Prefix 1 "[" "" "]" "" 0}
|
{DerefAsm Prefix 1 "[" "" "]" "" 0}
|
||||||
|
|||||||
@@ -4,6 +4,53 @@
|
|||||||
//- GENERATED CODE
|
//- GENERATED CODE
|
||||||
|
|
||||||
C_LINKAGE_BEGIN
|
C_LINKAGE_BEGIN
|
||||||
|
B8 e2_expr_kind_allow_type_operands_table[43] =
|
||||||
|
{
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
};
|
||||||
|
|
||||||
B8 e2_expr_kind_is_type_expr_table[43] =
|
B8 e2_expr_kind_is_type_expr_table[43] =
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
@@ -150,8 +197,9 @@ E2_LangInfo e2_lang_kind_info_table[1] =
|
|||||||
{ArrayCount(e2_expr_kind_parse_info_table__clike), (e2_expr_kind_parse_info_table__clike)},
|
{ArrayCount(e2_expr_kind_parse_info_table__clike), (e2_expr_kind_parse_info_table__clike)},
|
||||||
};
|
};
|
||||||
|
|
||||||
E2_ExprKindParseInfo e2_expr_kind_parse_info_table__clike[37] =
|
E2_ExprKindParseInfo e2_expr_kind_parse_info_table__clike[38] =
|
||||||
{
|
{
|
||||||
|
{E2_ExprKind_Dot, E2_ExprParseKind_Postfix, 1, 0, str8_lit_comp(""), str8_lit_comp("."), str8_lit_comp(""), str8_lit_comp("")},
|
||||||
{E2_ExprKind_Index, E2_ExprParseKind_Postfix, 1, 0, str8_lit_comp(""), str8_lit_comp("["), str8_lit_comp("]"), str8_lit_comp("")},
|
{E2_ExprKind_Index, E2_ExprParseKind_Postfix, 1, 0, str8_lit_comp(""), str8_lit_comp("["), str8_lit_comp("]"), str8_lit_comp("")},
|
||||||
{E2_ExprKind_Call, E2_ExprParseKind_Postfix, 1, 0, str8_lit_comp(""), str8_lit_comp("("), str8_lit_comp(")"), str8_lit_comp(",")},
|
{E2_ExprKind_Call, E2_ExprParseKind_Postfix, 1, 0, str8_lit_comp(""), str8_lit_comp("("), str8_lit_comp(")"), str8_lit_comp(",")},
|
||||||
{E2_ExprKind_DerefAsm, E2_ExprParseKind_Prefix, 1, 0, str8_lit_comp("["), str8_lit_comp(""), str8_lit_comp("]"), str8_lit_comp("")},
|
{E2_ExprKind_DerefAsm, E2_ExprParseKind_Prefix, 1, 0, str8_lit_comp("["), str8_lit_comp(""), str8_lit_comp("]"), str8_lit_comp("")},
|
||||||
|
|||||||
@@ -158,11 +158,12 @@ E2_ExprKindParseInfo *expr_kind_parse_infos;
|
|||||||
};
|
};
|
||||||
|
|
||||||
C_LINKAGE_BEGIN
|
C_LINKAGE_BEGIN
|
||||||
|
extern B8 e2_expr_kind_allow_type_operands_table[43];
|
||||||
extern B8 e2_expr_kind_is_type_expr_table[43];
|
extern B8 e2_expr_kind_is_type_expr_table[43];
|
||||||
extern B8 e2_expr_kind_is_first_operand_type_maybe_table[43];
|
extern B8 e2_expr_kind_is_first_operand_type_maybe_table[43];
|
||||||
extern U64 e2_expr_kind_target_operand_count_table[43];
|
extern U64 e2_expr_kind_target_operand_count_table[43];
|
||||||
extern E2_LangInfo e2_lang_kind_info_table[1];
|
extern E2_LangInfo e2_lang_kind_info_table[1];
|
||||||
extern E2_ExprKindParseInfo e2_expr_kind_parse_info_table__clike[37];
|
extern E2_ExprKindParseInfo e2_expr_kind_parse_info_table__clike[38];
|
||||||
extern U8 e2_type_kind_basic_byte_size_table[61];
|
extern U8 e2_type_kind_basic_byte_size_table[61];
|
||||||
extern String8 e2_type_kind_basic_string_table[61];
|
extern String8 e2_type_kind_basic_string_table[61];
|
||||||
|
|
||||||
|
|||||||
+22
-17
@@ -43,46 +43,51 @@ entry_point(CmdLine *cmdline)
|
|||||||
// (A)
|
// (A)
|
||||||
// int & B
|
// int & B
|
||||||
// (1 + (int)&B)
|
// (1 + (int)&B)
|
||||||
s("int32[100]"),
|
|
||||||
|
// TODO(rjf): this is now busted, `mul` root comes out - related to always having a top task maybe?
|
||||||
|
s("3 * 4 + 2"),
|
||||||
|
s("(3 * 4) + 2"),
|
||||||
|
s("3 * 4"),
|
||||||
|
s("foo"),
|
||||||
|
s("foo.bar"),
|
||||||
|
s("[123]"),
|
||||||
|
s("123[456]"),
|
||||||
|
s("2 + (3 * 4)"),
|
||||||
|
s("int32 == int32"),
|
||||||
|
s("123, 456"),
|
||||||
|
s("222.f"),
|
||||||
s("123 as float32"),
|
s("123 as float32"),
|
||||||
|
s("int32 (*) [100]"),
|
||||||
|
s("int32[100]"),
|
||||||
s("cast float32 123"),
|
s("cast float32 123"),
|
||||||
s("cast (float32) 123"),
|
s("cast (float32) 123"),
|
||||||
s("(int32 *)123"),
|
s("(int32 *)123"),
|
||||||
s("bar(a, b) = a + b"),
|
s("bar(a, b) = a + b"),
|
||||||
s("123, 456"),
|
|
||||||
s("int32 == int32"),
|
|
||||||
s("foo = 123"),
|
s("foo = 123"),
|
||||||
s("1 > 2"),
|
s("1 > 2"),
|
||||||
|
s("1 ? 123 : 456"),
|
||||||
|
s("0 ? 123 : 456"),
|
||||||
s("1 ? \"Test\" : 888"),
|
s("1 ? \"Test\" : 888"),
|
||||||
s("'a'"),
|
s("'a'"),
|
||||||
s("'b'"),
|
s("'b'"),
|
||||||
s("float32(111)"),
|
|
||||||
s("float64(111)"),
|
|
||||||
s("222.f"),
|
|
||||||
s("222.0"),
|
|
||||||
s("(float32)222"),
|
s("(float32)222"),
|
||||||
s("(float64)222"),
|
s("(float64)222"),
|
||||||
s("[123]"),
|
s("222.0"),
|
||||||
s("foo"),
|
|
||||||
s("foo.bar"),
|
|
||||||
s("123[456]"),
|
|
||||||
s("123"),
|
s("123"),
|
||||||
s("123 + 456"),
|
s("123 + 456"),
|
||||||
s("!1"),
|
s("!1"),
|
||||||
s("!0"),
|
s("!0"),
|
||||||
s("1 + 1 + 1"),
|
s("1 + 1 + 1"),
|
||||||
s("40 / 0"),
|
s("40 / 0"),
|
||||||
s("3 * 4"),
|
|
||||||
s("3 * 4 + 2"),
|
|
||||||
s("(3 * 4) + 2"),
|
|
||||||
s("2 + (3 * 4)"),
|
|
||||||
s("123 | 456"),
|
s("123 | 456"),
|
||||||
s("123 + "),
|
s("123 + "),
|
||||||
s("-123"),
|
s("-123"),
|
||||||
s("sizeof 123"),
|
s("sizeof 123"),
|
||||||
s("1 ? 123 : 456"),
|
|
||||||
s("0 ? 123 : 456"),
|
|
||||||
s("123(1, 2, 3)"),
|
s("123(1, 2, 3)"),
|
||||||
|
#if 0
|
||||||
|
// s("float32(111)"),
|
||||||
|
// s("float64(111)"),
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
for EachElement(idx, strings)
|
for EachElement(idx, strings)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user