Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: m-labs/flickernoise
base: cc9e057^
...
head fork: m-labs/flickernoise
compare: d755a0b
  • 13 commits
  • 24 files changed
  • 0 commit comments
  • 1 contributor
Commits on Jan 05, 2012
@wpwrak wpwrak compiler: define op_not such that we don't trigger a warning
lm32-rtems4.11-gcc doesn't like to compare enums "inherited" from other
enums. We just "manually" code the offset instead.
cc9e057
Commits on Jan 07, 2012
@wpwrak wpwrak compiler: track reduction of "label" use in libfpvm
First, we use the new node_is_op in parse_free. Second, we no longer
have a good error message if op_not "leaks" in test/not.
36ef9cd
Commits on Jan 10, 2012
@wpwrak wpwrak compiler: don't predefine identifiers for function names
Since function names are normally not used for variables, we keep them
separate and only allocate an identifier when needed. This will help
with a future migration towards a proper symbol table.

This also reduces the size of the table of predefined identifiers,
slightly accelerating the compiler.
eaf4b67
@wpwrak wpwrak test: allow leak tests to fail and count the failed tests
This adds instrumentation to expect() to make test failure non-fatal if
FAIL_ON_ERROR is set to "false", then uses it in the "leak" target.
55805a1
@wpwrak wpwrak ptest: new option -s to dump all variables/symbols
Also added the corresponding infrastructure to unique.c/unique.h
484399e
@wpwrak wpwrak tests: move list of patches from test/patches to shareable test/Patches 8e581f9
@wpwrak wpwrak test/nsyms: count the number of user-defined variables/symbols in pat…
…ch pool

This is less a regression test bit more an indicator for how adaquate
the structure of the symbol table is.
38815b5
@wpwrak wpwrak compiler: nMotionVectorsX was missing in fnp.ids 565d57d
@wpwrak wpwrak compiler: rename unique.[ch] to symtab.[ch] c0f929b
@wpwrak wpwrak compiler: "struct sym" megapatch
This changes the compiler to use "struct sym" instead of "const char *"
to refer to variables when communicating with libfpvm. This also
implies that the symbol table moves to "struct sym" and that things
that are not a variable have no identifier associated with them.
9783fb2
@wpwrak wpwrak compiler: separate file names more clearly from symbols
The goal is to get rid of "label", which now only serves as a pointer
into the source (or a copy thereof), for diagnostics.
bda6e87
Commits on Jan 11, 2012
@wpwrak wpwrak compiler: adapt to libfpvm use of "struct fpvm_sym" and introduce "st…
…ruct sym"

We now have a Flickernoise-local "struct sym" that contains the libfpvm
symbol.
35ec434
@wpwrak wpwrak compiler: record index of system variables in symbol table
This removes the list of variable names from compiler.c and lets
fnp.ids provide the mapping from name to index.
d755a0b
View
4 src/Makefile
@@ -63,7 +63,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 +99,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
244 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));
@@ -107,139 +108,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 +185,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 +248,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 +263,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 +344,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 +375,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,
View
3  src/compiler/compiler.h
@@ -236,9 +236,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
395 src/compiler/fnp.ids
@@ -11,232 +11,151 @@
#
#
-# 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
+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 +163,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
21 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,18 @@ 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,
+},
+EOF
i=`expr $i + 1`
done
}
View
115 src/compiler/parser.y
@@ -18,11 +18,15 @@
%include {
#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"
@@ -32,7 +36,7 @@
static void yy_parse_failed(struct yyParser *yypParser);
typedef const char *(*assign_callback)(struct parser_comm *comm,
- const char *label, struct ast_node *node);
+ struct sym *sym, struct ast_node *node);
#define FAIL \
do { \
@@ -81,36 +85,40 @@
[TOK_INT] = op_int,
};
- static struct ast_node *node_op(enum ast_op op, const char *id,
+ 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->label = id;
+ 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, const char *id,
+ static struct ast_node *node(int token, struct sym *sym,
struct ast_node *a, struct ast_node *b, struct ast_node *c)
{
- return node_op(tok2op[token], id, a, b, 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 = node_op(op_constant, NULL, NULL, NULL);
node->contents.constant = n;
return node;
}
- #define FOLD_UNARY(res, ast_op, name, arg, expr) \
+ #define FOLD_UNARY(res, ast_op, arg, expr) \
do { \
if((arg)->op == op_constant) { \
float a = (arg)->contents.constant; \
@@ -118,12 +126,11 @@
res = constant(expr); \
parse_free(arg); \
} else { \
- res = node_op(ast_op, name, \
- arg, NULL, NULL); \
+ res = node_op(ast_op, arg, NULL, NULL); \
} \
} while (0)
- #define FOLD_BINARY(res, ast_op, name, arg_a, arg_b, expr) \
+ #define FOLD_BINARY(res, ast_op, arg_a, arg_b, expr) \
do { \
if((arg_a)->op == op_constant && \
(arg_b)->op == op_constant) { \
@@ -134,7 +141,7 @@
parse_free(arg_a); \
parse_free(arg_b); \
} else { \
- res = node_op(ast_op, name, \
+ res = node_op(ast_op, \
arg_a, arg_b, NULL); \
} \
} while (0)
@@ -146,10 +153,10 @@
struct ast_node *next = a->contents.branches.a;
parse_free_one(a);
- return node_op(op_if, "if", next, c, b);
+ return node_op(op_if, next, c, b);
}
if(a->op != op_constant)
- return node_op(op_if, "if", a, b, c);
+ return node_op(op_if, a, b, c);
if(a->contents.constant) {
parse_free(a);
parse_free(c);
@@ -168,6 +175,15 @@
state->error_lineno = state->id->lineno;
}
}
+
+ static struct id *symbolify(struct id *id)
+ {
+ const char *p;
+
+ for(p = id->label; isalnum(*p); p++);
+ id->sym = unique_n(id->label, p-id->label);
+ return id;
+ }
}
%start_symbol start
@@ -237,7 +253,7 @@ assignments ::= assignments assignment.
assignments ::= .
assignment ::= ident(I) TOK_ASSIGN expr(N) opt_semi. {
- state->error = state->comm->assign_default(state->comm, I->label, N);
+ state->error = state->comm->assign_default(state->comm, I->sym, N);
free(I);
if(state->error) {
FAIL;
@@ -248,15 +264,15 @@ assignment ::= ident(I) TOK_ASSIGN expr(N) opt_semi. {
assignment ::= TOK_IMAGEFILE(I) TOK_ASSIGN TOK_FNAME(N). {
state->error = state->comm->assign_image_name(state->comm,
- atoi(I->label+9), N->label);
+ atoi(I->label+9), N->fname);
free(I);
if(state->error) {
FAIL;
- free((void *) N->label);
+ free((void *) N->fname);
free(N);
return;
}
- free((void *) N->label);
+ free((void *) N->fname);
free(N);
}
@@ -313,14 +329,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 +344,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 +370,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 +382,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 +398,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 +410,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 +428,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 +475,7 @@ primary_expr(N) ::= TOK_CONSTANT(C). {
}
primary_expr(N) ::= ident(I). {
- N = node(I->token, I->label, NULL, NULL, NULL);
+ N = node(I->token, I->sym, NULL, NULL, NULL);
free(I);
}
@@ -474,14 +490,17 @@ 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) ::= 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
35 src/compiler/parser_helper.c
@@ -19,9 +19,11 @@
#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"
@@ -41,7 +43,11 @@ 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;
}
@@ -85,29 +91,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;
@@ -151,7 +140,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
12 src/compiler/parser_helper.h
@@ -21,11 +21,11 @@
#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,
-};
+#define op_not (op_vops+1)
struct compiler_sc;
@@ -36,11 +36,11 @@ 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);
};
View
2  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;
};
View
4 src/compiler/ptest/Makefile
@@ -4,7 +4,7 @@ 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
@@ -60,7 +60,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
37 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');
}
@@ -238,6 +239,8 @@ static void parse_only(const char *pgm)
const char *error;
error = parse(pgm, TOK_START_ASSIGN, &comm);
+ if (symbols)
+ unique_dump();
unique_free();
if (!error)
return;
@@ -272,6 +275,11 @@ static void dump_regs(const int *alloc, const char (*names)[FPVM_MAXSYMLEN],
static void show_patch(const struct patch *patch)
{
+/*
+ * @@@ Disable for now since we have no good way to get the names and the
+ * mapping archtecture is still in flux.
+ */
+#if 0
int i;
printf("global:\n");
@@ -287,6 +295,7 @@ static void show_patch(const struct patch *patch)
dump_regs(patch->pvv_allocation, pvv_names, patch->pervertex_regs,
COMP_PVV_COUNT);
pfpu_dump(patch->pervertex_prog, patch->pervertex_prog_length);
+#endif
}
@@ -317,11 +326,12 @@ 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] [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"
, name);
exit(1);
}
@@ -334,7 +344,7 @@ int main(int argc, char **argv)
unsigned long repeat = 1;
char *end;
- while ((c = getopt(argc, argv, "cf:n:q")) != EOF)
+ while ((c = getopt(argc, argv, "cf:n:qs")) != EOF)
switch (c) {
case 'c':
codegen = 1;
@@ -350,11 +360,14 @@ int main(int argc, char **argv)
case 'q':
quiet = 1;
break;
+ case 's':
+ symbols = 1;
+ 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
6 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
@@ -158,13 +158,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
160 src/compiler/symtab.c
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "compiler.h"
+#include "symtab.h"
+
+
+#define INITIAL_ALLOC 64
+
+
+struct key_n {
+ const char *s;
+ int n;
+};
+
+struct sym well_known[] = {
+#include "fnp.inc"
+};
+
+static struct sym *syms = NULL;
+static int num_syms = 0, allocated = 0;
+
+
+/*
+ * "a" is not NUL-terminated and its length "a" is determined by "n".
+ * "b" is NUL-terminated.
+ */
+
+static int strcmp_n(const char *a, const char *b, int n)
+{
+ int diff;
+
+ diff = strncmp(a, b, n);
+ if (diff)
+ return diff;
+ /* handle implicit NUL in string "a" */
+ return -b[n];
+}
+
+
+static char *strdup_n(const char *s, int n)
+{
+ char *new;
+
+ new = malloc(n+1);
+ memcpy(new, s, n);
+ new[n] = 0;
+ return new;
+}
+
+
+static void grow_table(void)
+{
+ if(num_syms != allocated)
+ return;
+
+ allocated = allocated ? allocated*2 : INITIAL_ALLOC;
+ syms = realloc(syms, allocated*sizeof(*syms));
+}
+
+
+static int cmp(const void *a, const void *b)
+{
+ const struct sym *sym = b;
+
+ return strcmp(a, sym->fpvm_sym.name);
+}
+
+
+static int cmp_n(const void *a, const void *b)
+{
+ const struct key_n *key = a;
+ const struct sym *sym = b;
+
+ return strcmp_n(key->s, sym->fpvm_sym.name, key->n);
+}
+
+
+struct sym *unique(const char *s)
+{
+ struct sym *res;
+ struct sym *walk;
+
+ res = bsearch(s, well_known, sizeof(well_known)/sizeof(*well_known),
+ sizeof(*well_known), cmp);
+ if(res)
+ return res;
+ for(walk = syms; walk != syms+num_syms; walk++)
+ if(!strcmp(walk->fpvm_sym.name, s))
+ return walk;
+ grow_table();
+ syms[num_syms].fpvm_sym.name = strdup(s);
+ syms[num_syms].pfv_idx = syms[num_syms].pvv_idx = -1;
+ return syms+num_syms++;
+}
+
+
+struct sym *unique_n(const char *s, int n)
+{
+ struct key_n key = {
+ .s = s,
+ .n = n,
+ };
+ struct sym *res;
+ struct sym *walk;
+
+ assert(n);
+ res = bsearch(&key, well_known, sizeof(well_known)/sizeof(*well_known),
+ sizeof(*well_known), cmp_n);
+ if(res)
+ return res;
+ for(walk = syms; walk != syms+num_syms; walk++)
+ if(!strcmp_n(s, walk->fpvm_sym.name, n))
+ return walk;
+ grow_table();
+ syms[num_syms].fpvm_sym.name = strdup_n(s, n);
+ syms[num_syms].pfv_idx = syms[num_syms].pvv_idx = -1;
+ return syms+num_syms++;
+}
+
+
+void unique_free(void)
+{
+ int i;
+
+ for(i = 0; i != num_syms; i++)
+ free((void *) syms[i].fpvm_sym.name);
+ free(syms);
+ syms = NULL;
+ num_syms = allocated = 0;
+}
+
+
+#ifdef STANDALONE
+
+void unique_dump(void)
+{
+ int i;
+
+ for(i = 0; i != sizeof(well_known)/sizeof(*well_known); i++)
+ printf("%s\n", well_known[i].fpvm_sym.name);
+ printf("\n");
+ for(i = 0; i != num_syms; i++)
+ printf("%s\n", syms[i].fpvm_sym.name);
+}
+
+#endif /* STANDALONE */
View
30 src/compiler/symtab.h
@@ -0,0 +1,30 @@
+/*
+ * symtab.h - 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.
+ */
+
+#ifndef SYMTAB_H
+#define SYMTAB_H
+
+#include <fpvm/symbol.h>
+
+
+struct sym {
+ struct fpvm_sym fpvm_sym;
+ int pfv_idx, pvv_idx; /* index; -1 if not a variable known to FN */
+};
+
+
+#define FPVM2SYM(fpvm_sym) ((struct sym *) (fpvm_sym))
+
+struct sym *unique(const char *s);
+struct sym *unique_n(const char *s, int n);
+void unique_free(void);
+void unique_dump(void);
+
+#endif /* !SYMTAB_H */
View
7 src/compiler/test/Common
@@ -44,7 +44,12 @@ expect()
echo FAILED "($SCRIPT)" 1>&2
cat _diff 1>&2
rm -f _out _diff
- exit 1
+ if ${FAIL_ON_ERROR:-true}; then
+ exit 1
+ else
+ failed=`expr ${failed:-0} + 1`
+ return 1
+ fi
}
echo PASSED 1>&2
rm -f _out _diff
View
73 src/compiler/test/Patches
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+#
+# We explicitly list all the known patches here so that any local additions
+# won't interfere.
+#
+
+forall_patches()
+{
+for n in \
+ "Aderassi - Making time.fnp" \
+ "Aderrasi - Airs.fnp" \
+ "Aderrasi - Antidote (Aqualung Mix).fnp" \
+ "Aderrasi - Bow to gravity.fnp" \
+ "Aderrasi - Variants Of Eternity (Shaking mix).fnp" \
+ "Bmelgren & Krash - Rainbow Orb Peacock (Lonely Signal Gone Mad Mix).fnp" \
+ "EvilJim - Ice Drops.fnp" \
+ "Fvese - The Tunnel (Final Stage Mix).fnp" \
+ "Geiss & Werner - Tornado (Rain Dance MIDI RMX).fnp" \
+ "Geiss - Approach.fnp" \
+ "Geiss - Cruzin'.fnp" \
+ "Geiss - Eggs.fnp" \
+ "Geiss - Shift.fnp" \
+ "Geiss - The Fatty Lumpkin Sunkle Tweaker.fnp" \
+ "Geiss - Tornado.fnp" \
+ "Idiot & Rovastar - Altars Of Madness 2 (X42 Mix).fnp" \
+ "Illusion & Che - The Piper.fnp" \
+ "Illusion & Rovastar - Clouded Bottle.fnp" \
+ "Illusion & Unchained - Frozen Eye 1.fnp" \
+ "Jeremie - conduirebourre.com.fnp" \
+ "Krash - Digital Flame (Video remix).fnp" \
+ "Krash - Digital Flame.fnp" \
+ "Krash - Interwoven (Nightmare Weft Mix).fnp" \
+ "Lekernel & Geiss - Shaking.fnp" \
+ "Lekernel & Krash - Boil off (DMX).fnp" \
+ "Lekernel & Krash - Personal Shroomery.fnp" \
+ "Lekernel & Rovastar & Fvese - Subconscious Objects.fnp" \
+ "Lekernel & Rozzor & Aderassi - Video Cannon.fnp" \
+ "Lekernel & fiShbRaiN - crazy face.fnp" \
+ "Lekernel - Disc Explosion.fnp" \
+ "Lekernel - Drawing Board (DMX).fnp" \
+ "Lekernel - Eerie Beri.fnp" \
+ "Lekernel - Falling (DMX).fnp" \
+ "Lekernel - FullScreen Video-in Preview.fnp" \
+ "Lekernel - Musique de telephone.fnp" \
+ "Lekernel - Pulsating photography.fnp" \
+ "Lekernel - Sailing.fnp" \
+ "Lekernel - Spiralling.fnp" \
+ "Lekernel - Star Ballet (Bass Travel Mix).fnp" \
+ "Lekernel - Star Ballet (Fountain Mix).fnp" \
+ "Lekernel - Star Ballet.fnp" \
+ "Lekernel - Starpainter.fnp" \
+ "Lekernel - The psychedelic drunken boat.fnp" \
+ "Lekernel - Vibrant Plasma Streams.fnp" \
+ "Philpraxis - Eight bit starfield.fnp" \
+ "Rovastar & Fvese - Dark Subconscious.fnp" \
+ "Rovastar & Idiot24-7 - Balk Acid (DMX madness).fnp" \
+ "Rovastar & Idiot24-7 - Balk Acid.fnp" \
+ "Rovastar - A Million Miles from Earth.fnp" \
+ "Rovastar - Cosmic Echoes 2.fnp" \
+ "Rovastar - Explosive Minds.fnp" \
+ "Rovastar - Forgotten Moon.fnp" \
+ "Rovastar - Hallucinogenic Pyramids.fnp" \
+ "Rovastar - Torrid Tales.fnp" \
+ "Rozzor & Aderrasi - Canon (DMX out).fnp" \
+ "Telek - Slow Shift Matrix (bb4.5).fnp" \
+ "Unchained - A Matter Of Taste (Remix).fnp" \
+ "Zylot - The Inner Workings of my New Computer.fnp" \
+ "bmelgren - Godhead (Video mix).fnp" \
+ "nil - Cid and Lucy.fnp"; do
+ eval "$@"
+done
+}
View
31 src/compiler/test/dualuse
@@ -0,0 +1,31 @@
+#!/bin/sh
+. ./Common
+
+###############################################################################
+
+ptest "dual use: min = sin+cos" <<EOF
+min = sin+cos
+EOF
+expect <<EOF
+min = (+ (sin) (cos))
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "dual use: sin = sqr-if" <<EOF
+sin = sqr-if
+EOF
+expect <<EOF
+sin = (- (sqr) (if))
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "dual use: if = max*int" <<EOF
+if = max*int
+EOF
+expect <<EOF
+if = (* (max) (int))
+EOF
+
+###############################################################################
View
2  src/compiler/test/not
@@ -16,7 +16,7 @@ ptest_fail "not: !a (try to generate code)" -c << EOF
per_frame: wave_a = !a
EOF
expect <<EOF
-FPVM, line 2: Operation not supported: ! near 'EOF'
+FPVM, line 2: Operation not supported: 29 near 'EOF'
EOF
#------------------------------------------------------------------------------
View
32 src/compiler/test/nsyms
@@ -0,0 +1,32 @@
+#!/bin/sh
+. ./Common
+. ./Patches
+
+###############################################################################
+
+PATCHDIR=../../../patches
+
+count_syms()
+{
+
+ s=`${PTST:-../ptest/ptest} -q -s <"$PATCHDIR/$n" | \
+ sed '1,/^$/d' | wc -l`
+ ns=`expr $ns + $s`
+ np=`expr $np + 1`
+ [ $s -gt $max ] && max=$s
+}
+
+
+echo -n "nsyms: count number of symbols: " 1>&2
+
+max=0
+ns=0
+np=0
+forall_patches count_syms
+echo $max,$ns/$np >_out
+
+expect <<EOF
+12,112/60
+EOF
+
+###############################################################################
View
73 src/compiler/test/patches
@@ -1,5 +1,6 @@
#!/bin/sh
. ./Common
+. ./Patches
###############################################################################
@@ -13,77 +14,15 @@ if [ "$VALGRIND" ]; then
VALGRIND="$VALGRIND --leak-check=full --show-reachable=yes"
fi
-#
-# We explicitly list all the known patches here so that any local additions
-# won't interfere.
-#
-
PATCHDIR=../../../patches
-for n in \
- "Aderassi - Making time.fnp" \
- "Aderrasi - Airs.fnp" \
- "Aderrasi - Antidote (Aqualung Mix).fnp" \
- "Aderrasi - Bow to gravity.fnp" \
- "Aderrasi - Variants Of Eternity (Shaking mix).fnp" \
- "Bmelgren & Krash - Rainbow Orb Peacock (Lonely Signal Gone Mad Mix).fnp" \
- "EvilJim - Ice Drops.fnp" \
- "Fvese - The Tunnel (Final Stage Mix).fnp" \
- "Geiss & Werner - Tornado (Rain Dance MIDI RMX).fnp" \
- "Geiss - Approach.fnp" \
- "Geiss - Cruzin'.fnp" \
- "Geiss - Eggs.fnp" \
- "Geiss - Shift.fnp" \
- "Geiss - The Fatty Lumpkin Sunkle Tweaker.fnp" \
- "Geiss - Tornado.fnp" \
- "Idiot & Rovastar - Altars Of Madness 2 (X42 Mix).fnp" \
- "Illusion & Che - The Piper.fnp" \
- "Illusion & Rovastar - Clouded Bottle.fnp" \
- "Illusion & Unchained - Frozen Eye 1.fnp" \
- "Jeremie - conduirebourre.com.fnp" \
- "Krash - Digital Flame (Video remix).fnp" \
- "Krash - Digital Flame.fnp" \
- "Krash - Interwoven (Nightmare Weft Mix).fnp" \
- "Lekernel & Geiss - Shaking.fnp" \
- "Lekernel & Krash - Boil off (DMX).fnp" \
- "Lekernel & Krash - Personal Shroomery.fnp" \
- "Lekernel & Rovastar & Fvese - Subconscious Objects.fnp" \
- "Lekernel & Rozzor & Aderassi - Video Cannon.fnp" \
- "Lekernel & fiShbRaiN - crazy face.fnp" \
- "Lekernel - Disc Explosion.fnp" \
- "Lekernel - Drawing Board (DMX).fnp" \
- "Lekernel - Eerie Beri.fnp" \
- "Lekernel - Falling (DMX).fnp" \
- "Lekernel - FullScreen Video-in Preview.fnp" \
- "Lekernel - Musique de telephone.fnp" \
- "Lekernel - Pulsating photography.fnp" \
- "Lekernel - Sailing.fnp" \
- "Lekernel - Spiralling.fnp" \
- "Lekernel - Star Ballet (Bass Travel Mix).fnp" \
- "Lekernel - Star Ballet (Fountain Mix).fnp" \
- "Lekernel - Star Ballet.fnp" \
- "Lekernel - Starpainter.fnp" \
- "Lekernel - The psychedelic drunken boat.fnp" \
- "Lekernel - Vibrant Plasma Streams.fnp" \
- "Philpraxis - Eight bit starfield.fnp" \
- "Rovastar & Fvese - Dark Subconscious.fnp" \
- "Rovastar & Idiot24-7 - Balk Acid (DMX madness).fnp" \
- "Rovastar & Idiot24-7 - Balk Acid.fnp" \
- "Rovastar - A Million Miles from Earth.fnp" \
- "Rovastar - Cosmic Echoes 2.fnp" \
- "Rovastar - Explosive Minds.fnp" \
- "Rovastar - Forgotten Moon.fnp" \
- "Rovastar - Hallucinogenic Pyramids.fnp" \
- "Rovastar - Torrid Tales.fnp" \
- "Rozzor & Aderrasi - Canon (DMX out).fnp" \
- "Telek - Slow Shift Matrix (bb4.5).fnp" \
- "Unchained - A Matter Of Taste (Remix).fnp" \
- "Zylot - The Inner Workings of my New Computer.fnp" \
- "bmelgren - Godhead (Video mix).fnp" \
- "nil - Cid and Lucy.fnp"; do
+do_test()
+{
ptest "patch: $n" -c -q <"$PATCHDIR/$n"
expect </dev/null
-done
+}
+
+forall_patches do_test
VALGRIND=$valgrind_orig
View
135 src/compiler/unique.c
@@ -1,135 +0,0 @@
-/*
- * unique.c - Unique string store
- *
- * Copyright 2011 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.
- */
-
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "unique.h"
-
-
-#define INITIAL_ALLOC 64
-
-
-struct key_n {
- const char *s;
- int n;
-};
-
-const char *well_known[] = {
-#include "fnp.inc"
-};
-
-static const char **vars = NULL;
-static int num_vars = 0, allocated = 0;
-
-
-/*
- * "a" is not NUL-terminated and its length "a" is determined by "n".
- * "b" is NUL-terminated.
- */
-
-static int strcmp_n(const char *a, const char *b, int n)
-{
- int diff;
-
- diff = strncmp(a, b, n);
- if (diff)
- return diff;
- /* handle implicit NUL in string "a" */
- return -b[n];
-}
-
-
-static char *strdup_n(const char *s, int n)
-{
- char *new;
-
- new = malloc(n+1);
- memcpy(new, s, n);
- new[n] = 0;
- return new;
-}
-
-
-static void grow_table(void)
-{
- if(num_vars != allocated)
- return;
-
- allocated = allocated ? allocated*2 : INITIAL_ALLOC;
- vars = realloc(vars, allocated*sizeof(*vars));
-}
-
-
-static int cmp(const void *a, const void *b)
-{
- return strcmp(a, *(const char **) b);
-}
-
-
-static int cmp_n(const void *a, const void *b)
-{
- const struct key_n *key = a;
-
- return strcmp_n(key->s, *(const char **) b, key->n);
-}
-
-
-const char *unique(const char *s)
-{
- const char **res;
- const char **walk;
-
- res = bsearch(s, well_known, sizeof(well_known)/sizeof(*well_known),
- sizeof(s), cmp);
- if(res)
- return *res;
- for(walk = vars; walk != vars+num_vars; walk++)
- if(!strcmp(*walk, s))
- return *walk;
- grow_table();
- return vars[num_vars++] = strdup(s);
-}
-
-
-const char *unique_n(const char *s, int n)
-{
- struct key_n key = {
- .s = s,
- .n = n,
- };
- const char **res;
- const char **walk;
-
- assert(n);
- res = bsearch(&key, well_known, sizeof(well_known)/sizeof(*well_known),
- sizeof(s), cmp_n);
- if(res)
- return *res;
- for(walk = vars; walk != vars+num_vars; walk++)
- if(!strcmp_n(s, *walk, n))
- return *walk;
- grow_table();
- return vars[num_vars++] = strdup_n(s, n);
-}
-
-
-void unique_free(void)
-{
- int i;
-
- for(i = 0; i != num_vars; i++)
- free((void *) vars[i]);
- free(vars);
- vars = NULL;
- num_vars = allocated = 0;
-}
View
18 src/compiler/unique.h
@@ -1,18 +0,0 @@
-/*
- * unique.h - Unique string store
- *
- * Copyright 2011 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.
- */
-
-#ifndef UNIQUE_H
-#define UNIQUE_H
-
-const char *unique(const char *s);
-const char *unique_n(const char *s, int n);
-void unique_free(void);
-
-#endif /* !UNIQUE_H */

No commit comments for this range

Something went wrong with that request. Please try again.