summaryrefslogtreecommitdiffstats
path: root/dimension/parse.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-12-21 00:36:12 -0500
committerTavian Barnes <tavianator@gmail.com>2009-12-21 02:32:06 -0500
commit494079ee46d67ae7ef6504734f7400b543c6d848 (patch)
tree9f4ad236fe10ef99b422913edc98d85cf83f99aa /dimension/parse.c
parent0eb3d602df451f882e107ebed47b3bce9a1e68dc (diff)
downloaddimension-494079ee46d67ae7ef6504734f7400b543c6d848.tar.xz
Support #declare, #local, and #undef.
Diffstat (limited to 'dimension/parse.c')
-rw-r--r--dimension/parse.c395
1 files changed, 238 insertions, 157 deletions
diff --git a/dimension/parse.c b/dimension/parse.c
index 1916941..320277c 100644
--- a/dimension/parse.c
+++ b/dimension/parse.c
@@ -18,6 +18,7 @@
*************************************************************************/
#include "parse.h"
+#include "utility.h"
static dmnsn_astnode
dmnsn_new_astnode(dmnsn_astnode_type type)
@@ -89,11 +90,10 @@ dmnsn_delete_astnode(dmnsn_astnode astnode)
void
dmnsn_delete_astree(dmnsn_astree *astree)
{
- unsigned int i;
- dmnsn_astnode node;
-
if (astree) {
+ unsigned int i;
for (i = 0; i < dmnsn_array_size(astree); ++i) {
+ dmnsn_astnode node;
dmnsn_array_get(astree, i, &node);
dmnsn_delete_astnode(node);
}
@@ -218,7 +218,8 @@ dmnsn_undef_symbol(dmnsn_symbol_table *symtable, const char *id)
dmnsn_array_size(scope) - j - 1);
if (strcmp(id, symbol->id) == 0) {
- dmnsn_array_remove(scope, j);
+ dmnsn_delete_symbol(*symbol);
+ dmnsn_array_remove(scope, dmnsn_array_size(scope) - j - 1);
return;
}
}
@@ -267,20 +268,128 @@ dmnsn_copy_astnode(dmnsn_astnode astnode)
return copy;
}
+#define DMNSN_VECTOR_NELEM 5
+
+static dmnsn_astnode
+dmnsn_vector_promote(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
+{
+ dmnsn_astnode promoted = dmnsn_copy_astnode(astnode);
+
+ if (astnode.type == DMNSN_AST_VECTOR) {
+ dmnsn_astnode component;
+ unsigned int i;
+ for (i = 0; i < dmnsn_array_size(astnode.children); ++i) {
+ dmnsn_array_get(astnode.children, i, &component);
+ component = dmnsn_eval_scalar(component, symtable);
+
+ if (component.type == DMNSN_AST_NONE) {
+ dmnsn_delete_astnode(promoted);
+ return component;
+ } else {
+ dmnsn_array_push(promoted.children, &component);
+ }
+ }
+
+ while (dmnsn_array_size(promoted.children) < DMNSN_VECTOR_NELEM) {
+ component = dmnsn_copy_astnode(component);
+ component.type = DMNSN_AST_INTEGER;
+
+ long *val = malloc(sizeof(long));
+ *val = 0;
+
+ component.ptr = val;
+ dmnsn_array_push(promoted.children, &component);
+ }
+ } else {
+ dmnsn_astnode component = dmnsn_eval_scalar(astnode, symtable);
+
+ if (component.type == DMNSN_AST_NONE) {
+ promoted.type = DMNSN_AST_NONE;
+ } else {
+ promoted.type = DMNSN_AST_VECTOR;
+ while (dmnsn_array_size(promoted.children) < DMNSN_VECTOR_NELEM) {
+ dmnsn_array_push(promoted.children, &component);
+ ++*component.refcount;
+ }
+ }
+
+ dmnsn_delete_astnode(component);
+ }
+
+ return promoted;
+}
+
static dmnsn_astnode
-dmnsn_eval_scalar_unary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
+dmnsn_eval_unary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
{
- dmnsn_astnode ret = dmnsn_copy_astnode(astnode), rhs;
+ unsigned int i;
+
+ dmnsn_astnode rhs;
dmnsn_array_get(astnode.children, 0, &rhs);
- rhs = dmnsn_eval_scalar(rhs, symtable);
+ rhs = dmnsn_eval(rhs, symtable);
+
+ dmnsn_astnode ret = dmnsn_copy_astnode(astnode);
+
+ if (rhs.type == DMNSN_AST_NONE) {
+ ret.type = DMNSN_AST_NONE;
+ } else if (rhs.type == DMNSN_AST_VECTOR) {
+ switch (astnode.type) {
+ case DMNSN_AST_DOT_X:
+ dmnsn_array_get(rhs.children, 0, &ret);
+ ++*ret.refcount;
+ break;
+
+ case DMNSN_AST_DOT_Y:
+ dmnsn_array_get(rhs.children, 1, &ret);
+ ++*ret.refcount;
+ break;
+
+ case DMNSN_AST_DOT_Z:
+ dmnsn_array_get(rhs.children, 2, &ret);
+ ++*ret.refcount;
+ break;
- if (rhs.type == DMNSN_AST_INTEGER) {
+ case DMNSN_AST_DOT_T:
+ dmnsn_array_get(rhs.children, 3, &ret);
+ ++*ret.refcount;
+ break;
+
+ case DMNSN_AST_DOT_TRANSMIT:
+ dmnsn_array_get(rhs.children, 4, &ret);
+ ++*ret.refcount;
+ break;
+
+ default:
+ {
+ ret.type = DMNSN_AST_VECTOR;
+
+ dmnsn_astnode op = dmnsn_copy_astnode(astnode);
+ for (i = 0; i < DMNSN_VECTOR_NELEM; ++i) {
+ dmnsn_array_get(rhs.children, i, dmnsn_array_at(op.children, 0));
+ dmnsn_astnode temp = dmnsn_eval_unary(op, symtable);
+ dmnsn_array_set(ret.children, i, &temp);
+ }
+
+ dmnsn_delete_array(op.children);
+ op.children = NULL;
+ dmnsn_delete_astnode(op);
+ break;
+ }
+ }
+ } else if (rhs.type == DMNSN_AST_INTEGER) {
long n = *(long *)rhs.ptr;
long *res = malloc(sizeof(long));
if (!res)
dmnsn_error(DMNSN_SEVERITY_HIGH, "Failed to allocate room for integer.");
switch(astnode.type) {
+ case DMNSN_AST_DOT_X:
+ case DMNSN_AST_DOT_Y:
+ case DMNSN_AST_DOT_Z:
+ case DMNSN_AST_DOT_T:
+ case DMNSN_AST_DOT_TRANSMIT:
+ *res = n;
+
case DMNSN_AST_NEGATE:
*res = -n;
break;
@@ -299,6 +408,13 @@ dmnsn_eval_scalar_unary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
dmnsn_error(DMNSN_SEVERITY_HIGH, "Failed to allocate room for float.");
switch(astnode.type) {
+ case DMNSN_AST_DOT_X:
+ case DMNSN_AST_DOT_Y:
+ case DMNSN_AST_DOT_Z:
+ case DMNSN_AST_DOT_T:
+ case DMNSN_AST_DOT_TRANSMIT:
+ *res = n;
+
case DMNSN_AST_NEGATE:
*res = -n;
break;
@@ -311,8 +427,12 @@ dmnsn_eval_scalar_unary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
ret.type = DMNSN_AST_FLOAT;
ret.ptr = res;
} else {
- dmnsn_error(DMNSN_SEVERITY_HIGH,
- "Invalid right hand side to unary operator.");
+ dmnsn_diagnostic(rhs.filename, rhs.line, rhs.col,
+ "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));
+ ret.type = DMNSN_AST_NONE;
}
dmnsn_delete_astnode(rhs);
@@ -320,16 +440,42 @@ dmnsn_eval_scalar_unary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
}
static dmnsn_astnode
-dmnsn_eval_scalar_binary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
+dmnsn_eval_binary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
{
- dmnsn_astnode ret = dmnsn_copy_astnode(astnode), lhs, rhs;
+ unsigned int i;
+
+ dmnsn_astnode lhs, rhs;
dmnsn_array_get(astnode.children, 0, &lhs);
dmnsn_array_get(astnode.children, 1, &rhs);
- lhs = dmnsn_eval_scalar(lhs, symtable);
- rhs = dmnsn_eval_scalar(rhs, symtable);
+ lhs = dmnsn_eval(lhs, symtable);
+ rhs = dmnsn_eval(rhs, symtable);
+
+ dmnsn_astnode ret = dmnsn_copy_astnode(astnode);
+
+ if (lhs.type == DMNSN_AST_NONE || rhs.type == DMNSN_AST_NONE) {
+ 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);
+ }
- if (lhs.type == DMNSN_AST_INTEGER && rhs.type == DMNSN_AST_INTEGER
- && astnode.type != DMNSN_AST_DIV) {
+ dmnsn_delete_array(op.children);
+ op.children = NULL;
+ dmnsn_delete_astnode(op);
+ } else if (lhs.type == DMNSN_AST_INTEGER && rhs.type == DMNSN_AST_INTEGER
+ && astnode.type != DMNSN_AST_DIV) {
long l, r;
l = *(long *)lhs.ptr;
r = *(long *)rhs.ptr;
@@ -359,21 +505,37 @@ dmnsn_eval_scalar_binary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
} else {
double l = 0.0, r = 0.0;
- if (lhs.type == DMNSN_AST_INTEGER)
+ if (lhs.type == DMNSN_AST_INTEGER) {
l = *(long *)lhs.ptr;
- else if (lhs.type == DMNSN_AST_FLOAT)
+ } else if (lhs.type == DMNSN_AST_FLOAT) {
l = *(double *)lhs.ptr;
- else
- dmnsn_error(DMNSN_SEVERITY_HIGH,
- "Invalid left hand side to binary operator.");
+ } else {
+ dmnsn_diagnostic(lhs.filename, lhs.line, lhs.col,
+ "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));
+ ret.type = DMNSN_AST_NONE;
+ dmnsn_delete_astnode(lhs);
+ dmnsn_delete_astnode(rhs);
+ return ret;
+ }
- if (rhs.type == DMNSN_AST_INTEGER)
+ if (rhs.type == DMNSN_AST_INTEGER) {
r = *(long *)rhs.ptr;
- else if (rhs.type == DMNSN_AST_FLOAT)
+ } else if (rhs.type == DMNSN_AST_FLOAT) {
r = *(double *)rhs.ptr;
- else
- dmnsn_error(DMNSN_SEVERITY_HIGH,
- "Invalid right hand side to binary operator.");
+ } else {
+ dmnsn_diagnostic(rhs.filename, rhs.line, rhs.col,
+ "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));
+ ret.type = DMNSN_AST_NONE;
+ dmnsn_delete_astnode(lhs);
+ dmnsn_delete_astnode(rhs);
+ return ret;
+ }
double *res = malloc(sizeof(double));
if (!res)
@@ -401,170 +563,89 @@ dmnsn_eval_scalar_binary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
ret.type = DMNSN_AST_FLOAT;
ret.ptr = res;
}
-
+
dmnsn_delete_astnode(lhs);
dmnsn_delete_astnode(rhs);
return ret;
}
dmnsn_astnode
-dmnsn_eval_scalar(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
+dmnsn_eval(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
{
- dmnsn_astnode ret;
-
switch (astnode.type) {
+ case DMNSN_AST_NONE:
case DMNSN_AST_INTEGER:
- ret = dmnsn_copy_astnode(astnode);
- ret.ptr = malloc(sizeof(long));
- if (!ret.ptr)
- dmnsn_error(DMNSN_SEVERITY_HIGH, "Failed to allocate room for integer.");
-
- memcpy(ret.ptr, astnode.ptr, sizeof(long));
- return ret;
-
case DMNSN_AST_FLOAT:
- ret = dmnsn_copy_astnode(astnode);
- ret.ptr = malloc(sizeof(double));
- if (!ret.ptr)
- dmnsn_error(DMNSN_SEVERITY_HIGH, "Failed to allocate room for float.");
+ ++*astnode.refcount;
+ return astnode;
- memcpy(ret.ptr, astnode.ptr, sizeof(double));
- return ret;
+ case DMNSN_AST_VECTOR:
+ return dmnsn_vector_promote(astnode, symtable);
+
+ case DMNSN_AST_IDENTIFIER:
+ {
+ dmnsn_astnode *symbol = dmnsn_find_symbol(symtable, astnode.ptr);
+ if (symbol) {
+ return dmnsn_eval(*symbol, symtable);
+ } else {
+ dmnsn_diagnostic(astnode.filename, astnode.line, astnode.col,
+ "unbound identifier '%s'", astnode.ptr);
+ dmnsn_astnode error = dmnsn_new_astnode(DMNSN_AST_NONE);
+ ++*error.refcount;
+ return error;
+ }
+ }
+ case DMNSN_AST_DOT_X:
+ case DMNSN_AST_DOT_Y:
+ case DMNSN_AST_DOT_Z:
+ case DMNSN_AST_DOT_T:
+ case DMNSN_AST_DOT_TRANSMIT:
case DMNSN_AST_NEGATE:
- return dmnsn_eval_scalar_unary(astnode, symtable);
+ return dmnsn_eval_unary(astnode, symtable);
case DMNSN_AST_ADD:
case DMNSN_AST_SUB:
case DMNSN_AST_MUL:
case DMNSN_AST_DIV:
- return dmnsn_eval_scalar_binary(astnode, symtable);
+ return dmnsn_eval_binary(astnode, symtable);
default:
- dmnsn_error(DMNSN_SEVERITY_HIGH,
- "Given non-arithmetic-expression to evaluate.");
- return astnode; /* Silence warning */
- }
-}
-
-#define DMNSN_VECTOR_NELEM 5
-
-static dmnsn_astnode
-dmnsn_vector_promote(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
-{
- dmnsn_astnode promoted = dmnsn_copy_astnode(astnode), component;
- promoted.type = DMNSN_AST_VECTOR;
-
- if (astnode.type == DMNSN_AST_VECTOR) {
- unsigned int i;
- for (i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_array_get(astnode.children, i, &component);
- component = dmnsn_eval_scalar(component, symtable);
- dmnsn_array_push(promoted.children, &component);
- }
-
- while (dmnsn_array_size(promoted.children) < DMNSN_VECTOR_NELEM) {
- component = dmnsn_copy_astnode(component);
- component.type = DMNSN_AST_INTEGER;
-
- long *val = malloc(sizeof(long));
- *val = 0;
-
- component.ptr = val;
- dmnsn_array_push(promoted.children, &component);
- }
- } else {
- component = dmnsn_eval_scalar(astnode, symtable);
- dmnsn_array_push(promoted.children, &component);
-
- while (dmnsn_array_size(promoted.children) < DMNSN_VECTOR_NELEM) {
- component = dmnsn_eval_scalar(component, symtable);
- dmnsn_array_push(promoted.children, &component);
- }
- }
-
- return promoted;
-}
-
-static dmnsn_astnode
-dmnsn_eval_vector_unary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
-{
- unsigned int i;
-
- dmnsn_astnode rhs;
- dmnsn_array_get(astnode.children, 0, &rhs);
- rhs = dmnsn_eval_vector(rhs, symtable);
-
- dmnsn_astnode ret = dmnsn_copy_astnode(astnode), temp;
- ret.type = DMNSN_AST_VECTOR;
-
- dmnsn_astnode op = dmnsn_copy_astnode(astnode);
- for (i = 0; i < DMNSN_VECTOR_NELEM; ++i) {
- dmnsn_array_get(rhs.children, i, dmnsn_array_at(op.children, 0));
- temp = dmnsn_eval_scalar_unary(op, symtable);
- dmnsn_array_set(ret.children, i, &temp);
+ dmnsn_diagnostic(astnode.filename, astnode.line, astnode.col,
+ "expected arithmetic expression; found %s",
+ dmnsn_astnode_string(astnode.type));
+ dmnsn_astnode error = dmnsn_new_astnode(DMNSN_AST_NONE);
+ ++*error.refcount;
+ return error;
}
- dmnsn_delete_array(op.children);
- op.children = NULL;
- dmnsn_delete_astnode(op);
- dmnsn_delete_astnode(rhs);
- return ret;
+ return astnode;
}
-static dmnsn_astnode
-dmnsn_eval_vector_binary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
+dmnsn_astnode
+dmnsn_eval_scalar(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
{
- unsigned int i;
-
- dmnsn_astnode lhs, rhs;
- dmnsn_array_get(astnode.children, 0, &lhs);
- dmnsn_array_get(astnode.children, 1, &rhs);
- lhs = dmnsn_eval_vector(lhs, symtable);
- rhs = dmnsn_eval_vector(rhs, symtable);
-
- dmnsn_astnode ret = dmnsn_copy_astnode(astnode), temp;
- 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));
- temp = dmnsn_eval_scalar_binary(op, symtable);
- dmnsn_array_set(ret.children, i, &temp);
+ dmnsn_astnode ret = dmnsn_eval(astnode, symtable);
+ if (ret.type == DMNSN_AST_VECTOR) {
+ dmnsn_diagnostic(ret.filename, ret.line, ret.col,
+ "expected %s or %s; found %s",
+ dmnsn_astnode_string(DMNSN_AST_INTEGER),
+ dmnsn_astnode_string(DMNSN_AST_FLOAT),
+ dmnsn_astnode_string(ret.type));
+ dmnsn_delete_astnode(ret);
+ ret = dmnsn_new_astnode(DMNSN_AST_NONE);
}
-
- dmnsn_delete_array(op.children);
- op.children = NULL;
- dmnsn_delete_astnode(op);
- dmnsn_delete_astnode(lhs);
- dmnsn_delete_astnode(rhs);
return ret;
}
dmnsn_astnode
dmnsn_eval_vector(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
{
- switch (astnode.type) {
- case DMNSN_AST_INTEGER:
- case DMNSN_AST_FLOAT:
- case DMNSN_AST_VECTOR:
- return dmnsn_vector_promote(astnode, symtable);
+ dmnsn_astnode eval = dmnsn_eval(astnode, symtable);
+ dmnsn_astnode ret = dmnsn_vector_promote(eval, symtable);
- case DMNSN_AST_NEGATE:
- return dmnsn_eval_vector_unary(astnode, symtable);
-
- case DMNSN_AST_ADD:
- case DMNSN_AST_SUB:
- case DMNSN_AST_MUL:
- case DMNSN_AST_DIV:
- return dmnsn_eval_vector_binary(astnode, symtable);
-
- default:
- dmnsn_error(DMNSN_SEVERITY_HIGH,
- "Given non-arithmetic-expression to evaluate.");
- return astnode; /* Silence warning */
- }
+ dmnsn_delete_astnode(eval);
+ return ret;
}
static void