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:
parent
3c39600c1c
commit
3488cf80ec
15
README
15
README
@ -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
7
dump.c
@ -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
78
expr.c
@ -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
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 *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
33
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 (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
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,
|
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
4
obj.h
@ -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
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