parser
Dibyendu Majumdar 4 years ago
parent 5bf1847884
commit 1f4941fd2a

@ -41,6 +41,7 @@ b) Perform type checking (Ravi enhancement)
//////////////////////////
struct lua_symbol_list;
struct linearizer;
/*
* Userdata object to hold the abstract syntax tree;
@ -55,6 +56,7 @@ struct ast_container {
struct allocator block_scope_allocator;
struct allocator symbol_allocator;
struct ast_node *main_function;
struct linearizer *linearizer;
bool killed; /* flag to check if this is already destroyed */
};
@ -302,30 +304,71 @@ DECLARE_PTR_LIST(proc_list, struct proc);
#define container_of(ptr, type, member) ((type *)((char *)(ptr)-offsetof(type, member)))
/* order is important here ! */
enum opcode { op_nop, op_ret, op_loadk, op_add, op_addff, op_addfi, op_addii,
op_sub, op_subff, op_subfi, op_subif, op_subii, op_mul, op_mulff, op_mulfi, op_mulii,
op_div, op_divff, op_divfi, op_divif, op_divii, op_idiv, op_band, op_bandii, op_bor, op_borii,
op_bxor, op_bxorii, op_shl, opshlii, op_shr, op_shrii, op_eq, op_eqii, op_eqff,
op_lt, op_ltii, op_ltff, op_le, op_leii, op_leff, op_mod, op_pow
enum opcode {
op_nop,
op_ret,
op_loadk,
op_add,
op_addff,
op_addfi,
op_addii,
op_sub,
op_subff,
op_subfi,
op_subif,
op_subii,
op_mul,
op_mulff,
op_mulfi,
op_mulii,
op_div,
op_divff,
op_divfi,
op_divif,
op_divii,
op_idiv,
op_band,
op_bandii,
op_bor,
op_borii,
op_bxor,
op_bxorii,
op_shl,
opshlii,
op_shr,
op_shrii,
op_eq,
op_eqii,
op_eqff,
op_lt,
op_ltii,
op_ltff,
op_le,
op_leii,
op_leff,
op_mod,
op_pow,
op_closure
};
enum pseudo_type { PSEUDO_LOCAL, PSEUDO_TEMP_FLT, PSEUDO_TEMP_INT, PSEUDO_TEMP_ANY, PSEUDO_CONSTANT };
enum pseudo_type { PSEUDO_LOCAL, PSEUDO_TEMP_FLT, PSEUDO_TEMP_INT, PSEUDO_TEMP_ANY, PSEUDO_CONSTANT, PSEUDO_PROC };
/* pseudo represents a pseudo (virtual) register */
struct pseudo {
unsigned type : 4, regnum : 16;
union {
struct lua_symbol *symbol; /* If local var this should be set */
const struct constant *constant;
ravitype_t temp_type;
struct lua_symbol *symbol; /* PSEUDO_LOCAL */
const struct constant *constant; /* PSEUDO_CONSTANT */
ravitype_t temp_type; /* PSEUDO_TEMP* */
struct proc *proc; /* PSEUDO_PROC */
};
};
/* single instruction */
struct instruction {
unsigned opcode : 8;
struct pseudo_list* operands;
struct pseudo_list* targets;
struct pseudo_list *operands;
struct pseudo_list *targets;
};
struct edge {
@ -383,7 +426,7 @@ struct proc {
struct proc *parent; /* enclosing proc */
struct ast_node *function_expr; /* function ast that we are compiling */
struct block_scope *current_scope;
struct basic_block* current_bb;
struct basic_block *current_bb;
struct pseudo_generator local_pseudos; /* locals */
struct pseudo_generator temp_int_pseudos; /* temporaries known to be integer type */
struct pseudo_generator temp_flt_pseudos; /* temporaries known to be number type */
@ -410,6 +453,9 @@ struct linearizer {
struct proc *current_proc; /* proc being compiled */
};
void raviA_ast_linearize(struct linearizer *linearizer, struct ast_container *container);
void raviA_init_linearizer(struct linearizer *linearizer, struct ast_container *container);
void raviA_destroy_linearizer(struct linearizer *linearizer);
void raviA_ast_linearize(struct linearizer *linearizer);
void raviA_show_linearizer(struct linearizer *linearizer, membuff_t *mb);
#endif
#endif

@ -29,7 +29,7 @@ static inline void free_reg(struct pseudo_generator *generator, unsigned reg) {
}
/* Linearizer - WIP */
static void ravi_init_linearizer(struct linearizer *linearizer, struct ast_container *container) {
void raviA_init_linearizer(struct linearizer *linearizer, struct ast_container *container) {
memset(linearizer, 0, sizeof *linearizer);
linearizer->ast_container = container;
dmrC_allocator_init(&linearizer->edge_allocator, "edge_allocator", sizeof(struct edge), sizeof(double), CHUNK);
@ -46,7 +46,7 @@ static void ravi_init_linearizer(struct linearizer *linearizer, struct ast_conta
CHUNK);
}
static void ravi_destroy_linearizer(struct linearizer *linearizer) {
void raviA_destroy_linearizer(struct linearizer *linearizer) {
struct proc *proc;
FOR_EACH_PTR(linearizer->all_procs, proc) {
if (proc->constants)
@ -132,6 +132,13 @@ struct pseudo *allocate_constant_pseudo(struct proc *proc, const struct constant
return pseudo;
}
struct pseudo *allocate_closure_pseudo(struct linearizer *linearizer, struct proc *proc) {
struct pseudo *pseudo = dmrC_allocator_allocate(&proc->linearizer->pseudo_allocator, 0);
pseudo->type = PSEUDO_PROC;
pseudo->proc = proc;
return pseudo;
}
struct pseudo *allocate_temp_pseudo(struct proc *proc, ravitype_t type) {
struct pseudo_generator *gen;
enum pseudo_type pseudo_type;
@ -389,6 +396,25 @@ static struct pseudo *linearize_binaryop(struct proc *proc, struct ast_node *nod
return target;
}
/* generates closure instruction - linearize a proc, and then add instruction to create closure from it */
static struct pseudo *linearize_function_expr(struct proc *proc, struct ast_node *expr) {
struct proc *curproc = proc->linearizer->current_proc;
struct proc *newproc = allocate_proc(proc->linearizer, expr);
set_current_proc(proc->linearizer, newproc);
printf("linearizing function\n");
set_current_proc(proc->linearizer, curproc); // restore the proc
ravitype_t target_type = expr->function_expr.type.type_code;
struct pseudo *target = allocate_temp_pseudo(proc, target_type);
struct pseudo *operand = allocate_closure_pseudo(proc->linearizer, newproc);
struct instruction *insn = alloc_instruction(proc, op_closure);
ptrlist_add((struct ptr_list **)&insn->operands, operand, &proc->linearizer->ptrlist_allocator);
ptrlist_add((struct ptr_list **)&insn->targets, target, &proc->linearizer->ptrlist_allocator);
ptrlist_add((struct ptr_list **)&proc->current_bb->insns, insn, &proc->linearizer->ptrlist_allocator);
return target;
}
static struct pseudo *linearize_expr(struct proc *proc, struct ast_node *expr) {
switch (expr->type) {
case AST_LITERAL_EXPR: {
@ -396,9 +422,10 @@ static struct pseudo *linearize_expr(struct proc *proc, struct ast_node *expr) {
} break;
case AST_BINARY_EXPR: {
return linearize_binaryop(proc, expr);
break;
}
} break;
case AST_FUNCTION_EXPR: {
return linearize_function_expr(proc, expr);
} break;
default:
abort();
break;
@ -642,14 +669,17 @@ void output_pseudo(struct pseudo *pseudo, membuff_t *mb) {
case PSEUDO_TEMP_ANY:
membuff_add_fstring(mb, "T(%d)", pseudo->regnum);
break;
case PSEUDO_PROC:
membuff_add_fstring(mb, "Proc(%p)", pseudo->proc);
break;
}
}
static const char *op_codenames[] = {"NOOP", "RET", "LOADK", "ADD", "ADDff", "ADDfi", "ADDii", "SUB", "SUBff",
"SUBfi", "SUBif", "SUBii", "MUL", "MULff", "MULfi", "MULii", "DIV", "DIVff",
"DIVfi", "DIVif", "DIVii", "IDIV", "BAND", "BANDii", "BOR", "BORii", "BXOR",
"BXORii", "SHL", "SHLii", "SHR", "SHRii", "EQ", "EQii", "EQff", "LT",
"LIii", "LTff", "LE", "LEii", "LEff", "MOD", "POW"};
static const char *op_codenames[] = {"NOOP", "RET", "LOADK", "ADD", "ADDff", "ADDfi", "ADDii", "SUB", "SUBff",
"SUBfi", "SUBif", "SUBii", "MUL", "MULff", "MULfi", "MULii", "DIV", "DIVff",
"DIVfi", "DIVif", "DIVii", "IDIV", "BAND", "BANDii", "BOR", "BORii", "BXOR",
"BXORii", "SHL", "SHLii", "SHR", "SHRii", "EQ", "EQii", "EQff", "LT",
"LIii", "LTff", "LE", "LEii", "LEff", "MOD", "POW", "CLOSURE"};
void output_pseudo_list(struct pseudo_list *list, membuff_t *mb) {
struct pseudo *pseudo;
@ -695,15 +725,11 @@ void output_proc(struct proc *proc, membuff_t *mb) {
}
}
void raviA_ast_linearize(struct linearizer *linearizer, struct ast_container *container) {
ravi_init_linearizer(linearizer, container);
struct proc *proc = allocate_proc(linearizer, container->main_function);
void raviA_ast_linearize(struct linearizer *linearizer) {
struct proc *proc = allocate_proc(linearizer, linearizer->ast_container->main_function);
set_main_proc(linearizer, proc);
set_current_proc(linearizer, proc);
linearize_function(linearizer);
membuff_t mb;
membuff_init(&mb, 1024);
output_proc(proc, &mb);
printf(mb.buf);
ravi_destroy_linearizer(linearizer);
}
void raviA_show_linearizer(struct linearizer *linearizer, membuff_t *mb) { output_proc(linearizer->main_proc, mb); }

@ -1434,8 +1434,6 @@ static void parse_lua_chunk(struct parser_state *parser) {
assert(parser->current_scope == NULL);
check(parser->ls, TK_EOS);
raviA_ast_typecheck(parser->container);
struct linearizer linearizer;
raviA_ast_linearize(&linearizer, parser->container);
}
static void parser_state_init(struct parser_state *parser, LexState *ls, struct ast_container *container) {
@ -1653,6 +1651,7 @@ static struct ast_container *new_ast_container(lua_State *L) {
dmrC_allocator_init(&container->symbol_allocator, "symbols", sizeof(struct lua_symbol), sizeof(double), CHUNK);
container->main_function = NULL;
container->killed = false;
container->linearizer = NULL;
luaL_getmetatable(L, AST_type);
lua_setmetatable(L, -2);
return container;
@ -1662,6 +1661,10 @@ static struct ast_container *new_ast_container(lua_State *L) {
static int collect_ast_container(lua_State *L) {
struct ast_container *container = check_Ravi_AST(L, 1);
if (!container->killed) {
if (container->linearizer) {
raviA_destroy_linearizer(container->linearizer);
free(container->linearizer);
}
dmrC_allocator_destroy(&container->symbol_allocator);
dmrC_allocator_destroy(&container->block_scope_allocator);
dmrC_allocator_destroy(&container->ast_node_allocator);
@ -1671,8 +1674,37 @@ static int collect_ast_container(lua_State *L) {
return 0;
}
static const luaL_Reg container_methods[] = {
{"tostring", ast_container_to_string}, {"release", collect_ast_container}, {NULL, NULL}};
static int ast_linearize(lua_State *L) {
struct ast_container *container = check_Ravi_AST(L, 1);
if (container->linearizer) {
luaL_error(L, "Already linearized");
}
struct linearizer *linearizer = (struct linearizer *)calloc(1, sizeof(struct linearizer));
raviA_init_linearizer(linearizer, container);
container->linearizer = linearizer;
raviA_ast_linearize(container->linearizer);
return 0;
}
static int ast_show_linearized(lua_State *L) {
struct ast_container *container = check_Ravi_AST(L, 1);
if (!container->linearizer) {
luaL_error(L, "Not yet linearized");
return 0;
}
membuff_t mb;
membuff_init(&mb, 1024);
raviA_show_linearizer(container->linearizer, &mb);
lua_pushstring(L, mb.buf);
membuff_free(&mb);
return 1;
}
static const luaL_Reg container_methods[] = {{"tostring", ast_container_to_string},
{"release", collect_ast_container},
{"linearize", ast_linearize},
{"showlinear", ast_show_linearized},
{NULL, NULL}};
static const luaL_Reg astlib[] = {
/* Entrypoint for new AST */

Loading…
Cancel
Save