Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: m-labs/flickernoise
base: ab02b37^
...
head fork: m-labs/flickernoise
compare: c4ed46c
  • 5 commits
  • 9 files changed
  • 0 commit comments
  • 1 contributor
20 src/compiler/compiler.c
View
@@ -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)
{
9 src/compiler/compiler.h
View
@@ -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);
38 src/compiler/parser.y
View
@@ -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 ----------------------------------------------- */
2  src/compiler/parser_itf.h
View
@@ -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,
14 src/compiler/ptest/ptest.c
View
@@ -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);
}
4 src/compiler/scanner.re
View
@@ -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; }
17 src/compiler/test/dualuse
View
@@ -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
+
###############################################################################
9 src/compiler/test/not
View
@@ -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
+
###############################################################################
34 src/compiler/test/stmtmod
View
@@ -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.