2025-04-14 09:48:16 +01:00
|
|
|
#ifndef _LANG_CODEGEN_H_
|
|
|
|
|
#define _LANG_CODEGEN_H_
|
|
|
|
|
|
lang: codegen: redesign variable definition/resolution system to support capturing
the codegen scope system has been removed. instead, each generator state in the stack,
from the current state backwards, is informed when a variable is defined, resolved, or
captured.
when a variable is defined, the state stack is traversed back-to-front (current generator
first). each state has a chance to record the variable definition. once one state has
signalled that it has recorded the variable definition, the traversal ends.
when a variable is resolved, the state stack is traversed back-to-front (current generator
first). each state is asked whether or not it recognises the variable identifier being resolved.
if a state has the variable in question defined, it returns information about the variable
definition, and the traversal stops.
once a variable has been resolved, the state stack is traversed front-to-back (current generator
last), starting from the generator /after/ the one that provided the variable definition. each
generator in the iteration is given the chance to adjust the variable information, or generate
IR in response to the variable being accessed. this is used to implement variable capture,
where the state of a variable in the enclosing context is captured for later use.
2025-04-22 15:23:42 +01:00
|
|
|
#include "var-map.h"
|
|
|
|
|
|
2025-04-14 09:48:16 +01:00
|
|
|
#include <blue/core/queue.h>
|
2025-04-14 20:15:05 +01:00
|
|
|
#include <ivy/lang/ast.h>
|
|
|
|
|
#include <ivy/lang/lex.h>
|
2025-08-16 21:00:22 +01:00
|
|
|
#include <mie/ctx.h>
|
2025-06-02 11:31:35 +01:00
|
|
|
#include <mie/ir/builder.h>
|
2025-04-14 09:48:16 +01:00
|
|
|
|
2025-04-17 21:44:38 +01:00
|
|
|
struct ivy_codegen;
|
|
|
|
|
struct ivy_ast_node;
|
|
|
|
|
|
|
|
|
|
struct mie_value;
|
|
|
|
|
struct mie_func;
|
|
|
|
|
|
lang: codegen: redesign variable definition/resolution system to support capturing
the codegen scope system has been removed. instead, each generator state in the stack,
from the current state backwards, is informed when a variable is defined, resolved, or
captured.
when a variable is defined, the state stack is traversed back-to-front (current generator
first). each state has a chance to record the variable definition. once one state has
signalled that it has recorded the variable definition, the traversal ends.
when a variable is resolved, the state stack is traversed back-to-front (current generator
first). each state is asked whether or not it recognises the variable identifier being resolved.
if a state has the variable in question defined, it returns information about the variable
definition, and the traversal stops.
once a variable has been resolved, the state stack is traversed front-to-back (current generator
last), starting from the generator /after/ the one that provided the variable definition. each
generator in the iteration is given the chance to adjust the variable information, or generate
IR in response to the variable being accessed. this is used to implement variable capture,
where the state of a variable in the enclosing context is captured for later use.
2025-04-22 15:23:42 +01:00
|
|
|
struct codegen_var;
|
|
|
|
|
|
2025-04-14 20:15:05 +01:00
|
|
|
#define CODEGEN_RESULT_OK(flags) \
|
|
|
|
|
(struct code_generator_result) \
|
|
|
|
|
{ \
|
|
|
|
|
.r_status = (IVY_OK), .r_flags = (flags) \
|
|
|
|
|
}
|
|
|
|
|
#define CODEGEN_RESULT_ERR(status) \
|
|
|
|
|
(struct code_generator_result) \
|
|
|
|
|
{ \
|
|
|
|
|
.r_status = (status), .r_flags = (0) \
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-17 21:44:38 +01:00
|
|
|
#define __AST_INDEX(type) IVY_AST_##type
|
|
|
|
|
#define NODE_CODEGEN(type, func) [__AST_INDEX(type)] = func
|
2025-04-14 09:48:16 +01:00
|
|
|
|
2025-04-17 21:44:38 +01:00
|
|
|
enum code_generator_flags {
|
|
|
|
|
CODEGEN_F_IGNORE_RESULT = 0x01u,
|
|
|
|
|
};
|
|
|
|
|
|
2025-04-14 20:15:05 +01:00
|
|
|
enum code_generator_type {
|
|
|
|
|
CODE_GENERATOR_NONE = 0,
|
|
|
|
|
CODE_GENERATOR_UNIT,
|
2025-04-21 21:11:45 +01:00
|
|
|
CODE_GENERATOR_BLOCK,
|
2025-04-14 20:15:05 +01:00
|
|
|
CODE_GENERATOR_EXPR,
|
2025-09-08 16:10:11 +01:00
|
|
|
CODE_GENERATOR_GLOBAL,
|
2025-04-17 21:44:38 +01:00
|
|
|
CODE_GENERATOR_MSG,
|
2025-04-18 23:17:39 +01:00
|
|
|
CODE_GENERATOR_FSTRING,
|
2025-04-21 21:11:45 +01:00
|
|
|
CODE_GENERATOR_LAMBDA,
|
2025-04-24 09:25:36 +01:00
|
|
|
CODE_GENERATOR_RETURN,
|
2025-04-28 15:44:44 +01:00
|
|
|
CODE_GENERATOR_COND_GROUP,
|
|
|
|
|
CODE_GENERATOR_COND,
|
2025-05-08 10:53:00 +01:00
|
|
|
CODE_GENERATOR_FOR_LOOP,
|
2025-09-08 16:25:39 +01:00
|
|
|
CODE_GENERATOR_WHILE_LOOP,
|
2025-09-12 10:01:07 +01:00
|
|
|
CODE_GENERATOR_CASCADE,
|
2025-04-16 21:58:52 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum code_generator_scope_type {
|
|
|
|
|
CODE_GENERATOR_SCOPE_NONE = 0,
|
|
|
|
|
CODE_GENERATOR_SCOPE_UNIT,
|
|
|
|
|
CODE_GENERATOR_SCOPE_FUNC,
|
|
|
|
|
CODE_GENERATOR_SCOPE_BLOCK,
|
2025-04-14 20:15:05 +01:00
|
|
|
};
|
|
|
|
|
|
2025-09-08 16:17:29 +01:00
|
|
|
enum code_generator_value_type {
|
|
|
|
|
CODE_GENERATOR_VALUE_NONE = 0,
|
|
|
|
|
CODE_GENERATOR_VALUE_MIE_VALUE,
|
|
|
|
|
CODE_GENERATOR_VALUE_PHI_EDGE,
|
|
|
|
|
};
|
|
|
|
|
|
2025-04-14 20:15:05 +01:00
|
|
|
struct code_generator_result {
|
|
|
|
|
enum ivy_status r_status;
|
|
|
|
|
|
|
|
|
|
enum code_generator_result_flags {
|
2025-04-17 21:44:38 +01:00
|
|
|
CODEGEN_R_REPEAT_NODE = 0x01u,
|
|
|
|
|
CODEGEN_R_POP_GENERATOR = 0x02u,
|
2025-04-14 20:15:05 +01:00
|
|
|
} r_flags;
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-08 16:17:29 +01:00
|
|
|
struct code_generator_value {
|
|
|
|
|
enum code_generator_value_type v_type;
|
|
|
|
|
|
|
|
|
|
union {
|
|
|
|
|
struct mie_value *mie_value;
|
|
|
|
|
struct mie_phi_edge *phi_edge;
|
|
|
|
|
} v_value;
|
lang: codegen: redesign variable definition/resolution system to support capturing
the codegen scope system has been removed. instead, each generator state in the stack,
from the current state backwards, is informed when a variable is defined, resolved, or
captured.
when a variable is defined, the state stack is traversed back-to-front (current generator
first). each state has a chance to record the variable definition. once one state has
signalled that it has recorded the variable definition, the traversal ends.
when a variable is resolved, the state stack is traversed back-to-front (current generator
first). each state is asked whether or not it recognises the variable identifier being resolved.
if a state has the variable in question defined, it returns information about the variable
definition, and the traversal stops.
once a variable has been resolved, the state stack is traversed front-to-back (current generator
last), starting from the generator /after/ the one that provided the variable definition. each
generator in the iteration is given the chance to adjust the variable information, or generate
IR in response to the variable being accessed. this is used to implement variable capture,
where the state of a variable in the enclosing context is captured for later use.
2025-04-22 15:23:42 +01:00
|
|
|
};
|
|
|
|
|
|
2025-04-14 20:15:05 +01:00
|
|
|
struct code_generator_state;
|
|
|
|
|
|
|
|
|
|
typedef enum ivy_status (*code_generator_state_init_callback)(
|
2025-04-17 21:44:38 +01:00
|
|
|
struct ivy_codegen *, struct code_generator_state *, uintptr_t, void *);
|
2025-04-14 20:15:05 +01:00
|
|
|
typedef enum ivy_status (*code_generator_state_fini_callback)(
|
2025-09-08 16:17:29 +01:00
|
|
|
struct ivy_codegen *, struct code_generator_state *,
|
|
|
|
|
struct code_generator_value *);
|
2025-04-14 20:15:05 +01:00
|
|
|
typedef struct code_generator_result (*code_generator_callback)(
|
|
|
|
|
struct ivy_codegen *);
|
|
|
|
|
typedef struct code_generator_result (*code_generator_node_callback)(
|
2025-04-16 21:58:52 +01:00
|
|
|
struct ivy_codegen *, struct code_generator_state *,
|
|
|
|
|
struct ivy_ast_node *, size_t);
|
|
|
|
|
typedef struct code_generator_result (*code_generator_value_received_callback)(
|
2025-09-08 16:17:29 +01:00
|
|
|
struct ivy_codegen *, struct code_generator_state *,
|
|
|
|
|
struct code_generator_value *);
|
lang: codegen: redesign variable definition/resolution system to support capturing
the codegen scope system has been removed. instead, each generator state in the stack,
from the current state backwards, is informed when a variable is defined, resolved, or
captured.
when a variable is defined, the state stack is traversed back-to-front (current generator
first). each state has a chance to record the variable definition. once one state has
signalled that it has recorded the variable definition, the traversal ends.
when a variable is resolved, the state stack is traversed back-to-front (current generator
first). each state is asked whether or not it recognises the variable identifier being resolved.
if a state has the variable in question defined, it returns information about the variable
definition, and the traversal stops.
once a variable has been resolved, the state stack is traversed front-to-back (current generator
last), starting from the generator /after/ the one that provided the variable definition. each
generator in the iteration is given the chance to adjust the variable information, or generate
IR in response to the variable being accessed. this is used to implement variable capture,
where the state of a variable in the enclosing context is captured for later use.
2025-04-22 15:23:42 +01:00
|
|
|
typedef enum ivy_status (*code_generator_define_variable_callback)(
|
|
|
|
|
struct ivy_codegen *, struct code_generator_state *, const char *,
|
|
|
|
|
const struct codegen_var *);
|
|
|
|
|
typedef enum ivy_status (*code_generator_resolve_variable_callback)(
|
|
|
|
|
struct ivy_codegen *, struct code_generator_state *, const char *,
|
|
|
|
|
struct codegen_var *);
|
|
|
|
|
typedef enum ivy_status (*code_generator_capture_variable_callback)(
|
|
|
|
|
struct ivy_codegen *, struct code_generator_state *, const char *,
|
|
|
|
|
struct codegen_var *);
|
2025-04-14 20:15:05 +01:00
|
|
|
|
|
|
|
|
struct code_generator {
|
|
|
|
|
enum code_generator_type g_type;
|
|
|
|
|
size_t g_state_size;
|
|
|
|
|
|
|
|
|
|
code_generator_state_init_callback g_state_init;
|
|
|
|
|
code_generator_state_fini_callback g_state_fini;
|
2025-04-16 21:58:52 +01:00
|
|
|
code_generator_node_callback g_node_generators[IVY_AST_TYPE_COUNT];
|
2025-04-17 21:44:38 +01:00
|
|
|
code_generator_node_callback g_expr_generator;
|
2025-04-16 21:58:52 +01:00
|
|
|
code_generator_value_received_callback g_value_received;
|
lang: codegen: redesign variable definition/resolution system to support capturing
the codegen scope system has been removed. instead, each generator state in the stack,
from the current state backwards, is informed when a variable is defined, resolved, or
captured.
when a variable is defined, the state stack is traversed back-to-front (current generator
first). each state has a chance to record the variable definition. once one state has
signalled that it has recorded the variable definition, the traversal ends.
when a variable is resolved, the state stack is traversed back-to-front (current generator
first). each state is asked whether or not it recognises the variable identifier being resolved.
if a state has the variable in question defined, it returns information about the variable
definition, and the traversal stops.
once a variable has been resolved, the state stack is traversed front-to-back (current generator
last), starting from the generator /after/ the one that provided the variable definition. each
generator in the iteration is given the chance to adjust the variable information, or generate
IR in response to the variable being accessed. this is used to implement variable capture,
where the state of a variable in the enclosing context is captured for later use.
2025-04-22 15:23:42 +01:00
|
|
|
code_generator_define_variable_callback g_define_var;
|
|
|
|
|
code_generator_resolve_variable_callback g_resolve_var;
|
|
|
|
|
code_generator_capture_variable_callback g_capture_var;
|
2025-04-14 20:15:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct code_generator_state {
|
|
|
|
|
b_queue_entry s_entry;
|
2025-04-17 21:44:38 +01:00
|
|
|
uintptr_t s_argv;
|
|
|
|
|
void *s_argp;
|
2025-04-14 20:15:05 +01:00
|
|
|
const struct code_generator *s_gen;
|
2025-04-16 21:58:52 +01:00
|
|
|
struct ivy_ast_node *s_root;
|
|
|
|
|
size_t s_depth;
|
2025-09-08 16:25:39 +01:00
|
|
|
|
|
|
|
|
struct mie_block *s_loop_break_target, *s_loop_repeat_target;
|
2025-04-16 21:58:52 +01:00
|
|
|
};
|
|
|
|
|
|
2025-04-14 09:48:16 +01:00
|
|
|
struct ivy_codegen {
|
2025-04-16 21:58:52 +01:00
|
|
|
b_queue c_values;
|
2025-04-14 20:15:05 +01:00
|
|
|
b_queue c_state;
|
2025-04-16 21:58:52 +01:00
|
|
|
b_queue c_scope;
|
2025-04-14 09:48:16 +01:00
|
|
|
struct mie_builder *c_builder;
|
|
|
|
|
struct mie_ctx *c_ctx;
|
|
|
|
|
struct mie_module *c_module;
|
|
|
|
|
};
|
|
|
|
|
|
2025-04-14 20:15:05 +01:00
|
|
|
extern const struct code_generator *get_code_generator(
|
|
|
|
|
enum code_generator_type type);
|
2025-04-16 21:58:52 +01:00
|
|
|
extern const struct code_generator *get_root_code_generator(
|
|
|
|
|
enum ivy_ast_node_type type);
|
2025-04-14 20:15:05 +01:00
|
|
|
|
|
|
|
|
extern enum ivy_status codegen_push_generator(
|
2025-04-17 21:44:38 +01:00
|
|
|
struct ivy_codegen *gen, enum code_generator_type gen_type,
|
|
|
|
|
uintptr_t argv, void *argp);
|
2025-04-16 21:58:52 +01:00
|
|
|
extern enum ivy_status codegen_pop_generator(
|
2025-09-08 16:17:29 +01:00
|
|
|
struct ivy_codegen *gen, struct code_generator_value *result);
|
2025-04-16 21:58:52 +01:00
|
|
|
|
lang: codegen: redesign variable definition/resolution system to support capturing
the codegen scope system has been removed. instead, each generator state in the stack,
from the current state backwards, is informed when a variable is defined, resolved, or
captured.
when a variable is defined, the state stack is traversed back-to-front (current generator
first). each state has a chance to record the variable definition. once one state has
signalled that it has recorded the variable definition, the traversal ends.
when a variable is resolved, the state stack is traversed back-to-front (current generator
first). each state is asked whether or not it recognises the variable identifier being resolved.
if a state has the variable in question defined, it returns information about the variable
definition, and the traversal stops.
once a variable has been resolved, the state stack is traversed front-to-back (current generator
last), starting from the generator /after/ the one that provided the variable definition. each
generator in the iteration is given the chance to adjust the variable information, or generate
IR in response to the variable being accessed. this is used to implement variable capture,
where the state of a variable in the enclosing context is captured for later use.
2025-04-22 15:23:42 +01:00
|
|
|
extern enum ivy_status codegen_define_variable(
|
|
|
|
|
struct ivy_codegen *gen, const char *ident, const struct codegen_var *var);
|
|
|
|
|
extern enum ivy_status codegen_resolve_variable(
|
|
|
|
|
struct ivy_codegen *gen, const char *ident, struct codegen_var *out);
|
|
|
|
|
extern struct mie_value *codegen_load_variable(
|
|
|
|
|
struct ivy_codegen *gen, struct codegen_var *var);
|
2025-09-08 16:17:29 +01:00
|
|
|
extern void codegen_store_variable(
|
|
|
|
|
struct ivy_codegen *gen, struct codegen_var *var, struct mie_value *val);
|
|
|
|
|
|
|
|
|
|
extern struct mie_value *code_generator_value_get_mie_value(
|
|
|
|
|
struct code_generator_value *vp);
|
|
|
|
|
extern void code_generator_value_set_mie_value(
|
|
|
|
|
struct code_generator_value *vp, struct mie_value *value);
|
|
|
|
|
extern struct mie_phi_edge *code_generator_value_get_phi_edge(
|
|
|
|
|
struct code_generator_value *vp);
|
|
|
|
|
extern void code_generator_value_set_phi_edge(
|
|
|
|
|
struct code_generator_value *vp, struct mie_phi_edge *edge);
|
2025-04-14 20:15:05 +01:00
|
|
|
|
2025-04-14 09:48:16 +01:00
|
|
|
#endif
|