.form = FORM_STRING,
.size = -1
};
-
-
-static size_t MaxBlocks = 0;
-static size_t NumBlocks = 0;
-static Block* Blocks = NULL;
-static size_t Level = 0;
-static struct {
- size_t curr;
- size_t join;
-} Levels[32] = {0};
-
-static size_t block_new(void)
-{
- if (NumBlocks == MaxBlocks)
- {
- MaxBlocks = (MaxBlocks ? 16u : (MaxBlocks << 1u));
- Blocks = realloc(Blocks, MaxBlocks * sizeof(Block));
- }
- memset(&Blocks[NumBlocks], 0, sizeof(Block));
- NumBlocks++;
- return (NumBlocks-1);
-}
-
-static void put_op(Operation* op)
-{
- Block* block = &Blocks[Levels[Level].curr];
- if (block->nops == block->mops)
- {
- block->mops = (block->mops ? 4u : (block->mops << 1u));
- block->ops = realloc(block->ops, block->mops * sizeof(Operation));
- }
- block->ops[block->nops++] = *op;
-}
-
-static void load_var(Parser* p, Item* item)
-{
- if (!item->reg)
- {
- switch (item->mode)
- {
- case ITEM_CONST:
- /* TODO: range check the constant */
- item->reg = p->curr_reg++;
- printf(" $%d = %lld;\n", item->reg, item->imm.i);
- break;
-
-// case ITEM_VAR:
-// item->reg = declare_temp(p, item->type, isref);
-// if (item->type->form == FORM_RECORD)
-// {
-// printf(" = (Byte*)&%s[0];\n", item->imm.s);
-// }
-// else
-// {
-// printf(" = %c%s;\n", (isref ? '&' : ' '), item->imm.s);
-// }
-// item->imm.i = 0;
-// break;
//
-// case ITEM_MVAR:
-// item->reg = declare_temp(p, item->type, isref);
-// if (item->type->form == FORM_RECORD)
-// {
-// printf(" = &%s_%s[0];\n", p->name, item->imm.s);
-// }
-// else
-// {
-// printf(" = %c%s_%s;\n", (isref ? '&' : ' '), p->name, item->imm.s);
-// }
-// item->imm.i = 0;
+//
+//static size_t MaxBlocks = 0;
+//static size_t NumBlocks = 0;
+//static Block* Blocks = NULL;
+//static size_t Level = 0;
+//static struct {
+// size_t curr;
+// size_t join;
+//} Levels[32] = {0};
+//
+//static size_t block_new(void)
+//{
+// if (NumBlocks == MaxBlocks)
+// {
+// MaxBlocks = (MaxBlocks ? 16u : (MaxBlocks << 1u));
+// Blocks = realloc(Blocks, MaxBlocks * sizeof(Block));
+// }
+// memset(&Blocks[NumBlocks], 0, sizeof(Block));
+// NumBlocks++;
+// return (NumBlocks-1);
+//}
+//
+//static void put_op(Operation* op)
+//{
+// Block* block = &Blocks[Levels[Level].curr];
+// if (block->nops == block->mops)
+// {
+// block->mops = (block->mops ? 4u : (block->mops << 1u));
+// block->ops = realloc(block->ops, block->mops * sizeof(Operation));
+// }
+// block->ops[block->nops++] = *op;
+//}
+//
+//static void load_var(Parser* p, Item* item)
+//{
+// if (!item->reg)
+// {
+// switch (item->mode)
+// {
+// case ITEM_CONST:
+// /* TODO: range check the constant */
+// item->reg = p->curr_reg++;
+// printf(" $%d = %lld;\n", item->reg, item->imm.i);
// break;
-
- default:
- assert(!"bad load_var()");
- }
- }
-}
-
-
-
-
-void codegen_startmod(Parser* p)
-{
- (void)p;
-}
-
-void codegen_endmod(Parser* p)
-{
- (void)p;
-}
-
-void codegen_setint(Item* item, Type* type, long long val)
-{
- item->mode = ITEM_CONST;
- item->type = type;
- item->reg = 0;
- item->imm.i = val;
-}
-
-void codegen_setreal(Item* item, double val)
-{
- item->mode = ITEM_CONST;
- item->type = &RealType;
- item->reg = 0;
- item->imm.f = val;
-}
-
-void codegen_setstr(Item* item, char* val)
-{
- item->mode = ITEM_CONST;
- item->type = &StringType;
- item->reg = 0;
- item->imm.s = val;
-}
-
-void codegen_imports(Parser* p)
-{
- (void)p;
-}
-
-void codegen_var(Parser* p, Symbol* sym)
-{
- (void)p, (void)sym;
-}
-
-void codegen_main(Parser* p)
-{
- (void)p;
-}
-
-void codegen_startproc(Parser* p, Symbol* proc)
-{
- (void)p, (void)proc;
- printf("func %s(){\n", (proc ? proc->name : p->name));
- printf("L%lu:\n", block_new());
-}
-
-void codegen_endproc(Parser* p)
-{
- (void)p;
- printf("}\n");
-}
-
-void codegen_unop(Parser* p, int op, Item* a)
-{
- (void)p, (void)op, (void)a;
-}
-
-void codegen_binop(Parser* p, int op, Item* a, Item* b)
-{
- (void)p, (void)op, (void)a, (void)b;
-}
-
-void codegen_store(Parser* p, Item* a, Item* b)
-{
- (void)p, (void)a, (void)b;
- load_var(p, b);
-}
-
-void codegen_if(Parser* p, Item* item)
-{
- (void)p, (void)item;
-}
-
-void codegen_else(Parser* p, Item* item)
-{
- (void)p, (void)item;
-}
-
-void codegen_endif(Parser* p, long elsifs, Item* item)
-{
- (void)p, (void)elsifs, (void)item;
-}
-
-void codegen_prepcall(Parser* p, Item* item)
-{
- (void)p, (void)item;
-}
-
-void codegen_call(Parser* p, Item* item, Item* args)
-{
- (void)p, (void)item, (void)args;
-}
-
-void codegen_setarg(Parser* p, Item* item, bool firstarg)
-{
- (void)p, (void)item, (void)firstarg;
-}
-
-void codegen_return(Parser* p, Item* item)
-{
- (void)p, (void)item;
-}
-
-void codegen_index(Parser* p, Item* array, Item* index)
-{
- (void)p, (void)array, (void)index;
-}
-
-void codegen_field(Parser* p, Item* record, char* name)
-{
- (void)p, (void)record, (void)name;
-}
-
+//
+//// case ITEM_VAR:
+//// item->reg = declare_temp(p, item->type, isref);
+//// if (item->type->form == FORM_RECORD)
+//// {
+//// printf(" = (Byte*)&%s[0];\n", item->imm.s);
+//// }
+//// else
+//// {
+//// printf(" = %c%s;\n", (isref ? '&' : ' '), item->imm.s);
+//// }
+//// item->imm.i = 0;
+//// break;
+////
+//// case ITEM_MVAR:
+//// item->reg = declare_temp(p, item->type, isref);
+//// if (item->type->form == FORM_RECORD)
+//// {
+//// printf(" = &%s_%s[0];\n", p->name, item->imm.s);
+//// }
+//// else
+//// {
+//// printf(" = %c%s_%s;\n", (isref ? '&' : ' '), p->name, item->imm.s);
+//// }
+//// item->imm.i = 0;
+//// break;
+//
+// default:
+// assert(!"bad load_var()");
+// }
+// }
+//}
+//
+//
+//
+//
+//void codegen_startmod(Parser* p)
+//{
+// (void)p;
+//}
+//
+//void codegen_endmod(Parser* p)
+//{
+// (void)p;
+//}
+//
+//void codegen_setint(Item* item, Type* type, long long val)
+//{
+// item->mode = ITEM_CONST;
+// item->type = type;
+// item->reg = 0;
+// item->imm.i = val;
+//}
+//
+//void codegen_setreal(Item* item, double val)
+//{
+// item->mode = ITEM_CONST;
+// item->type = &RealType;
+// item->reg = 0;
+// item->imm.f = val;
+//}
+//
+//void codegen_setstr(Item* item, char* val)
+//{
+// item->mode = ITEM_CONST;
+// item->type = &StringType;
+// item->reg = 0;
+// item->imm.s = val;
+//}
+//
+//void codegen_imports(Parser* p)
+//{
+// (void)p;
+//}
+//
+//void codegen_var(Parser* p, Symbol* sym)
+//{
+// (void)p, (void)sym;
+//}
+//
+//void codegen_main(Parser* p)
+//{
+// (void)p;
+//}
+//
+//void codegen_startproc(Parser* p, Symbol* proc)
+//{
+// (void)p, (void)proc;
+// printf("func %s(){\n", (proc ? proc->name : p->name));
+// printf("L%lu:\n", block_new());
+//}
+//
+//void codegen_endproc(Parser* p)
+//{
+// (void)p;
+// printf("}\n");
+//}
+//
+//void codegen_unop(Parser* p, int op, Item* a)
+//{
+// (void)p, (void)op, (void)a;
+//}
+//
+//void codegen_binop(Parser* p, int op, Item* a, Item* b)
+//{
+// (void)p, (void)op, (void)a, (void)b;
+//}
+//
+//void codegen_store(Parser* p, Item* a, Item* b)
+//{
+// (void)p, (void)a, (void)b;
+// load_var(p, b);
+//}
+//
+//void codegen_if(Parser* p, Item* item)
+//{
+// (void)p, (void)item;
+//}
+//
+//void codegen_else(Parser* p, Item* item)
+//{
+// (void)p, (void)item;
+//}
+//
+//void codegen_endif(Parser* p, long elsifs, Item* item)
+//{
+// (void)p, (void)elsifs, (void)item;
+//}
+//
+//void codegen_prepcall(Parser* p, Item* item)
+//{
+// (void)p, (void)item;
+//}
+//
+//void codegen_call(Parser* p, Item* item, Item* args)
+//{
+// (void)p, (void)item, (void)args;
+//}
+//
+//void codegen_setarg(Parser* p, Item* item, bool firstarg)
+//{
+// (void)p, (void)item, (void)firstarg;
+//}
+//
+//void codegen_return(Parser* p, Item* item)
+//{
+// (void)p, (void)item;
+//}
+//
+//void codegen_index(Parser* p, Item* array, Item* index)
+//{
+// (void)p, (void)array, (void)index;
+//}
+//
+//void codegen_field(Parser* p, Item* record, char* name)
+//{
+// (void)p, (void)record, (void)name;
+//}
+//
//#define TRACE
#ifdef TRACE
static int Indent = 0;
- #define RULE(name) \
- static void name##_actual(Parser* p, Item* item); \
- static void name(Parser* p, Item* item) { \
- printf("%*c-> %s\n", ++Indent * 2, ' ', __func__); \
- name##_actual(p, item); \
- Indent--; } \
- static void name##_actual(Parser* p, Item* item)
+ #define ENTER_RULE() \
+ printf("%*c-> %s\n", ++Indent * 2, ' ', __func__)
+
+ #define EXIT_RULE() \
+ Indent--
#else
- #define RULE(name) \
- static void name(Parser* p, Item* item)
+ #define ENTER_RULE() ((void)0)
+ #define EXIT_RULE() ((void)0)
#endif
-/* Item Handling
+/* Basic Blocks and Operations
*****************************************************************************/
-static void init_item(Item* item, Symbol* sym)
+#define MAX_OPS (256)
+static size_t NumOps = 0;
+static Operation* Ops[MAX_OPS] = {0};
+
+static void print_op(Operation* op)
{
- item->type = sym->type;
- if (SYM_VAR == sym->class)
+ switch (op->code)
{
- item->mode = (sym->global ? ITEM_MVAR : ITEM_VAR);
- item->imm.s = sym->name;
+ case INT:
+ case BOOL:
+ printf(" $%ld = %ld\n", op->u.args[0].i, op->u.args[1].i);
+ break;
+
+ case REAL:
+ printf(" $%ld = %f\n", op->u.args[0].i, op->u.args[1].f);
+ break;
}
- else if (SYM_PROC == sym->class)
+}
+
+/* Intermediate Representation
+ *****************************************************************************/
+//void codegen_startproc(Parser* p, Symbol* func);
+//void codegen_endproc(Parser* p);
+//void codegen_unop(Parser* p, int op, Item* a);
+//void codegen_binop(Parser* p, int op, Item* a, Item* b);
+//void codegen_store(Parser* p, Item* a, Item* b);
+//void codegen_if(Parser* p, Item* item);
+//void codegen_else(Parser* p, Item* item);
+//void codegen_endif(Parser* p, long elsifs, Item* item);
+//void codegen_prepcall(Parser* p, Item* item);
+//void codegen_call(Parser* p, Item* item, Item* args);
+//void codegen_setarg(Parser* p, Item* item, bool firstarg);
+//void codegen_return(Parser* p, Item* item);
+//void codegen_index(Parser* p, Item* array, Item* index);
+//void codegen_field(Parser* p, Item* record, char* name);
+
+static Operation* ir_pop(void)
+{
+ assert(NumOps > 0);
+ return Ops[--NumOps];
+}
+
+static void ir_push(Operation* op)
+{
+ assert(NumOps < MAX_OPS);
+ Ops[NumOps++] = op;
+}
+
+static void ir_int(Parser* p, long val)
+{
+ Operation* op = calloc(1, sizeof(Operation));
+ op->code = INT;
+ op->mode = IR_CONST;
+ op->u.args[0].i = p->curr_reg++;
+ op->u.args[1].i = val;
+ print_op(op);
+ ir_push(op);
+}
+
+static void ir_real(Parser* p, double val)
+{
+ Operation* op = calloc(1, sizeof(Operation));
+ op->code = REAL;
+ op->mode = IR_CONST;
+ op->u.args[0].i = p->curr_reg++;
+ op->u.args[1].f = val;
+ print_op(op);
+ ir_push(op);
+}
+
+static void ir_getconst(Parser* p, Symbol* sym)
+{
+ Operation* op = ir_pop();
+ if (op->mode != IR_CONST)
+ {
+ error(p, "Constant definition is non-constant");
+ }
+// sym->type = op->type;
+ if (op->code == INT)
+ {
+ sym->imm.i = op->u.args[1].i;
+ }
+ else
+ {
+ sym->imm.i = op->u.args[1].f;
+ }
+}
+
+static void ir_unop(Parser* p, int op)
+{
+ Operation* a = ir_pop();
+ if (a->mode == IR_CONST)
{
- item->mode = ITEM_MVAR;
- item->imm.s = sym->name;
+ if (a->code == INT)
+ {
+ switch (op)
+ {
+ case '+': a->u.args[1].i = +a->u.args[1].i; break;
+ case '-': a->u.args[1].i = -a->u.args[1].i; break;
+ default: assert(!"not a valid op"); break;
+ }
+ }
+ else if (a->code == REAL)
+ {
+ switch (op)
+ {
+ case '+': a->u.args[1].f = +a->u.args[1].f; break;
+ case '-': a->u.args[1].f = -a->u.args[1].f; break;
+ default: assert(!"not a valid op"); break;
+ }
+ }
+ else if (a->code == BOOL)
+ {
+ switch (op)
+ {
+ case NOT: a->u.args[1].i = !a->u.args[1].i; break;
+ default: assert(!"not a valid op"); break;
+ }
+ }
}
else
{
- item->mode = ITEM_CONST;
- item->imm = sym->imm;
+ assert(!"unimplemented unary op");
}
+ print_op(a);
+ ir_push(a);
}
+/* Item Handling
+ *****************************************************************************/
Field* add_field(Parser* p, Type* type, char* name, bool export)
{
Field* prev = NULL;
/* Grammar Definition
*****************************************************************************/
-static void expression(Parser* p, Item* item);
-
-RULE(qualident)
-{
- char* name = expect_text(p, IDENT);
- Symbol* sym = symbol_get(p, name, -1);
- init_item(item, sym);
-
-// if (accept(p, '.'))
+static void expression(Parser* p);
+
+//RULE(qualident, Item* item)
+//{
+// ENTER_RULE();
+// char* name = expect_text(p, IDENT);
+// Symbol* sym = symbol_get(p, name, -1);
+// init_item(item, sym);
+// (void)sym;
+//
+//// if (accept(p, '.'))
+//// {
+//// expect(p, IDENT);
+//// }
+// EXIT_RULE();
+//}
+//
+//RULE(designator, Item* item)
+//{
+// ENTER_RULE();
+// qualident(p, item);
+// /* selector */
+// for (int done = 0; !done;)
// {
-// expect(p, IDENT);
+// switch ((int)peek(p)->type)
+// {
+// case '.':
+// {
+// expect(p, '.');
+// char* name = expect_text(p, IDENT);
+// if (item->type->form == FORM_RECORD)
+// {
+// codegen_field(p, item, name);
+// }
+// else
+// {
+// error(p, "attempting to access field of non-array object");
+// }
+// break;
+// }
+//
+// case '[':
+// {
+// Item index = {0};
+// expect(p, '[');
+// expression(p, &index);
+// if (item->type->form == FORM_ARRAY)
+// {
+// codegen_index(p, item, &index);
+// }
+// else
+// {
+// error(p, "attempting to index non-array value");
+// }
+// expect(p, ']');
+// break;
+// }
+//
+// // case '^':
+// // expect(p, '^');
+// // break;
+//
+// // case '(':
+// // qualident(p);
+// // expect(p, ')');
+// // break;
+//
+// default:
+// done = 1;
+// break;
+// }
// }
-}
+// EXIT_RULE();
+//}
-RULE(designator)
-{
- qualident(p, item);
- /* selector */
- for (int done = 0; !done;)
- {
- switch ((int)peek(p)->type)
- {
- case '.':
- {
- expect(p, '.');
- char* name = expect_text(p, IDENT);
- if (item->type->form == FORM_RECORD)
- {
- codegen_field(p, item, name);
- }
- else
- {
- error(p, "attempting to access field of non-array object");
- }
- break;
- }
-
- case '[':
- {
- Item index = {0};
- expect(p, '[');
- expression(p, &index);
- if (item->type->form == FORM_ARRAY)
- {
- codegen_index(p, item, &index);
- }
- else
- {
- error(p, "attempting to index non-array value");
- }
- expect(p, ']');
- break;
- }
-
- // case '^':
- // expect(p, '^');
- // break;
-
- // case '(':
- // qualident(p);
- // expect(p, ')');
- // break;
-
- default:
- done = 1;
- break;
- }
- }
-}
-
-RULE(factor)
+static void factor(Parser* p)
{
+ ENTER_RULE();
switch ((int)peek(p)->type)
{
case INT:
- codegen_setint(item, &IntType, peek(p)->value.integer);
+ ir_int(p, peek(p)->value.integer);
consume(p);
break;
case REAL:
- codegen_setreal(item, peek(p)->value.floating);
+ ir_real(p, peek(p)->value.floating);
consume(p);
break;
- case STRING:
- codegen_setstr(item, peek(p)->text);
- consume(p);
- break;
-
-// case NIL:
-// codegen_nil(item);
+// case STRING:
+// codegen_setstr(item, peek(p)->text);
// consume(p);
// break;
case BOOL:
- codegen_setint(item, &BoolType, peek(p)->value.integer);
+ ir_int(p, peek(p)->value.integer);
consume(p);
break;
- case '(':
- expect(p, '(');
- expression(p, item);
- expect(p, ')');
- break;
+// case '(':
+// expect(p, '(');
+// expression(p, item);
+// expect(p, ')');
+// break;
- case NOT:
- consume(p);
- factor(p, item);
- check_bool(p, item);
- codegen_unop(p, NOT, item);
- break;
+// case NOT:
+// consume(p);
+// factor(p, item);
+// check_bool(p, item);
+// codegen_unop(p, NOT, item);
+// break;
- case IDENT:
- designator(p, item);
- if (accept(p, '('))
- {
- Symbol* proc = symbol_get(p, item->imm.s, SYM_PROC);
- item->type = proc->type->base;
- Field* args = proc->type->fields;
- Item arglist = {0};
- Item** currarg = &(arglist.next);
- while (args && !matches(p, ')'))
- {
- Item argdef = { .type = args->type };
- Item* argval = calloc(1, sizeof(Item));
- expression(p, argval);
- check_types(p, &argdef, argval);
- codegen_setarg(p, argval, (arglist.next == 0));
- *currarg = argval;
- currarg = &(argval->next);
- args = args->next;
- if (args)
- {
- expect(p, ',');
- }
- }
- if (args)
- {
- error(p, "too few arguments to function '%s'", proc->name);
- }
- else if (!matches(p, ')'))
- {
- bool comma = accept(p, ',');
- if (comma && matches(p, ')'))
- {
- error(p, "trailing comma in argument list");
- }
- else
- {
- error(p, "too many arguments to function '%s'", proc->name);
- }
- }
- codegen_call(p, item, arglist.next);
- expect(p, ')');
- }
- break;
+// case IDENT:
+// designator(p, item);
+// if (accept(p, '('))
+// {
+// Symbol* proc = symbol_get(p, item->imm.s, SYM_PROC);
+// item->type = proc->type->base;
+// Field* args = proc->type->fields;
+// Item arglist = {0};
+// Item** currarg = &(arglist.next);
+// while (args && !matches(p, ')'))
+// {
+// Item argdef = { .type = args->type };
+// Item* argval = calloc(1, sizeof(Item));
+// expression(p, argval);
+// check_types(p, &argdef, argval);
+// codegen_setarg(p, argval, (arglist.next == 0));
+// *currarg = argval;
+// currarg = &(argval->next);
+// args = args->next;
+// if (args)
+// {
+// expect(p, ',');
+// }
+// }
+// if (args)
+// {
+// error(p, "too few arguments to function '%s'", proc->name);
+// }
+// else if (!matches(p, ')'))
+// {
+// bool comma = accept(p, ',');
+// if (comma && matches(p, ')'))
+// {
+// error(p, "trailing comma in argument list");
+// }
+// else
+// {
+// error(p, "too many arguments to function '%s'", proc->name);
+// }
+// }
+// codegen_call(p, item, arglist.next);
+// expect(p, ')');
+// }
+// break;
default:
printf("unknown factor: %d\n", peek(p)->type);
break;
}
+ EXIT_RULE();
}
-RULE(term)
+
+static void term(Parser* p)
{
- factor(p, item);
+ ENTER_RULE();
- while (matches_oneof(p, (int[]){'*', '/', '%', AND, 0}))
- {
- Item right = { 0 };
- int op = consume(p);
- factor(p, &right);
- switch(op)
- {
- case '*':
- case '/':
- case '%':
- check_nums(p, item, &right);
- codegen_binop(p, op, item, &right);
- break;
-
- case AND:
- check_bools(p, item, &right);
- codegen_binop(p, op, item, &right);
- break;
-
- default:
- assert(!"not supported");
- break;
- }
- }
+ factor(p);
+
+// while (matches_oneof(p, (int[]){'*', '/', '%', AND, 0}))
+// {
+// Item right = { 0 };
+// int op = consume(p);
+// factor(p, &right);
+// switch(op)
+// {
+// case '*':
+// case '/':
+// case '%':
+// check_nums(p, item, &right);
+// codegen_binop(p, op, item, &right);
+// break;
+//
+// case AND:
+// check_bools(p, item, &right);
+// codegen_binop(p, op, item, &right);
+// break;
+//
+// default:
+// assert(!"not supported");
+// break;
+// }
+// }
+
+ EXIT_RULE();
}
-RULE(simple_expr)
+static void simple_expr(Parser* p)
{
+ ENTER_RULE();
+
/* first term and +/- */
if (matches_oneof(p, (int[]){'+', '-', 0}))
{
int op = consume(p); // OP
- term(p, item);
- check_num(p, item);
- codegen_unop(p, op, item);
+ term(p);
+ ir_unop(p, op);
+// check_num(p, item);
+// codegen_unop(p, op, item);
}
else
{
- term(p, item);
+ term(p);
}
- /* optional second term and op */
- while (matches_oneof(p, (int[]){'+', '-', OR, 0}))
- {
- Item right = { 0 };
- int op = consume(p);
- term(p, &right);
- if (op == OR)
- {
- check_bools(p, item, &right);
- }
- else
- {
- check_nums(p, item, &right);
- }
- codegen_binop(p, op, item, &right);
- }
-}
-
-RULE(expression)
-{
- int ops[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 };
- simple_expr(p, item);
+// /* optional second term and op */
+// while (matches_oneof(p, (int[]){'+', '-', OR, 0}))
+// {
+// Item right = { 0 };
+// int op = consume(p);
+// term(p, &right);
+// if (op == OR)
+// {
+// check_bools(p, item, &right);
+// }
+// else
+// {
+// check_nums(p, item, &right);
+// }
+// codegen_binop(p, op, item, &right);
+// }
- if (matches_oneof(p, ops))
- {
- Item right = { 0 };
- int op = consume(p);
- simple_expr(p, &right);
- check_nums(p, item, &right);
- codegen_binop(p, op, item, &right);
- }
+ EXIT_RULE();
}
-RULE(type)
+static void expression(Parser* p)
{
- (void)item;
- if (matches(p, IDENT))
- {
- char* text = expect_text(p, IDENT);
- Symbol* sym = symbol_get(p, text, SYM_TYPE);
- item->type = sym->type;
- }
- else if (accept(p, ARRAY))
- {
- expression(p, item);
- if (item->mode != ITEM_CONST)
- {
- error(p, "non-constant array size");
- }
- expect(p, OF);
- Item base = {0};
- type(p, &base);
- item->type = calloc(1, sizeof(Type));
- item->type->form = FORM_ARRAY;
- item->type->size = item->imm.i;
- item->type->base = base.type;
- }
- else if (accept(p, RECORD))
- {
- long offset = 0;
- item->type = calloc(1, sizeof(Type));
- item->type->form = FORM_RECORD;
+ ENTER_RULE();
+// int ops[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 };
- while (peek(p)->type != END)
- {
- /* parse the field name list */
- Field* first = NULL;
- int nfields = 0;
- do
- {
- char* name = expect_text(p, IDENT);
- bool export = accept(p, '*');
- Field* f = add_field(p, item->type, name, export);
- nfields++;
- if (!first)
- {
- first = f;
- }
- }
- while (accept(p, ','));
-
- /* now parse the type designation */
- Item field_type = {0};
- expect(p, ':');
- type(p, &field_type);
-
- /* apply the type to the newly created symbols */
- for (int i = 0; i < nfields; i++)
- {
- offset = align_item(offset, field_type.type->size);
- first->type = field_type.type;
- first->offset = offset;
- offset += size_of(first->type);
- first = first->next;
- }
- }
- item->type->size = offset;
-
- expect(p, END);
- }
- else
- {
- error(p, "expected a type");
- }
-}
+ simple_expr(p);
-RULE(statement_seq)
-{
- do
- {
- if (matches(p, IF))
- {
- expect(p, IF);
- expression(p, item);
- check_bool(p, item);
- codegen_if(p, item);
- expect(p, THEN);
- statement_seq(p, &(Item){0});
- int elsifs = 0;
- while (accept(p, ELSIF))
- {
- elsifs++;
- codegen_else(p, item);
- expression(p, item);
- check_bool(p, item);
- codegen_if(p, item);
- expect(p, THEN);
- statement_seq(p, &(Item){0});
- }
- if (accept(p, ELSE))
- {
- codegen_else(p, item);
- statement_seq(p, &(Item){0});
- }
- codegen_endif(p, elsifs, item);
- expect(p, END);
- }
- else /* assignments/expressions */
- {
- expression(p, item);
- if (accept(p, '='))
- {
- Item right = { 0 };
- expression(p, &right);
- check_types(p, item, &right);
- codegen_store(p, item, &right);
- }
- expect(p, ';');
- }
- }
- while (!matches(p, END) && !matches(p, ELSE) && !matches(p, ELSIF) && !matches(p, RETURN));
-}
+// if (matches_oneof(p, ops))
+// {
+// Item right = { 0 };
+// int op = consume(p);
+// simple_expr(p, &right);
+// check_nums(p, item, &right);
+// codegen_binop(p, op, item, &right);
+// }
-RULE(var_decl)
-{
- (void)item;
- do
- {
- char* name = expect_text(p, IDENT);
- bool export = accept(p, '*');
- Symbol* sym = symbol_new(p, 0, name, SYM_VAR, export);
- Item base_type = {0};
- expect(p, ':');
- type(p, &base_type);
- sym->type = base_type.type;
- }
- while (matches(p, IDENT));
+ EXIT_RULE();
}
-RULE(type_decl)
-{
- char* name = NULL;
- bool export = false;
- Symbol* sym = NULL;
+//RULE(type, Item* item)
+//{
+// ENTER_RULE();
+// (void)item;
+// if (matches(p, IDENT))
+// {
+// char* text = expect_text(p, IDENT);
+// Symbol* sym = symbol_get(p, text, SYM_TYPE);
+// item->type = sym->type;
+// }
+// else if (accept(p, ARRAY))
+// {
+// expression(p, item);
+// if (item->mode != ITEM_CONST)
+// {
+// error(p, "non-constant array size");
+// }
+// expect(p, OF);
+// Item base = {0};
+// type(p, &base);
+// item->type = calloc(1, sizeof(Type));
+// item->type->form = FORM_ARRAY;
+// item->type->size = item->imm.i;
+// item->type->base = base.type;
+// }
+// else if (accept(p, RECORD))
+// {
+// long offset = 0;
+// item->type = calloc(1, sizeof(Type));
+// item->type->form = FORM_RECORD;
+//
+// while (peek(p)->type != END)
+// {
+// /* parse the field name list */
+// Field* first = NULL;
+// int nfields = 0;
+// do
+// {
+// char* name = expect_text(p, IDENT);
+// bool export = accept(p, '*');
+// Field* f = add_field(p, item->type, name, export);
+// nfields++;
+// if (!first)
+// {
+// first = f;
+// }
+// }
+// while (accept(p, ','));
+//
+// /* now parse the type designation */
+// Item field_type = {0};
+// expect(p, ':');
+// type(p, &field_type);
+//
+// /* apply the type to the newly created symbols */
+// for (int i = 0; i < nfields; i++)
+// {
+// offset = align_item(offset, field_type.type->size);
+// first->type = field_type.type;
+// first->offset = offset;
+// offset += size_of(first->type);
+// first = first->next;
+// }
+// }
+// item->type->size = offset;
+//
+// expect(p, END);
+// }
+// else
+// {
+// error(p, "expected a type");
+// }
+// EXIT_RULE();
+//}
- do
- {
- name = expect_text(p, IDENT);
- export = accept(p, '*');
- sym = symbol_new(p, 0, name, SYM_TYPE, export);
- expect(p, '=');
- type(p, item);
- sym->type = item->type;
- }
- while (matches(p, IDENT));
-}
+//RULE(statement_seq, Item* item)
+//{
+// ENTER_RULE();
+// do
+// {
+// if (matches(p, IF))
+// {
+// expect(p, IF);
+// expression(p, item);
+// check_bool(p, item);
+// codegen_if(p, item);
+// expect(p, THEN);
+// statement_seq(p, &(Item){0});
+// int elsifs = 0;
+// while (accept(p, ELSIF))
+// {
+// elsifs++;
+// codegen_else(p, item);
+// expression(p, item);
+// check_bool(p, item);
+// codegen_if(p, item);
+// expect(p, THEN);
+// statement_seq(p, &(Item){0});
+// }
+// if (accept(p, ELSE))
+// {
+// codegen_else(p, item);
+// statement_seq(p, &(Item){0});
+// }
+// codegen_endif(p, elsifs, item);
+// expect(p, END);
+// }
+// else /* assignments/expressions */
+// {
+// expression(p, item);
+// if (accept(p, '='))
+// {
+// Item right = { 0 };
+// expression(p, &right);
+// check_types(p, item, &right);
+// codegen_store(p, item, &right);
+// }
+// expect(p, ';');
+// }
+// }
+// while (!matches(p, END) && !matches(p, ELSE) && !matches(p, ELSIF) && !matches(p, RETURN));
+// EXIT_RULE();
+//}
+
+//RULE(var_decl, Item* item)
+//{
+// ENTER_RULE();
+// (void)item;
+// do
+// {
+// char* name = expect_text(p, IDENT);
+// bool export = accept(p, '*');
+// Symbol* sym = symbol_new(p, 0, name, SYM_VAR, export);
+// Item base_type = {0};
+// expect(p, ':');
+// type(p, &base_type);
+// sym->type = base_type.type;
+// }
+// while (matches(p, IDENT));
+// EXIT_RULE();
+//}
+//
+//RULE(type_decl, Item* item)
+//{
+// ENTER_RULE();
+// char* name = NULL;
+// bool export = false;
+// Symbol* sym = NULL;
+//
+// do
+// {
+// name = expect_text(p, IDENT);
+// export = accept(p, '*');
+// sym = symbol_new(p, 0, name, SYM_TYPE, export);
+// expect(p, '=');
+// type(p, item);
+// sym->type = item->type;
+// }
+// while (matches(p, IDENT));
+// EXIT_RULE();
+//}
-RULE(const_decl)
+static void const_decl(Parser* p)
{
+// ENTER_RULE();
char* name = NULL;
bool export = false;
Symbol* sym = NULL;
name = expect_text(p, IDENT);
export = accept(p, '*');
sym = symbol_new(p, 0, name, SYM_CONST, export);
-
expect(p, '=');
- expression(p, item);
- sym->imm = item->imm;
- sym->type = item->type;
+ expression(p);
+ ir_getconst(p, sym);
+// sym->imm = item->imm;
+// sym->type = item->type;
}
while (matches(p, IDENT));
+// EXIT_RULE();
}
-RULE(proc_decl)
-{
- expect(p, PROCEDURE);
- char* name = expect_text(p, IDENT);
- bool export = accept(p, '*');
- Symbol* proc = symbol_new(p, 0, name, SYM_PROC, export);
- Type* proctype = calloc(1, sizeof(Type));
- proctype->form = FORM_PROC;
- proc->type = proctype;
- size_t scope = symbol_openscope(p);
-
- /* construct the proc type */
- expect(p, '(');
- while (!matches(p, ')'))
- {
- char* name = expect_text(p, IDENT);
- expect(p, ':');
- type(p, item);
- proc->nargs++;
- add_field(p, proctype, name, false)->type = item->type;
- symbol_new(p, scope, name, SYM_VAR, export)->type = item->type;
- if (!matches(p, ')'))
- {
- expect(p, ',');
- }
- }
- expect(p, ')');
- if (accept(p, ':'))
- {
- type(p, item);
- proctype->base = item->type;
- }
-
- codegen_startproc(p, proc);
-
- /* parse the declarations */
- if (accept(p, CONST))
- {
- const_decl(p, item);
- }
-
- if (accept(p, TYPE))
- {
- type_decl(p, item);
- }
-
- if (accept(p, VAR))
- {
- var_decl(p, item);
- }
-
- /* parse the body of the procedure */
- expect(p, BEGIN);
- if (!matches(p, RETURN) && !matches(p, END))
- {
- statement_seq(p, item);
- }
- if (accept(p, RETURN))
- {
- expression(p, item);
- codegen_return(p, item);
- expect(p, ';');
- }
- else
- {
- codegen_return(p, NULL);
- }
- expect(p, END);
-
- codegen_endproc(p);
- symbol_closescope(p, scope);
-}
-
-RULE(import_list)
+//RULE(proc_decl, Item* item)
+//{
+// ENTER_RULE();
+// expect(p, PROCEDURE);
+// char* name = expect_text(p, IDENT);
+// bool export = accept(p, '*');
+// Symbol* proc = symbol_new(p, 0, name, SYM_PROC, export);
+// Type* proctype = calloc(1, sizeof(Type));
+// proctype->form = FORM_PROC;
+// proc->type = proctype;
+// size_t scope = symbol_openscope(p);
+//
+// /* construct the proc type */
+// expect(p, '(');
+// while (!matches(p, ')'))
+// {
+// char* name = expect_text(p, IDENT);
+// expect(p, ':');
+// type(p, item);
+// proc->nargs++;
+// add_field(p, proctype, name, false)->type = item->type;
+// symbol_new(p, scope, name, SYM_VAR, export)->type = item->type;
+// if (!matches(p, ')'))
+// {
+// expect(p, ',');
+// }
+// }
+// expect(p, ')');
+// if (accept(p, ':'))
+// {
+// type(p, item);
+// proctype->base = item->type;
+// }
+//
+// codegen_startproc(p, proc);
+//
+// /* parse the declarations */
+// if (accept(p, CONST))
+// {
+// const_decl(p, item);
+// }
+//
+// if (accept(p, TYPE))
+// {
+// type_decl(p, item);
+// }
+//
+// if (accept(p, VAR))
+// {
+// var_decl(p, item);
+// }
+//
+// /* parse the body of the procedure */
+// expect(p, BEGIN);
+// if (!matches(p, RETURN) && !matches(p, END))
+// {
+// statement_seq(p, item);
+// }
+// if (accept(p, RETURN))
+// {
+// expression(p, item);
+// codegen_return(p, item);
+// expect(p, ';');
+// }
+// else
+// {
+// codegen_return(p, NULL);
+// }
+// expect(p, END);
+//
+// codegen_endproc(p);
+// symbol_closescope(p, scope);
+// EXIT_RULE();
+//}
+
+static void import_list(Parser* p)
{
- (void)item;
+// ENTER_RULE();
expect(p, IMPORT);
do
{
m->next = p->imports;
p->imports = m;
}
+// EXIT_RULE();
}
-RULE(module)
+static void module(Parser* p)
{
+ ENTER_RULE();
size_t scope = symbol_openscope(p);
expect(p, MODULE);
p->name = expect_text(p, IDENT);
- /* TODO: Check that it matches filename here */
+ /* TODO: Check that it matches filename here */
if (matches(p, IMPORT))
{
- import_list(p, item);
+ import_list(p);
}
if (accept(p, CONST))
{
- const_decl(p, item);
+ const_decl(p);
}
- if (accept(p, TYPE))
- {
- type_decl(p, item);
- }
-
- if (accept(p, VAR))
- {
- var_decl(p, item);
- }
+// if (accept(p, TYPE))
+// {
+// type_decl(p);
+// }
+//
+// if (accept(p, VAR))
+// {
+// var_decl(p);
+// }
- while (matches(p, PROCEDURE))
- {
- proc_decl(p, item);
- }
+// while (matches(p, PROCEDURE))
+// {
+// proc_decl(p);
+// }
- codegen_startproc(p, NULL);
- if (accept(p, BEGIN))
- {
- codegen_imports(p);
- statement_seq(p, item);
- expect(p, END);
- }
- codegen_endproc(p);
+// codegen_startproc(p, NULL);
+// if (accept(p, BEGIN))
+// {
+// codegen_imports(p);
+// statement_seq(p, item);
+// expect(p, END);
+// }
+// codegen_endproc(p);
if (!matches(p, END_FILE))
{
}
symbol_closescope(p, scope);
+ EXIT_RULE();
}
static inline char* file_load(char* path)
symbol_new(p, 0, "Real", SYM_TYPE, 0)->type = &RealType;
symbol_new(p, 0, "String", SYM_TYPE, 0)->type = &StringType;
- codegen_startmod(p);
- module(p, &(Item){0});
- codegen_main(p);
- codegen_endmod(p);
+// codegen_startmod(p);
+ module(p);
+// codegen_main(p);
+// codegen_endmod(p);
}
/* Grammar Unit Tests
#ifdef CERISE_TESTS
#include "atf.h"
-Parser Ctx = {0};
-
-static void parse_init(char* fname, char* string)
-{
- memset(&Ctx, 0, sizeof(Ctx));
- symbol_new(&Ctx, 0, "Bool", SYM_TYPE, 0)->type = &BoolType;
- symbol_new(&Ctx, 0, "Int", SYM_TYPE, 0)->type = &IntType;
- symbol_new(&Ctx, 0, "Real", SYM_TYPE, 0)->type = &RealType;
- symbol_new(&Ctx, 0, "String", SYM_TYPE, 0)->type = &StringType;
- LexFile* file = calloc(sizeof(LexFile), 1u);
- file->path = strdup(fname);
- file->fbeg = file->fpos = strdup(string);
- file->next = Ctx.file;
- Ctx.file = file;
-}
-
-static void parse_rule(void (*rule)(Parser*, Item*), Item* item, char* string)
-{
-// puts("");
-// printf("%s\n", string);
- parse_init("test_input", string);
- rule(&Ctx, (item ? item : &(Item){0}));
-}
-
-static void parse_module(char* fname, char* string)
-{
- parse_init(fname, string);
- module(&Ctx, &(Item){0});
-}
+//Parser Ctx = {0};
+//
+//static void parse_init(char* fname, char* string)
+//{
+// memset(&Ctx, 0, sizeof(Ctx));
+// symbol_new(&Ctx, 0, "Bool", SYM_TYPE, 0)->type = &BoolType;
+// symbol_new(&Ctx, 0, "Int", SYM_TYPE, 0)->type = &IntType;
+// symbol_new(&Ctx, 0, "Real", SYM_TYPE, 0)->type = &RealType;
+// symbol_new(&Ctx, 0, "String", SYM_TYPE, 0)->type = &StringType;
+// LexFile* file = calloc(sizeof(LexFile), 1u);
+// file->path = strdup(fname);
+// file->fbeg = file->fpos = strdup(string);
+// file->next = Ctx.file;
+// Ctx.file = file;
+//}
+//
+//static void parse_rule(void (*rule)(Parser*, Item*), Item* item, char* string)
+//{
+//// puts("");
+//// printf("%s\n", string);
+// parse_init("test_input", string);
+// rule(&Ctx, (item ? item : &(Item){0}));
+//}
+//
+//static void parse_module(char* fname, char* string)
+//{
+// parse_init(fname, string);
+// module(&Ctx, &(Item){0});
+//}
TEST_SUITE(Grammar)
{
- TEST(Should parse basic module syntax)
- {
- parse_module("Empty", "module Empty");
- parse_module("ModA", "module ModA import ModB");
- parse_module("ModA", "module ModA const FOO = 42");
- parse_module("ModA", "module ModA var foo : Int");
- }
-
- TEST(Should parse imports)
- {
- parse_rule(import_list, 0, "import A;");
- parse_rule(import_list, 0, "import A = ModA;");
- parse_rule(import_list, 0, "import A, B;");
- parse_rule(import_list, 0, "import A, B = ModB, C;");
- }
-
- TEST(Should parse constant declarations and expressions)
- {
- parse_rule(const_decl, 0, "FOO = 123");
- parse_rule(const_decl, 0, "FOO = 123.123");
- parse_rule(const_decl, 0, "FOO = \"\"");
- parse_rule(const_decl, 0, "FOO = true");
- parse_rule(const_decl, 0, "FOO = false");
-// parse_rule(const_decl, 0, "FOO = nil");
- parse_rule(const_decl, 0, "FOO = not true");
- parse_rule(const_decl, 0, "FOO = (not false)");
- parse_rule(const_decl, 0, "FOO = +1");
- parse_rule(const_decl, 0, "FOO = -1");
- parse_rule(const_decl, 0, "FOO = +1.0");
- parse_rule(const_decl, 0, "FOO = -1.0");
- parse_rule(const_decl, 0, "FOO = 1 + 2");
- parse_rule(const_decl, 0, "FOO = 1.0 + 2.0");
- parse_rule(const_decl, 0, "FOO = 1 - 2");
- parse_rule(const_decl, 0, "FOO = 1.0 - 2.0");
- parse_rule(const_decl, 0, "FOO = 3 * 2");
- parse_rule(const_decl, 0, "FOO = 3.0 * 2.0");
- parse_rule(const_decl, 0, "FOO = 4 / 2");
- parse_rule(const_decl, 0, "FOO = 3.0 / 4.0");
- parse_rule(const_decl, 0, "FOO = 5 % 3");
- parse_rule(const_decl, 0, "FOO = 5 == 3");
- parse_rule(const_decl, 0, "FOO = 5 != 3");
- parse_rule(const_decl, 0, "FOO = 5 < 3");
- parse_rule(const_decl, 0, "FOO = 5 <= 3");
- parse_rule(const_decl, 0, "FOO = 5 > 3");
- parse_rule(const_decl, 0, "FOO = 5 >= 3");
- parse_rule(const_decl, 0, "FOO = 5, BAR = FOO - 3");
- }
-
- TEST(Should parse module level type declarations)
- {
- parse_rule(type_decl, 0, "a = Int");
- parse_rule(type_decl, 0, "a = Real");
- parse_rule(type_decl, 0, "a = Bool");
- parse_rule(type_decl, 0, "a = array 42 of Int");
- parse_rule(type_decl, 0, "a = array 42 of array 42 of Int");
- parse_rule(type_decl, 0, "a = record end");
- }
-
- TEST(Should parse module level variable declarations)
- {
- parse_rule(var_decl, 0, "i : Int");
- parse_rule(var_decl, 0, "i : Real");
- parse_rule(var_decl, 0, "i : Bool");
-// parse_rule(var_decl, 0, "x,y,z : Int");
- }
-
- TEST(Should parse module level procedure declarations)
- {
- parse_rule(proc_decl, 0,
- "procedure Foo*() : Int\n"
- "begin\n"
- " return 1;\n"
- "end"
- );
- }
+// TEST(Should parse basic module syntax)
+// {
+// parse_module("Empty", "module Empty");
+// parse_module("ModA", "module ModA import ModB");
+// parse_module("ModA", "module ModA const FOO = 42");
+// parse_module("ModA", "module ModA var foo : Int");
+// }
+//
+// TEST(Should parse imports)
+// {
+// parse_rule(import_list, 0, "import A;");
+// parse_rule(import_list, 0, "import A = ModA;");
+// parse_rule(import_list, 0, "import A, B;");
+// parse_rule(import_list, 0, "import A, B = ModB, C;");
+// }
+//
+// TEST(Should parse constant declarations and expressions)
+// {
+// parse_rule(const_decl, 0, "FOO = 123");
+// parse_rule(const_decl, 0, "FOO = 123.123");
+// parse_rule(const_decl, 0, "FOO = \"\"");
+// parse_rule(const_decl, 0, "FOO = true");
+// parse_rule(const_decl, 0, "FOO = false");
+//// parse_rule(const_decl, 0, "FOO = nil");
+// parse_rule(const_decl, 0, "FOO = not true");
+// parse_rule(const_decl, 0, "FOO = (not false)");
+// parse_rule(const_decl, 0, "FOO = +1");
+// parse_rule(const_decl, 0, "FOO = -1");
+// parse_rule(const_decl, 0, "FOO = +1.0");
+// parse_rule(const_decl, 0, "FOO = -1.0");
+// parse_rule(const_decl, 0, "FOO = 1 + 2");
+// parse_rule(const_decl, 0, "FOO = 1.0 + 2.0");
+// parse_rule(const_decl, 0, "FOO = 1 - 2");
+// parse_rule(const_decl, 0, "FOO = 1.0 - 2.0");
+// parse_rule(const_decl, 0, "FOO = 3 * 2");
+// parse_rule(const_decl, 0, "FOO = 3.0 * 2.0");
+// parse_rule(const_decl, 0, "FOO = 4 / 2");
+// parse_rule(const_decl, 0, "FOO = 3.0 / 4.0");
+// parse_rule(const_decl, 0, "FOO = 5 % 3");
+// parse_rule(const_decl, 0, "FOO = 5 == 3");
+// parse_rule(const_decl, 0, "FOO = 5 != 3");
+// parse_rule(const_decl, 0, "FOO = 5 < 3");
+// parse_rule(const_decl, 0, "FOO = 5 <= 3");
+// parse_rule(const_decl, 0, "FOO = 5 > 3");
+// parse_rule(const_decl, 0, "FOO = 5 >= 3");
+// parse_rule(const_decl, 0, "FOO = 5, BAR = FOO - 3");
+// }
+//
+// TEST(Should parse module level type declarations)
+// {
+// parse_rule(type_decl, 0, "a = Int");
+// parse_rule(type_decl, 0, "a = Real");
+// parse_rule(type_decl, 0, "a = Bool");
+// parse_rule(type_decl, 0, "a = array 42 of Int");
+// parse_rule(type_decl, 0, "a = array 42 of array 42 of Int");
+// parse_rule(type_decl, 0, "a = record end");
+// }
+//
+// TEST(Should parse module level variable declarations)
+// {
+// parse_rule(var_decl, 0, "i : Int");
+// parse_rule(var_decl, 0, "i : Real");
+// parse_rule(var_decl, 0, "i : Bool");
+//// parse_rule(var_decl, 0, "x,y,z : Int");
+// }
+//
+// TEST(Should parse module level procedure declarations)
+// {
+// parse_rule(proc_decl, 0,
+// "procedure Foo*() : Int\n"
+// "begin\n"
+// " return 1;\n"
+// "end"
+// );
+// }
}
#endif