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: 2aa0d1f
...
head fork: m-labs/flickernoise
compare: 152aaf7
  • 17 commits
  • 26 files changed
  • 0 commit comments
  • 1 contributor
Commits on Dec 12, 2011
@wpwrak wpwrak compiler: don't feed TOK_ERROR to the parser
TOK_ERROR returned after a scanner failure was still sent to the
parser, forcing a parse error as well. While this didn't have any
ill effects, it's better to disentangle the two.
5c6bc3e
@wpwrak wpwrak compiler: report the line number and the context of an error
We'll need this when the compiler parses the entire patch, not just
an expression.
6243f9f
@wpwrak wpwrak compiler: remove trailing whitespace
Some lines had trailing tabs and spaces. Get rid of them.
6b64d3a
@wpwrak wpwrak compiler: return error string from fpvm_parse
This way, the caller has access to the full diagnostics.
004c678
@wpwrak wpwrak compiler: fix multiple /* ... */ comments
The regexp was too greedy and treated  /* ... */ ... /* ... */ as
a single long comment. Luckily, others have already solved that
braintwister for us. This is the solution by Stephen Ostermiller.
75e5cf7
@wpwrak wpwrak compiler: bring out errors encountered by things called from parser
This seems awkward but works. Maybe there's a better way. lemon
documentation is silent about handling this kind of errors, and
the results found when googing for lemon and YYABORT aren't
encouraging.
1a02099
@wpwrak wpwrak compiler: moved prologue and epilogue to almost regular .fnp files
They only differ in not having the per_frame= and per_vertex= prefixes.
The files are then converted to a header containing #defines of strings
with the file content inside. The compiler simply calls fpvm_chunk to
compile the prologue and epilogue.
ec9fbb4
@wpwrak wpwrak compiler: ignore [preset]
The original MilkDrop presets are based on INF files and have a
"[preset]" at the beginning that should be ignored.
cad31ca
@wpwrak wpwrak compiler: infrastructure for supporting fragment selection prefixes
There are two changes:
- instead of calling fpvm_do_assign directly, use a callback
- support for pre_frame, per_vertex, and per_pixel prefixes
1d5a9a3
@wpwrak wpwrak compiler: support parsing imagefileN as well
This was tricky: since file names are bare and can contain all kinds of
special characters and keywords, we need to switch the scanner into a
different mode, which is a little awkward with re2c.
1b0a5d4
@wpwrak wpwrak compiler: dirty hacks to work around syntax problems in patches
This commit makes the parser accept the following constructs:

- per_frameinit_1=...	(becomes per_frame=)
- per_frame=		(or per_vertex; is ignored)
- per_frame=//...	(or per_vertex; is ignored)
35c6131
@wpwrak wpwrak compiler: make regression tester support per_frame and per_vertex as …
…well

Trival. Should have done this earlier.
f840e81
@wpwrak wpwrak patches: fix syntax error in Balk Acid (DMX madness) 081b9ee
@wpwrak wpwrak compiler: don't regularly use " in error messages; nicer format
MTK doesn't like strings containing double quotes. We can work around
this by minimizing the use of double quotes sent to MTK.

Since this changes all the error messages in the regression tests
anyway, we can use the opportunity and also make the message format
a little nicer.
10cbd9f
@wpwrak wpwrak compiler: replace the DIY parser in compiler.c 763007f
@wpwrak wpwrak compiler: remove fpvm_assign
We don't need it anymore.
1ecf4d1
@wpwrak wpwrak compiler: parse all patches in the regression test 152aaf7
View
2  patches/Rovastar & Idiot24-7 - Balk Acid (DMX madness).fnp
@@ -52,7 +52,7 @@ per_frame=rot=rot+0.10*sin(time);
per_frame=mv_r=0.5 +0.5*sin(time*1.23);
per_frame=mv_b=0.5 + 0.5*sin(time*1.26);
per_frame=mv_g=0.5+ 0.5*sin(time*1.19);
-per_frame=wave_g=wave_g*+.20*sin(idmx4*time*.13);
+per_frame=wave_g=wave_g+.20*sin(idmx4*time*.13);
per_frame=wave_r=wave_r+.13*sin(idmx4*time);
per_frame=wave_b=wave_b*sin(idmx4*time);
per_frame=wave_x=idmx3
View
9 src/Makefile
@@ -77,7 +77,7 @@ bandfilters.h: bandfilters.sce
scilab -nw -nwni -nogui -nb -f bandfilters.sce
%.c: %.re
- re2c -o $@ $<
+ re2c -c -o $@ $<
%.c: %.y
lemon $<
@@ -85,11 +85,16 @@ bandfilters.h: bandfilters.sce
%.h %.inc: %.ids
cd compiler && ./idgen `basename $<`
+compiler/infra-fnp.h: \
+ compiler/finish-pfv.fnp compiler/init-pvv.fnp compiler/finish-pvv.fnp
+ compiler/file2h $^ >$@ || { rm -f $@; }
+
compiler/parser.h: compiler/parser.c
obj/compiler/scanner.o: compiler/parser.h
obj/compiler/parser_helper.o: compiler/parser.h
obj/compiler/fpvm.o: compiler/parser.h
obj/compiler/unique.o: compiler/fnp.inc
+obj/compiler/compiler.o: compiler/infra-fnp.h compiler/parser.h
# boot images for Milkymist One
$(BINDIR)/flickernoise.bin: $(BINDIR)/flickernoise
@@ -119,6 +124,6 @@ clean:
rm -f $(POBJS)
rm -f compiler/scanner.c
rm -f compiler/parser.c compiler/parser.h compiler/parser.out
- rm -f compiler/fnp.h compiler/fnp.inc
+ rm -f compiler/fnp.h compiler/fnp.inc compiler/infra-fnp.h
.PHONY: clean load flash
View
309 src/compiler/compiler.c
@@ -29,8 +29,12 @@
#include "../pixbuf/pixbuf.h"
#include "fpvm.h"
#include "unique.h"
+#include "parser_helper.h"
+#include "parser.h"
#include "compiler.h"
+#include "infra-fnp.h"
+
struct compiler_sc {
struct patch *p;
@@ -292,9 +296,8 @@ static bool init_pfv(struct compiler_sc *sc)
static bool finalize_pfv(struct compiler_sc *sc)
{
/* assign dummy values for output */
- if(!fpvm_assign(&sc->pfv_fragment, "_Xo", "_Xi")) goto fail_fpvm;
- if(!fpvm_assign(&sc->pfv_fragment, "_Yo", "_Yi")) goto fail_fpvm;
- if(!fpvm_finalize(&sc->pfv_fragment)) goto fail_fpvm;
+ if(!fpvm_chunk(&sc->pfv_fragment, FINISH_PFV_FNP))
+ goto fail_fpvm;
#ifdef COMP_DEBUG
printf("per-frame FPVM fragment:\n");
fpvm_dump(&sc->pfv_fragment);
@@ -325,16 +328,6 @@ static bool schedule_pfv(struct compiler_sc *sc)
return true;
}
-static bool add_per_frame(struct compiler_sc *sc, char *dest, char *val)
-{
- if(!fpvm_assign(&sc->pfv_fragment, dest, val)) {
- comp_report(sc, "failed to add per-frame equation l. %d: %s",
- sc->linenr, fpvm_get_last_error(&sc->pfv_fragment));
- return false;
- }
- return true;
-}
-
/****************************************************************/
/* PER-VERTEX VARIABLES */
/****************************************************************/
@@ -443,12 +436,8 @@ static bool init_pvv(struct compiler_sc *sc)
fpvm_set_bind_callback(&sc->pvv_fragment, pvv_bind_callback, sc);
fpvm_set_bind_mode(&sc->pvv_fragment, FPVM_BIND_SOURCE);
- if(!fpvm_chunk(&sc->pvv_fragment,
- "x = i2f(_Xi)*_hmeshsize\n"
- "y = i2f(_Yi)*_vmeshsize\n"
- "rad = sqrt(sqr(x-0.5)+sqr(y-0.5))"))
+ if(!fpvm_chunk(&sc->pvv_fragment, INIT_PVV_FNP))
goto fail_assign;
- /* TODO: generate ang */
fpvm_set_bind_mode(&sc->pvv_fragment, FPVM_BIND_ALL);
return true;
@@ -463,52 +452,8 @@ static int finalize_pvv(struct compiler_sc *sc)
{
fpvm_set_bind_mode(&sc->pvv_fragment, FPVM_BIND_SOURCE);
- #define A(dest, val) \
- if(!fpvm_assign(&sc->pvv_fragment, dest, val)) goto fail_assign
-
- /* Zoom */
- A("_invzoom", "1/zoom");
- A("_xz", "_invzoom*(x-0.5)+0.5");
- A("_yz", "_invzoom*(y-0.5)+0.5");
-
- /* Scale */
- A("_xs", "(_xz-cx)/sx+cx");
- A("_ys", "(_yz-cy)/sy+cy");
-
- /* Warp */
- A("_warptime", "time*fWarpAnimSpeed");
- A("_invwarpscale", "1/fWarpScale");
- A("_f0", "11.68 + 4.0*cos(_warptime*1.413 + 10)");
- A("_f1", "8.77 + 3.0*cos(_warptime*1.113 + 7)");
- A("_f2", "10.54 + 3.0*cos(_warptime*1.233 + 3)");
- A("_f3", "11.49 + 4.0*cos(_warptime*0.933 + 5)");
- A("_ox2", "2*x-1");
- A("_oy2", "2*y-1");
- A("_xw", "_xs+warp*0.0035*("
- "sin(_warptime*0.333+_invwarpscale*(_ox2*_f0-_oy2*_f3))"
- "+cos(_warptime*0.753-_invwarpscale*(_ox2*_f1-_oy2*_f2)))");
- A("_yw", "_ys+warp*0.0035*("
- "cos(_warptime*0.375-_invwarpscale*(_ox2*_f2+_oy2*_f1))"
- "+sin(_warptime*0.825+_invwarpscale*(_ox2*_f0+_oy2*_f3)))");
-
- /* Rotate */
- A("_cosr", "cos(rot)");
- A("_sinr", "sin(0-rot)");
- A("_u", "_xw-cx");
- A("_v", "_yw-cy");
- A("_xr", "_u*_cosr-_v*_sinr+cx");
- A("_yr", "_u*_sinr+_v*_cosr+cy");
-
- /* Translate */
- A("_xd", "_xr-dx");
- A("_yd", "_yr-dy");
-
- /* Convert to framebuffer coordinates */
- A("_Xo", "f2i(_xd*_texsize)");
- A("_Yo", "f2i(_yd*_texsize)");
-
- #undef A
-
+ if(!fpvm_chunk(&sc->pvv_fragment, FINISH_PVV_FNP))
+ goto fail_assign;
if(!fpvm_finalize(&sc->pvv_fragment)) goto fail_finalize;
#ifdef COMP_DEBUG
printf("per-vertex FPVM fragment:\n");
@@ -545,179 +490,104 @@ static bool schedule_pvv(struct compiler_sc *sc)
return true;
}
-static bool add_per_vertex(struct compiler_sc *sc, char *dest, char *val)
-{
- if(!fpvm_assign(&sc->pvv_fragment, dest, val)) {
- comp_report(sc, "failed to add per-vertex equation l. %d: %s\n",
- sc->linenr, fpvm_get_last_error(&sc->pvv_fragment));
- return false;
- }
- return true;
-}
-
/****************************************************************/
/* PARSING */
/****************************************************************/
-static bool process_equation(struct compiler_sc *sc, char *equation,
- bool per_vertex)
+static const char *assign_default(struct parser_comm *comm,
+ const char *label, struct ast_node *node)
{
- char *c, *c2;
-
- c = strchr(equation, '=');
- if(!c) {
- comp_report(sc, "error l.%d: malformed equation (%s)",
- sc->linenr, equation);
- return false;
- }
- *c = 0;
-
- if(*equation == 0) {
- comp_report(sc, "error l.%d: missing lvalue", sc->linenr);
- return false;
+ struct compiler_sc *sc = comm->u.sc;
+ int pfv;
+ float v;
+
+ pfv = pfv_from_name(label);
+ if(pfv < 0)
+ return strdup("unknown parameter");
+
+ switch(node->op) {
+ case op_constant:
+ v = node->contents.constant;
+ break;
+ case op_not:
+ if(node->contents.branches.a->op == op_constant) {
+ v = -node->contents.branches.a->contents.constant;
+ break;
+ }
+ /* fall through */
+ default:
+ return strdup("value must be a constant");
}
- c2 = c - 1;
- while((c2 > equation) && (*c2 == ' ')) *c2-- = 0;
-
- c++;
- while(*c == ' ') c++;
- if(*equation == 0) {
- comp_report(sc, "error l.%d: missing lvalue", sc->linenr);
- return false;
- }
- if(*c == 0) {
- comp_report(sc, "error l.%d: missing rvalue", sc->linenr);
- return false;
- }
+ /* patch initial condition or global parameter */
+ pfv_update_patch_requires(sc, pfv);
+ set_initial(sc, pfv, v);
+ return NULL;
+}
- if(per_vertex)
- return add_per_vertex(sc, equation, c);
+static const char *assign_fragment(struct fpvm_fragment *frag,
+ const char *label, struct ast_node *node)
+{
+ if(fpvm_do_assign(frag, label, node))
+ return NULL;
else
- return add_per_frame(sc, equation, c);
+ return strdup(fpvm_get_last_error(frag));
}
-static bool process_equations(struct compiler_sc *sc, char *equations,
- bool per_vertex)
+static const char *assign_per_frame(struct parser_comm *comm,
+ const char *label, struct ast_node *node)
{
- char *c;
-
- while(*equations) {
- c = strchr(equations, ';');
- if(!c)
- return process_equation(sc, equations, per_vertex);
- *c = 0;
- if(!process_equation(sc, equations, per_vertex)) return false;
- equations = c + 1;
- }
- return true;
+ return assign_fragment(&comm->u.sc->pfv_fragment, label, node);
}
-static bool process_top_assign(struct compiler_sc *sc, char *left, char *right)
+static const char *assign_per_vertex(struct parser_comm *comm,
+ const char *label, struct ast_node *node)
{
- int pfv;
-
- while(*right == ' ') right++;
- if(*right == 0) return true;
-
- if(strncmp(left, "imagefile", 9) == 0) {
- int image_n;
- char *totalname;
-
- image_n = atoi(left+9);
- if((image_n < 1) || (image_n > IMAGE_COUNT)) {
- comp_report(sc, "warning l.%d: ignoring image with out of bounds number %d",
- sc->linenr, image_n);
- return true;
- }
- image_n--;
- if(right[0] == '/')
- totalname = strdup(right);
- else {
- totalname =
- malloc(strlen(sc->basedir) + strlen(right) + 1);
- if(totalname == NULL) return true;
- strcpy(totalname, sc->basedir);
- strcat(totalname, right);
- }
- pixbuf_dec_ref(sc->p->images[image_n]);
- sc->p->images[image_n] = pixbuf_get(totalname);
- free(totalname);
- return true;
- }
-
- pfv = pfv_from_name(left);
- if(pfv >= 0) {
- /* patch initial condition or global parameter */
- pfv_update_patch_requires(sc, pfv);
- set_initial(sc, pfv, atof(right));
- return true;
- }
-
- if(strncmp(left, "per_frame", 9) == 0)
- /* per-frame equation */
- return process_equations(sc, right, false);
-
- if((strncmp(left, "per_vertex", 10) == 0) ||
- (strncmp(left, "per_pixel", 9) == 0))
- /* per-vertex equation */
- return process_equations(sc, right, true);
-
- comp_report(sc, "warning l.%d: ignoring unknown parameter %s",
- sc->linenr, left);
-
- return true;
+ return assign_fragment(&comm->u.sc->pvv_fragment, label, node);
}
-static bool process_line(struct compiler_sc *sc, char *line)
+static const char *assign_image_name(struct parser_comm *comm,
+ int number, const char *name)
{
- char *c;
-
- while(*line == ' ') line++;
- if(*line == 0) return true;
- if(*line == '[') return true;
-
- c = strstr(line, "//");
- if(c) *c = 0;
-
- c = line + strlen(line) - 1;
- while((c >= line) && (*c == ' ')) *c-- = 0;
- if(*line == 0) return true;
-
- c = strchr(line, '=');
- if(!c) {
- comp_report(sc, "error l.%d: '=' expected", sc->linenr);
- return false;
+ struct compiler_sc *sc = comm->u.sc;
+ char *totalname;
+
+ if(number > IMAGE_COUNT)
+ return strdup("image number out of bounds");
+ number--;
+
+ if(*name == '/')
+ totalname = strdup(name);
+ else {
+ totalname = malloc(strlen(sc->basedir) + strlen(name) + 1);
+ if(totalname == NULL)
+ return strdup("out of memory");
+ strcpy(totalname, sc->basedir);
+ strcat(totalname, name);
}
- *c = 0;
- return process_top_assign(sc, line, c+1);
+ pixbuf_dec_ref(sc->p->images[number]);
+ sc->p->images[number] = pixbuf_get(totalname);
+ free(totalname);
+ return NULL;
}
-static bool parse_patch(struct compiler_sc *sc, char *patch_code)
+static bool parse_patch(struct compiler_sc *sc, const char *patch_code)
{
- char *eol;
-
- while(*patch_code) {
- sc->linenr++;
- eol = strchr(patch_code, '\n');
- if(!eol) {
- if(!process_line(sc, patch_code))
- return false;
- else
- return true;
- }
- *eol = 0;
- if(*patch_code == 0) {
- patch_code = eol + 1;
- continue;
- }
- if(*(eol - 1) == '\r') *(eol - 1) = 0;
- if(!process_line(sc, patch_code))
- return false;
- patch_code = eol + 1;
+ struct parser_comm comm = {
+ .u.sc = sc,
+ .assign_default = assign_default,
+ .assign_per_frame = assign_per_frame,
+ .assign_per_vertex = assign_per_vertex,
+ .assign_image_name = assign_image_name,
+ };
+ const char *error;
+
+ error = fpvm_parse(patch_code, TOK_START_ASSIGN, &comm);
+ if(error) {
+ sc->rmc(error);
+ free((void *) error);
}
-
- return true;
+ return !error;
}
struct patch *patch_compile(const char *basedir, const char *patch_code,
@@ -725,7 +595,6 @@ struct patch *patch_compile(const char *basedir, const char *patch_code,
{
struct compiler_sc *sc;
struct patch *p;
- char *patch_code_copy;
int i;
sc = malloc(sizeof(struct compiler_sc));
@@ -753,16 +622,8 @@ struct patch *patch_compile(const char *basedir, const char *patch_code,
if(!init_pfv(sc)) goto fail;
if(!init_pvv(sc)) goto fail;
- patch_code_copy = strdup(patch_code);
- if(patch_code_copy == NULL) {
- rmc("Failed to allocate memory for patch code");
- goto fail;
- }
- if(!parse_patch(sc, patch_code_copy)) {
- free(patch_code_copy);
+ if(!parse_patch(sc, patch_code))
goto fail;
- }
- free(patch_code_copy);
unique_free();
if(!finalize_pfv(sc)) goto fail;
View
6 src/compiler/compiler.h
@@ -117,7 +117,7 @@ enum {
pfv_osc2,
pfv_osc3,
pfv_osc4,
-
+
pfv_midi1,
pfv_midi2,
pfv_midi3,
@@ -128,7 +128,7 @@ enum {
pfv_midi8,
pfv_video_a,
-
+
pfv_image1_a,
pfv_image1_x,
pfv_image1_y,
@@ -191,7 +191,7 @@ enum {
pvv_osc2,
pvv_osc3,
pvv_osc4,
-
+
pvv_midi1,
pvv_midi2,
pvv_midi3,
View
9 src/compiler/file2h
@@ -0,0 +1,9 @@
+#!/bin/sh -e
+while [ "$1" ]; do
+ echo -n "#define "
+ basename $1 | sed 's/[^a-zA-Z0-9]/_/g' | tr a-z A-Z | tr -d '\n'
+ echo ' \'
+ sed 's/\\/\\\\/g;s/"/\\"/g;s/.*/ "&\\n" \\/' <$1
+ echo
+ shift
+done
View
19 src/compiler/finish-pfv.fnp
@@ -0,0 +1,19 @@
+/*
+ * Per-Frame Variables Epilogue
+ * Copyright (C) 2010, 2011 Sebastien Bourdeauducq
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+ _Xo = _Xi
+ _Yo = _Yi
View
57 src/compiler/finish-pvv.fnp
@@ -0,0 +1,57 @@
+/*
+ * Per-Vertex Variables Epilogue
+ * Copyright (C) 2010, 2011 Sebastien Bourdeauducq
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+ /* Zoom */
+ _invzoom = 1/zoom
+ _xz = _invzoom*(x-0.5)+0.5
+ _yz = _invzoom*(y-0.5)+0.5
+
+ /* Scale */
+ _xs = (_xz-cx)/sx+cx
+ _ys = (_yz-cy)/sy+cy
+
+ /* Warp */
+ _warptime = time*fWarpAnimSpeed
+ _invwarpscale = 1/fWarpScale
+ _f0 = 11.68 + 4.0*cos(_warptime*1.413 + 10)
+ _f1 = 8.77 + 3.0*cos(_warptime*1.113 + 7)
+ _f2 = 10.54 + 3.0*cos(_warptime*1.233 + 3)
+ _f3 = 11.49 + 4.0*cos(_warptime*0.933 + 5)
+ _ox2 = 2*x-1
+ _oy2 = 2*y-1
+ _xw = _xs+warp*0.0035*(
+ sin(_warptime*0.333+_invwarpscale*(_ox2*_f0-_oy2*_f3))
+ +cos(_warptime*0.753-_invwarpscale*(_ox2*_f1-_oy2*_f2)))
+ _yw = _ys+warp*0.0035*(
+ cos(_warptime*0.375-_invwarpscale*(_ox2*_f2+_oy2*_f1))
+ +sin(_warptime*0.825+_invwarpscale*(_ox2*_f0+_oy2*_f3)))
+
+ /* Rotate */
+ _cosr = cos(rot)
+ _sinr = sin(0-rot)
+ _u = _xw-cx
+ _v = _yw-cy
+ _xr = _u*_cosr-_v*_sinr+cx
+ _yr = _u*_sinr+_v*_cosr+cy
+
+ /* Translate */
+ _xd = _xr-dx
+ _yd = _yr-dy
+
+ /* Convert to framebuffer coordinates */
+ _Xo = f2i(_xd*_texsize)
+ _Yo = f2i(_yd*_texsize)
View
42 src/compiler/fpvm.c
@@ -15,7 +15,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include <fpvm/fpvm.h>
#include <fpvm/ast.h>
@@ -42,29 +44,37 @@ void fpvm_init(struct fpvm_fragment *fragment, int vector_mode)
}
-int fpvm_assign(struct fpvm_fragment *fragment, const char *dest,
- const char *expr)
+static const char *assign_default(struct parser_comm *comm,
+ const char *label, struct ast_node *node)
{
- union parser_comm comm;
- int res;
-
- if (!fpvm_parse(expr, TOK_START_EXPR, &comm)) {
- snprintf(fragment->last_error, FPVM_MAXERRLEN, "Parse error");
- return 0;
- }
-
- dest = unique(dest);
+ if(fpvm_do_assign(comm->u.fragment, label, node))
+ return NULL;
+ else
+ return strdup(fpvm_get_last_error(comm->u.fragment));
+}
- res = fpvm_do_assign(fragment, dest, comm.parseout);
- fpvm_parse_free(comm.parseout);
- return res;
+static const char *assign_unsupported(struct parser_comm *comm,
+ const char *label, struct ast_node *node)
+{
+ return strdup("assignment mode not supported yet");
}
int fpvm_chunk(struct fpvm_fragment *fragment, const char *chunk)
{
- union parser_comm comm = { .fragment = fragment };
+ struct parser_comm comm = {
+ .u.fragment = fragment,
+ .assign_default = assign_default,
+ .assign_per_frame = assign_unsupported,
+ .assign_per_vertex = assign_unsupported,
+ };
+ const char *error;
- return fpvm_parse(chunk, TOK_START_ASSIGN, &comm);
+ error = fpvm_parse(chunk, TOK_START_ASSIGN, &comm);
+ if(error) {
+ snprintf(fragment->last_error, FPVM_MAXERRLEN, "%s", error);
+ free((void *) error);
+ }
+ return !error;
}
View
3  src/compiler/fpvm.h
@@ -29,9 +29,6 @@
void fpvm_init(struct fpvm_fragment *fragment, int vector_mode);
-int fpvm_assign(struct fpvm_fragment *fragment, const char *dest,
- const char *expr);
-
int fpvm_chunk(struct fpvm_fragment *fragment, const char *chunk);
#endif /* __FPVM_H */
View
22 src/compiler/init-pvv.fnp
@@ -0,0 +1,22 @@
+/*
+ * Per-Vector Variables Prologue
+ * Copyright (C) 2010, 2011 Sebastien Bourdeauducq
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+ x = i2f(_Xi)*_hmeshsize
+ y = i2f(_Yi)*_vmeshsize
+ rad = sqrt(sqr(x-0.5)+sqr(y-0.5))
+
+ /* TODO: generate ang */
View
71 src/compiler/parser.y
@@ -28,6 +28,12 @@
#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);
+
const enum ast_op tok2op[] = {
[TOK_IDENT] = op_ident,
[TOK_CONSTANT] = op_constant,
@@ -56,11 +62,10 @@
[TOK_MIN] = op_min,
[TOK_MAX] = op_max,
[TOK_INT] = op_int,
-
};
- struct ast_node *node(int token, const char *id, struct ast_node *a,
- struct ast_node *b, struct ast_node *c)
+ static struct ast_node *node(int token, const char *id,
+ struct ast_node *a, struct ast_node *b, struct ast_node *c)
{
struct ast_node *n;
@@ -72,6 +77,14 @@
n->contents.branches.c = c;
return n;
}
+
+ static void syntax_error(struct parser_state *state)
+ {
+ if(!state->error_label) {
+ state->error_label = state->id->label;
+ state->error_lineno = state->id->lineno;
+ }
+ }
}
%start_symbol start
@@ -85,10 +98,16 @@
%type node {struct ast_node *}
%destructor node { free($$); }
-%syntax_error { yy_parse_failed(yypParser); }
+
+%type context {assign_callback}
+
+%syntax_error {
+ syntax_error(state);
+ yy_parse_failed(yypParser);
+}
start ::= TOK_START_EXPR node(N). {
- state->comm->parseout = N;
+ state->comm->u.parseout = N;
state->success = 1;
}
@@ -101,10 +120,50 @@ assignments ::= assignments assignment.
assignments ::= .
assignment ::= ident(I) TOK_ASSIGN node(N) opt_semi. {
- fpvm_do_assign(state->comm->fragment, I->label, N);
+ state->error = state->comm->assign_default(state->comm, I->label, N);
+ if(state->error) {
+ syntax_error(state);
+ yy_parse_failed(yypParser);
+ return;
+ }
fpvm_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);
+ if(state->error) {
+ syntax_error(state);
+ yy_parse_failed(yypParser);
+ return;
+ }
+}
+
+assignment ::= context(C). {
+ /*
+ * @@@ Vile madness ahead: a lot of patches have per_frame= or
+ * 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.
+ */
+ state->comm->assign_default = C;
+}
+
+context(C) ::= TOK_PER_FRAME TOK_ASSIGN. {
+ C = state->comm->assign_per_frame;
+}
+
+context(C) ::= TOK_PER_VERTEX TOK_ASSIGN. {
+ C = state->comm->assign_per_vertex;
+}
+
+context(C) ::= TOK_PER_PIXEL TOK_ASSIGN. {
+ C = state->comm->assign_per_vertex;
+}
+
opt_semi ::= opt_semi TOK_SEMI.
opt_semi ::= .
View
80 src/compiler/parser_helper.c
@@ -15,6 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdarg.h>
+#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <fpvm/ast.h>
@@ -24,17 +26,59 @@
#include "parser_itf.h"
#include "parser_helper.h"
-int fpvm_parse(const char *expr, int start_token, union parser_comm *comm)
+static char printable_char(unsigned char c)
+{
+ return c < ' ' || c > '~' ? '?' : c;
+}
+
+/*
+ * Since operators don't set "label" properly in unique(), we can't just print
+ * the whole string, but need to cut it at the first non-printable character.
+ */
+
+static int printable_label(const char *s)
+{
+ const char *p;
+
+ for(p = s; *p > ' '; p++);
+ return p-s;
+}
+
+static const char *alloc_printf(const char *fmt, ...)
+{
+ va_list ap;
+ int n;
+ char *s;
+
+ va_start(ap, fmt);
+ n = vsnprintf(NULL, 0, fmt, ap);
+ va_end(ap);
+
+ s = malloc(n+1);
+
+ va_start(ap, fmt);
+ vsnprintf(s, n+1, fmt, ap);
+ va_end(ap);
+
+ return s;
+}
+
+const char *fpvm_parse(const char *expr, int start_token,
+ struct parser_comm *comm)
{
struct scanner *s;
struct parser_state state = {
.comm = comm,
.success = 0,
+ .error = NULL,
+ .error_label = NULL,
+ .id = NULL,
};
int tok;
struct id *identifier;
void *p;
-
+ const char *error = NULL;
+
s = new_scanner((unsigned char *)expr);
p = ParseAlloc(malloc);
Parse(p, start_token, NULL, &state);
@@ -42,19 +86,31 @@ int fpvm_parse(const char *expr, int start_token, union parser_comm *comm)
while(tok != TOK_EOF) {
identifier = malloc(sizeof(struct id));
identifier->token = tok;
- if(tok == TOK_CONSTANT) {
+ identifier->lineno = s->lineno;
+
+ switch(tok) {
+ case TOK_CONSTANT:
identifier->constant = get_constant(s);
identifier->label = "";
- } else {
+ break;
+ case TOK_FNAME:
identifier->label = get_token(s);
+ break;
+ default:
+ identifier->label = get_unique_token(s);
+ break;
}
- Parse(p, tok, identifier, &state);
+
+ state.id = identifier;
if(tok == TOK_ERROR) {
- printf("FPVM: scan error\n");
+ error = alloc_printf(
+ "FPVM, line %d: scan error near '%c'",
+ s->lineno, printable_char(s->cursor[-1]));
ParseFree(p, free);
delete_scanner(s);
- return 0;
+ return error;
}
+ Parse(p, tok, identifier, &state);
tok = scan(s);
}
Parse(p, TOK_EOF, NULL, &state);
@@ -62,11 +118,15 @@ int fpvm_parse(const char *expr, int start_token, union parser_comm *comm)
delete_scanner(s);
if(!state.success) {
- printf("FPVM: parse error\n");
- return 0;
+ error = alloc_printf(
+ "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 state.success;
+ return error;
}
void fpvm_parse_free(struct ast_node *node)
View
23 src/compiler/parser_helper.h
@@ -21,13 +21,26 @@
#include <fpvm/ast.h>
#include <fpvm/fpvm.h>
-union parser_comm {
- struct ast_node *parseout;
- struct fpvm_fragment *fragment;
+struct compiler_sc;
+
+struct parser_comm {
+ union {
+ struct ast_node *parseout;
+ struct fpvm_fragment *fragment;
+ struct compiler_sc *sc;
+ } u;
+ const char *(*assign_default)(struct parser_comm *comm,
+ const char *label, struct ast_node *node);
+ const char *(*assign_per_frame)(struct parser_comm *comm,
+ const char *label, struct ast_node *node);
+ const char *(*assign_per_vertex)(struct parser_comm *comm,
+ const char *label, struct ast_node *node);
+ const char *(*assign_image_name)(struct parser_comm *comm,
+ int number, const char *name);
};
-int fpvm_parse(const char *expr, int start_token,
- union parser_comm *comm);
+const char *fpvm_parse(const char *expr, int start_token,
+ struct parser_comm *comm);
void fpvm_parse_free(struct ast_node *node);
#endif /* __PARSER_HELPER_H */
View
7 src/compiler/parser_itf.h
@@ -29,11 +29,16 @@ struct id {
int token;
const char *label;
float constant;
+ int lineno;
};
struct parser_state {
int success;
- union parser_comm *comm;
+ 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 struct id *id; /* input, for error handling */
};
void *ParseAlloc(void *(*mallocProc)(size_t));
View
2  src/compiler/ptest/Makefile
@@ -37,7 +37,7 @@ ptest: $(OBJS)
$(CC) $(CFLAGS) -c -o $@ $<
%.c: %.re
- $(GEN) re2c -o $@ $<
+ $(GEN) re2c -c -o $@ $<
%.c: %.y
$(GEN) lemon $<
View
76 src/compiler/ptest/ptest.c
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include <string.h>
#include "../fpvm.h"
#include "../parser_helper.h"
@@ -19,6 +20,7 @@
static int quiet = 0;
+static const char *fail = NULL;
static void dump_ast(const struct ast_node *ast);
@@ -133,18 +135,58 @@ static void dump_ast(const struct ast_node *ast)
}
-int fpvm_do_assign(struct fpvm_fragment *fragment, const char *dest,
- struct ast_node *ast)
+const char *fpvm_get_last_error(struct fpvm_fragment *fragment)
{
+ return fragment->last_error;
+}
+
+
+static const char *assign_default(struct parser_comm *comm,
+ const char *label, struct ast_node *node)
+{
+ if (fail)
+ return strdup(fail);
if (!quiet) {
- printf("%s = ", dest);
- dump_ast(ast);
+ printf("%s = ", label);
+ dump_ast(node);
putchar('\n');
}
- return 1;
+ return NULL;
+}
+
+
+static const char *assign_per_frame(struct parser_comm *comm,
+ const char *label, struct ast_node *node)
+{
+ if (!quiet) {
+ printf("per_frame = %s = ", label);
+ dump_ast(node);
+ putchar('\n');
+ }
+ return NULL;
}
+static const char *assign_per_vertex(struct parser_comm *comm,
+ const char *label, struct ast_node *node)
+{
+ if (!quiet) {
+ printf("per_vertex = %s = ", label);
+ dump_ast(node);
+ putchar('\n');
+ }
+ return NULL;
+}
+
+
+static const char *assign_image_name(struct parser_comm *comm,
+ int number, const char *name)
+{
+ if (!quiet)
+ printf("image %d = \"%s\"\n", number, name);
+ return NULL;
+}
+
static const char *read_stdin(void)
{
char *buf = NULL;
@@ -177,7 +219,7 @@ static const char *read_stdin(void)
static void usage(const char *name)
{
- fprintf(stderr, "usage: %s [-q] [expr]\n", name);
+ fprintf(stderr, "usage: %s [-f error] [-q] [expr]\n", name);
exit(1);
}
@@ -186,10 +228,21 @@ int main(int argc, char **argv)
{
int c;
const char *buf;
- union parser_comm comm;
+ struct fpvm_fragment fragment;
+ struct parser_comm comm = {
+ .u.fragment = &fragment,
+ .assign_default = assign_default,
+ .assign_per_frame = assign_per_frame,
+ .assign_per_vertex = assign_per_vertex,
+ .assign_image_name = assign_image_name,
+ };
+ const char *error;
- while ((c = getopt(argc, argv, "q")) != EOF)
+ while ((c = getopt(argc, argv, "f:q")) != EOF)
switch (c) {
+ case 'f':
+ fail = optarg;
+ break;
case 'q':
quiet = 1;
break;
@@ -207,5 +260,10 @@ int main(int argc, char **argv)
usage(*argv);
}
- return !fpvm_parse(buf, TOK_START_ASSIGN, &comm);
+ error = fpvm_parse(buf, TOK_START_ASSIGN, &comm);
+ if (!error)
+ return 0;
+ fflush(stdout);
+ fprintf(stderr, "%s\n", error);
+ return 1;
}
View
11 src/compiler/scanner.h
@@ -23,11 +23,19 @@
#include "parser.h"
+enum scanner_cond {
+ yycN = 1,
+ yycFNAME1,
+ yycFNAME2,
+};
+
struct scanner {
+ enum scanner_cond cond;
unsigned char *marker;
unsigned char *old_cursor;
unsigned char *cursor;
unsigned char *limit;
+ int lineno;
};
struct scanner *new_scanner(unsigned char *input);
@@ -38,6 +46,9 @@ int scan(struct scanner *s);
/* get the unique string comprising the current token
*/
+const char *get_unique_token(struct scanner *s);
+
+/* like get_unique_token, but malloc'ed non-unique string */
const char *get_token(struct scanner *s);
float get_constant(struct scanner *s);
View
150 src/compiler/scanner.re
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
@@ -30,18 +31,24 @@
#define YYMARKER s->marker
#define YYFILL(n)
+#define YYCONDTYPE enum scanner_cond
+#define YYGETCONDITION() s->cond
+#define YYSETCONDITION(c) s->cond = (c)
+
struct scanner *new_scanner(unsigned char *input)
{
struct scanner *s;
-
+
s = malloc(sizeof(struct scanner));
if(s == NULL) return NULL;
-
+
+ s->cond = yycN;
s->marker = input;
s->old_cursor = input;
s->cursor = input;
s->limit = input + strlen((char *)input);
-
+ s->lineno = 1;
+
return s;
}
@@ -50,64 +57,113 @@ void delete_scanner(struct scanner *s)
free(s);
}
+static int nls(const unsigned char *s, const unsigned char *end)
+{
+ int n = 0;
+
+ while(s != end)
+ if(*s++ == '\n')
+ n++;
+ return n;
+}
+
+/*
+ * Regular expression for C-style comments by Stephen Ostermiller, from
+ * http://ostermiller.org/findcomment.html
+ */
+
int scan(struct scanner *s)
{
std:
if(s->cursor == s->limit) return TOK_EOF;
s->old_cursor = s->cursor;
-
+
/*!re2c
- [\x20\n\r\t] { goto std; }
-
- "//"[^\n\x00]* { goto std; }
- "/*"("*"*[^/\x00]|[^*\x00])*"*"+"/"
- { goto std; }
-
- [0-9]+ { return TOK_CONSTANT; }
- [0-9]+ "." [0-9]* { return TOK_CONSTANT; }
- [0-9]* "." [0-9]+ { return TOK_CONSTANT; }
-
- "above" { return TOK_ABOVE; }
- "abs" { return TOK_ABS; }
- "below" { return TOK_BELOW; }
- "cos" { return TOK_COS; }
- "equal" { return TOK_EQUAL; }
- "f2i" { return TOK_F2I; }
- "icos" { return TOK_ICOS; }
- "i2f" { return TOK_I2F; }
- "if" { return TOK_IF; }
- "int" { return TOK_INT; }
- "invsqrt" { return TOK_INVSQRT; }
- "isin" { return TOK_ISIN; }
- "max" { return TOK_MAX; }
- "min" { return TOK_MIN; }
- "quake" { return TOK_QUAKE; }
- "sin" { return TOK_SIN; }
- "sqr" { return TOK_SQR; }
- "sqrt" { return TOK_SQRT; }
- "tsign" { return TOK_TSIGN; }
-
- [a-zA-Z_0-9]+ { return TOK_IDENT; }
- "+" { return TOK_PLUS; }
- "-" { return TOK_MINUS; }
- "*" { return TOK_MULTIPLY; }
- "/" { return TOK_DIVIDE; }
- "%" { return TOK_PERCENT; }
- "(" { return TOK_LPAREN; }
- ")" { return TOK_RPAREN; }
- "," { return TOK_COMMA; }
- "=" { return TOK_ASSIGN; }
- ";" { return TOK_SEMI; }
- [\x00-\xff] { return TOK_ERROR; }
+ <*>[\x20\r\t] { goto std; }
+ <*>"\n" { s->lineno++;
+ YYSETCONDITION(yycN);
+ goto std; }
+
+ <N>"//"[^\n\x00]* { goto std; }
+ <N>"/*"([^*\x00]|("*"+([^*/\x00])))*"*"+"/"
+ { s->lineno += nls(s->old_cursor,
+ s->cursor);
+ goto std; }
+
+ <N>"[preset]" { goto std; }
+
+ <N>[0-9]+ { return TOK_CONSTANT; }
+ <N>[0-9]+ "." [0-9]* { return TOK_CONSTANT; }
+ <N>[0-9]* "." [0-9]+ { return TOK_CONSTANT; }
+
+ <N>"above" { return TOK_ABOVE; }
+ <N>"abs" { return TOK_ABS; }
+ <N>"below" { return TOK_BELOW; }
+ <N>"cos" { return TOK_COS; }
+ <N>"equal" { return TOK_EQUAL; }
+ <N>"f2i" { return TOK_F2I; }
+ <N>"icos" { return TOK_ICOS; }
+ <N>"i2f" { return TOK_I2F; }
+ <N>"if" { return TOK_IF; }
+ <N>"int" { return TOK_INT; }
+ <N>"invsqrt" { return TOK_INVSQRT; }
+ <N>"isin" { return TOK_ISIN; }
+ <N>"max" { return TOK_MAX; }
+ <N>"min" { return TOK_MIN; }
+ <N>"quake" { return TOK_QUAKE; }
+ <N>"sin" { return TOK_SIN; }
+ <N>"sqr" { return TOK_SQR; }
+ <N>"sqrt" { return TOK_SQRT; }
+ <N>"tsign" { return TOK_TSIGN; }
+
+ <N>"per_frame"[a-z_0-9]*
+ { return TOK_PER_FRAME; }
+ <N>"per_vertex" { return TOK_PER_VERTEX; }
+ <N>"per_pixel" { return TOK_PER_PIXEL; }
+
+ <N>"imagefile"[1-9] { YYSETCONDITION(yycFNAME1);
+ return TOK_IMAGEFILE; }
+
+ <N>[a-zA-Z_0-9]+ { return TOK_IDENT; }
+
+ <N>"+" { return TOK_PLUS; }
+ <N>"-" { return TOK_MINUS; }
+ <N>"*" { return TOK_MULTIPLY; }
+ <N>"/" { return TOK_DIVIDE; }
+ <N>"%" { return TOK_PERCENT; }
+ <N>"(" { return TOK_LPAREN; }
+ <N>")" { return TOK_RPAREN; }
+ <N>"," { return TOK_COMMA; }
+ <N,FNAME1>"=" { if (YYGETCONDITION() == yycFNAME1)
+ YYSETCONDITION(yycFNAME2);
+ return TOK_ASSIGN; }
+ <N>";" { return TOK_SEMI; }
+
+ <FNAME2>[^ \x00\n\r\t]|[^ \x00\n\r\t][^\n\x00]*[^ \x00\n\r\t]
+ { return TOK_FNAME; }
+
+ <*>[\x00-\xff] { return TOK_ERROR; }
*/
}
-const char *get_token(struct scanner *s)
+const char *get_unique_token(struct scanner *s)
{
return unique_n((const char *) s->old_cursor,
s->cursor - s->old_cursor);
}
+const char *get_token(struct scanner *s)
+{
+ char *buf;
+ int n;
+
+ n = s->cursor - s->old_cursor;
+ buf = malloc(n+1);
+ memcpy(buf, s->old_cursor, n);
+ buf[n] = 0;
+ return buf;
+}
+
float get_constant(struct scanner *s)
{
const unsigned char *p;
View
27 src/compiler/test/comment
@@ -113,7 +113,7 @@ a = 9 /*/
b = a
EOF
expect <<EOF
-FPVM: parse error
+FPVM, line 1: parse error near '*/'
EOF
#------------------------------------------------------------------------------
@@ -123,14 +123,35 @@ a = b + c /* comment
d = e + f
EOF
expect <<EOF
-FPVM: parse error
+FPVM, line 1: parse error near '*'
EOF
#------------------------------------------------------------------------------
ptest_fail "comment: unterminated /* ... without newline" "a = b+c /* comment"
expect <<EOF
-FPVM: parse error
+FPVM, line 1: parse error near '*'
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "comment: multiple /*...*/ comments" <<EOF
+/* */ a /* */
+/***/ = /**/
+/**/ b /* */
+EOF
+expect <<EOF
+a = b
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "comment: [preset]" <<EOF
+ [preset]
+x=y
+EOF
+expect <<EOF
+x = y
EOF
###############################################################################
View
15 src/compiler/test/error
@@ -7,7 +7,7 @@ ptest_fail "syntax error: x = backtick" <<EOF
x = \`
EOF
expect <<EOF
-FPVM: scan error
+FPVM, line 1: scan error near '\`'
EOF
#------------------------------------------------------------------------------
@@ -17,7 +17,7 @@ x = a b
EOF
expect <<EOF
x = a
-FPVM: parse error
+FPVM, line 1: parse error near 'b'
EOF
#------------------------------------------------------------------------------
@@ -26,7 +26,16 @@ ptest_fail "syntax error: x = a + + b" <<EOF
x = a + + b
EOF
expect <<EOF
-FPVM: parse error
+FPVM, line 1: parse error near '+'
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "code generation error" -f "codegen" <<EOF
+x = a + b
+EOF
+expect <<EOF
+FPVM, line 1: codegen near 'b'
EOF
###############################################################################
View
69 src/compiler/test/image
@@ -0,0 +1,69 @@
+#!/bin/sh
+. ./Common
+
+# WORK IN PROGRESS
+
+###############################################################################
+
+ptest "image: imagefile1=hello" <<EOF
+imagefile1=hello
+EOF
+expect <<EOF
+image 1 = "hello"
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "image: imagefile2 = hello" <<EOF
+imagefile2 = hello
+EOF
+expect <<EOF
+image 2 = "hello"
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "image: imagefile1 = hel lo" <<EOF
+imagefile1 = hel lo
+EOF
+expect <<EOF
+image 1 = "hel lo"
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "image: imagefile2 = hel<nl>lo" <<EOF
+imagefile2 = hel
+lo = u
+EOF
+expect <<EOF
+image 2 = "hel"
+lo = u
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "image: imagefile1 = foo<spc><spc>" "imagefile1 = foo "
+expect <<EOF
+image 1 = "foo"
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "image: imagefile2 = /dev/null" <<EOF
+imagefile2 = /dev/null
+EOF
+expect <<EOF
+image 2 = "/dev/null"
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "image: imagefile1 = *** test - robust & ness ***" <<EOF
+imagefile1 = *** test - robust & ness ***
+EOF
+expect <<EOF
+image 1 = "*** test - robust & ness ***"
+EOF
+
+###############################################################################
View
158 src/compiler/test/location
@@ -0,0 +1,158 @@
+#!/bin/sh
+. ./Common
+
+###############################################################################
+
+ptest_fail "location: scanner, inside line" <<EOF
+a = b
+x = \` y
+c = d
+EOF
+expect <<EOF
+a = b
+FPVM, line 2: scan error near '\`'
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: scanner, beginning of line" <<EOF
+a = b
+\`x = y
+c = d
+EOF
+expect <<EOF
+FPVM, line 2: scan error near '\`'
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: scanner, end of line" <<EOF
+a = b
+x = y\`
+c = d
+EOF
+expect <<EOF
+a = b
+FPVM, line 2: scan error near '\`'
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: parser, inside line" <<EOF
+a = b
+x = * y
+c = d
+EOF
+expect <<EOF
+a = b
+FPVM, line 2: parse error near '*'
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: parser, beginning of line" <<EOF
+a = b
+)x = y
+c = d
+EOF
+expect <<EOF
+a = b
+FPVM, line 2: parse error near ')x'
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: parser, end of line (1)" <<EOF
+a = b
+x = y(
+c = d
+EOF
+expect <<EOF
+a = b
+x = y
+FPVM, line 2: parse error near '('
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: parser, end of line (2)" <<EOF
+a = b
+x = )
+c = d
+EOF
+expect <<EOF
+a = b
+FPVM, line 2: parse error near ')'
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: error is end of line" <<EOF
+a = b
+x =
+EOF
+expect <<EOF
+a = b
+FPVM, line 2: parse error near '='
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: error is EOF" "x="
+expect <<EOF
+FPVM, line 1: parse error near '='
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: error is identifier" <<EOF
+foo = this is an error
+EOF
+expect <<EOF
+foo = this
+FPVM, line 1: parse error near 'an'
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: 3rd line" <<EOF
+a = b
+c = d
+)
+EOF
+expect <<EOF
+a = b
+c = d
+FPVM, line 3: parse error near ')'
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: 5th line, with // comments" <<EOF
+// assign a
+a = b
+// assign c
+c = d
+)
+EOF
+expect <<EOF
+a = b
+c = d
+FPVM, line 5: parse error near ')'
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: 4th line, with /*...*/ comments" <<EOF
+a = b /* some
+comment */
+c = d
+)
+EOF
+expect <<EOF
+a = b
+c = d
+FPVM, line 4: parse error near ')'
+EOF
+
+###############################################################################
View
3  src/compiler/test/number
@@ -20,7 +20,6 @@ b = 1.2
EOF
#------------------------------------------------------------------------------
-#------------------------------------------------------------------------------
ptest "number: c = .3" <<EOF
c = .3
@@ -53,7 +52,7 @@ ptest_fail "number: f = ." <<EOF
f = .
EOF
expect <<EOF
-FPVM: scan error
+FPVM, line 1: scan error near '.'
EOF
###############################################################################
View
78 src/compiler/test/patches
@@ -0,0 +1,78 @@
+#!/bin/sh
+. ./Common
+
+###############################################################################
+
+#
+# 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
+ ptest "patch: $n" -q <"$PATCHDIR/$n"
+ expect </dev/null
+done
+
+###############################################################################
View
33 src/compiler/test/prefix
@@ -0,0 +1,33 @@
+#!/bin/sh
+. ./Common
+
+# WORK IN PROGRESS
+
+###############################################################################
+
+ptest "prefix: per_frame=x = a+b" <<EOF
+per_frame=x = a+b
+EOF
+expect <<EOF
+per_frame = x = (+ a b)
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "prefix: per_vertex= x = a+b" <<EOF
+per_vertex = x = a+b
+EOF
+expect <<EOF
+per_vertex = x = (+ a b)
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "prefix: per_pixel=x = a+b" <<EOF
+per_pixel=x = a+b
+EOF
+expect <<EOF
+per_vertex = x = (+ a b)
+EOF
+
+###############################################################################
View
4 src/compiler/test/wrap
@@ -75,7 +75,7 @@ ptest_fail "wrap: one assignment containing semicolon (1)" <<EOF
a = b +; c
EOF
expect <<EOF
-FPVM: parse error
+FPVM, line 1: parse error near ';'
EOF
#------------------------------------------------------------------------------
@@ -85,7 +85,7 @@ a = b; + c
EOF
expect <<EOF
a = b
-FPVM: parse error
+FPVM, line 1: parse error near '+'
EOF
###############################################################################

No commit comments for this range

Something went wrong with that request. Please try again.