item->mode = ITEM_CONST;
item->type = &RealType;
- item->imm.i = val;
+ item->imm.f = val;
}
void codegen_setstr(Item* item, char* val)
*/
-void codegen_not(Item* item)
+static int items_const(Item* a, Item* b)
{
- if (item->mode == ITEM_CONST)
- {
- item->imm.i = !item->imm.i;
- }
- else
- {
- assert(!"not implemented");
- }
+ return ((a->mode == ITEM_CONST) && (b->mode == ITEM_CONST));
}
-void codegen_add(Item* a, Item* b)
+static void const_binop(int op, Item* a, Item* b)
{
- (void)a, (void)b;
- assert(!"not implemented");
-}
+ if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
+ {
+ switch (op)
+ {
+ case '+': a->imm.i = a->imm.i + b->imm.i; break;
+ case '-': a->imm.i = a->imm.i - b->imm.i; break;
+ case '*': a->imm.i = a->imm.i * b->imm.i; break;
+ case '/': a->imm.i = a->imm.i / b->imm.i; break;
+ case '%': a->imm.i = a->imm.i % b->imm.i; break;
+ case AND: a->imm.i = a->imm.i && b->imm.i; break;
+ case OR: a->imm.i = a->imm.i || b->imm.i; break;
-void codegen_sub(Item* a, Item* b)
-{
- (void)a, (void)b;
- assert(!"not implemented");
-}
+ case EQ:
+ a->imm.i = a->imm.i == b->imm.i;
+ a->type = &BoolType;
+ break;
-void codegen_imul(Item* a, Item* b)
-{
- if ((b->mode == ITEM_CONST) && (b->mode == ITEM_CONST))
+ case NEQ:
+ a->imm.i = a->imm.i != b->imm.i;
+ a->type = &BoolType;
+ break;
+
+ case '<':
+ a->imm.i = a->imm.i < b->imm.i;
+ a->type = &BoolType;
+ break;
+
+ case LTEQ:
+ a->imm.i = a->imm.i <= b->imm.i;
+ a->type = &BoolType;
+ break;
+
+ case '>':
+ a->imm.i = a->imm.i > b->imm.i;
+ a->type = &BoolType;
+ break;
+
+ case GTEQ:
+ a->imm.i = a->imm.i >= b->imm.i;
+ a->type = &BoolType;
+ break;
+
+// case IS: break;
+
+ default:
+ assert(!"not a valid op");
+ break;
+ }
+ }
+ else if (a->type->form == FORM_REAL)
{
- a->imm.i = a->imm.i * b->imm.i;
+ switch (op)
+ {
+ case '+': a->imm.f = a->imm.f + b->imm.f; break;
+ case '-': a->imm.f = a->imm.f - b->imm.f; break;
+ case '*': a->imm.f = a->imm.f * b->imm.f; break;
+ case '/': a->imm.f = a->imm.f / b->imm.f; break;
+
+ case EQ:
+ a->imm.f = a->imm.f == b->imm.f;
+ a->type = &BoolType;
+ break;
+
+ case NEQ:
+ a->imm.f = a->imm.f != b->imm.f;
+ a->type = &BoolType;
+ break;
+
+ case '<':
+ a->imm.f = a->imm.f < b->imm.f;
+ a->type = &BoolType;
+ break;
+
+ case LTEQ:
+ a->imm.f = a->imm.f <= b->imm.f;
+ a->type = &BoolType;
+ break;
+
+ case '>':
+ a->imm.f = a->imm.f > b->imm.f;
+ a->type = &BoolType;
+ break;
+
+ case GTEQ:
+ a->imm.f = a->imm.f >= b->imm.f;
+ a->type = &BoolType;
+ break;
+
+ default:
+ assert(!"not a valid op");
+ break;
+ }
}
else
{
- assert(!"not implemented");
+ assert(!"not a valid form");
}
}
-void codegen_fmul(Item* a, Item* b)
+static void const_unop(int op, Item* a)
{
- if ((b->mode == ITEM_CONST) && (b->mode == ITEM_CONST))
+ if (a->type->form == FORM_INT)
+ {
+ switch (op)
+ {
+ case '+': a->imm.i = +a->imm.i; break;
+ case '-': a->imm.i = -a->imm.i; break;
+ default: assert(!"not a valid op"); break;
+ }
+ }
+ else if (a->type->form == FORM_REAL)
+ {
+ switch (op)
+ {
+ case '+': a->imm.f = +a->imm.f; break;
+ case '-': a->imm.f = -a->imm.f; break;
+ default: assert(!"not a valid op"); break;
+ }
+ }
+ else if (a->type->form == FORM_BOOL)
{
- a->imm.f = a->imm.f * b->imm.f;
+ switch (op)
+ {
+ case NOT: a->imm.i = !a->imm.i; break;
+ default: assert(!"not a valid op"); break;
+ }
}
else
{
- assert(!"not implemented");
+ assert(!"not a valid form");
}
}
-void codegen_mul(Item* a, Item* b)
+void codegen_unop(int op, Item* a)
{
- if (a->type->form == FORM_REAL)
+ if (a->mode == ITEM_CONST)
{
- codegen_fmul(a,b);
+ const_unop(op, a);
}
else
{
- codegen_imul(a,b);
+ assert(!"not supported");
}
}
-void codegen_div(Item* a, Item* b)
+void codegen_binop(int op, Item* a, Item* b)
{
- (void)a, (void)b;
- assert(!"not implemented");
-}
-
-void codegen_mod(Item* a, Item* b)
-{
- (void)a, (void)b;
- assert(!"not implemented");
+ if (items_const(a, b))
+ {
+ const_binop(op, a, b);
+ }
+ else
+ {
+ assert(!"not supported");
+ }
}
*****************************************************************************/
static Symbol* symbol_new(Parser* p, char* name, int class, bool export)
{
- (void)p, (void)name, (void)class, (void)export;
- return NULL;
+ Symbol* sym = calloc(1, sizeof(Symbol));
+ sym->name = name;
+ sym->class = class;
+ sym->export = export;
+ sym->next = p->scope;
+ p->scope = sym;
+ return sym;
}
/* Type Checking
check_real(p, b);
}
+static void check_num(Parser* p, Item* a)
+{
+ if (a->type->form == FORM_REAL)
+ {
+ check_real(p, a);
+ }
+ else
+ {
+ check_int(p, a);
+ }
+}
+
static void check_num2(Parser* p, Item* a, Item* b)
{
if (a->type->form == FORM_REAL)
}
}
+static void check_bool2(Parser* p, Item* a, Item* b)
+{
+ check_bool(p, a);
+ check_bool(p, b);
+}
+
/* Grammar Definition
*****************************************************************************/
void module(Parser* p, Item* item);
sym = symbol_new(p, name, SYM_CONST, export);
expect(p, '=');
expression(p, item);
- printf("-> %s\n", name);
+
+ sym->imm = item->imm;
+ (void)sym;
+
+ if (item->type->form == FORM_REAL)
+ {
+ printf("-> %s = R %f\n", name, item->imm.f);
+ }
+ else if (item->type->form == FORM_INT)
+ {
+ printf("-> %s = I %lld\n", name, item->imm.i);
+ }
+ else if (item->type->form == FORM_BOOL)
+ {
+ printf("-> %s = B %lld\n", name, item->imm.i);
+ }
+ else if (item->type->form == FORM_STRING)
+ {
+ printf("-> %s = S '%s'\n", name, item->imm.s);
+ }
if (!accept(p, ','))
{
simple_expr(p, item);
if (matches_oneof(p, ops))
{
- consume(p);
- simple_expr(p, item);
+ Item right = { 0 };
+ int op = consume(p);
+ simple_expr(p, &right);
+ check_num2(p, item, &right);
+ codegen_binop(op, item, &right);
}
}
{
int op = consume(p); // OP
term(p, item);
+ check_num(p, item);
+ codegen_unop(op, item);
}
else
{
/* optional second term and op */
while (matches_oneof(p, (int[]){'+', '-', OR, 0}))
{
+ Item right = { 0 };
int op = consume(p);
- term(p, item);
+ term(p, &right);
+ if (op == OR)
+ {
+ check_bool2(p, item, &right);
+ }
+ else
+ {
+ check_num2(p, item, &right);
+ }
+ codegen_binop(op, item, &right);
}
}
{
case '*':
check_num2(p, item, &right);
- codegen_mul(item, &right);
+ codegen_binop(op, item, &right);
break;
case '/':
check_num2(p, item, &right);
- codegen_div(item, &right);
+ codegen_binop(op, item, &right);
break;
case '%':
check_int2(p, item, &right);
- codegen_mod(item, &right);
+ codegen_binop(op, item, &right);
break;
case AND:
-// check_bool2(p, item, &right);
-// codegen_and(item, &right);
-// break;
+ check_bool2(p, item, &right);
+ codegen_binop(op, item, &right);
+ break;
default:
assert(!"not supported");
consume(p);
factor(p, item);
check_bool(p, item);
- codegen_not(item);
+ codegen_unop(NOT, item);
break;
//
// case IDENT:
"FOO = true");
parse_rule(const_decl, 0,
"FOO = false");
- parse_rule(const_decl, 0,
- "FOO = nil");
+// parse_rule(const_decl, 0,
+// "FOO = nil");
parse_rule(const_decl, 0,
"FOO = not true");
parse_rule(const_decl, 0,
parse_rule(const_decl, 0,
"FOO = 1.0 - 2.0");
parse_rule(const_decl, 0,
- "FOO = 1 * 2");
+ "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 = 1.0 * 2.0");
+ "FOO = 5 < 3");
parse_rule(const_decl, 0,
- "FOO = 1 / 2");
+ "FOO = 5 <= 3");
parse_rule(const_decl, 0,
- "FOO = 1.0 / 2.0");
+ "FOO = 5 > 3");
parse_rule(const_decl, 0,
- "FOO = 1 % 2");
+ "FOO = 5 >= 3");
}
}
#endif