summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2025-08-02 04:29:52 -0400
committerWormHeamer2025-08-02 04:29:52 -0400
commit828396144285492b14a6d8f5c50a4a0d9d0714ef (patch)
treecf19ff90ea0c296a0f9f6889109d5dbe63c9e990
parentdbfb6ab16c6ff83291b9401a0432d814f9c6fda0 (diff)
some junk
-rw-r--r--lex.h6
-rw-r--r--main.c136
-rw-r--r--test.lang3
3 files changed, 82 insertions, 63 deletions
diff --git a/lex.h b/lex.h
index 66de6d5..08608fe 100644
--- a/lex.h
+++ b/lex.h
@@ -26,9 +26,9 @@
X(AND, "&")\
X(OR, "|")\
X(XOR, "^")\
- X(LIT_STR, "string literal")\
- X(LIT_CHAR, "character literal")\
- X(LIT_NUM, "numeric literal")
+ X(LIT_STR, "string")\
+ X(LIT_CHAR, "character")\
+ X(LIT_NUM, "number")
#define LEX_TOK_CHAR_LIST\
X(TOK_LBRACE, '{')\
diff --git a/main.c b/main.c
index 64d3cf2..51aafe4 100644
--- a/main.c
+++ b/main.c
@@ -24,12 +24,26 @@ typedef enum {
const char *node_type_name[] = {
"start",
"return",
- "integer literal",
+ "literal",
"add", "sub", "mul", "div",
"and", "or", "xor",
"neg", "not",
};
+typedef enum {
+ T_BOT,
+ T_TOP,
+ T_CONST,
+ T_INT
+} Type;
+
+typedef struct {
+ Type type;
+ union {
+ int64_t i;
+ };
+} Value;
+
typedef struct Node {
union {
struct Node *prev_free;
@@ -39,11 +53,7 @@ typedef struct Node {
NodeType type;
LexSpan src_pos;
DYNARR(struct Node *) in, out;
- union {
- struct {
- int64_t i;
- } lit;
- };
+ Value val;
};
};
} Node;
@@ -176,7 +186,7 @@ Node *node_new(Proc *p, NodeType t, ...) {
void node_print(Node *n) {
if (n->type == N_LIT) {
- printf("\t%d [label=\"%ld\"]\n", n->id, n->lit.i);
+ printf("\t%d [label=\"%ld\"]\n", n->id, n->val.i);
} else {
printf("\t%d [label=\"%s\", shape=record]\n", n->id, node_type_name[n->type]);
}
@@ -213,7 +223,7 @@ void unit_print(Unit *u) {
Node *node_new_lit_i64(Proc *p, int64_t i) {
Node *n = node_new(p, N_LIT, p->start);
- n->lit.i = i;
+ n->val = (Value) { T_INT, { .i = i } };
return n;
}
@@ -225,71 +235,79 @@ static inline int node_op_communative(NodeType t) {
return 0;
}
-/* needs lexer for error reporting */
-Node *node_peephole(Node *n, Proc *p, Lexer *l) {
- /*
- * Is there a method to convey these transformations a little more nicely?
- *
- * add(lit, lit) -> lit
- * add(lit, add(N, lit)) -> add(N, add(lit, lit))
- *
- */
-
+Value node_compute(Node *n, Lexer *l) {
+ Type lit_type = T_BOT;
Node **in = n->in.data;
- Node *r = n;
-
- int all_lit = 1;
for (int i = 0; i < n->in.len; i++) {
- if (n->in.data[i]->type != N_LIT) all_lit = 0;
+ Node *p = in[i];
+ if (p->type != N_LIT) break;
+ if (p->val.type != lit_type) {
+ if (lit_type == T_BOT) {
+ lit_type = p->val.type;
+ } else {
+ lit_type = T_BOT;
+ break;
+ }
+ }
}
-
- if (all_lit) {
+ if (lit_type == T_INT) {
+ Value v = { .type = lit_type };
switch (n->type) {
- case N_OP_NEG: r = node_new_lit_i64(p, -in[0]->lit.i); break;
- case N_OP_NOT: r = node_new_lit_i64(p, ~in[0]->lit.i); break;
- case N_OP_ADD: r = node_new_lit_i64(p, in[0]->lit.i + in[1]->lit.i); break;
- case N_OP_SUB: r = node_new_lit_i64(p, in[0]->lit.i - in[1]->lit.i); break;
- case N_OP_MUL: r = node_new_lit_i64(p, in[0]->lit.i * in[1]->lit.i); break;
+ case N_OP_NEG: v.i = -in[0]->val.i; break;
+ case N_OP_NOT: v.i = ~in[0]->val.i; break;
+ case N_OP_ADD: v.i = in[0]->val.i + in[1]->val.i; break;
+ case N_OP_SUB: v.i = in[0]->val.i - in[1]->val.i; break;
+ case N_OP_MUL: v.i = in[0]->val.i * in[1]->val.i; break;
case N_OP_DIV:
- if (in[1]->lit.i == 0) {
- lex_error_at(l, in[1]->src_pos, LE_ERROR, S("divisor always evaluates to zero"));
- }
- r = node_new_lit_i64(p, in[0]->lit.i / in[1]->lit.i);
- break;
- case N_OP_AND: r = node_new_lit_i64(p, in[0]->lit.i & in[1]->lit.i); break;
- case N_OP_OR: r = node_new_lit_i64(p, in[0]->lit.i | in[1]->lit.i); break;
- case N_OP_XOR: r = node_new_lit_i64(p, in[0]->lit.i ^ in[1]->lit.i); break;
- default: break;
+ if (in[1]->val.i == 0) {
+ lex_error_at(l, in[1]->src_pos, LE_ERROR, S("divisor always evaluates to zero"));
+ }
+ v.i = in[0]->val.i / in[1]->val.i;
+ break;
+ case N_OP_AND: v.i = in[0]->val.i & in[1]->val.i; break;
+ case N_OP_OR: v.i = in[0]->val.i | in[1]->val.i; break;
+ case N_OP_XOR: v.i = in[0]->val.i ^ in[1]->val.i; break;
+ default: return n->val;
}
- } else {
- /* TODO: figure out to do peepholes recursively, without fucking up the graph or having to clone everything */
- if (node_op_communative(n->type)) {
- /* transformations to help encourage constant folding */
- if (in[0]->type == N_LIT
+ return v;
+ }
+ return n->val;
+}
+
+/* needs lexer for error reporting */
+Node *node_peephole(Node *n, Proc *p, Lexer *l) {
+ Value v = node_compute(n, l);
+ if (n->type != N_LIT && v.type > T_CONST) {
+ Node *r = node_new(p, N_LIT, p->start);
+ r->val = v;
+ r->src_pos = n->src_pos;
+ node_kill(n, p);
+ return r;
+ }
+
+ Node **in = n->in.data;
+ /* TODO: figure out to do peepholes recursively, without fucking up the graph or having to clone everything */
+ if (node_op_communative(n->type)) {
+ /* transformations to help encourage constant folding */
+ if (in[0]->type == N_LIT
&& in[1]->type == n->type
&& in[1]->in.data[0]->type != N_LIT
&& in[1]->in.data[1]->type == N_LIT) {
- /* op(lit, op(X, lit)) -> op(X, op(lit, lit)) */
- Node *tmp = in[1]->in.data[0];
- in[1]->in.data[0] = in[0];
- in[0] = tmp;
- } else if (in[0]->type == n->type
+ /* op(lit, op(X, lit)) -> op(X, op(lit, lit)) */
+ Node *tmp = in[1]->in.data[0];
+ in[1]->in.data[0] = in[0];
+ in[0] = tmp;
+ } else if (in[0]->type == n->type
&& in[0]->in.data[0]->type != N_LIT
&& in[0]->in.data[1]->type == N_LIT
&& in[1]->type != N_LIT) {
- /* op(op(X, lit), Y) -> op(op(X, Y), lit) */
- Node *tmp = in[0]->in.data[1];
- in[0]->in.data[1] = in[1];
- in[1] = tmp;
- }
+ /* op(op(X, lit), Y) -> op(op(X, Y), lit) */
+ Node *tmp = in[0]->in.data[1];
+ in[0]->in.data[1] = in[1];
+ in[1] = tmp;
}
}
-
- if (r != n) {
- r->src_pos = n->src_pos;
- if (n->out.len == 0) node_kill(n, p);
- }
- return r;
+ return n;
}
/* parsing */
diff --git a/test.lang b/test.lang
index 45cd53e..56ae6da 100644
--- a/test.lang
+++ b/test.lang
@@ -6,6 +6,7 @@
* let x = g
*/
+
proc main {
- return (3 * 5612 * -2) / (1 * (32 ^ 32) + (512 ^ 512) & 3131)
+ return (3 * 5612 * -2) / (1 * (32 ^ 32) + 1 + (512 ^ 512) & (3131 + (1023 - 3131)))
}