1
0
mirror of git://projects.qi-hardware.com/fped.git synced 2024-11-18 03:14:59 +02:00

introduce keyed tables (?var syntax; WIP)

This cannot be set/changed through the GUI yet.
This commit is contained in:
Werner Almesberger 2012-05-27 16:10:59 -03:00
parent 3c39600c1c
commit 3488cf80ec
8 changed files with 276 additions and 26 deletions

15
README
View File

@ -503,6 +503,21 @@ table
(x, y) assume the values (1, 2) and (3, 4). (x, y) assume the values (1, 2) and (3, 4).
Tables can also be used to provide information that depends on
other variables. The value of such a variable acts as a key, and a
row is only selected if all the keys in that row match the
respective variables. To mark a variable as being used as key, its
name it prefixed with a question mark.
Example:
loop n = 1, 2, 3
table
{ ?n, name }
{ 1, "one" }
{ 2, "two" }
{ 3, "three" }
Expressions Expressions
----------- -----------

7
dump.c
View File

@ -220,7 +220,8 @@ static void dump_var(FILE *file, const struct table *table,
char *s; char *s;
s = unparse(table->rows->values->expr); s = unparse(table->rows->values->expr);
fprintf(file, "%sset %s = %s\n\n", indent, table->vars->name, s); fprintf(file, "%sset %s%s = %s\n\n", indent,
table->vars->key ? "?" : "", table->vars->name, s);
free(s); free(s);
} }
@ -240,8 +241,8 @@ static void dump_table(FILE *file, const struct table *table,
} }
fprintf(file, "%stable\n%s {", indent, indent); fprintf(file, "%stable\n%s {", indent, indent);
for (var = table->vars; var; var = var->next) for (var = table->vars; var; var = var->next)
fprintf(file, "%s %s", var == table->vars ? "" : ",", fprintf(file, "%s %s%s", var == table->vars ? "" : ",",
var->name); var->key ? "?" : "", var->name);
fprintf(file, " }\n"); fprintf(file, " }\n");
for (row = table->rows; row; row = row->next) { for (row = table->rows; row; row = row->next) {
fprintf(file, "%s {", indent); fprintf(file, "%s {", indent);

78
expr.c
View File

@ -12,6 +12,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <math.h> #include <math.h>
#include "util.h" #include "util.h"
@ -95,6 +96,18 @@ int to_unit(struct num *n)
} }
/* ----- number to string conversion (hackish) ----------------------------- */
static char *num_to_string(struct num n)
{
static char buf[100]; /* enough :-) */
snprintf(buf, sizeof(buf), "%lg%s", n.n, str_unit(n));
return buf;
}
/* ----- primary expressions ----------------------------------------------- */ /* ----- primary expressions ----------------------------------------------- */
@ -131,7 +144,7 @@ struct num eval_var(const struct frame *frame, const char *name)
value = table->curr_row ? table->curr_row->values : value = table->curr_row ? table->curr_row->values :
table->active_row->values; table->active_row->values;
for (var = table->vars; var; var = var->next) { for (var = table->vars; var; var = var->next) {
if (var->name == name) { if (!var->key && var->name == name) {
if (var->visited) { if (var->visited) {
fail("recursive evaluation through " fail("recursive evaluation through "
"\"%s\"", name); "\"%s\"", name);
@ -141,7 +154,6 @@ struct num eval_var(const struct frame *frame, const char *name)
res = eval_num(value->expr, frame); res = eval_num(value->expr, frame);
var->visited = 0; var->visited = 0;
return res; return res;
} }
value = value->next; value = value->next;
} }
@ -176,14 +188,13 @@ static const char *eval_string_var(const struct frame *frame, const char *name)
value = table->curr_row ? table->curr_row->values : value = table->curr_row ? table->curr_row->values :
table->active_row->values; table->active_row->values;
for (var = table->vars; var; var = var->next) { for (var = table->vars; var; var = var->next) {
if (var->name == name) { if (!var->key && var->name == name) {
if (var->visited) if (var->visited)
return NULL; return NULL;
var->visited = 1; var->visited = 1;
res = eval_str(value->expr, frame); res = eval_str(value->expr, frame);
var->visited = 0; var->visited = 0;
return res; return res;
} }
value = value->next; value = value->next;
} }
@ -210,6 +221,55 @@ struct num op_var(const struct expr *self, const struct frame *frame)
} }
/* ----- Variable equivalence ---------------------------------------------- */
static int num_eq(struct num a, struct num b)
{
if (a.exponent != b.exponent)
return 0;
if (a.exponent && a.type != b.type) {
if (a.type == nt_mil)
return mil_to_mm(a.n, a.exponent) == b.n;
else
return a.n == mil_to_mm(b.n, b.exponent);
}
return a.n == b.n;
}
int var_eq(const struct frame *frame, const char *name,
const struct expr *expr)
{
const char *vs, *es;
struct num vn, en;
vs = eval_string_var(frame, name);
if (!vs) {
vn = eval_var(frame, name);
if (is_undef(vn)) {
fail("undefined variable \"%s\"", name);
return -1;
}
}
es = eval_str(expr, frame);
if (!es) {
en = eval_num(expr, frame);
if (is_undef(en))
return -1;
}
if (vs || es) {
if (!vs)
vs = num_to_string(vn);
if (!es)
es = num_to_string(en);
return !strcmp(vs, es);
} else {
return num_eq(vn, en);
}
}
/* ----- arithmetic -------------------------------------------------------- */ /* ----- arithmetic -------------------------------------------------------- */
@ -436,7 +496,6 @@ char *expand(const char *name, const struct frame *frame)
{ {
int len = strlen(name); int len = strlen(name);
char *buf = alloc_size(len+1); char *buf = alloc_size(len+1);
char num_buf[100]; /* enough :-) */
const char *s, *s0; const char *s, *s0;
char *var; char *var;
const char *var_unique, *value_string; const char *var_unique, *value_string;
@ -483,18 +542,15 @@ char *expand(const char *name, const struct frame *frame)
var_unique = unique(var); var_unique = unique(var);
free(var); free(var);
value_string = eval_string_var(frame, var_unique); value_string = eval_string_var(frame, var_unique);
if (value_string) { if (!value_string) {
value_len = strlen(value_string);
} else {
value = eval_var(frame, var_unique); value = eval_var(frame, var_unique);
if (is_undef(value)) { if (is_undef(value)) {
fail("undefined variable \"%s\"", var_unique); fail("undefined variable \"%s\"", var_unique);
goto fail; goto fail;
} }
value_len = snprintf(num_buf, sizeof(num_buf), "%lg%s", value_string = num_to_string(value);
value.n, str_unit(value));
value_string = num_buf;
} }
value_len = strlen(value_string);
len += value_len; len += value_len;
buf = realloc(buf, len+1); buf = realloc(buf, len+1);
if (!buf) if (!buf)

3
expr.h
View File

@ -126,6 +126,9 @@ struct num op_div(const struct expr *self, const struct frame *frame);
struct expr *new_op(op_type op); struct expr *new_op(op_type op);
struct expr *binary_op(op_type op, struct expr *a, struct expr *b); struct expr *binary_op(op_type op, struct expr *a, struct expr *b);
int var_eq(const struct frame *frame, const char *name,
const struct expr *expr);
struct num eval_var(const struct frame *frame, const char *name); struct num eval_var(const struct frame *frame, const char *name);
/* /*

33
fpd.y
View File

@ -107,7 +107,7 @@ static struct var *find_var(const struct frame *frame, const char *name)
for (table = frame->tables; table; table = table->next) for (table = frame->tables; table; table = table->next)
for (var = table->vars; var; var = var->next) for (var = table->vars; var; var = var->next)
if (var->name == name) if (!var->key && var->name == name)
return var; return var;
for (loop = frame->loops; loop; loop = loop->next) for (loop = frame->loops; loop; loop = loop->next)
if (loop->var.name == name) if (loop->var.name == name)
@ -130,7 +130,7 @@ static void set_frame(struct frame *frame)
} }
static void make_var(const char *id, struct expr *expr) static void make_var(const char *id, int key, struct expr *expr)
{ {
struct table *table; struct table *table;
@ -139,6 +139,7 @@ static void make_var(const char *id, struct expr *expr)
table->vars->name = id; table->vars->name = id;
table->vars->frame = curr_frame; table->vars->frame = curr_frame;
table->vars->table = table; table->vars->table = table;
table->vars->key = key;
table->rows = zalloc_type(struct row); table->rows = zalloc_type(struct row);
table->rows->table = table; table->rows->table = table;
table->rows->values = zalloc_type(struct value); table->rows->values = zalloc_type(struct value);
@ -425,6 +426,7 @@ static int dbg_meas(const char *name)
%union { %union {
struct num num; struct num num;
int flag;
char *str; char *str;
const char *id; const char *id;
struct expr *expr; struct expr *expr;
@ -474,6 +476,7 @@ static int dbg_meas(const char *name)
%type <obj> object obj meas unlabeled_meas %type <obj> object obj meas unlabeled_meas
%type <expr> expr opt_expr add_expr mult_expr unary_expr primary_expr %type <expr> expr opt_expr add_expr mult_expr unary_expr primary_expr
%type <num> opt_num %type <num> opt_num
%type <flag> opt_key
%type <frame> frame_qualifier %type <frame> frame_qualifier
%type <str> opt_string %type <str> opt_string
%type <pt> pad_type %type <pt> pad_type
@ -607,13 +610,13 @@ frame_items:
frame_item: frame_item:
table table
| TOK_SET ID '=' expr | TOK_SET opt_key ID '=' expr
{ {
if (find_var(curr_frame, $2)) { if (!$2 && find_var(curr_frame, $3)) {
yyerrorf("duplicate variable \"%s\"", $2); yyerrorf("duplicate variable \"%s\"", $3);
YYABORT; YYABORT;
} }
make_var($2, $4); make_var($3, $2, $5);
} }
| TOK_LOOP ID '=' expr ',' expr | TOK_LOOP ID '=' expr ',' expr
{ {
@ -755,21 +758,31 @@ vars:
; ;
var: var:
ID opt_key ID
{ {
if (find_var(curr_frame, $1)) { if (!$1 && find_var(curr_frame, $2)) {
yyerrorf("duplicate variable \"%s\"", $1); yyerrorf("duplicate variable \"%s\"", $2);
YYABORT; YYABORT;
} }
$$ = zalloc_type(struct var); $$ = zalloc_type(struct var);
$$->name = $1; $$->name = $2;
$$->frame = curr_frame; $$->frame = curr_frame;
$$->table = curr_table; $$->table = curr_table;
$$->key = $1;
$$->next = NULL; $$->next = NULL;
n_vars++; n_vars++;
} }
; ;
opt_key:
{
$$ = 0;
}
| '?'
{
$$ = 1;
}
;
rows: rows:
{ {

26
obj.c
View File

@ -350,6 +350,30 @@ static int generate_items(struct frame *frame, struct coord base, int active)
} }
static int match_keys(struct frame *frame, struct coord base, int active)
{
const struct table *table;
const struct var *var;
const struct value *value;
int res;
for (table = frame->tables; table; table = table->next) {
value = table->curr_row->values;
for (var = table->vars; var; var = var->next) {
if (var->key) {
res = var_eq(frame, var->name, value->expr);
if (!res)
return 1;
if (res < 0)
return 0;
}
value = value->next;
}
}
return generate_items(frame, base, active);
}
static int run_loops(struct frame *frame, struct loop *loop, static int run_loops(struct frame *frame, struct loop *loop,
struct coord base, int active) struct coord base, int active)
{ {
@ -358,7 +382,7 @@ static int run_loops(struct frame *frame, struct loop *loop,
int found_before, ok; int found_before, ok;
if (!loop) if (!loop)
return generate_items(frame, base, active); return match_keys(frame, base, active);
from = eval_num(loop->from.expr, frame); from = eval_num(loop->from.expr, frame);
if (is_undef(from)) { if (is_undef(from)) {
fail_expr(loop->from.expr); fail_expr(loop->from.expr);

4
obj.h
View File

@ -60,6 +60,10 @@ struct var {
struct frame *frame; struct frame *frame;
struct table *table; /* NULL if loop */ struct table *table; /* NULL if loop */
/* key: 0 if the variable is set, 1 if the variable is compared */
int key;
/* for the GUI */ /* for the GUI */
GtkWidget *widget; GtkWidget *widget;

134
test/keys Executable file
View File

@ -0,0 +1,134 @@
#!/bin/sh
. ./Common
###############################################################################
fped "keys: tables, master before slave" <<EOF
table { a, eng } { 1, "one" } { 2, "two" }
table { ?a, ger } { 1, "eins" } { 2, "zwei" }
%iprint eng
%iprint ger
EOF
expect <<EOF
one
eins
two
zwei
EOF
#------------------------------------------------------------------------------
fped "keys: tables, master after slave" <<EOF
table { ?a, eng } { 1, "one" } { 2, "two" }
table { a, spa } { 1, "uno" } { 2, "dos" }
%iprint eng
%iprint spa
EOF
expect <<EOF
one
uno
two
dos
EOF
#------------------------------------------------------------------------------
fped_fail "keys: tables, slaves without master" <<EOF
table { ?a, eng } { 1, "one" } { 2, "two" }
table { ?a, lat } { 1, "unum" } { 2, "duo" }
%iprint eng
%iprint lat
EOF
expect <<EOF
undefined variable "a"
EOF
#------------------------------------------------------------------------------
fped_fail "keys: tables, both masters" <<EOF
table { a, eng } { 1, "one" } { 2, "two" }
table { a, lat } { 1, "unum" } { 2, "duo" }
%iprint eng
%iprint lat
EOF
expect <<EOF
2: duplicate variable "a" near "a"
EOF
#------------------------------------------------------------------------------
fped "keys: master is single variable, slave is table" <<EOF
set n = 2
table { ?n, square } { 1, 1 } { 2, 4 } { 3, 9 } { 4, 16 }
%iprint square
EOF
expect <<EOF
4
EOF
#------------------------------------------------------------------------------
fped "keys: master is table, slave is single variable" <<EOF
table { n, cube } { 1, 1 } { 2, 8 } { 3, 27 } { 4, 64 }
set ?n = 3
%iprint cube
EOF
expect <<EOF
27
EOF
#------------------------------------------------------------------------------
fped "keys: master is loop, slave is table" <<EOF
loop n = 1, 3
table { ?n, sqr } { 1, 1 } { 2, 4 } { 3, 9 } { 4, 16 }
%iprint sqr
EOF
expect <<EOF
1
4
9
EOF
#------------------------------------------------------------------------------
fped "keys: two keys" <<EOF
table { a, an } { 1, "one" } { 2, "two" }
table { b, bn } { 3, "three" } { 4, "four" } { 5, "five" }
table { ?a, ?b, sum }
{ 1, 3, "four" }
{ 2, 4, "six" }
{ 3, 4, "seven" }
%iprint sum
EOF
expect <<EOF
four
six
EOF
#------------------------------------------------------------------------------
fped "keys: key set by outer frame" <<EOF
frame tab {
table { sqrt, ?n } { 1, 1 } { 2, 4 } { 3, 9 } { 4, 16 } { 5, 25 }
%iprint sqrt
}
table { n } { 25 } { 9 }
frame tab @
EOF
expect <<EOF
5
3
EOF
###############################################################################