diff options
Diffstat (limited to 'dimension/parse.c')
-rw-r--r-- | dimension/parse.c | 192 |
1 files changed, 177 insertions, 15 deletions
diff --git a/dimension/parse.c b/dimension/parse.c index 9357ef3..6ff5628 100644 --- a/dimension/parse.c +++ b/dimension/parse.c @@ -268,6 +268,7 @@ dmnsn_copy_astnode(dmnsn_astnode astnode) return copy; } +/* 5-element vectors */ #define DMNSN_VECTOR_NELEM 5 static dmnsn_astnode @@ -455,32 +456,189 @@ dmnsn_eval_binary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable) lhs = dmnsn_eval(lhs, symtable); rhs = dmnsn_eval(rhs, symtable); - dmnsn_astnode ret = dmnsn_copy_astnode(astnode); + dmnsn_astnode ret; if (lhs.type == DMNSN_AST_NONE || rhs.type == DMNSN_AST_NONE) { + ret = dmnsn_copy_astnode(astnode); ret.type = DMNSN_AST_NONE; } else if (lhs.type == DMNSN_AST_VECTOR || rhs.type == DMNSN_AST_VECTOR) { - ret.type = DMNSN_AST_VECTOR; - dmnsn_astnode oldlhs = lhs, oldrhs = rhs; lhs = dmnsn_vector_promote(lhs, symtable); rhs = dmnsn_vector_promote(rhs, symtable); dmnsn_delete_astnode(oldlhs); dmnsn_delete_astnode(oldrhs); - dmnsn_astnode op = dmnsn_copy_astnode(astnode); - for (i = 0; i < DMNSN_VECTOR_NELEM; ++i) { - dmnsn_array_get(lhs.children, i, dmnsn_array_at(op.children, 0)); - dmnsn_array_get(rhs.children, i, dmnsn_array_at(op.children, 1)); - dmnsn_astnode temp = dmnsn_eval_binary(op, symtable); - dmnsn_array_set(ret.children, i, &temp); - } + switch (astnode.type) { + case DMNSN_AST_EQUAL: + { + dmnsn_astnode rewrite = dmnsn_copy_astnode(astnode); + + dmnsn_astnode l, r; + dmnsn_array_get(lhs.children, 0, &l); + dmnsn_array_get(rhs.children, 0, &r); + ++*l.refcount; + ++*r.refcount; + dmnsn_array_push(rewrite.children, &l); + dmnsn_array_push(rewrite.children, &r); + + for (i = 1; i < DMNSN_VECTOR_NELEM; ++i) { + dmnsn_astnode temp = dmnsn_copy_astnode(astnode); + dmnsn_array_get(lhs.children, i, &l); + dmnsn_array_get(rhs.children, i, &r); + ++*l.refcount; + ++*r.refcount; + dmnsn_array_push(temp.children, &l); + dmnsn_array_push(temp.children, &r); + + dmnsn_astnode next = dmnsn_copy_astnode(astnode); + next.type = DMNSN_AST_AND; + dmnsn_array_push(next.children, &rewrite); + dmnsn_array_push(next.children, &temp); + rewrite = next; + } + + ret = dmnsn_eval_binary(rewrite, symtable); + dmnsn_delete_astnode(rewrite); + break; + } + + case DMNSN_AST_NOT_EQUAL: + { + dmnsn_astnode rewrite = dmnsn_copy_astnode(astnode); + + dmnsn_astnode l, r; + dmnsn_array_get(lhs.children, 0, &l); + dmnsn_array_get(rhs.children, 0, &r); + ++*l.refcount; + ++*r.refcount; + dmnsn_array_push(rewrite.children, &l); + dmnsn_array_push(rewrite.children, &r); + + for (i = 1; i < DMNSN_VECTOR_NELEM; ++i) { + dmnsn_astnode temp = dmnsn_copy_astnode(astnode); + dmnsn_array_get(lhs.children, i, &l); + dmnsn_array_get(rhs.children, i, &r); + ++*l.refcount; + ++*r.refcount; + dmnsn_array_push(temp.children, &l); + dmnsn_array_push(temp.children, &r); + + dmnsn_astnode next = dmnsn_copy_astnode(astnode); + next.type = DMNSN_AST_OR; + dmnsn_array_push(next.children, &rewrite); + dmnsn_array_push(next.children, &temp); + rewrite = next; + } - dmnsn_delete_array(op.children); - op.children = NULL; - dmnsn_delete_astnode(op); + ret = dmnsn_eval_binary(rewrite, symtable); + dmnsn_delete_astnode(rewrite); + break; + } + + case DMNSN_AST_AND: + { + dmnsn_astnode rewrite = dmnsn_copy_astnode(astnode); + rewrite.type = DMNSN_AST_OR; + + dmnsn_astnode l, r; + dmnsn_array_get(lhs.children, 0, &l); + dmnsn_array_get(rhs.children, 0, &r); + ++*l.refcount; + ++*r.refcount; + dmnsn_array_push(rewrite.children, &l); + dmnsn_array_push(rewrite.children, &r); + + for (i = 1; i < DMNSN_VECTOR_NELEM; ++i) { + dmnsn_astnode temp = dmnsn_copy_astnode(astnode); + temp.type = DMNSN_AST_OR; + dmnsn_array_get(lhs.children, i, &l); + dmnsn_array_get(rhs.children, i, &r); + ++*l.refcount; + ++*r.refcount; + dmnsn_array_push(temp.children, &l); + dmnsn_array_push(temp.children, &r); + + dmnsn_astnode next = dmnsn_copy_astnode(astnode); + next.type = DMNSN_AST_AND; + dmnsn_array_push(next.children, &rewrite); + dmnsn_array_push(next.children, &temp); + rewrite = next; + } + + ret = dmnsn_eval_binary(rewrite, symtable); + dmnsn_delete_astnode(rewrite); + break; + } + + case DMNSN_AST_OR: + { + dmnsn_astnode rewrite = dmnsn_copy_astnode(astnode); + rewrite.type = DMNSN_AST_OR; + + dmnsn_astnode l, r; + dmnsn_array_get(lhs.children, 0, &l); + dmnsn_array_get(rhs.children, 0, &r); + ++*l.refcount; + ++*r.refcount; + dmnsn_array_push(rewrite.children, &l); + dmnsn_array_push(rewrite.children, &r); + + for (i = 1; i < DMNSN_VECTOR_NELEM; ++i) { + dmnsn_astnode temp = dmnsn_copy_astnode(astnode); + temp.type = DMNSN_AST_OR; + dmnsn_array_get(lhs.children, i, &l); + dmnsn_array_get(rhs.children, i, &r); + ++*l.refcount; + ++*r.refcount; + dmnsn_array_push(temp.children, &l); + dmnsn_array_push(temp.children, &r); + + dmnsn_astnode next = dmnsn_copy_astnode(astnode); + next.type = DMNSN_AST_OR; + dmnsn_array_push(next.children, &rewrite); + dmnsn_array_push(next.children, &temp); + rewrite = next; + } + + ret = dmnsn_eval_binary(rewrite, symtable); + dmnsn_delete_astnode(rewrite); + break; + } + + case DMNSN_AST_LESS: + case DMNSN_AST_LESS_EQUAL: + case DMNSN_AST_GREATER: + case DMNSN_AST_GREATER_EQUAL: + dmnsn_diagnostic(astnode.filename, astnode.line, astnode.col, + "invalid comparison operator '%s' between vectors", + dmnsn_astnode_string(astnode.type)); + ret = dmnsn_copy_astnode(astnode); + ret.type = DMNSN_AST_NONE; + break; + + default: + { + ret = dmnsn_copy_astnode(astnode); + ret.type = DMNSN_AST_VECTOR; + + dmnsn_astnode op = dmnsn_copy_astnode(astnode); + for (i = 0; i < DMNSN_VECTOR_NELEM; ++i) { + dmnsn_array_get(lhs.children, i, dmnsn_array_at(op.children, 0)); + dmnsn_array_get(rhs.children, i, dmnsn_array_at(op.children, 1)); + dmnsn_astnode temp = dmnsn_eval_binary(op, symtable); + dmnsn_array_set(ret.children, i, &temp); + } + + dmnsn_delete_array(op.children); + op.children = NULL; + dmnsn_delete_astnode(op); + break; + } + } } else if (lhs.type == DMNSN_AST_INTEGER && rhs.type == DMNSN_AST_INTEGER && astnode.type != DMNSN_AST_DIV) { + ret = dmnsn_copy_astnode(astnode); + long l, r; l = *(long *)lhs.ptr; r = *(long *)rhs.ptr; @@ -532,6 +690,8 @@ dmnsn_eval_binary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable) ret.type = DMNSN_AST_INTEGER; ret.ptr = res; } else { + ret = dmnsn_copy_astnode(astnode); + double l = 0.0, r = 0.0; if (lhs.type == DMNSN_AST_INTEGER) { @@ -543,7 +703,8 @@ dmnsn_eval_binary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable) "expected %s, %s, or %s; found %s", dmnsn_astnode_string(DMNSN_AST_INTEGER), dmnsn_astnode_string(DMNSN_AST_FLOAT), - dmnsn_astnode_string(DMNSN_AST_VECTOR)); + dmnsn_astnode_string(DMNSN_AST_VECTOR), + dmnsn_astnode_string(lhs.type)); ret.type = DMNSN_AST_NONE; dmnsn_delete_astnode(lhs); dmnsn_delete_astnode(rhs); @@ -559,7 +720,8 @@ dmnsn_eval_binary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable) "expected %s, %s, or %s; found %s", dmnsn_astnode_string(DMNSN_AST_INTEGER), dmnsn_astnode_string(DMNSN_AST_FLOAT), - dmnsn_astnode_string(DMNSN_AST_VECTOR)); + dmnsn_astnode_string(DMNSN_AST_VECTOR), + dmnsn_astnode_string(rhs.type)); ret.type = DMNSN_AST_NONE; dmnsn_delete_astnode(lhs); dmnsn_delete_astnode(rhs); |