commit 33306912a82cb2efdc93b2e25d84704c085100e3
parent 55b25c1c04fc252550bfdb1dc5da808f8fb14fab
Author: m21c <ho*******@gmail.com>
Date: Fri, 2 Apr 2021 23:17:36 +0200
implemented printexpr() + worked on type-checking
Diffstat:
| M | aria.c | | | 378 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
1 file changed, 347 insertions(+), 31 deletions(-)
diff --git a/aria.c b/aria.c
@@ -267,6 +267,7 @@ typedef enum Kind {
/* Ast */
ASTMT, ADO, ADECL, ADECLREF, ALOOP, ALOOPUNTIL, AWHILE, AFOR, ACONTINUE,
ABREAK, ASCOPE, ARETURN, AGOTO, ALABEL, AIF, ASWITCH, ACASE,
+ ACONV,
MAXKINDS
} Kind;
@@ -279,6 +280,12 @@ typedef enum Kind {
#define isoperator(kind) ((kind) >= OSTART && (kind) < ASTART)
#define isastnode(kind) ((kind) >= ASTART && (kind) < MAXKINDS)
+bool isatomnode(Kind kind)
+{
+ return kind == 'I' || kind == ADECLREF || kind == 'N' || kind == 'S' ||
+ kind == 'C';
+}
+
int keywordlengths[OSTART - KSTART];
const int keywordtypeids[] = {
@@ -348,14 +355,14 @@ const char *nodestrings[] = {
[KFOR] = "for", [KLOOP] = "loop",
[KWHILE] = "while", [KUNTIL] = "until",
/* Operators */
- [OSUFINC] = "unary++", [OSUFDEC] = "unary--",
- [OARRAY] = "unary[]", [OCALL] = "unary()",
- [ODISP] = "unary._",
- [ODEREF] = "*unary", [OINC] = "++unary",
- [ODEC] = "--unary", [OBNOT] = "~unary",
- [OLNOT] = "!unary", [OFLIP] = "~=unary",
- [OADDR] = "&unary", [OPLUS] = "+unary",
- [OMINUS] = "-unary", [OCAST] = "(type) unary",
+ [OSUFINC] = "++", [OSUFDEC] = "--",
+ [OARRAY] = "[]", [OCALL] = "()",
+ [ODISP] = ".",
+ [ODEREF] = "*", [OINC] = "++",
+ [ODEC] = "--", [OBNOT] = "~",
+ [OLNOT] = "!", [OFLIP] = "~=",
+ [OADDR] = "&", [OPLUS] = "+",
+ [OMINUS] = "-", [OCAST] = "(type)",
[OMUL] = "*", [ODIV] = "/",
[OMOD] = "%", [OLSH] = "<<",
[OARSH] = ">>>", [ORSH] = ">>",
@@ -385,6 +392,7 @@ const char *nodestrings[] = {
[AGOTO] = "goto-statement", [ALABEL] = "label",
[AIF] = "if-clause", [ASWITCH] = "case-clause",
[ACASE] = "of-clause",
+ [ACONV] = "conversion",
[MAXKINDS] = NULL
};
@@ -467,7 +475,7 @@ const uint8_t opinfo[] = {
#define getnumops(kind) (opinfo[kind] >> 6)
#define israssoc(kind) ((opinfo[kind] >> 5) & 0x01)
-#define getprec(kind) ((opinfo[kind] & 0x2f))
+#define getprec(kind) ((opinfo[kind] & 0x1f))
#define lengthof(array) ((int) sizeof(array) / (int) sizeof(*(array)))
@@ -1335,7 +1343,12 @@ printast(Node *node, int indent) {
assert(node);
if (node->kind >= OSTART && node->kind != ADECLREF)
- n += printf("%s(", nodestrings[node->kind]);
+ if (getprec(node->kind) == PUNSUF)
+ n += printf("unary%s(", nodestrings[node->kind]);
+ else if (getprec(node->kind) == PUNARY)
+ n += printf("%sunary(", nodestrings[node->kind]);
+ else
+ n += printf("%s(", nodestrings[node->kind]);
else
printnode(stdout, node);
@@ -2073,6 +2086,13 @@ conv(Node *node)
Node *
wrap(Type *ty, Node *node)
{
+ if (node->type && ty->kind == node->type->kind)
+ return node;
+ if (node->kind == 'N')
+ return node->type = ty, node;
+ node = makenode(node);
+ node->kind = ACONV;
+ node->type = ty;
return node;
}
@@ -2082,31 +2102,63 @@ usualarithconv(Type *lt, Type *rt)
return lt;
}
-#if 0
-
typedef
Node *(*RuleFunc)(Node *expr);
Node *
-emptyrule(Node *expr)
-{
- return expr;
-}
+foldexpr(Node *expr);
Node *
identrule(Node *ident)
{
- ident->u.declref.ref = finddeclaration(ident->u.id);
- if (ident->u.declref.ref) {
- ident->kind = 'A';
- ident->u.declref.id = ADECLREF;
+ Decl *declref = finddeclaration(ident->u.key);
+
+ if (declref) {
+ ident->kind = ADECLREF;
+ ident->u.declref = declref;
} else {
- error("'%s' undeclared", getstring(idents, ident->u.id));
+ error("'%s' undeclared", getstring(idents, ident->u.key));
}
return ident;
}
+Node *
+binaryarithrule(Node *binary)
+{
+ Node *lhs = binary->lhs;
+ Node *rhs = binary->rhs;
+ Type *tt;
+
+ if (!lhs) return binary;
+ if (!rhs) return binary;
+
+ lhs = foldexpr(lhs);
+ rhs = foldexpr(rhs);
+ tt = usualarithconv(lhs->type, rhs->type);
+ lhs = wrap(tt, lhs);
+ rhs = wrap(tt, rhs);
+ binary->type = tt;
+
+ binary->lhs = lhs;
+ binary->rhs = rhs;
+ return binary;
+}
+
+RuleFunc ruletable[] = {
+ ['I'] = &identrule,
+
+ [OMUL] = &binaryarithrule,
+ [ODIV] = &binaryarithrule,
+ [OMOD] = &binaryarithrule,
+ [OADD] = &binaryarithrule,
+ [OSUB] = &binaryarithrule,
+
+ [MAXKINDS] = NULL
+};
+
+#if 0
+
RuleFunc opfunctable[] = {
[OSUFINC] = &emptyrule, [OSUFDEC] = &emptyrule,
[OARRAY] = &emptyrule, [OCALL] = &emptyrule,
@@ -2179,22 +2231,18 @@ astrules(Node *expr)
return astfunctable[expr->u.id](expr);
}
-RuleFunc ruletable[] = {
- ['A'] = &astrules,
- ['I'] = &identrule,
- ['O'] = &oprules,
-
- [127] = NULL
-};
-
#endif
-Node *foldexpr(Node *expr)
+Node *
+foldexpr(Node *expr)
{
Node *c, *n;
for (c = expr; c; c = c->next) {
-#if 1
+#if 0
+ if (c->kind == ADECL)
+ continue;
+
if (c->kind == 'I') {
Decl *declref = finddeclaration(c->u.key);
if (declref) {
@@ -2231,6 +2279,267 @@ Node *foldexpr(Node *expr)
return expr;
}
+/* - print ast */
+
+int
+printexpr(FILE *out, Node *expr, int indent);
+
+int printtype(FILE *out, Type *type, int indent)
+{
+ int n = 0;
+
+ if (!type)
+ return 0;
+
+ n += printtype(out, type->target, indent);
+
+ switch (type->kind) {
+ case TARRAY:
+ n += fprintf(out, "[");
+ n += printexpr(out, type->u.val, indent);
+ n += fprintf(out, "]");
+ break;
+ #define typecase(type, str) \
+ case type: n += fprintf(out, str); break
+ typecase(TPTR, "*");
+ typecase(TVOID, "void"); typecase(TBOOL, "bool");
+ typecase(TU8, "u8" ); typecase(TS8, "s8" );
+ typecase(TU16, "u16" ); typecase(TS16, "s16" );
+ typecase(TU32, "u32" ); typecase(TS32, "s32" );
+ typecase(TU64, "u64" ); typecase(TS64, "s64" );
+ typecase(TF32, "f32" ); typecase(TF64, "f64" );
+ #undef typecase
+ default:;
+ }
+}
+
+bool
+isclauseorempty(Node *expr)
+{
+ Kind kind;
+
+ while (expr && (expr->kind == ASCOPE || expr->kind == ASTMT))
+ expr = expr->lhs;
+
+ if (!expr)
+ return true;
+
+ kind = expr->kind;
+ return kind == ADO || kind == AIF || kind == AFOR || kind == AGOTO ||
+ kind == ARETURN || kind == ABREAK || kind == ACONTINUE;
+}
+
+int
+printclause(FILE *out, Node *expr, int indent)
+{
+ int n = 0;
+
+ if (isclauseorempty(expr)) {
+ n += fprintf(out, " ");
+ n += printexpr(out, expr, indent);
+ } else {
+ n += fprintf(out, "\n");
+ n += printexpr(out, expr, indent + 1);
+ }
+
+ return n;
+}
+
+int
+printstring(FILE *out, Node *string)
+{
+ const char *str = getstring(strings, string->u.key);
+ int len = getlength(strings, string->u.key);
+ int i, n = fprintf(out, "\"");
+ for (i = 0; i < len; ++i) {
+ switch (str[i]) {
+ case '\\':
+ n += fprintf(out, "\\\\");
+ break;
+ case '\n':
+ n += fprintf(out, "\\n");
+ break;
+ case '\r':
+ n += fprintf(out, "\\r");
+ break;
+ case '\t':
+ n += fprintf(out, "\\t");
+ break;
+ case '\"':
+ n += fprintf(out, "\\\"");
+ break;
+ case '\'':
+ n += fprintf(out, "\\\'");
+ break;
+ case 0:
+ n += fprintf(out, "\\0");
+ break;
+ default:
+ putc(str[i], out);
+ ++n;
+ }
+ }
+ n += fprintf(out, "\"");
+
+}
+
+int
+printoperant(FILE *out, Node *expr, int opprec, bool braceequalprec, int indent)
+{
+ int prec, n = 0;
+
+ if (!expr)
+ return 0;
+
+ prec = getprec(expr->kind);
+ if (expr->next || (
+ !isatomnode(expr->kind) && (
+ !getnumops(expr->kind) || prec < opprec ||
+ (braceequalprec && prec == prec)
+ )
+ )
+ ) {
+ n += fprintf(out, "(");
+ n += printexpr(out, expr, indent);
+ n += fprintf(out, ")");
+ } else {
+ n += printexpr(out, expr, indent);
+ }
+
+ return n;
+}
+
+int
+printexpr(FILE *out, Node *expr, int indent)
+{
+ Node *c;
+ int n = 0;
+
+ for (c = expr; c; c = c->next) {
+ if (c->kind == ASTMT) {
+ int i;
+
+ for (i = 0; i < indent; ++i)
+ n += fprintf(out, "\t");
+ }
+
+ if (getnumops(c->kind) == 2) {
+ n += printoperant(out, c->lhs, getprec(c->kind), israssoc(c->kind), indent);
+ n += printf(" %s ", nodestrings[c->kind]);
+ n += printoperant(out, c->rhs, getprec(c->kind), !israssoc(c->kind), indent);
+ } else if (getnumops(c->kind) == 1) {
+ if (getprec(c->kind) == PUNSUF) {
+ printoperant(out, c->lhs, PUNSUF, false, indent);
+ switch (c->kind) {
+ case OARRAY:
+ case OCALL:
+ n += fprintf(out, "%c", nodestrings[c->kind][0]);
+ n += printexpr(out, c->rhs, indent);
+ n += fprintf(out, "%c", nodestrings[c->kind][1]);
+ break;
+ case ODISP:
+ n += fprintf(out, ".");
+ n += printexpr(out, c->rhs, indent);
+ break;
+ default:
+ n += fprintf(out, "%s", nodestrings[c->kind]);
+ }
+ } else {
+ switch (c->kind) {
+ case OCAST:
+ default:
+ n += fprintf(out, "%s", nodestrings[c->kind]);
+ }
+ n += printoperant(out, c->lhs, PUNARY, false, indent);
+ }
+ } else {
+ switch (c->kind)
+ {
+ case 'I':
+ n += fprintf(out, "%s?", getstring(idents, c->u.key));
+ break;
+ case 'N':
+ if (c->type->kind == TFLOAT ||
+ c->type->kind == TDOUBLE ||
+ c->type->kind == TLDOUBLE)
+ n += fprintf(out, "%f", c->u.d);
+ else if (expr->type->kind & (TUINT - TINT))
+ n += fprintf(out, "%li", c->u.s);
+ else
+ n += fprintf(out, "%lu", c->u.u);
+ n += printtype(out, c->type, indent);
+ break;
+ case 'S':
+ n += printstring(out, c);
+ break;
+ case ADECLREF:
+ n += fprintf(out, "%s", getstring(idents, c->u.declref->key));
+ break;
+ case ADECL:
+ assert(c->lhs);
+ n += printtype(out, c->lhs->type, indent);
+ assert(c->rhs);
+ assert(c->rhs->kind == 'I');
+ n += fprintf(out, " %s", getstring(idents, c->rhs->u.key));
+ if (c->u.payload) {
+ n += fprintf(out, " = ");
+ n += printoperant(out, c->u.payload, PASSIGN, false, indent);
+ }
+ break;
+ case ARETURN:
+ n += fprintf(out, "return ");
+ n += printexpr(out, c->lhs, indent);
+ break;
+ case ABREAK:
+ n += fprintf(out, "break");
+ break;
+ case ACONTINUE:
+ n += fprintf(out, "continue");
+ break;
+ case AIF:
+ n += fprintf(out, "if ");
+ n += printexpr(out, c->u.payload, indent);
+ n += printclause(out, c->lhs, indent);
+ if (c->rhs) {
+ int i;
+
+ n += fprintf(out, "\n");
+ for (i = 0; i < indent; ++i)
+ n += fprintf(out, "\t");
+ n += fprintf(out, "else");
+ n += printclause(out, c->rhs, indent);
+ }
+ break;
+ case ADO:
+ n += fprintf(out, "do");
+ n += printclause(out, c->lhs, indent);
+ break;
+ case ASTMT:
+ n += printexpr(out, c->lhs, indent);
+ break;
+ case ASCOPE:
+ n += printexpr(out, c->lhs, indent);
+ break;
+ case ACONV:
+ n += fprintf(out, "conv(");
+ n += printtype(out, c->type, indent);
+ n += fprintf(out, ") ");
+ n += printoperant(out, c->lhs, PUNARY, false, indent);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (c->kind == ASTMT && c->next)
+ n += fprintf(out, "\n");
+ else if (c->next)
+ n += fprintf(out, ", ");
+ }
+
+ return n;
+}
+
/* - main-routine - */
int
@@ -2262,8 +2571,15 @@ main(int argc, char **argv) {
Node *ast;
ast = exprlist(false, NULL);
+ /*
printast(ast, 0);
printf("\n");
+ */
+ if (ast->kind != ADECL || !ast->u.payload || ast->u.payload->kind != ASCOPE)
+ ast = foldexpr(ast);
+ printexpr(stdout, ast, 0);
+ printf("\n");
+
if (tok.kind == '\n') {
if (filein == stdin)