void codegen_setint(Item* item, Type* type, long long val)
{
- if (type == &BoolType)
- printf("%s ", val ? "true" : "false");
- else
- printf("%lld ", val);
-
item->mode = ITEM_CONST;
item->type = type;
item->imm.i = val;
void codegen_setreal(Item* item, double val)
{
- printf("%f ", val);
-
item->mode = ITEM_CONST;
item->type = &RealType;
item->imm.f = val;
void codegen_setstr(Item* item, char* val)
{
- printf("'%s' ", val);
-
item->mode = ITEM_CONST;
item->type = &StringType;
item->imm.s = val;
}
-/* I do not "get" this code
- PROCEDURE MakeConstItem*(VAR x: Item; typ: Type; val: LONGINT);
- BEGIN
- x.mode := Const;
- x.type := typ;
- x.a := val
- END MakeConstItem;
-
- PROCEDURE negated(cond: LONGINT): LONGINT;
- BEGIN
- IF cond < 8 THEN
- cond := cond+8
- ELSE
- cond := cond-8
- END ;
- RETURN cond
- END negated;
-
- PROCEDURE Not*(VAR x: Item); (* x := ~x *)
- VAR t: LONGINT;
- BEGIN
- IF x.mode # Cond THEN loadCond(x) END ;
- x.r := negated(x.r);
- t := x.a;
- x.a := x.b;
- x.b := t
- END Not;
-
-
- PROCEDURE MulOp*(VAR x, y: Item); (* x := x * y *)
- BEGIN
- IF (x.mode = Const) & (y.mode = Const) THEN
- x.a := x.a * y.a
- ELSIF (y.mode = Const) & (y.a = 2) THEN
- load(x);
- Put1(Lsl, x.r, x.r, 1)
- ELSIF y.mode = Const THEN
- load(x);
- Put1(Mul, x.r, x.r, y.a)
- ELSIF x.mode = Const THEN
- load(y);
- Put1(Mul, y.r, y.r, x.a);
- x.mode := Reg;
- x.r := y.r
- ELSE
- load(x);
- load(y);
- Put0(Mul, RH-2, x.r, y.r);
- DEC(RH);
- x.r := RH-1
- END
- END MulOp;
-
-*/
-
static int items_const(Item* a, Item* b)
{
return ((a->mode == ITEM_CONST) && (b->mode == ITEM_CONST));
case AND: a->imm.i = a->imm.i && b->imm.i; break;
case OR: a->imm.i = a->imm.i || b->imm.i; break;
- case EQ:
- a->imm.i = a->imm.i == b->imm.i;
+ case EQ:
+ a->imm.i = a->imm.i == b->imm.i;
a->type = &BoolType;
break;
case NEQ:
- a->imm.i = a->imm.i != b->imm.i;
+ a->imm.i = a->imm.i != b->imm.i;
a->type = &BoolType;
break;
case '<':
- a->imm.i = a->imm.i < b->imm.i;
+ 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->imm.i = a->imm.i <= b->imm.i;
a->type = &BoolType;
break;
case '>':
- a->imm.i = a->imm.i > b->imm.i;
+ 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->imm.i = a->imm.i >= b->imm.i;
a->type = &BoolType;
break;
// case IS: break;
- default:
- assert(!"not a valid op");
+ default:
+ assert(!"not a valid op");
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;
+ 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->imm.f = a->imm.f != b->imm.f;
a->type = &BoolType;
break;
case '<':
- a->imm.f = a->imm.f < b->imm.f;
+ 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->imm.f = a->imm.f <= b->imm.f;
a->type = &BoolType;
break;
case '>':
- a->imm.f = a->imm.f > b->imm.f;
+ 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->imm.f = a->imm.f >= b->imm.f;
a->type = &BoolType;
break;
- default:
- assert(!"not a valid op");
+ default:
+ assert(!"not a valid op");
break;
}
}
assert(!"not supported");
}
}
+
+void codegen_startproc(long long localsz)
+{
+ printf(" pushq rbp\n");
+ printf(" movq rsp, rbp\n");
+ printf(" sub $%lld, rsp\n", localsz);
+}
+
+void codegen_endproc(void)
+{
+ printf(" pop rbp");
+ printf(" ret");
+}
void name(Parser* p, Item* item)
#endif
+/* Default Symbols
+ *****************************************************************************/
+static Symbol BoolSym = {
+ .class = SYM_TYPE,
+ .name = "Bool",
+ .type = &BoolType
+};
+
+static Symbol IntSym = {
+ .next = &BoolSym,
+ .class = SYM_TYPE,
+ .name = "Int",
+ .type = &IntType
+};
+
+static Symbol RealSym = {
+ .next = &IntSym,
+ .class = SYM_TYPE,
+ .name = "Real",
+ .type = &RealType
+};
+
/* Parsing Routines
*****************************************************************************/
static Tok* peek(Parser* p)
/* Grammar Definition
*****************************************************************************/
-void module(Parser* p, Item* item);
-void import_list(Parser* p, Item* item);
-void declaration_seq(Parser* p, Item* item);
-void statement_seq(Parser* p, Item* item);
-void const_decl(Parser* p, Item* item);
-void expression(Parser* p, Item* item);
-void simple_expr(Parser* p, Item* item);
-void term(Parser* p, Item* item);
-void factor(Parser* p, Item* item);
-void designator(Parser* p, Item* item);
-void qualident(Parser* p, Item* item);
-void expr_list(Parser* p, Item* item);
-RULE(module)
-{
- expect(p, MODULE);
- char* sname = expect_text(p, IDENT);
- /* TODO: Check that it matches filename here */
- expect(p, ';');
- if (matches(p, IMPORT))
- {
- import_list(p, item);
- }
- declaration_seq(p, item);
- if (accept(p, BEGIN))
- {
- statement_seq(p, item);
- }
- expect(p, END);
- char* ename = expect_text(p, IDENT);
- if (strcmp(sname, ename))
- {
- error(p, "Expected module name '%s', recieved '%s' instead", sname, ename);
- }
- expect(p, ';');
-}
+static void expression(Parser* p, Item* item);
-RULE(import_list)
-{
- (void)item;
- expect(p, IMPORT);
- while (1)
- {
- expect(p, IDENT);
- if (accept(p, '='))
- {
- expect(p, IDENT);
- }
- if (matches(p, ';'))
- {
- break;
- }
- expect(p, ',');
- }
- expect(p, ';');
-}
+//RULE(expr_list)
+//{
+// while (1)
+// {
+// expression(p);
+// if (!accept(p, ','))
+// {
+// break;
+// }
+// }
+//}
-RULE(declaration_seq)
+RULE(qualident)
{
- if (accept(p, CONST))
- {
- const_decl(p, item);
- expect(p, ';');
- }
- if (accept(p, TYPE))
- {
-// type_decl(p, item);
- expect(p, ';');
- }
- if (accept(p, VAR))
+ char* name = expect_text(p, IDENT);
+ Symbol* sym = symbol_get(p, name);
+
+ if (sym->class == SYM_CONST)
{
-// var_decl(p, item);
- expect(p, ';');
+ item->mode = ITEM_CONST;
+ item->imm = sym->imm;
}
+// if (accept(p, '.'))
+// {
+// expect(p, IDENT);
+// }
}
-RULE(statement_seq)
+RULE(designator)
{
- (void)p, (void)item;
+ qualident(p, item);
+// /* selector */
+// switch ((int)peek(p)->type)
+// {
+// case '.':
+// expect(p, IDENT);
+// break;
+//
+// case '[':
+// expr_list(p);
+// expect(p, ']');
+// break;
+//
+// case '^':
+// expect(p, '^');
+// break;
+//
+// case '(':
+// qualident(p);
+// expect(p, ')');
+// break;
+// }
}
-RULE(const_decl)
+RULE(factor)
{
-/*
- VAR
- obj, first: OSG.Object;
- x: OSG.Item;
- tp: OSG.Type;
- L: LONGINT;
-
- (* ... *)
-
- WHILE sym = OSS.ident DO
- NewObj(obj, OSG.Const);
- OSS.Get(sym);
- IF sym = OSS.eql THEN
- OSS.Get(sym)
- ELSE
- OSS.Mark("=?")
- END;
- expression(x);
- IF x.mode = OSG.Const THEN
- obj.val := x.a;
- obj.type := x.type
- ELSE
- OSS.Mark("expression not constant")
- END ;
- Check(OSS.semicolon, "; expected")
- END
-*/
+ switch ((int)peek(p)->type)
+ {
+ case INT:
+ codegen_setint(item, &IntType, peek(p)->value.integer);
+ consume(p);
+ break;
+ case REAL:
+ codegen_setreal(item, peek(p)->value.floating);
+ consume(p);
+ break;
- while (1)
- {
- char* name = NULL;
- bool export = false;
- Symbol* sym = NULL;
+ case STRING:
+ codegen_setstr(item, peek(p)->text);
+ consume(p);
+ break;
- name = expect_text(p, IDENT);
- export = accept(p, '*');
- sym = symbol_new(p, name, SYM_CONST, export);
- expect(p, '=');
- expression(p, item);
+// case NIL:
+// codegen_nil(item);
+// consume(p);
+// break;
- sym->imm = item->imm;
- (void)sym;
+ case BOOL:
+ codegen_setint(item, &BoolType, peek(p)->value.integer);
+ consume(p);
+ break;
- 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);
- }
+ case '(':
+ expect(p, '(');
+ expression(p, item);
+ expect(p, ')');
+ break;
- if (!accept(p, ','))
- {
+ case NOT:
+ consume(p);
+ factor(p, item);
+ check_bool(p, item);
+ codegen_unop(NOT, item);
+ break;
+
+ case IDENT:
+ designator(p, item);
+// actual_params(p);
break;
- }
}
}
-RULE(expression)
+RULE(term)
{
- // expression = SimpleExpression [relation SimpleExpression].
- // relation = "=" | "!=" | "<" | "<=" | ">" | ">=" | "is".
+ factor(p, item);
- int ops[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 };
- simple_expr(p, item);
- if (matches_oneof(p, ops))
+ while (matches_oneof(p, (int[]){'*', '/', '%', AND, 0}))
{
Item right = { 0 };
int op = consume(p);
- simple_expr(p, &right);
- check_num2(p, item, &right);
- codegen_binop(op, item, &right);
+ factor(p, &right);
+ switch(op)
+ {
+ case '*':
+ case '/':
+ case '%':
+ check_num2(p, item, &right);
+ codegen_binop(op, item, &right);
+ break;
+
+ case AND:
+ check_bool2(p, item, &right);
+ codegen_binop(op, item, &right);
+ break;
+
+ default:
+ assert(!"not supported");
+ break;
+ }
}
}
RULE(simple_expr)
{
- // SimpleExpression = ["+" | "-"] term {AddOperator term}.
- // AddOperator = "+" | "-" | "or".
-
/* first term and +/- */
if (matches_oneof(p, (int[]){'+', '-', 0}))
{
}
}
-RULE(term)
+RULE(expression)
{
- // term = factor {MulOperator factor}.
- // MulOperator = "*" | "/" | "and".
- factor(p, item);
- while (matches_oneof(p, (int[]){'*', '/', '%', AND, 0}))
+ int ops[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 };
+ simple_expr(p, item);
+ if (matches_oneof(p, ops))
{
Item right = { 0 };
int op = consume(p);
- factor(p, &right);
- switch(op)
- {
- case '*':
- check_num2(p, item, &right);
- codegen_binop(op, item, &right);
- break;
-
- case '/':
- check_num2(p, item, &right);
- codegen_binop(op, item, &right);
- break;
-
- case '%':
- check_int2(p, item, &right);
- codegen_binop(op, item, &right);
- break;
-
- case AND:
- check_bool2(p, item, &right);
- codegen_binop(op, item, &right);
- break;
-
- default:
- assert(!"not supported");
- break;
- }
+ simple_expr(p, &right);
+ check_num2(p, item, &right);
+ codegen_binop(op, item, &right);
}
}
-/*
-factor = number
- | string
- | "nil"
- | "true"
- | "false"
- | designator [ActualParameters]
- | "(" expression ")"
- | "not" factor.
-*/
-
-RULE(factor)
+RULE(var_decl)
{
- switch ((int)peek(p)->type)
- {
- case INT:
- codegen_setint(item, &IntType, peek(p)->value.integer);
- consume(p);
- break;
-
- case REAL:
- codegen_setreal(item, peek(p)->value.floating);
- consume(p);
- break;
-
- case STRING:
- codegen_setstr(item, peek(p)->text);
- consume(p);
- break;
-
-// case NIL:
-// codegen_nil(item);
-// consume(p);
-// break;
+ (void)p, (void)item;
+}
- case BOOL:
- codegen_setint(item, &BoolType, peek(p)->value.integer);
- consume(p);
- break;
+RULE(type_decl)
+{
+ (void)p, (void)item;
+}
- case '(':
- expect(p, '(');
- expression(p, item);
- expect(p, ')');
- break;
+RULE(const_decl)
+{
+ while (1)
+ {
+ char* name = NULL;
+ bool export = false;
+ Symbol* sym = NULL;
- case NOT:
- consume(p);
- factor(p, item);
- check_bool(p, item);
- codegen_unop(NOT, item);
- break;
+ name = expect_text(p, IDENT);
+ export = accept(p, '*');
+ sym = symbol_new(p, name, SYM_CONST, export);
+ expect(p, '=');
+ expression(p, item);
+ sym->imm = item->imm;
- case IDENT:
- designator(p, item);
-// actual_params(p);
+ if (!accept(p, ','))
+ {
break;
+ }
}
}
-/*
- designator = qualident {selector}.
- selector = "." ident | "[" ExpList "]" | "^" | "(" qualident ")".
- ExpList = expression {"," expression}.
- qualident = [ident "."] ident.
+RULE(statement_seq)
+{
+ (void)p, (void)item;
+}
- ActualParameters = "(" [ExpList] ")" .
-*/
-RULE(designator)
+RULE(declaration_seq)
{
- qualident(p, item);
-// /* selector */
-// switch ((int)peek(p)->type)
-// {
-// case '.':
-// expect(p, IDENT);
-// break;
-//
-// case '[':
-// expr_list(p);
-// expect(p, ']');
-// break;
-//
-// case '^':
-// expect(p, '^');
-// break;
-//
-// case '(':
-// qualident(p);
-// expect(p, ')');
-// break;
-// }
+ if (accept(p, CONST))
+ {
+ const_decl(p, item);
+ expect(p, ';');
+ }
+ if (accept(p, TYPE))
+ {
+// type_decl(p, item);
+ expect(p, ';');
+ }
+ if (accept(p, VAR))
+ {
+// var_decl(p, item);
+ expect(p, ';');
+ }
}
-RULE(qualident)
+RULE(import_list)
{
- char* name = expect_text(p, IDENT);
- Symbol* sym = symbol_get(p, name);
+ (void)item;
+ expect(p, IMPORT);
+ while (1)
+ {
+ expect(p, IDENT);
+ if (accept(p, '='))
+ {
+ expect(p, IDENT);
+ }
+ if (matches(p, ';'))
+ {
+ break;
+ }
+ expect(p, ',');
+ }
+ expect(p, ';');
+}
- if (sym->class == SYM_CONST)
+RULE(module)
+{
+ expect(p, MODULE);
+ char* sname = expect_text(p, IDENT);
+ /* TODO: Check that it matches filename here */
+ expect(p, ';');
+ if (matches(p, IMPORT))
{
- item->mode = ITEM_CONST;
- item->imm = sym->imm;
+ import_list(p, item);
}
-// if (accept(p, '.'))
-// {
-// expect(p, IDENT);
-// }
+ declaration_seq(p, item);
+ if (accept(p, BEGIN))
+ {
+ codegen_startproc(0);
+ statement_seq(p, item);
+ codegen_endproc();
+ }
+ expect(p, END);
+ char* ename = expect_text(p, IDENT);
+ if (strcmp(sname, ename))
+ {
+ error(p, "Expected module name '%s', recieved '%s' instead", sname, ename);
+ }
+ expect(p, ';');
}
-//
-//RULE(expr_list)
-//{
-// while (1)
-// {
-// expression(p);
-// if (!accept(p, ','))
-// {
-// break;
-// }
-// }
-//}
/* Grammar Unit Tests
*****************************************************************************/
Parser Ctx = {0};
-void parse_init(char* fname, char* string)
+static void parse_init(char* fname, char* string)
{
memset(&Ctx, 0, sizeof(Ctx));
+ Ctx.scope = &RealSym;
LexFile* file = calloc(sizeof(LexFile), 1u);
file->path = strdup(fname);
file->fbeg = file->fpos = strdup(string);