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: ab02b37^
...
head fork: m-labs/flickernoise
compare: c4ed46c
Checking mergeability… Don't worry, you can still create the pull request.
  • 5 commits
  • 9 files changed
  • 0 commit comments
  • 1 contributor
View
20 src/compiler/compiler.c
@@ -284,7 +284,7 @@ static void pvv_bind_callback(void *_sc, struct fpvm_sym *sym, int reg)
r->regs->pvv = sc->p->pervertex_regs+reg;
}
-static bool init_pvv(struct compiler_sc *sc)
+static bool init_pvv(struct compiler_sc *sc, int framework)
{
int i;
@@ -294,7 +294,7 @@ 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(!compile_chunk(&sc->pvv_fragment, INIT_PVV_FNP))
+ if(framework && !compile_chunk(&sc->pvv_fragment, INIT_PVV_FNP))
goto fail_assign;
fpvm_set_bind_mode(&sc->pvv_fragment, FPVM_BIND_ALL);
@@ -474,8 +474,8 @@ static bool parse_patch(struct compiler_sc *sc, const char *patch_code)
return ok;
}
-struct patch *patch_compile(const char *basedir, const char *patch_code,
- report_message rmc)
+struct patch *patch_do_compile(const char *basedir, const char *patch_code,
+ report_message rmc, int framework)
{
struct compiler_sc *sc;
struct patch *p;
@@ -507,14 +507,14 @@ struct patch *patch_compile(const char *basedir, const char *patch_code,
load_defaults(sc);
if(!init_pfv(sc)) goto fail;
- if(!init_pvv(sc)) goto fail;
+ if(!init_pvv(sc, framework)) goto fail;
if(!parse_patch(sc, patch_code))
goto fail;
- if(!finalize_pfv(sc)) goto fail;
+ if(framework && !finalize_pfv(sc)) goto fail;
if(!schedule_pfv(sc)) goto fail;
- if(!finalize_pvv(sc)) goto fail;
+ if(framework && !finalize_pvv(sc)) goto fail;
if(!schedule_pvv(sc)) goto fail;
#ifndef STANDALONE
@@ -532,6 +532,12 @@ struct patch *patch_compile(const char *basedir, const char *patch_code,
return NULL;
}
+struct patch *patch_compile(const char *basedir, const char *patch_code,
+ report_message rmc)
+{
+ return patch_do_compile(basedir, patch_code, rmc, 1);
+}
+
struct patch *patch_compile_filename(const char *filename,
const char *patch_code, report_message rmc)
{
View
9 src/compiler/compiler.h
@@ -267,8 +267,17 @@ typedef void (*report_message)(const char *);
struct compiler_sc;
void init_fpvm(struct fpvm_fragment *fragment, int vector_mode);
+
+/*
+ * Flickernoise only uses patch_compile. patch_do_compile allows disabling
+ * the patch framework, which is useful for code analysis in ptest.
+ */
+
+struct patch *patch_do_compile(const char *basedir, const char *patch_code,
+ report_message rmc, int framework);
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 stimuli *compiler_get_stimulus(struct compiler_sc *sc);
View
38 src/compiler/parser.y
@@ -35,6 +35,7 @@
struct yyParser;
+int syntax_is_new_style = 0;
static void yy_parse_failed(struct yyParser *yypParser);
typedef const char *(*assign_callback)(struct parser_comm *comm,
@@ -58,6 +59,7 @@ static struct stim_db_midi *midi_dev;
return; \
} \
state->style = which; \
+ syntax_is_new_style = which == new_style; \
} while (0)
static const enum ast_op tok2op[] = {
@@ -79,6 +81,7 @@ static const enum ast_op tok2op[] = {
[TOK_I2F] = op_i2f,
[TOK_F2I] = op_f2i,
[TOK_IF] = op_if,
+ [TOK_IF_NEW] = op_if,
[TOK_TSIGN] = op_tsign,
[TOK_QUAKE] = op_quake,
[TOK_SQR] = op_sqr,
@@ -155,11 +158,15 @@ static struct ast_node *constant(float n)
static struct ast_node *conditional(struct ast_node *a,
struct ast_node *b, struct ast_node *c)
{
- if(a->op == op_bnot) {
+ while(a->op == op_bnot) {
struct ast_node *next = a->contents.branches.a;
+ struct ast_node *tmp;
parse_free_one(a);
- return node_op(op_if, next, c, b);
+ a = next;
+ tmp = b;
+ b = c;
+ c = tmp;
}
if(a->op != op_constant)
return node_op(op_if, a, b, c);
@@ -249,6 +256,7 @@ static void free_file_list(struct file_list *l)
%destructor primary_expr { free($$); }
%type context {assign_callback}
+%type opt_if {struct ast_node *}
%type opt_arg {struct ast_node *}
%type midi_dev_type {enum stim_midi_dev_type}
%type midi_fn_type {enum stim_midi_fn_type}
@@ -256,6 +264,7 @@ static void free_file_list(struct file_list *l)
%type file_list {struct file_list *}
%type opt_tag {struct id *}
+%destructor opt_if { free($$); }
%destructor opt_arg { parse_free($$); }
%destructor file_list { free_file_list($$); }
%destructor opt_tag { free($$); }
@@ -310,7 +319,7 @@ assignments ::= .
/* ----- Variable assignments ---------------------------------------------- */
-assignment ::= ident(I) TOK_ASSIGN expr(N) opt_semi. {
+assignment ::= ident(I) TOK_ASSIGN expr(N) opt_if(IF) opt_semi. {
I->sym->flags |= SF_ASSIGNED;
/*
* The conditions are as follows:
@@ -332,10 +341,20 @@ assignment ::= ident(I) TOK_ASSIGN expr(N) opt_semi. {
"to zero");
return;
}
+ if(IF) {
+ FAIL("initialization cannot be conditional");
+ return;
+ }
IS_STYLE(new_style);
} else {
const char *msg;
+ if(IF) {
+ struct ast_node *var;
+
+ var = node(I->token, I->sym, NULL, NULL, NULL);
+ N = conditional(IF, N, var);
+ }
msg = state->assign(state->comm, I->sym, N);
free(I);
if(msg) {
@@ -344,9 +363,17 @@ assignment ::= ident(I) TOK_ASSIGN expr(N) opt_semi. {
return;
}
}
+ /*
+ * Q: Why don't we parse_free(IF) ?
+ * A: If IF is non-NULL, it's now in the AST under N and gets free
+ * with it.
+ */
parse_free(N);
}
+opt_if(IF) ::= . { IF = NULL; }
+opt_if(IF) ::= TOK_IF_NEW expr(E). { IF = E; }
+
/* ----- MIDI device database ---------------------------------------------- */
@@ -757,6 +784,11 @@ primary_expr(N) ::= TOK_IF TOK_LPAREN expr(A) TOK_COMMA expr(B) TOK_COMMA
N = conditional(A, B, C);
}
+primary_expr(N) ::= TOK_IF_NEW TOK_LPAREN expr(A) TOK_COMMA expr(B) TOK_COMMA
+ expr(C) TOK_RPAREN. {
+ N = conditional(A, B, C);
+}
+
/* ----- Primary expressions ----------------------------------------------- */
View
2  src/compiler/parser_itf.h
@@ -54,6 +54,8 @@ struct parser_state {
} style;
};
+extern int syntax_is_new_style;
+
void *ParseAlloc(void *(*mallocProc)(size_t));
void ParseFree(void *p, void (*freeProc)(void*));
void Parse(void *yyp, int yymajor, struct id *yyminor,
View
14 src/compiler/ptest/ptest.c
@@ -401,11 +401,11 @@ static void play_midi(struct patch *patch)
}
-static void compile(const char *pgm)
+static void compile(const char *pgm, int framework)
{
struct patch *patch;
- patch = patch_compile("/", pgm, report);
+ patch = patch_do_compile("/", pgm, report, framework);
if (!patch) {
symtab_free();
exit(1);
@@ -497,10 +497,11 @@ static void free_buffer(void)
static void usage(const char *name)
{
fprintf(stderr,
-"usage: %s [-c [-c]|-f error] [-m [chan.]ctrl=value ...] [-n runs]\n"
+"usage: %s [-c [-c [-c]]|-f error] [-m [chan.]ctrl=value ...] [-n runs]\n"
" %*s [-q] [-s] [-v var] [-Wwarning ...] [expr]\n\n"
-" -c generate code and dump generated code (unless -q is set)\n"
+" -c generate PFPU code and dump generated code (unless -q is set)\n"
" -c -c generate and dump VM code\n"
+" -c -c -c generate and dump PFPU code (without patch framework)\n"
" -f error fail any assignment with specified error message\n"
" -m [chan.]ctrl=value\n"
" send a MIDI message to the stimuli subsystem\n"
@@ -582,11 +583,14 @@ int main(int argc, char **argv)
parse_only(buffer);
break;
case 1:
- compile(buffer);
+ compile(buffer, 1);
break;
case 2:
compile_vm(buffer);
break;
+ case 3:
+ compile(buffer, 0);
+ break;
default:
usage(*argv);
}
View
4 src/compiler/scanner.re
@@ -21,6 +21,7 @@
#include <malloc.h>
#include "symtab.h"
+#include "parser_itf.h" /* for syntax_is_new_style */
#include "scanner.h"
#define YYCTYPE unsigned char
@@ -146,7 +147,8 @@ int scan(struct scanner *s)
<N>"f2i" { return TOK_F2I; }
<N>"icos" { return TOK_ICOS; }
<N>"i2f" { return TOK_I2F; }
- <N>"if" { return TOK_IF; }
+ <N>"if" { return syntax_is_new_style ?
+ TOK_IF_NEW : TOK_IF; }
<N>"int" { return TOK_INT; }
<N>"invsqrt" { return TOK_INVSQRT; }
<N>"isin" { return TOK_ISIN; }
View
17 src/compiler/test/dualuse
@@ -14,7 +14,7 @@ EOF
#------------------------------------------------------------------------------
ptest "dual use: sin = sqr-if" <<EOF
-per_frame:
+per_frame=
sin = sqr-if
EOF
expect <<EOF
@@ -23,12 +23,23 @@ EOF
#------------------------------------------------------------------------------
-ptest "dual use: if = max*int" <<EOF
-per_frame:
+ptest "dual use: if = max*int (old style)" <<EOF
+per_frame=
if = max*int
EOF
expect <<EOF
per_frame = if = (* (max) (int))
EOF
+#------------------------------------------------------------------------------
+
+ptest_fail "dual use: if = max*int (new style)" <<EOF
+per_frame:
+dummy = 0 /* scanner switches one token after section */
+if = max*int
+EOF
+expect <<EOF
+line 3: parse error near '='
+EOF
+
###############################################################################
View
9 src/compiler/test/not
@@ -137,4 +137,13 @@ expect <<EOF
sx = (if a c b)
EOF
+#------------------------------------------------------------------------------
+
+ptest "not: if(!!a, b, c)" << EOF
+sx = if(!!a, b, c)
+EOF
+expect <<EOF
+sx = (if a b c)
+EOF
+
###############################################################################
View
34 src/compiler/test/stmtmod
@@ -0,0 +1,34 @@
+#!/bin/sh
+. ./Common
+
+###############################################################################
+
+ptest "statement modifier: foo = foo+1 if cond" <<EOF
+per_frame:
+foo = foo+1 if cond
+EOF
+expect <<EOF
+per_frame = foo = (if cond (+ foo 1) foo)
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "statement modifier: foo = foo+1 if !cond" <<EOF
+per_frame:
+foo = foo+1 if !cond
+EOF
+expect <<EOF
+per_frame = foo = (if cond foo (+ foo 1))
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "statement modifier: initial = 0 if 1 (error)" <<EOF
+foo = 0
+bar = 0 if 1
+EOF
+expect <<EOF
+line 3: initialization cannot be conditional near 'EOF'
+EOF
+
+###############################################################################

No commit comments for this range

Something went wrong with that request. Please try again.