Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'symtab'

  • Loading branch information...
commit 6cd45f7bb8abaed204628ec8566fa1690b84bf97 2 parents 6bc121b + 7496b45
@wpwrak wpwrak authored
Showing with 1,742 additions and 1,395 deletions.
  1. +8 −7 patches/Unchained - A Matter Of Taste (Remix).fnp
  2. +3 −2 src/Makefile
  3. +12 −6 src/compiler/Makefile
  4. +39 −236 src/compiler/compiler.c
  5. +2 −3 src/compiler/compiler.h
  6. +158 −238 src/compiler/fnp.ids
  7. +15 −7 src/compiler/idgen
  8. +269 −203 src/compiler/parser.y
  9. +91 −37 src/compiler/parser_helper.c
  10. +15 −8 src/compiler/parser_helper.h
  11. +11 −3 src/compiler/parser_itf.h
  12. +7 −3 src/compiler/ptest/Makefile
  13. +78 −27 src/compiler/ptest/ptest.c
  14. +4 −4 src/compiler/scanner.h
  15. +10 −6 src/compiler/scanner.re
  16. +158 −0 src/compiler/symtab.c
  17. +44 −0 src/compiler/symtab.h
  18. +6 −1 src/compiler/test/Common
  19. +73 −0 src/compiler/test/Patches
  20. +15 −15 src/compiler/test/arith
  21. +2 −2 src/compiler/test/codegen
  22. +47 −47 src/compiler/test/comment
  23. +12 −12 src/compiler/test/cond
  24. +34 −0 src/compiler/test/dualuse
  25. +51 −0 src/compiler/test/eqnum
  26. +11 −11 src/compiler/test/error
  27. +18 −18 src/compiler/test/fcond
  28. +53 −53 src/compiler/test/fold
  29. +3 −3 src/compiler/test/image
  30. +48 −0 src/compiler/test/initial
  31. +43 −43 src/compiler/test/location
  32. +39 −29 src/compiler/test/not
  33. +32 −0 src/compiler/test/nsyms
  34. +18 −18 src/compiler/test/number
  35. +7 −68 src/compiler/test/patches
  36. +42 −42 src/compiler/test/prec
  37. +56 −56 src/compiler/test/relop
  38. +19 −9 src/compiler/test/sections
  39. +23 −23 src/compiler/test/wrap
  40. +79 −0 src/compiler/test/wsection
  41. +77 −0 src/compiler/test/wundef
  42. +0 −135 src/compiler/unique.c
  43. +0 −18 src/compiler/unique.h
  44. +3 −1 src/gui/monitor.c
  45. +2 −0  src/renderer/eval.c
  46. +1 −0  src/renderer/framedescriptor.h
  47. +4 −1 src/renderer/sampler.c
View
15 patches/Unchained - A Matter Of Taste (Remix).fnp
@@ -38,16 +38,17 @@ ib_r=0.250000
ib_g=0.250000
ib_b=0.250000
ib_a=0.000000
-per_frame=pulse=above(bass,0.7)//if(above(abs(pulse),9.42),-9.42,pulse+.1*bor(bor(bass_changed*bnot(treb_changed),treb_changed*bnot(bass_changed))*bnot(mid_changed),mid_changed)+(mid+bass+treb)*entropy*.01);
-per_frame=q1=mid_residual;
-per_frame=q2=bass_residual;
-per_frame=q3=treb_residual;
+per_frame=pulse=above(bass,0.7);
+//if(above(abs(pulse),9.42),-9.42,pulse+.1*bor(bor(bass_changed*bnot(treb_changed),treb_changed*bnot(bass_changed))*bnot(mid_changed),mid_changed)+(mid+bass+treb)*entropy*.01);
+//per_frame=q1=mid_residual;
+//per_frame=q2=bass_residual;
+//per_frame=q3=treb_residual;
per_frame=q4=sin(pulse);
per_frame=q5=cos(pulse);
per_frame=wave_mystery=-.2+.2*q4;
-per_frame=wave_r=wave_r+.5*bass_residual;
-per_frame=wave_r=wave_g+.5*mid_residual;
-per_frame=wave_r=wave_b+.5*treb_residual;
+//per_frame=wave_r=wave_r+.5*bass_residual;
+//per_frame=wave_r=wave_g+.5*mid_residual;
+//per_frame=wave_r=wave_b+.5*treb_residual;
per_frame=zoom=zoom-.0035*q1;
per_frame=decay=decay+.003*sin(pulse);
per_vertex=anti_rad=(1-rad);
View
5 src/Makefile
@@ -34,6 +34,7 @@ endif
CFLAGS = -O9 -Wall -Wstrict-prototypes -Wmissing-prototypes \
-Wold-style-declaration -Wold-style-definition \
+ -Wno-char-subscripts \
-mbarrel-shift-enabled -mmultiply-enabled \
-mdivide-enabled -msign-extend-enabled -fsingle-precision-constant \
-I$(RTEMS_MAKEFILE_PATH)/lib/include -g
@@ -63,7 +64,7 @@ OBJS += $(addprefix renderer/,framedescriptor.o analyzer.o sampler.o \
eval.o line.o wave.o font.o osd.o raster.o renderer.o \
videoinreconf.o)
OBJS += $(addprefix compiler/,compiler.o parser_helper.o scanner.o \
- parser.o unique.o)
+ parser.o symtab.o)
POBJS=$(addprefix $(OBJDIR)/,$(OBJS))
@@ -99,7 +100,7 @@ compiler/infra-fnp.h: \
compiler/parser.h: compiler/parser.c
obj/compiler/scanner.o: compiler/parser.h
obj/compiler/parser_helper.o: compiler/parser.h
-obj/compiler/unique.o: compiler/fnp.inc
+obj/compiler/symtab.o: compiler/fnp.inc
obj/compiler/compiler.o: compiler/infra-fnp.h compiler/parser.h
# boot images for Milkymist One
View
18 src/compiler/Makefile
@@ -7,18 +7,24 @@ all:
# ----- Tests -----------------------------------------------------------------
test tests: all
- LANG= sh -c \
- 'passed=0 && cd test && \
- for n in [a-z]*; do \
- [ $$n != core ] && SCRIPT=$$n . ./$$n; done; \
- echo "Passed all $$passed tests"'
+ LANG= sh -c \
+ 'passed=0 && failed=0 && cd test && \
+ for n in [a-z]*; do \
+ [ $$n != core ] && SCRIPT=$$n . ./$$n; done; \
+ if [ $$failed = 0 ]; then \
+ echo "Passed all $$passed tests"; \
+ else \
+ total=`expr $$passed + $$failed`; \
+ echo "Failed $$failed/$$total tests"; \
+ exit 1; \
+ fi'
valgrind:
VALGRIND="valgrind -q" $(MAKE) tests
leak leaks:
VALGRIND="valgrind -q --leak-check=full --show-reachable=yes" \
- $(MAKE) tests
+ FAIL_ON_ERROR=false $(MAKE) tests
# ----- Cleanup ---------------------------------------------------------------
View
275 src/compiler/compiler.c
@@ -23,12 +23,13 @@
#include <string.h>
#include <fpvm/fpvm.h>
+#include <fpvm/symbol.h>
#include <fpvm/ast.h>
#include <fpvm/schedulers.h>
#include <fpvm/pfpu.h>
#include "../pixbuf/pixbuf.h"
-#include "unique.h"
+#include "symtab.h"
#include "parser_helper.h"
#include "parser.h"
#include "compiler.h"
@@ -65,10 +66,10 @@ static void init_fpvm(struct fpvm_fragment *fragment, int vector_mode)
* the same. We can get rid of these calls to unique() later.
*/
- _Xi = unique("_Xi");
- _Xo = unique("_Xo");
- _Yi = unique("_Yi");
- _Yo = unique("_Yo");
+ _Xi = &unique("_Xi")->fpvm_sym;
+ _Xo = &unique("_Xo")->fpvm_sym;
+ _Yi = &unique("_Yi")->fpvm_sym;
+ _Yo = &unique("_Yo")->fpvm_sym;
fpvm_do_init(fragment, vector_mode);
}
@@ -76,9 +77,9 @@ static void init_fpvm(struct fpvm_fragment *fragment, int vector_mode)
static const char *assign_chunk(struct parser_comm *comm,
- const char *label, struct ast_node *node)
+ struct sym *sym, struct ast_node *node)
{
- if(fpvm_do_assign(comm->u.fragment, label, node))
+ if(fpvm_do_assign(comm->u.fragment, &sym->fpvm_sym, node))
return NULL;
else
return strdup(fpvm_get_last_error(comm->u.fragment));
@@ -92,14 +93,12 @@ static int compile_chunk(struct fpvm_fragment *fragment, const char *chunk)
.assign_per_frame = NULL, /* crash ... */
.assign_per_vertex = NULL, /* and burn */
};
- const char *error;
- error = parse(chunk, TOK_START_ASSIGN, &comm);
- if(error) {
- snprintf(fragment->last_error, FPVM_MAXERRLEN, "%s", error);
- free((void *) error);
- }
- return !error;
+ if(parse(chunk, TOK_START_ASSIGN, &comm))
+ return 1;
+ snprintf(fragment->last_error, FPVM_MAXERRLEN, "%s", comm.msg);
+ free((void *) comm.msg);
+ return 0;
}
@@ -107,139 +106,9 @@ static int compile_chunk(struct fpvm_fragment *fragment, const char *chunk)
/* PER-FRAME VARIABLES */
/****************************************************************/
-const char pfv_names[COMP_PFV_COUNT][FPVM_MAXSYMLEN] = {
- "sx",
- "sy",
- "cx",
- "cy",
- "rot",
- "dx",
- "dy",
- "zoom",
- "decay",
- "wave_mode",
- "wave_scale",
- "wave_additive",
- "wave_usedots",
- "wave_brighten",
- "wave_thick",
- "wave_x",
- "wave_y",
- "wave_r",
- "wave_g",
- "wave_b",
- "wave_a",
-
- "ob_size",
- "ob_r",
- "ob_g",
- "ob_b",
- "ob_a",
- "ib_size",
- "ib_r",
- "ib_g",
- "ib_b",
- "ib_a",
-
- "nMotionVectorsX",
- "nMotionVectorsY",
- "mv_dx",
- "mv_dy",
- "mv_l",
- "mv_r",
- "mv_g",
- "mv_b",
- "mv_a",
-
- "bTexWrap",
-
- "time",
- "bass",
- "mid",
- "treb",
- "bass_att",
- "mid_att",
- "treb_att",
-
- "warp",
- "fWarpAnimSpeed",
- "fWarpScale",
-
- "q1",
- "q2",
- "q3",
- "q4",
- "q5",
- "q6",
- "q7",
- "q8",
-
- "fVideoEchoAlpha",
- "fVideoEchoZoom",
- "nVideoEchoOrientation",
-
- "dmx1",
- "dmx2",
- "dmx3",
- "dmx4",
- "dmx5",
- "dmx6",
- "dmx7",
- "dmx8",
-
- "idmx1",
- "idmx2",
- "idmx3",
- "idmx4",
- "idmx5",
- "idmx6",
- "idmx7",
- "idmx8",
-
- "osc1",
- "osc2",
- "osc3",
- "osc4",
-
- "midi1",
- "midi2",
- "midi3",
- "midi4",
- "midi5",
- "midi6",
- "midi7",
- "midi8",
-
- "video_a",
-
- "image1_a",
- "image1_x",
- "image1_y",
- "image1_zoom",
- "image2_a",
- "image2_x",
- "image2_y",
- "image2_zoom"
-};
-
-static int pfv_from_name(const char *name)
+static int pfv_from_sym(const struct sym *sym)
{
- int i;
-
- for(i=0;i<COMP_PFV_COUNT;i++) {
- if(strcmp(pfv_names[i], name) == 0)
- return i;
- }
-
- if(strcmp(name, "fDecay") == 0) return pfv_decay;
- if(strcmp(name, "nWaveMode") == 0) return pfv_wave_mode;
- if(strcmp(name, "fWaveScale") == 0) return pfv_wave_scale;
- if(strcmp(name, "bAdditiveWaves") == 0) return pfv_wave_additive;
- if(strcmp(name, "bWaveDots") == 0) return pfv_wave_usedots;
- if(strcmp(name, "bMaximizeWaveColor") == 0) return pfv_wave_brighten;
- if(strcmp(name, "bWaveThick") == 0) return pfv_wave_thick;
- if(strcmp(name, "fWaveAlpha") == 0) return pfv_wave_a;
- return -1;
+ return sym->pfv_idx;
}
static void pfv_update_patch_requires(struct compiler_sc *sc, int pfv)
@@ -314,12 +183,12 @@ static void all_initials_to_pfv(struct compiler_sc *sc)
initial_to_pfv(sc, i);
}
-static void pfv_bind_callback(void *_sc, const char *sym, int reg)
+static void pfv_bind_callback(void *_sc, struct fpvm_sym *sym, int reg)
{
struct compiler_sc *sc = _sc;
int pfv;
- pfv = pfv_from_name(sym);
+ pfv = pfv_from_sym(FPVM2SYM(sym));
if(pfv >= 0) {
pfv_update_patch_requires(sc, pfv);
sc->p->pfv_allocation[pfv] = reg;
@@ -377,76 +246,9 @@ static bool schedule_pfv(struct compiler_sc *sc)
/* PER-VERTEX VARIABLES */
/****************************************************************/
-const char pvv_names[COMP_PVV_COUNT][FPVM_MAXSYMLEN] = {
- /* System */
- "_texsize",
- "_hmeshsize",
- "_vmeshsize",
-
- /* MilkDrop */
- "sx",
- "sy",
- "cx",
- "cy",
- "rot",
- "dx",
- "dy",
- "zoom",
-
- "time",
- "bass",
- "mid",
- "treb",
- "bass_att",
- "mid_att",
- "treb_att",
-
- "warp",
- "fWarpAnimSpeed",
- "fWarpScale",
-
- "q1",
- "q2",
- "q3",
- "q4",
- "q5",
- "q6",
- "q7",
- "q8",
-
- "idmx1",
- "idmx2",
- "idmx3",
- "idmx4",
- "idmx5",
- "idmx6",
- "idmx7",
- "idmx8",
-
- "osc1",
- "osc2",
- "osc3",
- "osc4",
-
- "midi1",
- "midi2",
- "midi3",
- "midi4",
- "midi5",
- "midi6",
- "midi7",
- "midi8",
-};
-
-static int pvv_from_name(const char *name)
+static int pvv_from_sym(const struct sym *sym)
{
- int i;
-
- for(i=0;i<COMP_PVV_COUNT;i++) {
- if(strcmp(pvv_names[i], name) == 0)
- return i;
- }
- return -1;
+ return sym->pvv_idx;
}
static void pvv_update_patch_requires(struct compiler_sc *sc, int pvv)
@@ -459,12 +261,12 @@ static void pvv_update_patch_requires(struct compiler_sc *sc, int pvv)
sc->p->require |= REQUIRE_MIDI;
}
-static void pvv_bind_callback(void *_sc, const char *sym, int reg)
+static void pvv_bind_callback(void *_sc, struct fpvm_sym *sym, int reg)
{
struct compiler_sc *sc = _sc;
int pvv;
- pvv = pvv_from_name(sym);
+ pvv = pvv_from_sym(FPVM2SYM(sym));
if(pvv >= 0) {
pvv_update_patch_requires(sc, pvv);
sc->p->pvv_allocation[pvv] = reg;
@@ -540,13 +342,13 @@ static bool schedule_pvv(struct compiler_sc *sc)
/****************************************************************/
static const char *assign_default(struct parser_comm *comm,
- const char *label, struct ast_node *node)
+ struct sym *sym, struct ast_node *node)
{
struct compiler_sc *sc = comm->u.sc;
int pfv;
float v;
- pfv = pfv_from_name(label);
+ pfv = pfv_from_sym(sym);
if(pfv < 0)
return strdup("unknown parameter");
@@ -571,24 +373,24 @@ static const char *assign_default(struct parser_comm *comm,
}
static const char *assign_fragment(struct fpvm_fragment *frag,
- const char *label, struct ast_node *node)
+ struct sym *sym, struct ast_node *node)
{
- if(fpvm_do_assign(frag, label, node))
+ if(fpvm_do_assign(frag, &sym->fpvm_sym, node))
return NULL;
else
return strdup(fpvm_get_last_error(frag));
}
static const char *assign_per_frame(struct parser_comm *comm,
- const char *label, struct ast_node *node)
+ struct sym *sym, struct ast_node *node)
{
- return assign_fragment(&comm->u.sc->pfv_fragment, label, node);
+ return assign_fragment(&comm->u.sc->pfv_fragment, sym, node);
}
static const char *assign_per_vertex(struct parser_comm *comm,
- const char *label, struct ast_node *node)
+ struct sym *sym, struct ast_node *node)
{
- return assign_fragment(&comm->u.sc->pvv_fragment, label, node);
+ return assign_fragment(&comm->u.sc->pvv_fragment, sym, node);
}
static const char *assign_image_name(struct parser_comm *comm,
@@ -627,14 +429,13 @@ static bool parse_patch(struct compiler_sc *sc, const char *patch_code)
.assign_per_vertex = assign_per_vertex,
.assign_image_name = assign_image_name,
};
- const char *error;
+ int ok;
- error = parse(patch_code, TOK_START_ASSIGN, &comm);
- if(error) {
- sc->rmc(error);
- free((void *) error);
- }
- return !error;
+ ok = parse(patch_code, TOK_START_ASSIGN, &comm);
+ if(comm.msg)
+ sc->rmc(comm.msg);
+ free((void *) comm.msg);
+ return ok;
}
struct patch *patch_compile(const char *basedir, const char *patch_code,
@@ -665,6 +466,8 @@ struct patch *patch_compile(const char *basedir, const char *patch_code,
sc->rmc = rmc;
sc->linenr = 0;
+ symtab_init();
+
load_defaults(sc);
if(!init_pfv(sc)) goto fail;
if(!init_pvv(sc)) goto fail;
@@ -677,13 +480,13 @@ struct patch *patch_compile(const char *basedir, const char *patch_code,
if(!finalize_pvv(sc)) goto fail;
if(!schedule_pvv(sc)) goto fail;
- unique_free();
+ symtab_free();
free(sc);
return p;
fail:
- unique_free();
+ symtab_free();
free(sc->p);
free(sc);
return NULL;
View
5 src/compiler/compiler.h
@@ -77,6 +77,7 @@ enum {
pfv_tex_wrap,
pfv_time,
+ pfv_frame,
pfv_bass,
pfv_mid,
pfv_treb,
@@ -164,6 +165,7 @@ enum {
pvv_zoom,
pvv_time,
+ pvv_frame,
pvv_bass,
pvv_mid,
pvv_treb,
@@ -236,9 +238,6 @@ struct patch {
typedef void (*report_message)(const char *);
-extern const char pfv_names[COMP_PFV_COUNT][FPVM_MAXSYMLEN];
-extern const char pvv_names[COMP_PVV_COUNT][FPVM_MAXSYMLEN];
-
struct patch *patch_compile(const char *basedir, const char *patch_code, report_message rmc);
struct patch *patch_compile_filename(const char *filename, const char *patch_code, report_message rmc);
struct patch *patch_copy(struct patch *p);
View
396 src/compiler/fnp.ids
@@ -11,232 +11,152 @@
#
#
-# Built-in functions
-#
-
-above
-abs
-below
-cos
-equal
-f2i
-icos
-i2f
-if
-int
-invsqrt
-isin
-max
-min
-quake
-sin
-sqr
-sqrt
-tsign
-
-#
-#
-# Per-Frame Variables
-#
-
-sx
-sy
-cx
-cy
-rot
-dx
-dy
-zoom
-decay
-wave_mode
-wave_scale
-wave_additive
-wave_usedots
-wave_brighten
-wave_thick
-wave_x
-wave_y
-wave_r
-wave_g
-wave_b
-wave_a
-
-ob_size
-ob_r
-ob_g
-ob_b
-ob_a
-ib_size
-ib_r
-ib_g
-ib_b
-ib_a
-
-nMotionVectorsY
-mv_dx
-mv_dy
-mv_l
-mv_r
-mv_g
-mv_b
-mv_a
-
-bTexWrap
-
-time
-bass
-mid
-treb
-bass_att
-mid_att
-treb_att
-
-warp
-fWarpAnimSpeed
-fWarpScale
-
-q1
-q2
-q3
-q4
-q5
-q6
-q7
-q8
-
-fVideoEchoAlpha
-fVideoEchoZoom
-nVideoEchoOrientation
-
-dmx1
-dmx2
-dmx3
-dmx4
-dmx5
-dmx6
-dmx7
-dmx8
-
-idmx1
-idmx2
-idmx3
-idmx4
-idmx5
-idmx6
-idmx7
-idmx8
-
-osc1
-osc2
-osc3
-osc4
-
-midi1
-midi2
-midi3
-midi4
-midi5
-midi6
-midi7
-midi8
-
-video_a
-
-image1_a
-image1_x
-image1_y
-image1_zoom
-image2_a
-image2_x
-image2_y
-image2_zoom
+# Per-Frame and Per-Vertex Variables
+#
+
+sx pfv_sx pvv_sx
+sy pfv_sy pvv_sy
+cx pfv_cx pvv_cx
+cy pfv_cy pvv_cy
+rot pfv_rot pvv_rot
+dx pfv_dx pvv_dx
+dy pfv_dy pvv_dy
+zoom pfv_zoom pvv_zoom
+decay pfv_decay -1
+wave_mode pfv_wave_mode -1
+wave_scale pfv_wave_scale -1
+wave_additive pfv_wave_additive -1
+wave_usedots pfv_wave_usedots -1
+wave_brighten pfv_wave_brighten -1
+wave_thick pfv_wave_thick -1
+wave_x pfv_wave_x -1
+wave_y pfv_wave_y -1
+wave_r pfv_wave_r -1
+wave_g pfv_wave_g -1
+wave_b pfv_wave_b -1
+wave_a pfv_wave_a -1
+
+ob_size pfv_ob_size -1
+ob_r pfv_ob_r -1
+ob_g pfv_ob_g -1
+ob_b pfv_ob_b -1
+ob_a pfv_ob_a -1
+ib_size pfv_ib_size -1
+ib_r pfv_ib_r -1
+ib_g pfv_ib_g -1
+ib_b pfv_ib_b -1
+ib_a pfv_ib_a -1
+
+nMotionVectorsX pfv_mv_x -1
+nMotionVectorsY pfv_mv_y -1
+mv_dx pfv_mv_dx -1
+mv_dy pfv_mv_dy -1
+mv_l pfv_mv_l -1
+mv_r pfv_mv_r -1
+mv_g pfv_mv_g -1
+mv_b pfv_mv_b -1
+mv_a pfv_mv_a -1
+
+bTexWrap pfv_tex_wrap -1
+
+time pfv_time pvv_time
+frame pfv_frame pvv_frame
+bass pfv_bass pvv_bass
+mid pfv_mid pvv_mid
+treb pfv_treb pvv_treb
+bass_att pfv_bass_att pvv_bass_att
+mid_att pfv_mid_att pvv_mid_att
+treb_att pfv_treb_att pvv_treb_att
+
+warp pfv_warp pvv_warp
+fWarpAnimSpeed pfv_warp_anim_speed pvv_warp_anim_speed
+fWarpScale pfv_warp_scale pvv_warp_scale
+
+q1 pfv_q1 pvv_q1
+q2 pfv_q2 pvv_q2
+q3 pfv_q3 pvv_q3
+q4 pfv_q4 pvv_q4
+q5 pfv_q5 pvv_q5
+q6 pfv_q6 pvv_q6
+q7 pfv_q7 pvv_q7
+q8 pfv_q8 pvv_q8
+
+fVideoEchoAlpha pfv_video_echo_alpha -1
+fVideoEchoZoom pfv_video_echo_zoom -1
+nVideoEchoOrientation pfv_video_echo_orientation -1
+
+dmx1 pfv_dmx1 -1
+dmx2 pfv_dmx2 -1
+dmx3 pfv_dmx3 -1
+dmx4 pfv_dmx4 -1
+dmx5 pfv_dmx5 -1
+dmx6 pfv_dmx6 -1
+dmx7 pfv_dmx7 -1
+dmx8 pfv_dmx8 -1
+
+idmx1 pfv_idmx1 pvv_idmx1
+idmx2 pfv_idmx2 pvv_idmx2
+idmx3 pfv_idmx3 pvv_idmx3
+idmx4 pfv_idmx4 pvv_idmx4
+idmx5 pfv_idmx5 pvv_idmx5
+idmx6 pfv_idmx6 pvv_idmx6
+idmx7 pfv_idmx7 pvv_idmx7
+idmx8 pfv_idmx8 pvv_idmx8
+
+osc1 pfv_osc1 pvv_osc1
+osc2 pfv_osc2 pvv_osc2
+osc3 pfv_osc3 pvv_osc3
+osc4 pfv_osc4 pvv_osc4
+
+midi1 pfv_midi1 pvv_midi1
+midi2 pfv_midi2 pvv_midi2
+midi3 pfv_midi3 pvv_midi3
+midi4 pfv_midi4 pvv_midi4
+midi5 pfv_midi5 pvv_midi5
+midi6 pfv_midi6 pvv_midi6
+midi7 pfv_midi7 pvv_midi7
+midi8 pfv_midi8 pvv_midi8
+
+video_a pfv_video_a -1
+
+image1_a pfv_image1_a -1
+image1_x pfv_image1_x -1
+image1_y pfv_image1_y -1
+image1_zoom pfv_image1_zoom -1
+image2_a pfv_image2_a -1
+image2_x pfv_image2_x -1
+image2_y pfv_image2_y -1
+image2_zoom pfv_image2_zoom -1
#
# Aliases
#
-fDecay
-nWaveMode
-fWaveScale
-bAdditiveWaves
-bWaveDots
-bMaximizeWaveColor
-bWaveThick
-fWaveAlpha
+fDecay pfv_decay -1
+nWaveMode pfv_wave_mode -1
+fWaveScale pfv_wave_scale -1
+bAdditiveWaves pfv_wave_additive -1
+bWaveDots pfv_wave_usedots -1
+bMaximizeWaveColor pfv_wave_brighten -1
+bWaveThick pfv_wave_thick -1
+fWaveAlpha pfv_wave_a -1
#
-# Per-Vertex Variables
+# Per-Vertex Variables (system)
#
-# System
-
-_texsize
-_hmeshsize
-_vmeshsize
-
-# MilkDrop
-
-sx
-sy
-cx
-cy
-rot
-dx
-dy
-zoom
-
-time
-bass
-mid
-treb
-bass_att
-mid_att
-treb_att
-
-warp
-fWarpAnimSpeed
-fWarpScale
-
-q1
-q2
-q3
-q4
-q5
-q6
-q7
-q8
-
-idmx1
-idmx2
-idmx3
-idmx4
-idmx5
-idmx6
-idmx7
-idmx8
-
-osc1
-osc2
-osc3
-osc4
-
-midi1
-midi2
-midi3
-midi4
-midi5
-midi6
-midi7
-midi8
+_texsize -1 pvv_texsize
+_hmeshsize -1 pvv_hmeshsize
+_vmeshsize -1 pvv_vmeshsize
#
# FPVM internal variables
#
-_Xo
-_Yo
-_Xi
-_Yi
+_Xo -1 -1
+_Yo -1 -1
+_Xi -1 -1
+_Yi -1 -1
#
# PVV internal variables
@@ -244,41 +164,41 @@ _Yi
# Initialization
-x
-y
-rad
+x -1 -1
+y -1 -1
+rad -1 -1
# Zoom
-_invzoom
-_xy
-_yz
+_invzoom -1 -1
+_xy -1 -1
+_yz -1 -1
# Scale
-_xs
-_ys
+_xs -1 -1
+_ys -1 -1
# Warp
-_warptime
-_invwarpscale
-_f0
-_f1
-_f2
-_f3
-_ox2
-_oy2
-_xw
-_yw
+_warptime -1 -1
+_invwarpscale -1 -1
+_f0 -1 -1
+_f1 -1 -1
+_f2 -1 -1
+_f3 -1 -1
+_ox2 -1 -1
+_oy2 -1 -1
+_xw -1 -1
+_yw -1 -1
# Rotate
-_cosr
-_sinr
-_u
-_v
-_xr
-_yr
-_xd
-_yd
+_cosr -1 -1
+_sinr -1 -1
+_u -1 -1
+_v -1 -1
+_xr -1 -1
+_yr -1 -1
+_xd -1 -1
+_yd -1 -1
View
22 src/compiler/idgen
@@ -2,7 +2,7 @@
#
# idgen - Identifier table generator
#
-# Copyright 2011 by Werner Almesberger
+# Copyright 2011-2012 by Werner Almesberger
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,17 +21,17 @@ usage()
[ "$2" ] && usage
[ -r "$1" ] || { echo "$1: not found" 1&2; exit 1; }
-trap "echo $1.h $1.inc" 0
-
f=`basename "$1" .ids`
+trap "rm $f.h $f.inc" 0
+
cat <<EOF >$f.h
/* MACHINE-GENERATED. DO NOT EDIT ! */
#ifndef IDS_H
#define IDS_H
-extern const char *well_known[];
+extern struct sym *well_known[];
EOF
@@ -40,11 +40,19 @@ cat <<EOF >$f.inc
EOF
-sed 's/#.*//;s/ //g;/^$/d' $1 | sort | uniq | {
+sed 's/#.*//;/^ *$/d' $1 | sort | {
i=0
while read n; do
- echo "#define ID_$n (well_known[$i])" >>$f.h
- echo "\"$n\"," >>$f.inc
+ set - $n
+ echo "#define ID_$1 (well_known[$i])" >>$f.h
+ cat <<EOF >>$f.inc
+{
+ .fpvm_sym = { .name = "$1" },
+ .pfv_idx = $2,
+ .pvv_idx = $3,
+ .flags = SF_SYSTEM,
+},
+EOF
i=`expr $i + 1`
done
}
View
472 src/compiler/parser.y
@@ -16,160 +16,170 @@
*/
%include {
- #include <assert.h>
- #include <string.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include <math.h>
- #include <fpvm/ast.h>
- #include <fpvm/fpvm.h>
- #include "parser_itf.h"
- #include "parser_helper.h"
- #include "parser.h"
-
-
- struct yyParser;
- static void yy_parse_failed(struct yyParser *yypParser);
-
- typedef const char *(*assign_callback)(struct parser_comm *comm,
- const char *label, struct ast_node *node);
-
- #define FAIL \
- do { \
- syntax_error(state); \
- yy_parse_failed(yypParser); \
- } while (0)
-
- #define OTHER_STYLE_new_style old_style
- #define OTHER_STYLE_old_style new_style
-
- #define IS_STYLE(which) \
- do { \
- if(state->style == OTHER_STYLE_##which) { \
- FAIL; \
- return; \
- } \
- state->style = which; \
- } while (0)
-
- const enum ast_op tok2op[] = {
- [TOK_IDENT] = op_ident,
- [TOK_CONSTANT] = op_constant,
- [TOK_PLUS] = op_plus,
- [TOK_MINUS] = op_minus,
- [TOK_MULTIPLY] = op_multiply,
- [TOK_DIVIDE] = op_divide,
- [TOK_PERCENT] = op_percent,
- [TOK_ABS] = op_abs,
- [TOK_ISIN] = op_isin,
- [TOK_ICOS] = op_icos,
- [TOK_SIN] = op_sin,
- [TOK_COS] = op_cos,
- [TOK_ABOVE] = op_above,
- [TOK_BELOW] = op_below,
- [TOK_EQUAL] = op_equal,
- [TOK_I2F] = op_i2f,
- [TOK_F2I] = op_f2i,
- [TOK_IF] = op_if,
- [TOK_TSIGN] = op_tsign,
- [TOK_QUAKE] = op_quake,
- [TOK_SQR] = op_sqr,
- [TOK_SQRT] = op_sqrt,
- [TOK_INVSQRT] = op_invsqrt,
- [TOK_MIN] = op_min,
- [TOK_MAX] = op_max,
- [TOK_INT] = op_int,
- };
-
- static struct ast_node *node_op(enum ast_op op, const char *id,
- struct ast_node *a, struct ast_node *b, struct ast_node *c)
- {
- struct ast_node *n;
-
- n = malloc(sizeof(struct ast_node));
- n->op = op;
- n->label = id;
- n->contents.branches.a = a;
- n->contents.branches.b = b;
- n->contents.branches.c = c;
- return n;
- }
- static struct ast_node *node(int token, const char *id,
- struct ast_node *a, struct ast_node *b, struct ast_node *c)
- {
- return node_op(tok2op[token], id, a, b, c);
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <math.h>
+
+#include <fpvm/ast.h>
+#include <fpvm/fpvm.h>
+
+#include "symtab.h"
+#include "parser_itf.h"
+#include "parser_helper.h"
+#include "parser.h"
+
+
+struct yyParser;
+static void yy_parse_failed(struct yyParser *yypParser);
+
+typedef const char *(*assign_callback)(struct parser_comm *comm,
+ struct sym *sym, struct ast_node *node);
+
+#define FAIL(msg) \
+ do { \
+ error(state, msg); \
+ yy_parse_failed(yypParser); \
+ } while (0)
+
+#define OTHER_STYLE_new_style old_style
+#define OTHER_STYLE_old_style new_style
+
+#define IS_STYLE(which) \
+ do { \
+ if(state->style == OTHER_STYLE_##which) { \
+ FAIL("style mismatch"); \
+ return; \
+ } \
+ state->style = which; \
+ } while (0)
+
+static const enum ast_op tok2op[] = {
+ [TOK_IDENT] = op_ident,
+ [TOK_CONSTANT] = op_constant,
+ [TOK_PLUS] = op_plus,
+ [TOK_MINUS] = op_minus,
+ [TOK_MULTIPLY] = op_multiply,
+ [TOK_DIVIDE] = op_divide,
+ [TOK_PERCENT] = op_percent,
+ [TOK_ABS] = op_abs,
+ [TOK_ISIN] = op_isin,
+ [TOK_ICOS] = op_icos,
+ [TOK_SIN] = op_sin,
+ [TOK_COS] = op_cos,
+ [TOK_ABOVE] = op_above,
+ [TOK_BELOW] = op_below,
+ [TOK_EQUAL] = op_equal,
+ [TOK_I2F] = op_i2f,
+ [TOK_F2I] = op_f2i,
+ [TOK_IF] = op_if,
+ [TOK_TSIGN] = op_tsign,
+ [TOK_QUAKE] = op_quake,
+ [TOK_SQR] = op_sqr,
+ [TOK_SQRT] = op_sqrt,
+ [TOK_INVSQRT] = op_invsqrt,
+ [TOK_MIN] = op_min,
+ [TOK_MAX] = op_max,
+ [TOK_INT] = op_int,
+};
+
+static struct ast_node *node_op(enum ast_op op,
+ struct ast_node *a, struct ast_node *b, struct ast_node *c)
+{
+ struct ast_node *n;
+
+ n = malloc(sizeof(struct ast_node));
+ n->op = op;
+ n->sym = NULL;
+ n->contents.branches.a = a;
+ n->contents.branches.b = b;
+ n->contents.branches.c = c;
+ return n;
+}
+
+static struct ast_node *node(int token, struct sym *sym,
+ struct ast_node *a, struct ast_node *b, struct ast_node *c)
+{
+ struct ast_node *n;
+
+ n = node_op(tok2op[token], a, b, c);
+ n->sym = &sym->fpvm_sym;
+ return n;
+}
+
+static struct ast_node *constant(float n)
+{
+ struct ast_node *node;
+
+ node = node_op(op_constant, NULL, NULL, NULL);
+ node->contents.constant = n;
+ return node;
+}
+
+#define FOLD_UNARY(res, ast_op, arg, expr) \
+ do { \
+ if((arg)->op == op_constant) { \
+ float a = (arg)->contents.constant; \
+ \
+ res = constant(expr); \
+ parse_free(arg); \
+ } else { \
+ res = node_op(ast_op, arg, NULL, NULL); \
+ } \
+ } while (0)
+
+#define FOLD_BINARY(res, ast_op, arg_a, arg_b, expr) \
+ do { \
+ if((arg_a)->op == op_constant && \
+ (arg_b)->op == op_constant) { \
+ float a = (arg_a)->contents.constant; \
+ float b = (arg_b)->contents.constant; \
+ \
+ res = constant(expr); \
+ parse_free(arg_a); \
+ parse_free(arg_b); \
+ } else { \
+ res = node_op(ast_op, arg_a, arg_b, NULL); \
+ } \
+ } while (0)
+
+static struct ast_node *conditional(struct ast_node *a,
+ struct ast_node *b, struct ast_node *c)
+{
+ if(a->op == op_not) {
+ struct ast_node *next = a->contents.branches.a;
+
+ parse_free_one(a);
+ return node_op(op_if, next, c, b);
}
-
- static struct ast_node *constant(float n)
- {
- struct ast_node *node;
-
- node = node_op(op_constant, "", NULL, NULL, NULL);
- node->contents.constant = n;
- return node;
+ if(a->op != op_constant)
+ return node_op(op_if, a, b, c);
+ if(a->contents.constant) {
+ parse_free(a);
+ parse_free(c);
+ return b;
+ } else {
+ parse_free(a);
+ parse_free(b);
+ return c;
}
+}
- #define FOLD_UNARY(res, ast_op, name, arg, expr) \
- do { \
- if((arg)->op == op_constant) { \
- float a = (arg)->contents.constant; \
- \
- res = constant(expr); \
- parse_free(arg); \
- } else { \
- res = node_op(ast_op, name, \
- arg, NULL, NULL); \
- } \
- } while (0)
-
- #define FOLD_BINARY(res, ast_op, name, arg_a, arg_b, expr) \
- do { \
- if((arg_a)->op == op_constant && \
- (arg_b)->op == op_constant) { \
- float a = (arg_a)->contents.constant; \
- float b = (arg_b)->contents.constant; \
- \
- res = constant(expr); \
- parse_free(arg_a); \
- parse_free(arg_b); \
- } else { \
- res = node_op(ast_op, name, \
- arg_a, arg_b, NULL); \
- } \
- } while (0)
-
- static struct ast_node *conditional(struct ast_node *a,
- struct ast_node *b, struct ast_node *c)
- {
- if(a->op == op_not) {
- struct ast_node *next = a->contents.branches.a;
-
- parse_free_one(a);
- return node_op(op_if, "if", next, c, b);
- }
- if(a->op != op_constant)
- return node_op(op_if, "if", a, b, c);
- if(a->contents.constant) {
- parse_free(a);
- parse_free(c);
- return b;
- } else {
- parse_free(a);
- parse_free(b);
- return c;
- }
- }
+static struct id *symbolify(struct id *id)
+{
+ const char *p;
- static void syntax_error(struct parser_state *state)
- {
- if(!state->error_label) {
- state->error_label = state->id->label;
- state->error_lineno = state->id->lineno;
- }
- }
+ for(p = id->label; isalnum(*p); p++);
+ id->sym = unique_n(id->label, p-id->label);
+ return id;
}
+} /* %include */
+
+
%start_symbol start
%extra_argument {struct parser_state *state}
%token_type {struct id *}
@@ -200,7 +210,7 @@
%type context {assign_callback}
%syntax_error {
- FAIL;
+ FAIL("parse error");
}
start ::= TOK_START_EXPR expr(N). {
@@ -209,6 +219,15 @@ start ::= TOK_START_EXPR expr(N). {
}
start ::= TOK_START_ASSIGN sections. {
+ if(warn_undefined && state->style == old_style) {
+ const struct sym *sym;
+
+ foreach_sym(sym)
+ if(!(sym->flags & (SF_SYSTEM | SF_ASSIGNED)))
+ warn(state,
+ "variable %s is only read, never set",
+ sym->fpvm_sym.name);
+ }
state->success = 1;
}
@@ -224,12 +243,12 @@ sections ::= assignments per_vertex_label assignments.
per_frame_label ::= TOK_PER_FRAME TOK_COLON. {
IS_STYLE(new_style);
- state->comm->assign_default = state->comm->assign_per_frame;
+ state->assign = state->comm->assign_per_frame;
}
per_vertex_label ::= TOK_PER_VERTEX TOK_COLON. {
IS_STYLE(new_style);
- state->comm->assign_default = state->comm->assign_per_vertex;
+ state->assign = state->comm->assign_per_vertex;
}
assignments ::= assignments assignment.
@@ -237,26 +256,52 @@ assignments ::= assignments assignment.
assignments ::= .
assignment ::= ident(I) TOK_ASSIGN expr(N) opt_semi. {
- state->error = state->comm->assign_default(state->comm, I->label, N);
- free(I);
- if(state->error) {
- FAIL;
- return;
+ I->sym->flags |= SF_ASSIGNED;
+ /*
+ * The conditions are as follows:
+ * - we must be outside compile_chunk (has different rules)
+ * - must be in the initial section
+ * - must not assign to a per-frame system variable
+ */
+ if(state->comm->assign_per_frame &&
+ state->assign != state->comm->assign_per_frame &&
+ state->assign != state->comm->assign_per_vertex &&
+ I->sym->pfv_idx == -1) {
+ free(I);
+ if(N->op != op_constant || N->contents.constant) {
+ FAIL("can initialize non-system variables only "
+ "to zero");
+ return;
+ }
+ IS_STYLE(new_style);
+ } else {
+ const char *msg;
+
+ msg = state->assign(state->comm, I->sym, N);
+ free(I);
+ if(msg) {
+ FAIL(msg);
+ free((void *) msg);
+ return;
+ }
}
parse_free(N);
}
assignment ::= TOK_IMAGEFILE(I) TOK_ASSIGN TOK_FNAME(N). {
- state->error = state->comm->assign_image_name(state->comm,
- atoi(I->label+9), N->label);
+ const char *msg;
+
+ msg = state->comm->assign_image_name(state->comm,
+ atoi(I->label+9), N->fname);
free(I);
- if(state->error) {
- FAIL;
- free((void *) N->label);
+ if(msg) {
+ FAIL(msg);
+ free((void *) msg);
+ free((void *) N->fname);
free(N);
return;
}
- free((void *) N->label);
+ free((void *) N->fname);
free(N);
}
@@ -266,27 +311,28 @@ assignment ::= context(C). {
* per_vertex= tags followed by nothing else. We work around the
* syntax issue by making these tags "sticky".
*
- * This subtly changes the semantics. Also, changing assign_default
- * is not a good idea, since the caller may rely on it staying the
- * same.
+ * This subtly changes the semantics.
*/
- state->comm->assign_default = C;
+ state->assign = C;
}
-context(C) ::= TOK_PER_FRAME TOK_ASSIGN. {
+context(C) ::= old_per_frame TOK_ASSIGN. {
IS_STYLE(old_style);
C = state->comm->assign_per_frame;
}
-context(C) ::= TOK_PER_VERTEX TOK_ASSIGN. {
+context(C) ::= old_per_vertex TOK_ASSIGN. {
IS_STYLE(old_style);
C = state->comm->assign_per_vertex;
}
-context(C) ::= TOK_PER_PIXEL TOK_ASSIGN. {
- IS_STYLE(old_style);
- C = state->comm->assign_per_vertex;
-}
+old_per_frame ::= TOK_PER_FRAME.
+old_per_frame ::= TOK_PER_FRAME_UGLY.
+
+old_per_vertex ::= TOK_PER_VERTEX.
+old_per_vertex ::= TOK_PER_VERTEX_UGLY.
+old_per_vertex ::= TOK_PER_PIXEL.
+old_per_vertex ::= TOK_PER_PIXEL_UGLY.
opt_semi ::= opt_semi TOK_SEMI.
@@ -313,14 +359,14 @@ equal_expr(N) ::= rel_expr(A). {
}
equal_expr(N) ::= equal_expr(A) TOK_EQ rel_expr(B). {
- FOLD_BINARY(N, op_equal, "equal", A, B, a == b);
+ FOLD_BINARY(N, op_equal, A, B, a == b);
}
equal_expr(N) ::= equal_expr(A) TOK_NE rel_expr(B). {
struct ast_node *tmp;
- FOLD_BINARY(tmp, op_equal, "equal", A, B, a == b);
- FOLD_UNARY(N, op_not, "!", tmp, !a);
+ FOLD_BINARY(tmp, op_equal, A, B, a == b);
+ FOLD_UNARY(N, op_not, tmp, !a);
}
rel_expr(N) ::= add_expr(A). {
@@ -328,25 +374,25 @@ rel_expr(N) ::= add_expr(A). {
}
rel_expr(N) ::= rel_expr(A) TOK_LT add_expr(B). {
- FOLD_BINARY(N, op_below, "below", A, B, a < b);
+ FOLD_BINARY(N, op_below, A, B, a < b);
}
rel_expr(N) ::= rel_expr(A) TOK_GT add_expr(B). {
- FOLD_BINARY(N, op_above, "above", A, B, a > b);
+ FOLD_BINARY(N, op_above, A, B, a > b);
}
rel_expr(N) ::= rel_expr(A) TOK_LE add_expr(B). {
struct ast_node *tmp;
- FOLD_BINARY(tmp, op_above, "above", A, B, a > b);
- FOLD_UNARY(N, op_not, "!", tmp, !a);
+ FOLD_BINARY(tmp, op_above, A, B, a > b);
+ FOLD_UNARY(N, op_not, tmp, !a);
}
rel_expr(N) ::= rel_expr(A) TOK_GE add_expr(B). {
struct ast_node *tmp;
- FOLD_BINARY(tmp, op_below, "below", A, B, a < b);
- FOLD_UNARY(N, op_not, "!", tmp, !a);
+ FOLD_BINARY(tmp, op_below, A, B, a < b);
+ FOLD_UNARY(N, op_not, tmp, !a);
}
add_expr(N) ::= mult_expr(A). {
@@ -354,11 +400,11 @@ add_expr(N) ::= mult_expr(A). {
}
add_expr(N) ::= add_expr(A) TOK_PLUS mult_expr(B). {
- FOLD_BINARY(N, op_plus, "+", A, B, a + b);
+ FOLD_BINARY(N, op_plus, A, B, a + b);
}
add_expr(N) ::= add_expr(A) TOK_MINUS mult_expr(B). {
- FOLD_BINARY(N, op_minus, "-", A, B, a - b);
+ FOLD_BINARY(N, op_minus, A, B, a - b);
}
mult_expr(N) ::= unary_expr(A). {
@@ -366,15 +412,15 @@ mult_expr(N) ::= unary_expr(A). {
}
mult_expr(N) ::= mult_expr(A) TOK_MULTIPLY unary_expr(B). {
- FOLD_BINARY(N, op_multiply, "*", A, B, a * b);
+ FOLD_BINARY(N, op_multiply, A, B, a * b);
}
mult_expr(N) ::= mult_expr(A) TOK_DIVIDE unary_expr(B). {
- FOLD_BINARY(N, op_divide, "/", A, B, a / b);
+ FOLD_BINARY(N, op_divide, A, B, a / b);
}
mult_expr(N) ::= mult_expr(A) TOK_PERCENT unary_expr(B). {
- FOLD_BINARY(N, op_percent, "%", A, B, a-b*(int) (a/b));
+ FOLD_BINARY(N, op_percent, A, B, a-b*(int) (a/b));
}
unary_expr(N) ::= primary_expr(A). {
@@ -382,11 +428,11 @@ unary_expr(N) ::= primary_expr(A). {
}
unary_expr(N) ::= TOK_MINUS unary_expr(A). {
- FOLD_UNARY(N, op_negate, "-", A, -a);
+ FOLD_UNARY(N, op_negate, A, -a);
}
unary_expr(N) ::= TOK_NOT unary_expr(A). {
- FOLD_UNARY(N, op_not, "!", A, !a);
+ FOLD_UNARY(N, op_not, A, !a);
}
@@ -394,16 +440,16 @@ unary_expr(N) ::= TOK_NOT unary_expr(A). {
primary_expr(N) ::= unary_misc(I) TOK_LPAREN expr(A) TOK_RPAREN. {
- N = node(I->token, I->label, A, NULL, NULL);
+ N = node(I->token, NULL, A, NULL, NULL);
free(I);
}
primary_expr(N) ::= TOK_SQR TOK_LPAREN expr(A) TOK_RPAREN. {
- FOLD_UNARY(N, op_sqr, "sqr", A, a*a);
+ FOLD_UNARY(N, op_sqr, A, a*a);
}
primary_expr(N) ::= TOK_SQRT TOK_LPAREN expr(A) TOK_RPAREN. {
- FOLD_UNARY(N, op_sqrt, "sqrt", A, sqrtf(a));
+ FOLD_UNARY(N, op_sqrt, A, sqrtf(a));
}
@@ -412,28 +458,28 @@ primary_expr(N) ::= TOK_SQRT TOK_LPAREN expr(A) TOK_RPAREN. {
primary_expr(N) ::= binary_misc(I) TOK_LPAREN expr(A) TOK_COMMA expr(B)
TOK_RPAREN. {
- N = node(I->token, I->label, A, B, NULL);
+ N = node(I->token, NULL, A, B, NULL);
free(I);
}
primary_expr(N) ::= TOK_ABOVE TOK_LPAREN expr(A) TOK_COMMA expr(B) TOK_RPAREN. {
- FOLD_BINARY(N, op_above, "above", A, B, a > b);
+ FOLD_BINARY(N, op_above, A, B, a > b);
}
primary_expr(N) ::= TOK_BELOW TOK_LPAREN expr(A) TOK_COMMA expr(B) TOK_RPAREN. {
- FOLD_BINARY(N, op_below, "below", A, B, a < b);
+ FOLD_BINARY(N, op_below, A, B, a < b);
}
primary_expr(N) ::= TOK_EQUAL TOK_LPAREN expr(A) TOK_COMMA expr(B) TOK_RPAREN. {
- FOLD_BINARY(N, op_equal, "equal", A, B, a == b);
+ FOLD_BINARY(N, op_equal, A, B, a == b);
}
primary_expr(N) ::= TOK_MAX TOK_LPAREN expr(A) TOK_COMMA expr(B) TOK_RPAREN. {
- FOLD_BINARY(N, op_max, "max", A, B, a > b ? a : b);
+ FOLD_BINARY(N, op_max, A, B, a > b ? a : b);
}
primary_expr(N) ::= TOK_MIN TOK_LPAREN expr(A) TOK_COMMA expr(B) TOK_RPAREN. {
- FOLD_BINARY(N, op_min, "min", A, B, a < b ? a : b);
+ FOLD_BINARY(N, op_min, A, B, a < b ? a : b);
}
@@ -459,7 +505,11 @@ primary_expr(N) ::= TOK_CONSTANT(C). {
}
primary_expr(N) ::= ident(I). {
- N = node(I->token, I->label, NULL, NULL, NULL);
+ if(warn_undefined && state->style == new_style &&
+ !(I->sym->flags & (SF_SYSTEM | SF_ASSIGNED)))
+ warn(state, "reading undefined variable %s",
+ I->sym->fpvm_sym.name);
+ N = node(I->token, I->sym, NULL, NULL, NULL);
free(I);
}
@@ -474,14 +524,30 @@ primary_expr(N) ::= ident(I). {
* they have function-specific code for constant folding. {u,bi,ter}nary_misc
* are identifiers the parser treats as generic functions, without knowing
* anything about their semantics.
+ *
+ * The use of symbolify() is somewhat inefficient, but use of function names
+ * for variables should be a rare condition anyway.
*/
-ident(O) ::= TOK_IDENT(I). { O = I; }
-ident(O) ::= unary(I). { O = I; }
-ident(O) ::= unary_misc(I). { O = I; }
-ident(O) ::= binary(I). { O = I; }
-ident(O) ::= binary_misc(I). { O = I; }
-ident(O) ::= ternary(I). { O = I; }
+ident(O) ::= TOK_IDENT(I). {
+ if(warn_section) {
+ if(state->assign == state->comm->assign_per_frame &&
+ I->sym->pfv_idx == -1 && I->sym->pvv_idx != -1)
+ warn(state, "using per-vertex variable %s in "
+ "per-frame section", I->sym->fpvm_sym.name);
+ if(state->assign == state->comm->assign_per_vertex &&
+ I->sym->pfv_idx != -1 && I->sym->pvv_idx == -1)
+ warn(state, "using per-frame variable %s in "
+ "per-vertex section", I->sym->fpvm_sym.name);
+ }
+ O = I;
+}
+
+ident(O) ::= unary(I). { O = symbolify(I); }
+ident(O) ::= unary_misc(I). { O = symbolify(I); }
+ident(O) ::= binary(I). { O = symbolify(I); }
+ident(O) ::= binary_misc(I). { O = symbolify(I); }
+ident(O) ::= ternary(I). { O = symbolify(I); }
unary_misc(O) ::= TOK_ABS(I). { O = I; }
unary_misc(O) ::= TOK_COS(I). { O = I; }
View
128 src/compiler/parser_helper.c
@@ -19,14 +19,74 @@
#define _GNU_SOURCE /* for asprintf */
#include <stdlib.h>
#include <stdio.h>
+#include <ctype.h>
#include <malloc.h>
+
#include <fpvm/ast.h>
+#include "symtab.h"
#include "scanner.h"
#include "parser.h"
#include "parser_itf.h"
#include "parser_helper.h"
+
+int warn_section = 1;
+int warn_undefined = 1;
+
+static void vmsg(struct parser_state *state, const char *fmt, va_list ap,
+ int is_error)
+{
+ char *tmp;
+
+ if(is_error && !state->is_error) {
+ free((void *) state->msg);
+ state->msg = NULL;
+ state->is_error = 1;
+ }
+
+ /*
+ * If "msg" is already set, then we keep the previous value. There are
+ * two reasons for this:
+ *
+ * - "msg" may have already been set before calling vmsg()
+ *
+ * - we may be in the process of exiting the parser and are running
+ * into false or unrelated problems
+ */
+
+ if(state->msg)
+ return;
+
+ vasprintf(&tmp, fmt, ap);
+ state->msg = tmp;
+ state->msg_label = state->id->label;
+ state->msg_lineno = state->id->lineno;
+}
+
+void error(struct parser_state *state, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vmsg(state, fmt, ap, 1);
+ va_end(ap);
+}
+
+void warn(struct parser_state *state, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+#ifdef STANDALONE
+ vprintf(fmt, ap);
+ putchar('\n');
+#else
+ vmsg(state, fmt, ap, 0);
+#endif
+ va_end(ap);
+}
+
static char printable_char(unsigned char c)
{
return c < ' ' || c > '~' ? '?' : c;
@@ -41,18 +101,24 @@ static int printable_label(const char *s)
{
const char *p;
- for(p = s; *p > ' '; p++);
+ if(isalnum(*s)) {
+ for(p = s; isalnum(*p); p++);
+ } else {
+ for(p = s; *p > ' '; p++);
+ }
return p-s;
}
-const char *parse(const char *expr, int start_token, struct parser_comm *comm)
+int parse(const char *expr, int start_token, struct parser_comm *comm)
{
struct scanner *s;
struct parser_state state = {
.comm = comm,
+ .assign = comm->assign_default,
.success = 0,
- .error = NULL,
- .error_label = NULL,
+ .msg = NULL,
+ .msg_label = NULL,
+ .is_error = 0,
.id = NULL,
.style = unknown_style,
};
@@ -61,6 +127,7 @@ const char *parse(const char *expr, int start_token, struct parser_comm *comm)
void *p;
char *error = NULL;
+ comm->msg = NULL;
s = new_scanner((unsigned char *)expr);
p = ParseAlloc(malloc);
Parse(p, start_token, NULL, &state);
@@ -68,11 +135,12 @@ const char *parse(const char *expr, int start_token, struct parser_comm *comm)
while(tok != TOK_EOF) {
if(tok == TOK_ERROR) {
asprintf(&error,
- "FPVM, line %d: scan error near '%c'",
+ "line %d: scan error near '%c'",
s->lineno, printable_char(s->cursor[-1]));
ParseFree(p, free);
delete_scanner(s);
- return error;
+ comm->msg = error;
+ return 0;
}
identifier = malloc(sizeof(struct id));
@@ -85,29 +153,12 @@ const char *parse(const char *expr, int start_token, struct parser_comm *comm)
identifier->label = "";
break;
case TOK_FNAME:
- identifier->label = get_token(s);
+ identifier->fname = get_name(s);
+ identifier->label = identifier->fname;
break;
case TOK_IDENT:
- case TOK_ABOVE:
- case TOK_ABS:
- case TOK_BELOW:
- case TOK_COS:
- case TOK_EQUAL:
- case TOK_F2I:
- case TOK_ICOS:
- case TOK_I2F:
- case TOK_IF:
- case TOK_INT:
- case TOK_INVSQRT:
- case TOK_ISIN:
- case TOK_MAX:
- case TOK_MIN:
- case TOK_QUAKE:
- case TOK_SIN:
- case TOK_SQR:
- case TOK_SQRT:
- case TOK_TSIGN:
- identifier->label = get_unique_token(s);
+ identifier->sym = get_symbol(s);
+ identifier->label = identifier->sym->fpvm_sym.name;
break;
default:
identifier->label = (const char *) s->old_cursor;
@@ -131,16 +182,19 @@ const char *parse(const char *expr, int start_token, struct parser_comm *comm)
free(identifier);
- if(!state.success) {
+ if(!state.success)
asprintf(&error,
- "FPVM, line %d: %s near '%.*s'",
- state.error_lineno,
- state.error ? state.error : "parse error",
- printable_label(state.error_label), state.error_label);
- free((void *) state.error);
- }
-
- return error;
+ "line %d: %s near '%.*s'",
+ state.msg_lineno,
+ state.msg ? state.msg : "parse error",
+ printable_label(state.msg_label), state.msg_label);
+ if(state.success && state.msg)
+ asprintf(&error, "line %d: %s",
+ state.msg_lineno, state.msg);
+ free((void *) state.msg);
+ comm->msg = error;
+
+ return state.success;
}
void parse_free_one(struct ast_node *node)
@@ -151,7 +205,7 @@ void parse_free_one(struct ast_node *node)
void parse_free(struct ast_node *node)
{
if(node == NULL) return;
- if(node->label[0] != 0) {
+ if(node_is_op(node)) {
parse_free(node->contents.branches.a);
parse_free(node->contents.branches.b);
parse_free(node->contents.branches.c);
View
23 src/compiler/parser_helper.h
@@ -18,16 +18,16 @@
#ifndef __PARSER_HELPER_H
#define __PARSER_HELPER_H
+#include <stdarg.h>
+
#include <fpvm/ast.h>
#include <fpvm/fpvm.h>
+#include "symtab.h"
-/* virtual operation - for use inside the parser only */
-enum {
- op_not = op_vops+1,
-};
struct compiler_sc;
+struct parser_state;
struct parser_comm {
union {
@@ -36,16 +36,23 @@ struct parser_comm {
struct compiler_sc *sc;
} u;
const char *(*assign_default)(struct parser_comm *comm,
- const char *label, struct ast_node *node);
+ struct sym *sym, struct ast_node *node);
const char *(*assign_per_frame)(struct parser_comm *comm,
- const char *label, struct ast_node *node);
+ struct sym *sym, struct ast_node *node);
const char *(*assign_per_vertex)(struct parser_comm *comm,
- const char *label, struct ast_node *node);
+ struct sym *sym, struct ast_node *node);
const char *(*assign_image_name)(struct parser_comm *comm,
int number, const char *name);
+ const char *msg; /* NULL if neither error nor warning */
};
-const char *parse(const char *expr, int start_token, struct parser_comm *comm);
+extern int warn_section;
+extern int warn_undefined;
+
+void error(struct parser_state *state, const char *fmt, ...);
+void warn(struct parser_state *state, const char *fmt, ...);
+
+int parse(const char *expr, int start_token, struct parser_comm *comm);
void parse_free_one(struct ast_node *node);
void parse_free(struct ast_node *node);
View
14 src/compiler/parser_itf.h
@@ -28,6 +28,8 @@
struct id {
int token;
const char *label;
+ struct sym *sym;
+ const char *fname;
float constant;
int lineno;
};
@@ -35,10 +37,16 @@ struct id {
struct parser_state {
int success;
struct parser_comm *comm;
- const char *error; /* malloc'ed error message or NULL */
- const char *error_label;/* details about the failing token */
- int error_lineno;
+ const char *(*assign)(struct parser_comm *comm,
+ struct sym *sym, struct ast_node *node);
+
+ const char *msg; /* malloc'ed diagnostic message or NULL */
+ const char *msg_label; /* details about the failing token */
+ int msg_lineno;
+ int is_error; /* non-zero if error (not just warning) */
+
const struct id *id; /* input, for error handling */
+
enum {
unknown_style, /* haven't seen any fragment selection yet */
old_style, /* patch uses per_frame=var=expr */
View
10 src/compiler/ptest/Makefile
@@ -4,23 +4,27 @@ LIBFPVM_X86 = $(MMDIR)/software/libfpvm/x86-linux
CFLAGS_STANDALONE = -DSTANDALONE=\"standalone.h\"
CFLAGS = -Wall -g -I.. -I. $(CFLAGS_STANDALONE)
-OBJS = ptest.o scanner.o parser.o parser_helper.o unique.o compiler.o \
+OBJS = ptest.o scanner.o parser.o parser_helper.o symtab.o compiler.o \
libfpvm.a
LDLIBS = -lm
# ----- Verbosity control -----------------------------------------------------
CC_normal := $(CC)
+CP_normal := cp
CC_quiet = @echo " CC " $@ && $(CC_normal)
GEN_quiet = @echo " GENERATE " $@ &&
+CP_quiet = @echo " CP " $@ && $(CP_normal)
ifeq ($(V),1)
CC = $(CC_normal)
GEN =
+ CP = $(CP_normal)
else
CC = $(CC_quiet)
GEN = $(GEN_quiet)
+ CP = $(CP_quiet)
endif
# ----- Rules -----------------------------------------------------------------
@@ -52,7 +56,7 @@ ptest: $(OBJS)
libfpvm.a:
$(MAKE) -C $(LIBFPVM_X86)
- cp $(LIBFPVM_X86)/$@ .
+ $(CP) $(LIBFPVM_X86)/$@ .
# ----- Dependencies ----------------------------------------------------------
@@ -60,7 +64,7 @@ libfpvm.a:
scanner.o: ../parser.h
parser_helper.o: ../parser.h
ptest.o: ../parser.h
-unique.o: ../fnp.inc
+symtab.o: ../fnp.inc
compiler.o: ../infra-fnp.h
# ----- Cleanup ---------------------------------------------------------------
View
105 src/compiler/ptest/ptest.c
@@ -1,7 +1,7 @@
/*
* ptest.c - FNP parser tester
*
- * Copyright 2011 by Werner Almesberger
+ * Copyright 2011-2012 by Werner Almesberger
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,10 +19,11 @@
#include "../parser_helper.h"
#include "../parser.h"
#include "../compiler.h"
-#include "../unique.h"
+#include "../symtab.h"
static int quiet = 0;
+static int symbols = 0;
static const char *fail = NULL;
static const char *buffer;
@@ -53,7 +54,7 @@ static void dump_ast(const struct ast_node *ast)
{
switch (ast->op) {
case op_ident:
- printf("%s", ast->label);
+ printf("%s", ast->sym->name);
break;
case op_constant:
printf("%g", ast->contents.constant);
@@ -143,12 +144,12 @@ static void dump_ast(const struct ast_node *ast)
static const char *assign_default(struct parser_comm *comm,
- const char *label, struct ast_node *node)
+ struct sym *sym, struct ast_node *node)
{
if (fail)
return strdup(fail);
if (!quiet) {
- printf("%s = ", label);
+ printf("%s = ", sym->fpvm_sym.name);
dump_ast(node);
putchar('\n');
}
@@ -157,10 +158,10 @@ static const char *assign_default(struct parser_comm *comm,
static const char *assign_per_frame(struct parser_comm *comm,
- const char *label, struct ast_node *node)
+ struct sym *sym, struct ast_node *node)
{
if (!quiet) {
- printf("per_frame = %s = ", label);
+ printf("per_frame = %s = ", sym->fpvm_sym.name);
dump_ast(node);
putchar('\n');
}
@@ -169,10 +170,10 @@ static const char *assign_per_frame(struct parser_comm *comm,
static const char *assign_per_vertex(struct parser_comm *comm,
- const char *label, struct ast_node *node)
+ struct sym *sym, struct ast_node *node)
{
if (!quiet) {
- printf("per_vertex = %s = ", label);
+ printf("per_vertex = %s = ", sym->fpvm_sym.name);
dump_ast(node);
putchar('\n');
}
@@ -234,21 +235,54 @@ static void parse_only(const char *pgm)
.assign_per_frame = assign_per_frame,
.assign_per_vertex = assign_per_vertex,
.assign_image_name = assign_image_name,
- };
- const char *error;
-
- error = parse(pgm, TOK_START_ASSIGN, &comm);
- unique_free();
- if (!error)
+ };
+ int ok;
+
+ symtab_init();
+ ok = parse(pgm, TOK_START_ASSIGN, &comm);
+ if (symbols) {
+ const struct sym *sym;
+ int user = 0;
+
+ foreach_sym(sym) {
+ if (!user && !(sym->flags & SF_SYSTEM)) {
+ printf("\n");
+ user = 1;
+ }
+ printf("%s\n", sym->fpvm_sym.name);
+ }
+ }
+ symtab_free();
+ if (ok)
return;
fflush(stdout);
- fprintf(stderr, "%s\n", error);
- free((void *) error);
+ fprintf(stderr, "%s\n", comm.msg);
+ free((void *) comm.msg);
exit(1);
}
-static void dump_regs(const int *alloc, const char (*names)[FPVM_MAXSYMLEN],
+/*
+ * "sym" and "field" are used to access a field chosen by the caller in the
+ * "struct sym". For this, the caller provides a buffer (sym) and a pointer to
+ * the respective field inside the buffer. This way, it's perfectly type-safe
+ * and we don't need offsetof acrobatics.
+ */
+
+static const char *lookup_name(int idx, struct sym *sym, const int *field)
+{
+ const struct sym *walk;
+
+ foreach_sym(walk) {
+ *sym = *walk;
+ if (*field == idx)
+ return walk->fpvm_sym.name;
+ }
+ return NULL;
+}
+
+
+static void dump_regs(const int *alloc, struct sym *sym, const int *field,
const float *values, int n)
{
const char *mapped[n];
@@ -258,7 +292,7 @@ static void dump_regs(const int *alloc, const char (*names)[FPVM_MAXSYMLEN],
mapped[i] = NULL;
for (i = 0; i != n; i++)
if (alloc[i] != -1)
- mapped[alloc[i]] = names[i];
+ mapped[alloc[i]] = lookup_name(i, sym, field);
for (i = 0; i != n; i++) {
if (!values[i] && !mapped[i])
continue;
@@ -273,19 +307,20 @@ static void dump_regs(const int *alloc, const char (*names)[FPVM_MAXSYMLEN],
static void show_patch(const struct patch *patch)
{
int i;
+ struct sym sym;
printf("global:\n");
for (i = 0; i != COMP_PFV_COUNT; i++)
if (patch->pfv_initial[i])
printf("R%03d = %f %s\n", i, patch->pfv_initial[i],
- pfv_names[i]);
+ lookup_name(i, &sym, &sym.pfv_idx));
printf("per-frame PFPU fragment:\n");
- dump_regs(patch->pfv_allocation, pfv_names, patch->perframe_regs,
- COMP_PFV_COUNT);
+ dump_regs(patch->pfv_allocation, &sym, &sym.pfv_idx,
+ patch->perframe_regs, COMP_PFV_COUNT);
pfpu_dump(patch->perframe_prog, patch->perframe_prog_length);
printf("per-vertex PFPU fragment:\n");
- dump_regs(patch->pvv_allocation, pvv_names, patch->pervertex_regs,
- COMP_PVV_COUNT);
+ dump_regs(patch->pvv_allocation, &sym, &sym.pvv_idx,
+ patch->pervertex_regs, COMP_PVV_COUNT);
pfpu_dump(patch->pervertex_prog, patch->pervertex_prog_length);
}
@@ -317,11 +352,13 @@ static void free_buffer(void)
static void usage(const char *name)
{
fprintf(stderr,
-"usage: %s [-c|-f error] [-n runs] [-q] [expr]\n\n"
+"usage: %s [-c|-f error] [-n runs] [-q] [-s] [-Wwarning...] [expr]\n\n"
" -c generate code and dump generated code (unless -q is set)\n"
" -f error fail any assignment with specified error message\n"
" -n runs run compilation repeatedly (default: run only once)\n"
" -q quiet operation\n"
+" -s dump symbol table after parsing (only if -c is not set)\n"
+" -Wwarning enable compiler warning (one of: section, undefined)\n"
, name);
exit(1);
}
@@ -334,7 +371,10 @@ int main(int argc, char **argv)
unsigned long repeat = 1;
char *end;
- while ((c = getopt(argc, argv, "cf:n:q")) != EOF)
+ warn_section = 0;
+ warn_undefined = 0;
+
+ while ((c = getopt(argc, argv, "cf:n:qsW:")) != EOF)
switch (c) {
case 'c':
codegen = 1;
@@ -350,11 +390,22 @@ int main(int argc, char **argv)
case 'q':
quiet = 1;
break;
+ case 's':
+ symbols = 1;
+ break;
+ case 'W':
+ if (!strcmp(optarg, "section"))
+ warn_section = 1;
+ else if (!strcmp(optarg, "undefined"))
+ warn_undefined = 1;
+ else
+ usage(*argv);
+ break;
default:
usage(*argv);
}
- if (codegen && fail)
+ if (codegen && (fail || symbols))
usage(*argv);
switch (argc-optind) {
View
8 src/compiler/scanner.h
@@ -44,12 +44,12 @@ void delete_scanner(struct scanner *s);
/* get to the next token and return its type */
int scan(struct scanner *s);
-/* get the unique string comprising the current token
+/* get the symbol for the unique string comprising the current token
*/
-const char *get_unique_token(struct scanner *s);
+struct sym *get_symbol(struct scanner *s);
-/* like get_unique_token, but malloc'ed non-unique string */
-const char *get_token(struct scanner *s);
+/* malloc'ed non-unique string */
+const char *get_name(struct scanner *s);
float get_constant(struct scanner *s);
View
16 src/compiler/scanner.re
@@ -20,7 +20,7 @@
#include <string.h>
#include <malloc.h>
-#include "unique.h"
+#include "symtab.h"
#include "scanner.h"
#define YYCTYPE unsigned char
@@ -118,10 +118,14 @@ int scan(struct scanner *s)
<N>"sqrt" { return TOK_SQRT; }
<N>"tsign" { return TOK_TSIGN; }
- <N>"per_frame"[a-z_0-9]*
- { return TOK_PER_FRAME; }
+ <N>"per_frame" { return TOK_PER_FRAME; }
<N>"per_vertex" { return TOK_PER_VERTEX; }
- <N>"per_pixel" { return TOK_PER_PIXEL; }
+ <N>"per_frame"[a-z_0-9]+
+ { return TOK_PER_FRAME_UGLY; }
+ <N>"per_vertex"[a-z_0-9]+
+ { return TOK_PER_VERTEX_UGLY; }
+ <N>"per_pixel"[a-z_0-9]*
+ { return TOK_PER_PIXEL_UGLY; }
<N>"imagefile"[1-9] { YYSETCONDITION(yycFNAME1);
return TOK_IMAGEFILE; }
@@ -158,13 +162,13 @@ int scan(struct scanner *s)
*/
}
-const char *get_unique_token(struct scanner *s)
+struct sym *get_symbol(struct scanner *s)
{
return unique_n((const char *) s->old_cursor,
s->cursor - s->old_cursor);
}
-const char *get_token(struct scanner *s)
+const char *get_name(struct scanner *s)
{
char *buf;
int n;
View
158 src/compiler/symtab.c
@@ -0,0 +1,158 @@
+/*
+ * symtab.c - Symbol table
+ *
+ * Copyright 2011-2012 by Werner Almesberger
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ */
+