1
0
mirror of git://projects.qi-hardware.com/fped.git synced 2024-11-18 01:28:25 +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).
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
-----------

7
dump.c
View File

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

78
expr.c
View File

@ -12,6 +12,7 @@
#include <stdlib.h>
#include <string.h>
#include <math.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 ----------------------------------------------- */
@ -131,7 +144,7 @@ struct num eval_var(const struct frame *frame, const char *name)
value = table->curr_row ? table->curr_row->values :
table->active_row->values;
for (var = table->vars; var; var = var->next) {
if (var->name == name) {
if (!var->key && var->name == name) {
if (var->visited) {
fail("recursive evaluation through "
"\"%s\"", name);
@ -141,7 +154,6 @@ struct num eval_var(const struct frame *frame, const char *name)
res = eval_num(value->expr, frame);
var->visited = 0;
return res;
}
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 :
table->active_row->values;
for (var = table->vars; var; var = var->next) {
if (var->name == name) {
if (!var->key && var->name == name) {
if (var->visited)
return NULL;
var->visited = 1;
res = eval_str(value->expr, frame);
var->visited = 0;
return res;
}
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 -------------------------------------------------------- */
@ -436,7 +496,6 @@ char *expand(const char *name, const struct frame *frame)
{
int len = strlen(name);
char *buf = alloc_size(len+1);
char num_buf[100]; /* enough :-) */
const char *s, *s0;
char *var;
const char *var_unique, *value_string;
@ -483,18 +542,15 @@ char *expand(const char *name, const struct frame *frame)
var_unique = unique(var);
free(var);
value_string = eval_string_var(frame, var_unique);
if (value_string) {
value_len = strlen(value_string);
} else {
if (!value_string) {
value = eval_var(frame, var_unique);
if (is_undef(value)) {
fail("undefined variable \"%s\"", var_unique);
goto fail;
}
value_len = snprintf(num_buf, sizeof(num_buf), "%lg%s",
value.n, str_unit(value));
value_string = num_buf;
value_string = num_to_string(value);
}
value_len = strlen(value_string);
len += value_len;
buf = realloc(buf, len+1);
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 *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);
/*

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

4
obj.h
View File

@ -60,6 +60,10 @@ struct var {
struct frame *frame;
struct table *table; /* NULL if loop */
/* key: 0 if the variable is set, 1 if the variable is compared */
int key;
/* for the GUI */
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
###############################################################################