mirror of
git://projects.qi-hardware.com/fped.git
synced 2024-12-22 17:59:33 +02:00
introduce keyed tables (?var syntax; WIP)
This cannot be set/changed through the GUI yet.
This commit is contained in:
parent
3c39600c1c
commit
3488cf80ec
15
README
15
README
@ -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
7
dump.c
@ -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
78
expr.c
@ -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
3
expr.h
@ -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);
|
||||
|
||||
/*
|
||||
|
35
fpd.y
35
fpd.y
@ -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,22 +758,32 @@ 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:
|
||||
{
|
||||
$$ = NULL;
|
||||
|
26
obj.c
26
obj.c
@ -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
4
obj.h
@ -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
134
test/keys
Executable 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
|
||||
|
||||
###############################################################################
|
Loading…
Reference in New Issue
Block a user