diff options
author | Tavian Barnes <tavianator@gmail.com> | 2010-04-18 23:18:45 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@gmail.com> | 2010-04-18 23:18:45 -0400 |
commit | 919121bdf572b632cc5bfbbee502664682b26ab8 (patch) | |
tree | 528a83bb716851152ebc12aee385417b8f407601 | |
parent | 004d63c0c199a1544dc9b3af9cdd3367a6969d23 (diff) | |
download | dimension-919121bdf572b632cc5bfbbee502664682b26ab8.tar.xz |
Give backtraces for diagnostics from macros and include files.
Partly this means that dmnsn_diagnostic() can't be called anywhere except
during parsing, because the dmnsn_parse_location::parent pointers dangle.
-rw-r--r-- | dimension/common.nonterminals | 1 | ||||
-rw-r--r-- | dimension/common.prologue | 1 | ||||
-rw-r--r-- | dimension/common.rules | 8 | ||||
-rw-r--r-- | dimension/grammar.rules | 4 | ||||
-rw-r--r-- | dimension/lexer.l | 1 | ||||
-rw-r--r-- | dimension/parse.h | 2 | ||||
-rw-r--r-- | dimension/realize.c | 16 | ||||
-rw-r--r-- | dimension/tokenize.c | 56 | ||||
-rw-r--r-- | dimension/utility.c | 4 |
9 files changed, 66 insertions, 27 deletions
diff --git a/dimension/common.nonterminals b/dimension/common.nonterminals index 5bd7da6..1d39424 100644 --- a/dimension/common.nonterminals +++ b/dimension/common.nonterminals @@ -75,6 +75,7 @@ /* Floats */ %type <astnode> FLOAT +%type <astnode> INT %type <astnode> FLOAT_LITERAL /* Vectors */ diff --git a/dimension/common.prologue b/dimension/common.prologue index d82b110..4fdfcee 100644 --- a/dimension/common.prologue +++ b/dimension/common.prologue @@ -37,6 +37,7 @@ (Current).last_filename = YYRHSLOC(Rhs, N).last_filename; \ (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ (Current).last_column = YYRHSLOC(Rhs, N).last_column; \ + (Current).parent = YYRHSLOC(Rhs, 1).parent; \ } else { \ (Current) = YYRHSLOC(Rhs, 0); \ } \ diff --git a/dimension/common.rules b/dimension/common.rules index d77ab1a..157edca 100644 --- a/dimension/common.rules +++ b/dimension/common.rules @@ -477,6 +477,14 @@ FLOAT: ARITH_EXPR { } ; +INT: FLOAT { + $$ = $1; + if ($$.type == DMNSN_AST_FLOAT) { + dmnsn_diagnostic(@$, "WARNING: float rounded to integer"); + } + } +; + FLOAT_LITERAL: "integer" { $$ = dmnsn_new_astnode(DMNSN_AST_INTEGER, @$); $$.ptr = dmnsn_malloc(sizeof(long)); diff --git a/dimension/grammar.rules b/dimension/grammar.rules index 25f8a3c..0963a1e 100644 --- a/dimension/grammar.rules +++ b/dimension/grammar.rules @@ -56,9 +56,11 @@ GLOBAL_SETTINGS_ITEMS: /* empty */ { ; GLOBAL_SETTINGS_ITEM: "assumed_gamma" FLOAT { + dmnsn_diagnostic(@1, + "WARNING: assumed_gamma not supported"); $$ = dmnsn_new_astnode1(DMNSN_AST_ASSUMED_GAMMA, @$, $2); } - | "max_trace_level" FLOAT { + | "max_trace_level" INT { $$ = dmnsn_new_astnode1(DMNSN_AST_MAX_TRACE_LEVEL, @$, $2); } diff --git a/dimension/lexer.l b/dimension/lexer.l index f4685b8..1abb4b8 100644 --- a/dimension/lexer.l +++ b/dimension/lexer.l @@ -56,6 +56,7 @@ llocp->first_line = llocp->last_line = yylineno; \ llocp->first_column = yycolumn; \ llocp->last_column = yycolumn + yyleng; \ + llocp->parent = NULL; \ } while (0) #define CALCULATE_COLUMN() do { yycolumn += yyleng; } while (0) diff --git a/dimension/parse.h b/dimension/parse.h index 3a830b8..1e8fa2c 100644 --- a/dimension/parse.h +++ b/dimension/parse.h @@ -171,6 +171,8 @@ typedef struct dmnsn_parse_location { const char *first_filename, *last_filename; int first_line, last_line; int first_column, last_column; + + struct dmnsn_parse_location *parent; } dmnsn_parse_location; /* Abstract syntax tree node (a dmnsn_array* of these is an AST) */ diff --git a/dimension/realize.c b/dimension/realize.c index b6c6a60..8a1f024 100644 --- a/dimension/realize.c +++ b/dimension/realize.c @@ -21,6 +21,7 @@ #include "parse.h" #include "utility.h" #include <math.h> +#include <fenv.h> #include <stdio.h> #include <stdbool.h> @@ -31,8 +32,13 @@ dmnsn_realize_integer(dmnsn_astnode astnode) case DMNSN_AST_INTEGER: return *(long *)astnode.ptr; case DMNSN_AST_FLOAT: - dmnsn_diagnostic(astnode.location, "WARNING: float rounded to integer"); - return *(double *)astnode.ptr; + { + feclearexcept(FE_ALL_EXCEPT); + long ret = lrint(*(double *)astnode.ptr); + if (fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW)) + dmnsn_error(DMNSN_SEVERITY_HIGH, "Float out of range of integer."); + return ret; + } default: dmnsn_assert(false, "Invalid integer."); @@ -191,7 +197,7 @@ dmnsn_realize_global_settings(dmnsn_astnode astnode, dmnsn_scene *scene) switch (item.type) { case DMNSN_AST_ASSUMED_GAMMA: - dmnsn_diagnostic(item.location, "WARNING: assumed_gamma not supported"); + /* assumed_gamma not supported */ break; case DMNSN_AST_MAX_TRACE_LEVEL: @@ -756,9 +762,7 @@ dmnsn_realize_light_source_modifiers(dmnsn_astnode astnode, dmnsn_light *light) case DMNSN_AST_PIGMENT: case DMNSN_AST_FINISH: case DMNSN_AST_INTERIOR: - dmnsn_diagnostic(modifier.location, - "WARNING: ignoring %s applied to light source", - dmnsn_astnode_string(modifier.type)); + /* Ignore other object modifiers */ break; default: diff --git a/dimension/tokenize.c b/dimension/tokenize.c index c821a3c..f46c450 100644 --- a/dimension/tokenize.c +++ b/dimension/tokenize.c @@ -35,6 +35,7 @@ typedef struct dmnsn_token_buffer { /* Indicate that the first token should be returned as-is */ #define DMNSN_T_LEX_VERBATIM DMNSN_T_EOF + dmnsn_parse_location lloc; dmnsn_array *buffered; unsigned int i; @@ -45,11 +46,13 @@ typedef struct dmnsn_token_buffer { } dmnsn_token_buffer; static dmnsn_token_buffer * -dmnsn_new_token_buffer(int type, dmnsn_token_buffer *prev, const char *filename) +dmnsn_new_token_buffer(dmnsn_parse_location lloc, int type, + dmnsn_token_buffer *prev, const char *filename) { dmnsn_token_buffer *tbuffer = dmnsn_malloc(sizeof(dmnsn_token_buffer)); tbuffer->type = type; + tbuffer->lloc = lloc; tbuffer->buffered = dmnsn_new_array(sizeof(dmnsn_buffered_token)); tbuffer->i = 0; tbuffer->prev = prev; @@ -175,7 +178,7 @@ dmnsn_include_buffer(int token, dmnsn_token_buffer *prev, void *yyscanner) { dmnsn_token_buffer *include_buffer - = dmnsn_new_token_buffer(DMNSN_T_LEX_VERBATIM, prev, filename); + = dmnsn_new_token_buffer(*llocp, DMNSN_T_LEX_VERBATIM, prev, filename); /* Buffer the current token */ dmnsn_buffered_token buffered = { @@ -208,7 +211,8 @@ dmnsn_include_buffer(int token, dmnsn_token_buffer *prev, dmnsn_yyset_extra(include_buffer->prev, yyscanner); dmnsn_delete_token_buffer(include_buffer); - dmnsn_token_buffer *tbuffer = dmnsn_new_token_buffer(token, prev, filename); + dmnsn_token_buffer *tbuffer + = dmnsn_new_token_buffer(*llocp, token, prev, filename); dmnsn_astnode *inode = dmnsn_find_symbol(symtable, "$include"); dmnsn_assert(inode, "$include unset."); @@ -273,7 +277,7 @@ dmnsn_declaration_buffer(int token, dmnsn_token_buffer *prev, void *yyscanner) { dmnsn_token_buffer *tbuffer - = dmnsn_new_token_buffer(DMNSN_T_LEX_VERBATIM, prev, filename); + = dmnsn_new_token_buffer(*llocp, DMNSN_T_LEX_VERBATIM, prev, filename); /* Buffer the current token */ dmnsn_buffered_token buffered = { @@ -332,7 +336,7 @@ dmnsn_undef_buffer(int token, dmnsn_token_buffer *prev, void *yyscanner) { dmnsn_token_buffer *tbuffer - = dmnsn_new_token_buffer(DMNSN_T_LEX_VERBATIM, prev, filename); + = dmnsn_new_token_buffer(*llocp, DMNSN_T_LEX_VERBATIM, prev, filename); /* Buffer the current token */ dmnsn_buffered_token buffered = { @@ -372,7 +376,7 @@ dmnsn_if_buffer(int token, dmnsn_token_buffer *prev, void *yyscanner) { dmnsn_token_buffer *cond_buffer - = dmnsn_new_token_buffer(DMNSN_T_LEX_VERBATIM, prev, filename); + = dmnsn_new_token_buffer(*llocp, DMNSN_T_LEX_VERBATIM, prev, filename); /* Buffer the current token */ dmnsn_buffered_token buffered = { @@ -406,7 +410,8 @@ dmnsn_if_buffer(int token, dmnsn_token_buffer *prev, dmnsn_yyset_extra(cond_buffer->prev, yyscanner); dmnsn_delete_token_buffer(cond_buffer); - dmnsn_token_buffer *tbuffer = dmnsn_new_token_buffer(token, prev, filename); + dmnsn_token_buffer *tbuffer + = dmnsn_new_token_buffer(*llocp, token, prev, filename); dmnsn_astnode *cnode = dmnsn_find_symbol(symtable, "$cond"); dmnsn_assert(cnode, "$cond unset."); @@ -484,7 +489,8 @@ dmnsn_while_buffer(int token, dmnsn_token_buffer *prev, const char *filename, dmnsn_symbol_table *symtable, void *yyscanner) { - dmnsn_token_buffer *tbuffer = dmnsn_new_token_buffer(token, prev, filename); + dmnsn_token_buffer *tbuffer + = dmnsn_new_token_buffer(*llocp, token, prev, filename); /* Pretend to be an if */ dmnsn_buffered_token buffered = { @@ -542,7 +548,7 @@ dmnsn_version_buffer(int token, dmnsn_token_buffer *prev, void *yyscanner) { dmnsn_token_buffer *tbuffer - = dmnsn_new_token_buffer(DMNSN_T_LEX_VERBATIM, prev, filename); + = dmnsn_new_token_buffer(*llocp, DMNSN_T_LEX_VERBATIM, prev, filename); /* Buffer the current token */ dmnsn_buffered_token buffered = { @@ -584,7 +590,7 @@ dmnsn_stream_buffer(int token, dmnsn_token_buffer *prev, void *yyscanner) { dmnsn_token_buffer *tbuffer - = dmnsn_new_token_buffer(DMNSN_T_LEX_VERBATIM, prev, filename); + = dmnsn_new_token_buffer(*llocp, DMNSN_T_LEX_VERBATIM, prev, filename); /* Buffer the current token */ dmnsn_buffered_token buffered = { @@ -617,7 +623,7 @@ dmnsn_declare_macro(int token, dmnsn_token_buffer *prev, void *yyscanner) { dmnsn_token_buffer *decl_buffer - = dmnsn_new_token_buffer(DMNSN_T_LEX_VERBATIM, prev, filename); + = dmnsn_new_token_buffer(*llocp, DMNSN_T_LEX_VERBATIM, prev, filename); /* Buffer the current token */ dmnsn_buffered_token buffered = { @@ -651,7 +657,8 @@ dmnsn_declare_macro(int token, dmnsn_token_buffer *prev, dmnsn_yyset_extra(decl_buffer->prev, yyscanner); dmnsn_delete_token_buffer(decl_buffer); - dmnsn_token_buffer *tbuffer = dmnsn_new_token_buffer(token, NULL, filename); + dmnsn_token_buffer *tbuffer + = dmnsn_new_token_buffer(*llocp, token, NULL, filename); dmnsn_astnode *mname = dmnsn_find_symbol(symtable, "$macro"); dmnsn_assert(mname, "$macro unset."); @@ -709,7 +716,7 @@ dmnsn_macro_buffer(int token, dmnsn_astnode *mnode, dmnsn_token_buffer *prev, void *yyscanner) { dmnsn_token_buffer *invoke_buffer - = dmnsn_new_token_buffer(DMNSN_T_LEX_VERBATIM, prev, filename); + = dmnsn_new_token_buffer(*llocp, DMNSN_T_LEX_VERBATIM, prev, filename); /* Buffer the current token */ dmnsn_buffered_token buffered = { @@ -745,6 +752,7 @@ dmnsn_macro_buffer(int token, dmnsn_astnode *mnode, dmnsn_token_buffer *prev, dmnsn_delete_token_buffer(invoke_buffer); dmnsn_token_buffer *tbuffer = mnode->ptr; + tbuffer->lloc = *llocp; tbuffer->i = 0; tbuffer->prev = prev; return tbuffer; @@ -800,17 +808,25 @@ dmnsn_yylex_wrapper(dmnsn_parse_item *lvalp, dmnsn_parse_location *llocp, } *llocp = buffered.lloc; + if (tbuffer->type == DMNSN_T_MACRO) + llocp->parent = &tbuffer->lloc; ++tbuffer->i; } else { const char *real_filename = tbuffer ? tbuffer->filename : filename; token = dmnsn_yylex_impl(lvalp, llocp, real_filename, yyscanner); - if (token == DMNSN_T_EOF && tbuffer && tbuffer->type == DMNSN_T_INCLUDE) { - dmnsn_yy_pop_buffer(yyscanner); - fclose(tbuffer->ptr); - dmnsn_pop_scope(symtable); - dmnsn_yyset_extra(tbuffer->prev, yyscanner); - dmnsn_delete_token_buffer(tbuffer); - return dmnsn_yylex_wrapper(lvalp, llocp, filename, symtable, yyscanner); + + if (tbuffer && tbuffer->type == DMNSN_T_INCLUDE) { + if (token == DMNSN_T_EOF) { + dmnsn_yy_pop_buffer(yyscanner); + fclose(tbuffer->ptr); + dmnsn_pop_scope(symtable); + dmnsn_yyset_extra(tbuffer->prev, yyscanner); + dmnsn_delete_token_buffer(tbuffer); + return dmnsn_yylex_wrapper(lvalp, llocp, filename, symtable, + yyscanner); + } else { + llocp->parent = &tbuffer->lloc; + } } } diff --git a/dimension/utility.c b/dimension/utility.c index 17a7bba..aaee59b 100644 --- a/dimension/utility.c +++ b/dimension/utility.c @@ -45,4 +45,8 @@ dmnsn_diagnostic(dmnsn_parse_location location, const char *format, ...) fprintf(stderr, "\n"); va_end(ap); + + if (location.parent) { + dmnsn_diagnostic(*location.parent, "-- from here"); + } } |