eval2: split string -> expr compilation path into frontend / middle end - string -> expr, where expr is a loose structural syntax tree (where we can get macros and stuff without doing typechecking etc.), and expr -> irtree, where irtree is the usual typed / typechecked / ir structured representation - preserve minimal identifier resolution path for parser, but move most resolution things to the middle-end

This commit is contained in:
Ryan Fleury
2026-06-25 15:48:14 -07:00
parent c2b74260ef
commit d7393b2f65
6 changed files with 1124 additions and 860 deletions
+938 -744
View File
File diff suppressed because it is too large Load Diff
+60 -20
View File
@@ -11,6 +11,7 @@ typedef enum E2_ExprParseKind
{
E2_ExprParseKind_Null,
E2_ExprParseKind_UnaryPrefix,
E2_ExprParseKind_UnaryPostfix,
E2_ExprParseKind_Binary,
E2_ExprParseKind_Ternary,
E2_ExprParseKind_Call,
@@ -54,14 +55,10 @@ typedef enum E2_ParseStatus
E2_ParseStatus_LastTerminal = E2_ParseStatus_Error,
//- rjf: caller-provided info
E2_ParseStatus_MissedIdentifierResolution,
E2_ParseStatus_NewIdentifierDefinition,
E2_ParseStatus_MemberAccess,
E2_ParseStatus_IndexAccess,
E2_ParseStatus_Call,
E2_ParseStatus_CompileTimeEval,
E2_ParseStatus_FirstCallerRequest = E2_ParseStatus_MissedIdentifierResolution,
E2_ParseStatus_LastCallerRequest = E2_ParseStatus_CompileTimeEval,
E2_ParseStatus_CheckIdentifierIsType,
E2_ParseStatus_NewMacro,
E2_ParseStatus_FirstCallerRequest = E2_ParseStatus_CheckIdentifierIsType,
E2_ParseStatus_LastCallerRequest = E2_ParseStatus_NewMacro,
}
E2_ParseStatus;
@@ -333,10 +330,6 @@ struct E2_Expr
E2_ExprKind kind;
Rng1U64 src_range;
String8 string;
RDI_EvalOp op;
E2_TypeKey type_key;
E2_Mode mode;
E2_Val val;
};
typedef struct E2_ExprMapNode E2_ExprMapNode;
@@ -434,14 +427,48 @@ struct E2_IRNode
E2_Val val;
};
typedef struct E2_IdentifierMapNode E2_IdentifierMapNode;
struct E2_IdentifierMapNode
{
E2_IdentifierMapNode *next;
String8 name;
E2_IRNode *irtree;
};
typedef struct E2_IdentifierMap E2_IdentifierMap;
struct E2_IdentifierMap
{
E2_IdentifierMapNode **slots;
U64 slots_count;
};
typedef struct E2_CompileTask E2_CompileTask;
struct E2_CompileTask
{
E2_CompileTask *next;
E2_Expr *expr;
E2_ExprNode *last_compiled_child_node;
E2_IRNodePtrNode *first_irtree_child;
E2_IRNodePtrNode *last_irtree_child;
U64 irtree_child_count;
};
typedef struct E2_CompileState E2_CompileState;
struct E2_CompileState
{
E2_CompileTask *top_task;
E2_CompileTask *free_task;
U64 caller_request_count;
};
typedef struct E2_Compile E2_Compile;
struct E2_Compile
{
E2_CompileStatus status;
String8 identifier;
E2_Expr *expr;
E2_IRNode *irtree;
String8 member_name;
E2_Expr *params_expr;
E2_IRNode *params_irtree;
E2_MsgList msgs;
};
@@ -515,6 +542,12 @@ internal U64 e2_space_map_read(E2_SpaceMap *map, E2_SpaceID space_id, Rng1U64 ad
internal void e2_expr_map_push(Arena *arena, E2_ExprMap *map, String8 name, E2_Expr *expr);
internal E2_Expr *e2_expr_from_name(E2_ExprMap *map, String8 name);
////////////////////////////////
//~ rjf: Identifier Map Helpers
internal void e2_identifier_map_push(Arena *arena, E2_IdentifierMap *map, String8 name, E2_IRNode *irtree);
internal E2_IRNode *e2_irtree_from_identifier(E2_IdentifierMap *map, String8 name);
////////////////////////////////
//~ rjf: Messages
@@ -607,7 +640,10 @@ internal E2_TypeKey e2_coerced_type_key_from_operands(E2_TypeKey lhs, E2_TypeKey
////////////////////////////////
//~ rjf: Expression Constructors
internal E2_Expr *e2_expr(Arena *arena);
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);
#if 0
internal E2_Expr *e2_expr_const_u64_or_smaller(Arena *arena, U64 u);
internal E2_Expr *e2_expr_const_f32(Arena *arena, F32 f32);
internal E2_Expr *e2_expr_const_f64(Arena *arena, F64 f64);
@@ -617,8 +653,7 @@ internal E2_Expr *e2_expr_resolve_to_value(Arena *arena, E2_Expr *expr);
internal E2_Expr *e2_expr_truncate(Arena *arena, E2_Expr *expr, E2_TypeKey dst_type_key);
internal E2_Expr *e2_expr_convert_if_possible(Arena *arena, E2_Expr *expr, E2_TypeKey dst_type_key);
internal E2_Expr *e2_expr_type(Arena *arena, E2_TypeKey type_key);
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);
#endif
////////////////////////////////
//~ rjf: IR Tree Constructors
@@ -642,12 +677,17 @@ internal void e2_irnode_push_child(Arena *arena, E2_IRNode *parent, E2_IRNode *e
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, E2_Expr *access_result, E2_Val compile_time_eval_result, String8 string);
internal E2_Parse e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type, String8 string);
////////////////////////////////
//~ rjf: Expression -> Bytecode
//~ rjf: Expression -> IR Tree
internal String8 e2_bytecode_from_expr(Arena *arena, E2_Expr *expr);
internal E2_Compile e2_compile_from_expr(Arena *arena, E2_CompileState *state, E2_IRNode *resolve_result, E2_Val compile_time_eval_result, E2_Expr *expr);
////////////////////////////////
//~ rjf: IR Tree -> Bytecode
internal String8 e2_bytecode_from_irnode(Arena *arena, E2_IRNode *irnode);
////////////////////////////////
//~ rjf: Bytecode -> Result
+40 -34
View File
@@ -4,40 +4,46 @@
@table(name parse_kind precedence pre sep pos chain)
E2_ExprKindTable:
{
{Dot Binary 1 "" "." "" "" }
{Index Binary 1 "" "[" "]" "" }
{Call Call 1 "" "(" ")" ","}
{DerefAsm UnaryPrefix 1 "[" "" "]" "" }
{SizeOf UnaryPrefix 1 "sizeof " "" "" "" }
{TypeOf UnaryPrefix 1 "typeof " "" "" "" }
{CCast UnaryPrefix 1 "" "" "" "" }
{Deref UnaryPrefix 2 "*" "" "" "" }
{Address UnaryPrefix 2 "&" "" "" "" }
{Pos UnaryPrefix 2 "+" "" "" "" }
{Neg UnaryPrefix 2 "-" "" "" "" }
{LogNot UnaryPrefix 2 "!" "" "" "" }
{BitNot UnaryPrefix 2 "~" "" "" "" }
{Mul Binary 3 "" "*" "" "" }
{Div Binary 3 "" "/" "" "" }
{Mod Binary 3 "" "%" "" "" }
{Add Binary 4 "" "+" "" "" }
{Sub Binary 4 "" "-" "" "" }
{LShift Binary 5 "" "<<" "" "" }
{RShift Binary 5 "" ">>" "" "" }
{Less Binary 6 "" "<" "" "" }
{LtEq Binary 6 "" "<=" "" "" }
{Grtr Binary 6 "" ">" "" "" }
{GrEq Binary 6 "" ">=" "" "" }
{EqEq Binary 7 "" "==" "" "" }
{NtEq Binary 7 "" "!=" "" "" }
{BitAnd Binary 8 "" "&" "" "" }
{BitXor Binary 9 "" "^" "" "" }
{BitOr Binary 10 "" "|" "" "" }
{LogAnd Binary 11 "" "&&" "" "" }
{LogOr Binary 12 "" "||" "" "" }
{Define Null 13 "" "=" "" "" }
{Macro Null 14 "" "" "" "" }
{Cond Ternary 14 "" "?" "" ":"}
{Identifier Null 0}
{TypeIdentifier Null 0}
{Numeric Null 0}
{StringLiteral Null 0}
{CharLiteral Null 0}
{Dot Null 0 "" "." "" "" }
{Index Binary 1 "" "[" "]" "" }
{Call Call 1 "" "(" ")" ","}
{DerefAsm UnaryPrefix 1 "[" "" "]" "" }
{SizeOf UnaryPrefix 1 "sizeof " "" "" "" }
{TypeOf UnaryPrefix 1 "typeof " "" "" "" }
{CCast UnaryPrefix 1 "" "" "" "" }
{Deref UnaryPrefix 2 "*" "" "" "" }
{Address UnaryPrefix 2 "&" "" "" "" }
{Pos UnaryPrefix 2 "+" "" "" "" }
{Neg UnaryPrefix 2 "-" "" "" "" }
{LogNot UnaryPrefix 2 "!" "" "" "" }
{BitNot UnaryPrefix 2 "~" "" "" "" }
{Ptr UnaryPostfix 1 "" "" "*" "" }
{Mul Binary 3 "" "*" "" "" }
{Div Binary 3 "" "/" "" "" }
{Mod Binary 3 "" "%" "" "" }
{Add Binary 4 "" "+" "" "" }
{Sub Binary 4 "" "-" "" "" }
{LShift Binary 5 "" "<<" "" "" }
{RShift Binary 5 "" ">>" "" "" }
{Less Binary 6 "" "<" "" "" }
{LtEq Binary 6 "" "<=" "" "" }
{Grtr Binary 6 "" ">" "" "" }
{GrEq Binary 6 "" ">=" "" "" }
{EqEq Binary 7 "" "==" "" "" }
{NtEq Binary 7 "" "!=" "" "" }
{BitAnd Binary 8 "" "&" "" "" }
{BitXor Binary 9 "" "^" "" "" }
{BitOr Binary 10 "" "|" "" "" }
{LogAnd Binary 11 "" "&&" "" "" }
{LogOr Binary 12 "" "||" "" "" }
{Define Null 13 "" "=" "" "" }
{Macro Null 14 "" "" "" "" }
{Cond Ternary 14 "" "?" "" ":"}
}
@enum E2_ExprKind:
+8 -2
View File
@@ -4,10 +4,15 @@
//- GENERATED CODE
C_LINKAGE_BEGIN
E2_ExprKindInfo e2_expr_kind_info_table[35] =
E2_ExprKindInfo e2_expr_kind_info_table[41] =
{
{0},
{E2_ExprParseKind_Binary, 1, str8_lit_comp(""), str8_lit_comp("."), str8_lit_comp(""), str8_lit_comp("")},
{E2_ExprParseKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
{E2_ExprParseKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
{E2_ExprParseKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
{E2_ExprParseKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
{E2_ExprParseKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
{E2_ExprParseKind_Null, 0, str8_lit_comp(""), str8_lit_comp("."), str8_lit_comp(""), str8_lit_comp("")},
{E2_ExprParseKind_Binary, 1, str8_lit_comp(""), str8_lit_comp("["), str8_lit_comp("]"), str8_lit_comp("")},
{E2_ExprParseKind_Call, 1, str8_lit_comp(""), str8_lit_comp("("), str8_lit_comp(")"), str8_lit_comp(",")},
{E2_ExprParseKind_UnaryPrefix, 1, str8_lit_comp("["), str8_lit_comp(""), str8_lit_comp("]"), str8_lit_comp("")},
@@ -20,6 +25,7 @@ E2_ExprKindInfo e2_expr_kind_info_table[35] =
{E2_ExprParseKind_UnaryPrefix, 2, str8_lit_comp("-"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
{E2_ExprParseKind_UnaryPrefix, 2, str8_lit_comp("!"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
{E2_ExprParseKind_UnaryPrefix, 2, str8_lit_comp("~"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
{E2_ExprParseKind_UnaryPostfix, 1, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("*"), str8_lit_comp("")},
{E2_ExprParseKind_Binary, 3, str8_lit_comp(""), str8_lit_comp("*"), str8_lit_comp(""), str8_lit_comp("")},
{E2_ExprParseKind_Binary, 3, str8_lit_comp(""), str8_lit_comp("/"), str8_lit_comp(""), str8_lit_comp("")},
{E2_ExprParseKind_Binary, 3, str8_lit_comp(""), str8_lit_comp("%"), str8_lit_comp(""), str8_lit_comp("")},
+7 -1
View File
@@ -9,6 +9,11 @@
typedef enum E2_ExprKind
{
E2_ExprKind_Null,
E2_ExprKind_Identifier,
E2_ExprKind_TypeIdentifier,
E2_ExprKind_Numeric,
E2_ExprKind_StringLiteral,
E2_ExprKind_CharLiteral,
E2_ExprKind_Dot,
E2_ExprKind_Index,
E2_ExprKind_Call,
@@ -22,6 +27,7 @@ E2_ExprKind_Pos,
E2_ExprKind_Neg,
E2_ExprKind_LogNot,
E2_ExprKind_BitNot,
E2_ExprKind_Ptr,
E2_ExprKind_Mul,
E2_ExprKind_Div,
E2_ExprKind_Mod,
@@ -125,7 +131,7 @@ E2_TypeKind_LastMeta = E2_TypeKind_MetaDescription,
} E2_TypeKind;
C_LINKAGE_BEGIN
extern E2_ExprKindInfo e2_expr_kind_info_table[35];
extern E2_ExprKindInfo e2_expr_kind_info_table[41];
extern U8 e2_type_kind_basic_byte_size_table[61];
extern String8 e2_type_kind_basic_string_table[61];
+71 -59
View File
@@ -46,7 +46,7 @@ entry_point(CmdLine *cmdline)
s("123, 456"),
s("int32 == int32"),
s("foo = 123"),
s("bar(a, b) = a + b"),
// s("bar(a, b) = a + b"),
s("1 > 2"),
s("1 ? \"Test\" : 888"),
s("'a'"),
@@ -88,67 +88,16 @@ entry_point(CmdLine *cmdline)
E2_Expr *expr = &e2_expr_nil;
{
E2_ParseState state = {0};
E2_ExprMap expr_map = {0};
E2_Expr *access_expr = &e2_expr_nil;
E2_Val compile_time_eval_result = {0};
B32 identifier_is_type = 0;
for(;;)
{
E2_Parse parse = e2_parse_from_string(scratch.arena, &state, &expr_map, access_expr, compile_time_eval_result, strings[idx]);
E2_Parse parse = e2_parse_from_string(scratch.arena, &state, identifier_is_type, strings[idx]);
identifier_is_type = 0;
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 *expr = &e2_expr_nil;
if(str8_match(parse.identifier, s("float32"), 0))
{
expr = e2_expr_type(scratch.arena, e2_type_key_basic(E2_TypeKind_F32));
}
else if(str8_match(parse.identifier, s("float64"), 0))
{
expr = e2_expr_type(scratch.arena, e2_type_key_basic(E2_TypeKind_F64));
}
else if(str8_match(parse.identifier, s("int32"), 0))
{
expr = e2_expr_type(scratch.arena, e2_type_key_basic(E2_TypeKind_S32));
}
else if(str8_match(parse.identifier, s("int64"), 0))
{
expr = e2_expr_type(scratch.arena, e2_type_key_basic(E2_TypeKind_S64));
}
else
{
expr = e2_expr_const_u64_or_smaller(scratch.arena, 123);
}
e2_expr_map_push(scratch.arena, &expr_map, parse.identifier, expr);
}
if(parse.status == E2_ParseStatus_NewIdentifierDefinition)
{
e2_expr_map_push(scratch.arena, &expr_map, parse.identifier, expr);
}
if(parse.status == E2_ParseStatus_MemberAccess)
{
access_expr = e2_expr_const_u64_or_smaller(scratch.arena, 456);
}
if(parse.status == E2_ParseStatus_IndexAccess)
{
access_expr = e2_expr_const_u64_or_smaller(scratch.arena, 111);
}
if(parse.status == E2_ParseStatus_Call)
{
access_expr = e2_expr_const_u64_or_smaller(scratch.arena, 123456);
}
if(parse.status == E2_ParseStatus_CompileTimeEval)
{
String8 bytecode = e2_bytecode_from_expr(scratch.arena, expr);
E2_InterpState interp_state = {0};
E2_SpaceMap space_map = {0};
E2_Interp interp = e2_interp_from_bytecode(scratch.arena, &interp_state, &space_map, bytecode);
compile_time_eval_result = interp.val;
}
if(e2_parse_status_is_terminal(parse.status))
{
break;
@@ -156,8 +105,71 @@ entry_point(CmdLine *cmdline)
}
}
// rjf: expr -> bytecode
String8 bytecode = e2_bytecode_from_expr(scratch.arena, expr);
// rjf: expr -> ir tree
E2_IRNode *irtree = &e2_irnode_nil;
{
E2_IRNode *resolve_result = &e2_irnode_nil;
E2_Val compile_time_eval_result = {0};
E2_CompileState state = {0};
for(;;)
{
E2_Compile compile = e2_compile_from_expr(scratch.arena, &state, resolve_result, compile_time_eval_result, expr);
irtree = compile.irtree;
resolve_result = &e2_irnode_nil;
if(compile.status == E2_CompileStatus_MissedIdentifierResolution)
{
E2_IRNode *irnode = &e2_irnode_nil;
if(str8_match(compile.identifier, s("float32"), 0))
{
irnode = e2_irnode_type(scratch.arena, e2_type_key_basic(E2_TypeKind_F32));
}
else if(str8_match(compile.identifier, s("float64"), 0))
{
irnode = e2_irnode_type(scratch.arena, e2_type_key_basic(E2_TypeKind_F64));
}
else if(str8_match(compile.identifier, s("int32"), 0))
{
irnode = e2_irnode_type(scratch.arena, e2_type_key_basic(E2_TypeKind_S32));
}
else if(str8_match(compile.identifier, s("int64"), 0))
{
irnode = e2_irnode_type(scratch.arena, e2_type_key_basic(E2_TypeKind_S64));
}
else
{
irnode = e2_irnode_const_u64_or_smaller(scratch.arena, 123);
}
resolve_result = irnode;
}
if(compile.status == E2_CompileStatus_MemberAccess)
{
resolve_result = e2_irnode_const_u64_or_smaller(scratch.arena, 456);
}
if(compile.status == E2_CompileStatus_IndexAccess)
{
resolve_result = e2_irnode_const_u64_or_smaller(scratch.arena, 111);
}
if(compile.status == E2_CompileStatus_Call)
{
resolve_result = e2_irnode_const_u64_or_smaller(scratch.arena, 123456);
}
if(compile.status == E2_CompileStatus_CompileTimeEval)
{
String8 bytecode = e2_bytecode_from_irnode(scratch.arena, irtree);
E2_InterpState interp_state = {0};
E2_SpaceMap space_map = {0};
E2_Interp interp = e2_interp_from_bytecode(scratch.arena, &interp_state, &space_map, bytecode);
compile_time_eval_result = interp.val;
}
if(e2_compile_status_is_terminal(compile.status))
{
break;
}
}
}
// rjf: ir tree -> bytecode
String8 bytecode = e2_bytecode_from_irnode(scratch.arena, irtree);
// rjf: bytecode -> value
E2_Val val = {0};
@@ -189,8 +201,8 @@ entry_point(CmdLine *cmdline)
val.s64,
val.f32,
val.f64,
expr->mode == E2_Mode_Type ? "type" :
expr->mode == E2_Mode_Value ? "value" :
irtree->mode == E2_Mode_Type ? "type" :
irtree->mode == E2_Mode_Value ? "value" :
"address",
msgs_string.size != 0 ? " // " : "", msgs_string);
raddbg_log("%S", log);