summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2010-04-18 23:18:45 -0400
committerTavian Barnes <tavianator@gmail.com>2010-04-18 23:18:45 -0400
commit919121bdf572b632cc5bfbbee502664682b26ab8 (patch)
tree528a83bb716851152ebc12aee385417b8f407601
parent004d63c0c199a1544dc9b3af9cdd3367a6969d23 (diff)
downloaddimension-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.nonterminals1
-rw-r--r--dimension/common.prologue1
-rw-r--r--dimension/common.rules8
-rw-r--r--dimension/grammar.rules4
-rw-r--r--dimension/lexer.l1
-rw-r--r--dimension/parse.h2
-rw-r--r--dimension/realize.c16
-rw-r--r--dimension/tokenize.c56
-rw-r--r--dimension/utility.c4
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");
+ }
}