From fdbcf7ccdcedb5b1917355425d794190a6b046a1 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 26 Jun 2026 16:19:19 -0700 Subject: [PATCH] eval2: first pass at c recursive type expression parsing --- src/eval2/eval2.c | 201 ++++++++++++++++++++++++------- src/eval2/eval2.h | 7 ++ src/eval2/eval2.mdesk | 93 +++++++------- src/eval2/generated/eval2.meta.c | 50 +++++++- src/eval2/generated/eval2.meta.h | 3 +- src/scratch/ryan_scratch.c | 39 +++--- 6 files changed, 285 insertions(+), 108 deletions(-) diff --git a/src/eval2/eval2.c b/src/eval2/eval2.c index e1aecb5a..86807f60 100644 --- a/src/eval2/eval2.c +++ b/src/eval2/eval2.c @@ -1070,6 +1070,21 @@ e2_expr_push_child(Arena *arena, E2_Expr *parent, E2_Expr *expr) 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 @@ -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_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 // 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); + S64 max_precedence = state->top_task->max_precedence; + 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}; //- 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 - 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->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); 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 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 - 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; { @@ -1862,16 +1889,17 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type, expr->string = raw_string; } - //- rjf: extend parsed expression tree with completed trailing type operators (right-to-left) - if(!state->caller_info_completes_task && expr != &e2_expr_nil) + //- rjf: parse left-hand-side type operators + if(!state->caller_info_completes_task && (expr != &e2_expr_nil || state->top_task->do_type_ancestors)) { U64 trailing_symbol_off = off; if(e2_try_token(lang, string, E2_TokenKind_Symbol, s(""), &trailing_symbol_off, &token)) { - B32 is_expr_type = (expr->kind == E2_ExprKind_TypeIdentifier || - expr->kind == E2_ExprKind_Ptr || - (state->top_task != 0 && state->top_task->expr_kind == E2_ExprKind_Cast)); - if(is_expr_type) + 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 || state->top_task->do_type_ancestors) { // rjf: token string -> operator kind 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) { 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; 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 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]; if(expr_kind_info->precedence <= max_precedence && 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; 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) { 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->max_precedence = precedence; task->expected_splitter = splitter; + task->splitter_min_child_count = 2; task->expected_closer = closer; task->splitter_is_required = splitter_is_required; 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 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 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 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->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 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->child_count == 0 && 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 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; 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 E2_Expr *finished_root = &e2_expr_nil; { - 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; + if(completed_task->expr_kind == E2_ExprKind_Null && completed_task->child_count == 1) + { + finished_root = completed_task->first_child->v; + } + 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 @@ -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); } + //- 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 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); } - //- rjf: work on the parent of the finished expression next - expr = finished_root; + //- rjf: if this task still has potential right-hand-sides, then we need to + // 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 { - expr = &e2_expr_nil; + if(state->top_task->expr_kind != E2_ExprKind_Null) + { + expr = &e2_expr_nil; + } 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))) { 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; - } - if(parse.status == E2_ParseStatus_Error) - { - parse.status = E2_ParseStatus_Good; - } + parse.expr = expr; + } + if(parse.status == E2_ParseStatus_Error) + { + 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 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}; 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->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->mode = E2_Mode_Value; }break; //- 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."); } - else if(e2_type_kind_is_ptr_or_ref(e2_type_kind_from_key(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); - } + E2_IRNode *castee_ir = rhs; + finished_root = e2_irnode_convert_if_possible(arena, castee_ir, cast_type_key); }break; //- rjf: dereferences @@ -2912,6 +3016,10 @@ e2_compile_from_expr(Arena *arena, E2_CompileState *state, E2_IRNode *resolve_re { compile_time_cond = 1; } + if(pass_ir->mode != fail_ir->mode) + { + compile_time_cond = 1; + } } // 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 finished_root = cond_root; + finished_root->mode = pass_ir->mode; } }break; } diff --git a/src/eval2/eval2.h b/src/eval2/eval2.h index 3b1aa869..6abdcea4 100644 --- a/src/eval2/eval2.h +++ b/src/eval2/eval2.h @@ -341,6 +341,7 @@ struct E2_ParseTask Rng1U64 src_range; E2_ExprNode *first_child; E2_ExprNode *last_child; + E2_Expr *next_type_ancestor; U64 child_count; U64 child_count_target; B32 reverse_children; @@ -349,14 +350,18 @@ struct E2_ParseTask String8 identifier; String8 expected_closer; String8 expected_splitter; + U64 splitter_min_child_count; B32 splitter_is_required; String8List macro_arg_names; + B32 do_type_ancestors; + E2_Expr *type_lhs; }; typedef struct E2_ParseState E2_ParseState; struct E2_ParseState { U64 string_off; + E2_ParseTask start_task; E2_ParseTask *top_task; E2_ParseTask *free_task; 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 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_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 diff --git a/src/eval2/eval2.mdesk b/src/eval2/eval2.mdesk index 9392574c..359d1f21 100644 --- a/src/eval2/eval2.mdesk +++ b/src/eval2/eval2.mdesk @@ -1,51 +1,51 @@ // Copyright (c) Epic Games Tools // 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: { - {Identifier 0 0 0 } - {MacroArg 0 0 0 } - {TypeIdentifier 1 0 0 } - {Ptr 1 1 1 } - {Array 1 1 2 } - {Numeric 0 0 0 } - {StringLiteral 0 0 0 } - {CharLiteral 0 0 0 } - {Dot 0 0 1 } - {Index 0 0 2 } - {Call 0 0 0xffffffffffffffffull} - {DerefAsm 0 0 1 } - {SizeOf 0 1 1 } - {TypeOf 1 1 1 } - {Cast 0 1 2 } - {Deref 0 0 1 } - {Address 0 0 1 } - {Pos 0 0 1 } - {Neg 0 0 1 } - {LogNot 0 0 1 } - {BitNot 0 0 1 } - {Mul 0 0 2 } - {Div 0 0 2 } - {Mod 0 0 2 } - {Add 0 0 2 } - {Sub 0 0 2 } - {LShift 0 0 2 } - {RShift 0 0 2 } - {Less 0 0 2 } - {LtEq 0 0 2 } - {Grtr 0 0 2 } - {GrEq 0 0 2 } - {EqEq 0 0 2 } - {NtEq 0 0 2 } - {BitAnd 0 0 2 } - {BitXor 0 0 2 } - {BitOr 0 0 2 } - {LogAnd 0 0 2 } - {LogOr 0 0 2 } - {Define 0 0 1 } - {Macro 0 0 1 } - {Cond 0 0 3 } + {Identifier 0 0 0 0 } + {MacroArg 0 0 0 0 } + {TypeIdentifier 0 1 0 0 } + {Ptr 1 1 1 1 } + {Array 1 1 1 2 } + {Numeric 0 0 0 0 } + {StringLiteral 0 0 0 0 } + {CharLiteral 0 0 0 0 } + {Dot 1 0 0 1 } + {Index 0 0 0 2 } + {Call 1 0 0 0xffffffffffffffffull} + {DerefAsm 1 0 0 1 } + {SizeOf 1 0 1 1 } + {TypeOf 1 1 1 1 } + {Cast 1 0 1 2 } + {Deref 1 0 0 1 } + {Address 1 0 0 1 } + {Pos 1 0 0 1 } + {Neg 1 0 0 1 } + {LogNot 1 0 0 1 } + {BitNot 1 0 0 1 } + {Mul 1 0 0 2 } + {Div 1 0 0 2 } + {Mod 1 0 0 2 } + {Add 1 0 0 2 } + {Sub 1 0 0 2 } + {LShift 1 0 0 2 } + {RShift 1 0 0 2 } + {Less 1 0 0 2 } + {LtEq 1 0 0 2 } + {Grtr 1 0 0 2 } + {GrEq 1 0 0 2 } + {EqEq 1 0 0 2 } + {NtEq 1 0 0 2 } + {BitAnd 1 0 0 2 } + {BitXor 1 0 0 2 } + {BitOr 1 0 0 2 } + {LogAnd 1 0 0 2 } + {LogOr 1 0 0 2 } + {Define 1 0 0 1 } + {Macro 1 0 0 1 } + {Cond 1 0 0 3 } } @enum E2_ExprKind: @@ -55,6 +55,12 @@ E2_ExprKindTable: 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: { 0, @@ -110,6 +116,7 @@ E2_LangKindTable: @table(name parse_kind precedence pre sep pos chain reverse_children) E2_ExprKindParseInfoTable_CLike: { + {Dot Postfix 1 "" "." "" "" 0} {Index Postfix 1 "" "[" "]" "" 0} {Call Postfix 1 "" "(" ")" "," 0} {DerefAsm Prefix 1 "[" "" "]" "" 0} diff --git a/src/eval2/generated/eval2.meta.c b/src/eval2/generated/eval2.meta.c index 7f578104..ead6d5f3 100644 --- a/src/eval2/generated/eval2.meta.c +++ b/src/eval2/generated/eval2.meta.c @@ -4,6 +4,53 @@ //- GENERATED CODE 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] = { 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)}, }; -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_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("")}, diff --git a/src/eval2/generated/eval2.meta.h b/src/eval2/generated/eval2.meta.h index 5995845e..4a974d85 100644 --- a/src/eval2/generated/eval2.meta.h +++ b/src/eval2/generated/eval2.meta.h @@ -158,11 +158,12 @@ E2_ExprKindParseInfo *expr_kind_parse_infos; }; 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_first_operand_type_maybe_table[43]; extern U64 e2_expr_kind_target_operand_count_table[43]; 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 String8 e2_type_kind_basic_string_table[61]; diff --git a/src/scratch/ryan_scratch.c b/src/scratch/ryan_scratch.c index 02673e0f..647b16e3 100644 --- a/src/scratch/ryan_scratch.c +++ b/src/scratch/ryan_scratch.c @@ -43,46 +43,51 @@ entry_point(CmdLine *cmdline) // (A) // 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("int32 (*) [100]"), + s("int32[100]"), s("cast float32 123"), s("cast (float32) 123"), s("(int32 *)123"), s("bar(a, b) = a + b"), - s("123, 456"), - s("int32 == int32"), s("foo = 123"), s("1 > 2"), + s("1 ? 123 : 456"), + s("0 ? 123 : 456"), s("1 ? \"Test\" : 888"), s("'a'"), s("'b'"), - s("float32(111)"), - s("float64(111)"), - s("222.f"), - s("222.0"), s("(float32)222"), s("(float64)222"), - s("[123]"), - s("foo"), - s("foo.bar"), - s("123[456]"), + s("222.0"), s("123"), s("123 + 456"), s("!1"), s("!0"), s("1 + 1 + 1"), s("40 / 0"), - s("3 * 4"), - 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("0 ? 123 : 456"), s("123(1, 2, 3)"), +#if 0 + // s("float32(111)"), + // s("float64(111)"), +#endif }; for EachElement(idx, strings) {