diff --git a/lang/codegen/cascade.c b/lang/codegen/cascade.c new file mode 100644 index 0000000..5dd06ea --- /dev/null +++ b/lang/codegen/cascade.c @@ -0,0 +1,84 @@ +#include "codegen.h" + +#include +#include + +struct cascade_codegen_state { + struct code_generator_state s_base; + struct mie_value *s_recipient; + struct mie_value *s_result; +}; + +static struct code_generator_result gen_cascade( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + return CODEGEN_RESULT_OK(0); +} + +static struct code_generator_result gen_msg( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + struct cascade_codegen_state *cascade + = (struct cascade_codegen_state *)state; + + codegen_push_generator( + gen, CODE_GENERATOR_MSG, CODEGEN_F_IGNORE_RESULT, + cascade->s_recipient); + return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); +} + +static struct code_generator_result gen_expr( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + struct cascade_codegen_state *cascade + = (struct cascade_codegen_state *)state; + + if (cascade->s_recipient) { + return CODEGEN_RESULT_ERR(IVY_ERR_BAD_SYNTAX); + } + + codegen_push_generator( + gen, CODE_GENERATOR_EXPR, CODEGEN_F_IGNORE_RESULT, NULL); + return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); +} + +static enum ivy_status state_fini( + struct ivy_codegen *gen, struct code_generator_state *state, + struct code_generator_value *result) +{ + struct cascade_codegen_state *cascade + = (struct cascade_codegen_state *)state; + + code_generator_value_set_mie_value(result, cascade->s_result); + return IVY_OK; +} + +static struct code_generator_result value_received( + struct ivy_codegen *gen, struct code_generator_state *state, + struct code_generator_value *value) +{ + struct cascade_codegen_state *cascade + = (struct cascade_codegen_state *)state; + struct mie_value *mie_value = code_generator_value_get_mie_value(value); + if (!cascade->s_recipient) { + cascade->s_recipient = mie_value; + } + + cascade->s_result = mie_value; + return CODEGEN_RESULT_OK(0); +} + +struct code_generator cascade_generator = { + .g_type = CODE_GENERATOR_CASCADE, + .g_state_size = sizeof(struct cascade_codegen_state), + .g_state_fini = state_fini, + .g_value_received = value_received, + .g_node_generators = { + NODE_CODEGEN(CASCADE, gen_cascade), + NODE_CODEGEN(MSG, gen_msg), + }, + .g_expr_generator = gen_expr, +}; diff --git a/lang/codegen/codegen.h b/lang/codegen/codegen.h index cf4af4c..69da1c7 100644 --- a/lang/codegen/codegen.h +++ b/lang/codegen/codegen.h @@ -49,6 +49,7 @@ enum code_generator_type { CODE_GENERATOR_COND, CODE_GENERATOR_FOR_LOOP, CODE_GENERATOR_WHILE_LOOP, + CODE_GENERATOR_CASCADE, }; enum code_generator_scope_type { diff --git a/lang/codegen/expr.c b/lang/codegen/expr.c index a5be549..ab0add1 100644 --- a/lang/codegen/expr.c +++ b/lang/codegen/expr.c @@ -87,6 +87,16 @@ static enum ivy_status push_operator( return IVY_OK; } +static struct code_generator_result gen_cascade( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + struct expr_codegen_state *expr = (struct expr_codegen_state *)state; + + codegen_push_generator(gen, CODE_GENERATOR_CASCADE, 0, NULL); + return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); +} + static struct code_generator_result gen_int( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node, size_t depth) @@ -705,6 +715,7 @@ struct code_generator expr_generator = { NODE_CODEGEN(C_TRUE, gen_keyword_const), NODE_CODEGEN(C_FALSE, gen_keyword_const), NODE_CODEGEN(C_NULL, gen_keyword_const), + NODE_CODEGEN(CASCADE, gen_cascade), NODE_CODEGEN(INT, gen_int), NODE_CODEGEN(OP, gen_op), NODE_CODEGEN(MSG, gen_msg), diff --git a/lang/codegen/generator.c b/lang/codegen/generator.c index eecea7f..c561823 100644 --- a/lang/codegen/generator.c +++ b/lang/codegen/generator.c @@ -14,6 +14,7 @@ extern const struct code_generator cond_generator; extern const struct code_generator cond_group_generator; extern const struct code_generator for_loop_generator; extern const struct code_generator while_loop_generator; +extern const struct code_generator cascade_generator; static const struct code_generator *code_generators[] = { [CODE_GENERATOR_UNIT] = &unit_generator, @@ -28,6 +29,7 @@ static const struct code_generator *code_generators[] = { [CODE_GENERATOR_COND_GROUP] = &cond_group_generator, [CODE_GENERATOR_FOR_LOOP] = &for_loop_generator, [CODE_GENERATOR_WHILE_LOOP] = &while_loop_generator, + [CODE_GENERATOR_CASCADE] = &cascade_generator, }; static const size_t nr_code_generators = sizeof code_generators / sizeof code_generators[0];