diff options
author | Tavian Barnes <tavianator@gmail.com> | 2009-11-24 20:44:52 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@gmail.com> | 2009-11-24 20:44:52 -0500 |
commit | a3a951ce9e87af1036c97c99987812273f62224c (patch) | |
tree | bd464c92ed31d91384f8d9c840588d2e058f00ca | |
parent | 810901c1c0f6bbfade2e4d7f3717eed19d166aa8 (diff) | |
download | dimension-a3a951ce9e87af1036c97c99987812273f62224c.tar.xz |
Support vector arithmetic.
-rw-r--r-- | dimension/grammar.y | 185 | ||||
-rw-r--r-- | tests/dimension/demo.pov | 2 | ||||
-rwxr-xr-x | tests/dimension/demo.sh | 4 |
3 files changed, 181 insertions, 10 deletions
diff --git a/dimension/grammar.y b/dimension/grammar.y index 12b9344..e2162a3 100644 --- a/dimension/grammar.y +++ b/dimension/grammar.y @@ -119,6 +119,33 @@ dmnsn_new_astnode3(dmnsn_astnode_type type, YYLTYPE lloc, return astnode; } +static dmnsn_astnode +dmnsn_new_astnode4(dmnsn_astnode_type type, YYLTYPE lloc, + dmnsn_astnode n1, dmnsn_astnode n2, dmnsn_astnode n3, + dmnsn_astnode n4) +{ + dmnsn_astnode astnode = dmnsn_new_astnode(type, lloc); + dmnsn_array_push(astnode.children, &n1); + dmnsn_array_push(astnode.children, &n2); + dmnsn_array_push(astnode.children, &n3); + dmnsn_array_push(astnode.children, &n4); + return astnode; +} + +static dmnsn_astnode +dmnsn_new_astnode5(dmnsn_astnode_type type, YYLTYPE lloc, + dmnsn_astnode n1, dmnsn_astnode n2, dmnsn_astnode n3, + dmnsn_astnode n4, dmnsn_astnode n5) +{ + dmnsn_astnode astnode = dmnsn_new_astnode(type, lloc); + dmnsn_array_push(astnode.children, &n1); + dmnsn_array_push(astnode.children, &n2); + dmnsn_array_push(astnode.children, &n3); + dmnsn_array_push(astnode.children, &n4); + dmnsn_array_push(astnode.children, &n5); + return astnode; +} + /* Delete a single, unused astnode */ static void dmnsn_delete_astnode(dmnsn_astnode astnode) @@ -685,6 +712,7 @@ yyerror(YYLTYPE *locp, dmnsn_array *astree, dmnsn_token_iterator *iterator, /* Vectors */ %type <astnode> VECTOR +%type <astnode> VECTOR_EXPR %type <astnode> VECTOR_LITERAL %destructor { dmnsn_delete_astnode($$); } <astnode> @@ -692,9 +720,9 @@ yyerror(YYLTYPE *locp, dmnsn_array *astree, dmnsn_token_iterator *iterator, %% SCENE: /* empty */ { } - | SCENE SCENE_ITEM { - dmnsn_array_push(astree, &$2); - } + | SCENE SCENE_ITEM { + dmnsn_array_push(astree, &$2); + } ; SCENE_ITEM: OBJECT @@ -770,12 +798,45 @@ FLOAT_LITERAL: "integer" } ; -VECTOR: VECTOR_LITERAL +VECTOR: VECTOR_EXPR { + $$ = dmnsn_eval_vector($1); + dmnsn_delete_astnode($1); + } ; -VECTOR_LITERAL: "<" FLOAT "," FLOAT "," FLOAT ">" { +VECTOR_EXPR: VECTOR_LITERAL + | VECTOR_EXPR "+" VECTOR_EXPR { + $$ = dmnsn_new_astnode2(DMNSN_AST_ADD, @$, $1, $3); + } + | VECTOR_EXPR "-" VECTOR_EXPR { + $$ = dmnsn_new_astnode2(DMNSN_AST_SUB, @$, $1, $3); + } + | VECTOR_EXPR "*" VECTOR_EXPR { + $$ = dmnsn_new_astnode2(DMNSN_AST_MUL, @$, $1, $3); + } + | VECTOR_EXPR "/" VECTOR_EXPR { + $$ = dmnsn_new_astnode2(DMNSN_AST_DIV, @$, $1, $3); + } + | "+" VECTOR_EXPR %prec DMNSN_T_NEGATE { $$ = $2; } + | "-" VECTOR_EXPR %prec DMNSN_T_NEGATE { + $$ = dmnsn_new_astnode1(DMNSN_AST_NEGATE, @$, $2); + } + | "(" VECTOR_EXPR ")" { $$ = $2; } +; + +VECTOR_LITERAL: "<" FLOAT "," FLOAT ">" { + $$ = dmnsn_new_astnode2(DMNSN_AST_VECTOR, @$, $2, $4); + } + | "<" FLOAT "," FLOAT "," FLOAT ">" { $$ = dmnsn_new_astnode3(DMNSN_AST_VECTOR, @$, $2, $4, $6); } + | "<" FLOAT "," FLOAT "," FLOAT "," FLOAT ">" { + $$ = dmnsn_new_astnode4(DMNSN_AST_VECTOR, @$, $2, $4, $6, $8); + } + | "<" FLOAT "," FLOAT "," FLOAT "," FLOAT "," FLOAT ">" { + $$ = dmnsn_new_astnode5(DMNSN_AST_VECTOR, @$, + $2, $4, $6, $8, $10); + } ; %% @@ -990,8 +1051,118 @@ dmnsn_eval_scalar(dmnsn_astnode astnode) } } -/* TODO */ -dmnsn_astnode dmnsn_eval_vector(dmnsn_astnode astnode); +static dmnsn_astnode +dmnsn_vector_promote(dmnsn_astnode astnode) +{ + dmnsn_astnode promoted = dmnsn_copy_astnode(astnode), component; + + 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); + dmnsn_array_push(promoted.children, &component); + } + + while (dmnsn_array_size(promoted.children) < 5) { + 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); + dmnsn_array_push(promoted.children, &component); + + while (dmnsn_array_size(promoted.children) < 5) { + component = dmnsn_eval_scalar(component); + dmnsn_array_push(promoted.children, &component); + } + } + + return promoted; +} + +static dmnsn_astnode +dmnsn_eval_vector_unary(dmnsn_astnode astnode) +{ + unsigned int i; + + dmnsn_astnode rhs; + dmnsn_array_get(astnode.children, 0, &rhs); + rhs = dmnsn_eval_vector(rhs); + + dmnsn_astnode ret = dmnsn_copy_astnode(astnode), temp; + ret.type = DMNSN_AST_VECTOR; + + dmnsn_astnode op = dmnsn_copy_astnode(astnode); + for (i = 0; i < 5; ++i) { + dmnsn_array_get(rhs.children, i, dmnsn_array_at(op.children, 0)); + temp = dmnsn_eval_scalar_unary(op); + dmnsn_array_set(ret.children, i, &temp); + } + + dmnsn_delete_array(op.children); + dmnsn_delete_astnode(rhs); + return ret; +} + +static dmnsn_astnode +dmnsn_eval_vector_binary(dmnsn_astnode astnode) +{ + unsigned int i; + + dmnsn_astnode lhs, rhs; + dmnsn_array_get(astnode.children, 0, &lhs); + dmnsn_array_get(astnode.children, 0, &rhs); + lhs = dmnsn_eval_vector(lhs); + rhs = dmnsn_eval_vector(rhs); + + dmnsn_astnode ret = dmnsn_copy_astnode(astnode), temp; + ret.type = DMNSN_AST_VECTOR; + + dmnsn_astnode op = dmnsn_copy_astnode(astnode); + for (i = 0; i < 5; ++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); + dmnsn_array_set(ret.children, i, &temp); + } + + dmnsn_delete_array(op.children); + dmnsn_delete_astnode(lhs); + dmnsn_delete_astnode(rhs); + return ret; +} + +dmnsn_astnode +dmnsn_eval_vector(dmnsn_astnode astnode) +{ + switch (astnode.type) { + case DMNSN_AST_INTEGER: + case DMNSN_AST_FLOAT: + case DMNSN_AST_VECTOR: + return dmnsn_vector_promote(astnode); + + case DMNSN_AST_NEGATE: + return dmnsn_eval_vector_unary(astnode); + + case DMNSN_AST_ADD: + case DMNSN_AST_SUB: + case DMNSN_AST_MUL: + case DMNSN_AST_DIV: + return dmnsn_eval_vector_binary(astnode); + + default: + dmnsn_error(DMNSN_SEVERITY_HIGH, + "Given non-arithmetic-expression to evaluate."); + return astnode; /* Silence warning */ + } +} static void dmnsn_print_astnode(FILE *file, dmnsn_astnode astnode) diff --git a/tests/dimension/demo.pov b/tests/dimension/demo.pov index 764130d..c37ef48 100644 --- a/tests/dimension/demo.pov +++ b/tests/dimension/demo.pov @@ -24,5 +24,5 @@ box { } sphere { - <1/5 + -1/5, 1/5.0 - 1.0/5, -1 - -1>, 1.25 + <1/5 + -1/5, 1/5.0 - 1.0/5, -1> - -<0, 0, 1>, 1.25 } diff --git a/tests/dimension/demo.sh b/tests/dimension/demo.sh index 816a317..8119969 100755 --- a/tests/dimension/demo.sh +++ b/tests/dimension/demo.sh @@ -20,8 +20,8 @@ ######################################################################### demo=$(${top_builddir}/dimension/dimension --tokenize --parse ${srcdir}/demo.pov) -demo_exp='(box { < - (float "2.0") + (integer "1") , - (integer "2") / (float "2.0") , - (float "1.0") > , < (float "1.0") , \( (float "1.0") + (integer "2") \) * (integer "2") - (integer "5") , (float "1.0") + (integer "2") * (integer "2") - (integer "4") > } sphere { < (integer "1") / (integer "5") + - (integer "1") / (integer "5") , (integer "1") / (float "5.0") - (float "1.0") / (integer "5") , - (integer "1") - - (integer "1") > , (float "1.25") }) -((box (vector (float -1) (float -1) (float -1)) (vector (float 1) (float 1) (float 1))) (sphere (vector (float 0) (float 0) (integer 0)) (float 1.25)))' +demo_exp='(box { < - (float "2.0") + (integer "1") , - (integer "2") / (float "2.0") , - (float "1.0") > , < (float "1.0") , \( (float "1.0") + (integer "2") \) * (integer "2") - (integer "5") , (float "1.0") + (integer "2") * (integer "2") - (integer "4") > } sphere { < (integer "1") / (integer "5") + - (integer "1") / (integer "5") , (integer "1") / (float "5.0") - (float "1.0") / (integer "5") , - (integer "1") > - - < (integer "0") , (integer "0") , (integer "1") > , (float "1.25") }) +((box (vector (float -1) (float -1) (float -1) (integer 0) (integer 0)) (vector (float 1) (float 1) (float 1) (integer 0) (integer 0))) (sphere (vector (float 0) (float 0) (integer 0) (integer 0) (integer 0)) (float 1.25)))' if [ "$demo" != "$demo_exp" ]; then echo "demo.pov parsed as \"$demo\"" >&2 |