Contiki 3.x
lvm.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /**
31  * \file
32  * Logic engine used for quickly evaluating data constraints in relations.
33  * \author
34  * Nicolas Tsiftes <nvt@sics.se>
35  */
36 
37 #include <limits.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #include "aql.h"
43 #include "lvm.h"
44 
45 #define DEBUG DEBUG_NONE
46 #include "debug.h"
47 
48 /*
49  * The logic engine determines whether a logical predicate is true for
50  * each tuple in a relation. It uses a stack-based execution model of
51  * operations that are arranged in prefix (Polish) notation.
52  */
53 
54 /* Default option values. */
55 #ifndef LVM_MAX_NAME_LENGTH
56 #define LVM_MAX_NAME_LENGTH 16
57 #endif
58 
59 #ifndef LVM_MAX_VARIABLE_ID
60 #define LVM_MAX_VARIABLE_ID 8
61 #endif
62 
63 #ifndef LVM_USE_FLOATS
64 #define LVM_USE_FLOATS 0
65 #endif
66 
67 #define IS_CONNECTIVE(op) ((op) & LVM_CONNECTIVE)
68 
69 struct variable {
70  operand_type_t type;
71  operand_value_t value;
72  char name[LVM_MAX_NAME_LENGTH + 1];
73 };
74 typedef struct variable variable_t;
75 
76 struct derivation {
77  operand_value_t max;
78  operand_value_t min;
79  uint8_t derived;
80 };
81 typedef struct derivation derivation_t;
82 
83 /* Registered variables for a LVM expression. Their values may be
84  changed between executions of the expression. */
85 static variable_t variables[LVM_MAX_VARIABLE_ID - 1];
86 
87 /* Range derivations of variables that are used for index searches. */
88 static derivation_t derivations[LVM_MAX_VARIABLE_ID - 1];
89 
90 #if DEBUG
91 static void
92 print_derivations(derivation_t *d)
93 {
94  int i;
95 
96  for(i = 0; i < LVM_MAX_VARIABLE_ID; i++) {
97  if(d[i].derived) {
98  printf("%s is constrained to (%ld,%ld)\n", variables[i].name,
99  d[i].min.l, d[i].max.l);
100  }
101  }
102 }
103 #endif /* DEBUG */
104 
105 static variable_id_t
106 lookup(char *name)
107 {
108  variable_t *var;
109 
110  for(var = variables; var <= &variables[LVM_MAX_VARIABLE_ID - 1] && var->name[0] != '\0'; var++) {
111  if(strcmp(var->name, name) == 0) {
112  break;
113  }
114  }
115 
116  return (variable_id_t)(var - &variables[0]);
117 }
118 
119 static operator_t *
120 get_operator(lvm_instance_t *p)
121 {
122  operator_t *operator;
123 
124  operator = (operator_t *)&p->code[p->ip];
125  p->ip += sizeof(operator_t);
126  return operator;
127 }
128 
129 static void
130 get_operand(lvm_instance_t *p, operand_t *operand)
131 {
132  memcpy(operand, &p->code[p->ip], sizeof(*operand));
133  p->ip += sizeof(*operand);
134 }
135 
136 static node_type_t
137 get_type(lvm_instance_t *p)
138 {
139  node_type_t node_type;
140 
141  node_type = *(node_type_t *)(p->code + p->ip);
142  p->ip += sizeof(node_type);
143 
144  return node_type;
145 }
146 
147 static long
148 operand_to_long(operand_t *operand)
149 {
150  switch(operand->type) {
151  case LVM_LONG:
152  return operand->value.l;
153 #if LVM_USE_FLOATS
154  case LVM_FLOAT:
155  return (long)operand->value.f;
156  break;
157 #endif /* LVM_USE_FLOATS */
158  case LVM_VARIABLE:
159  return variables[operand->value.id].value.l;
160  default:
161  return 0;
162  }
163 }
164 
165 static lvm_status_t
166 eval_expr(lvm_instance_t *p, operator_t op, operand_t *result)
167 {
168  int i;
169  node_type_t type;
170  operator_t *operator;
171  operand_t operand[2];
172  long value[2];
173  long result_value;
174  lvm_status_t r;
175 
176  for(i = 0; i < 2; i++) {
177  type = get_type(p);
178  switch(type) {
179  case LVM_ARITH_OP:
180  operator = get_operator(p);
181  r = eval_expr(p, *operator, &operand[i]);
182  if(LVM_ERROR(r)) {
183  return r;
184  }
185  break;
186  case LVM_OPERAND:
187  get_operand(p, &operand[i]);
188  break;
189  default:
190  return SEMANTIC_ERROR;
191  }
192  value[i] = operand_to_long(&operand[i]);
193  }
194 
195  switch(op) {
196  case LVM_ADD:
197  result_value = value[0] + value[1];
198  break;
199  case LVM_SUB:
200  result_value = value[0] - value[1];
201  break;
202  case LVM_MUL:
203  result_value = value[0] * value[1];
204  break;
205  case LVM_DIV:
206  if(value[1] == 0) {
207  return MATH_ERROR;
208  }
209  result_value = value[0] / value[1];
210  break;
211  default:
212  return EXECUTION_ERROR;
213  }
214 
215  result->type = LVM_LONG;
216  result->value.l = result_value;
217 
218  return TRUE;
219 }
220 
221 static int
222 eval_logic(lvm_instance_t *p, operator_t *op)
223 {
224  int i;
225  int r;
226  operand_t operand;
227  long result[2];
228  node_type_t type;
229  operator_t *operator;
230  long l1, l2;
231  int logic_result[2];
232  unsigned arguments;
233 
234  if(IS_CONNECTIVE(*op)) {
235  arguments = *op == LVM_NOT ? 1 : 2;
236  for(i = 0; i < arguments; i++) {
237  type = get_type(p);
238  if(type != LVM_CMP_OP) {
239  return SEMANTIC_ERROR;
240  }
241  operator = get_operator(p);
242  logic_result[i] = eval_logic(p, operator);
243  if(LVM_ERROR(logic_result[i])) {
244  return logic_result[i];
245  }
246  }
247 
248  if(*op == LVM_NOT) {
249  return !logic_result[0];
250  } else if(*op == LVM_AND) {
251  return logic_result[0] == TRUE && logic_result[1] == TRUE;
252  } else {
253  return logic_result[0] == TRUE || logic_result[1] == TRUE;
254  }
255  }
256 
257  for(i = 0; i < 2; i++) {
258  type = get_type(p);
259  switch(type) {
260  case LVM_ARITH_OP:
261  operator = get_operator(p);
262  r = eval_expr(p, *operator, &operand);
263  if(LVM_ERROR(r)) {
264  return r;
265  }
266  break;
267  case LVM_OPERAND:
268  get_operand(p, &operand);
269  break;
270  default:
271  return SEMANTIC_ERROR;
272  }
273  result[i] = operand_to_long(&operand);
274  }
275 
276  l1 = result[0];
277  l2 = result[1];
278  PRINTF("Result1: %ld\nResult2: %ld\n", l1, l2);
279 
280  switch(*op) {
281  case LVM_EQ:
282  return l1 == l2;
283  case LVM_NEQ:
284  return l1 != l2;
285  case LVM_GE:
286  return l1 > l2;
287  case LVM_GEQ:
288  return l1 >= l2;
289  case LVM_LE:
290  return l1 < l2;
291  case LVM_LEQ:
292  return l1 <= l2;
293  default:
294  break;
295  }
296 
297  return EXECUTION_ERROR;
298 }
299 
300 void
301 lvm_reset(lvm_instance_t *p, unsigned char *code, lvm_ip_t size)
302 {
303  memset(code, 0, size);
304  p->code = code;
305  p->size = size;
306  p->end = 0;
307  p->ip = 0;
308  p->error = 0;
309 
310  memset(variables, 0, sizeof(variables));
311  memset(derivations, 0, sizeof(derivations));
312 }
313 
314 lvm_ip_t
315 lvm_jump_to_operand(lvm_instance_t *p)
316 {
317  lvm_ip_t old_end;
318 
319  old_end = p->end;
320  p->end += sizeof(operator_t) + sizeof(node_type_t);
321  if(p->end >= p->size) {
322  p->error = __LINE__;
323  p->end = old_end;
324  }
325 
326  return old_end;
327 }
328 
329 lvm_ip_t
330 lvm_shift_for_operator(lvm_instance_t *p, lvm_ip_t end)
331 {
332  unsigned char *ptr;
333  lvm_ip_t old_end;
334 
335  old_end = p->end;
336 
337  if(p->end + sizeof(operator_t) > p->size || end >= old_end) {
338  p->error = __LINE__;
339  return 0;
340  }
341 
342  ptr = p->code + end;
343 
344  memmove(ptr + sizeof(operator_t) + sizeof(node_type_t), ptr, old_end - end);
345  p->end = end;
346 
347  return old_end + sizeof(operator_t) + sizeof(node_type_t);
348 }
349 
350 lvm_ip_t
351 lvm_get_end(lvm_instance_t *p)
352 {
353  return p->end;
354 }
355 
356 lvm_ip_t
357 lvm_set_end(lvm_instance_t *p, lvm_ip_t end)
358 {
359  lvm_ip_t old_end;
360 
361  if(end >= p->size) {
362  p->error = __LINE__;
363  return p->end;
364  }
365 
366  old_end = p->end;
367  p->end = end;
368 
369  return old_end;
370 }
371 
372 void
373 lvm_set_type(lvm_instance_t *p, node_type_t type)
374 {
375  *(node_type_t *)(p->code + p->end) = type;
376  p->end += sizeof(type);
377 }
378 
379 lvm_status_t
380 lvm_execute(lvm_instance_t *p)
381 {
382  node_type_t type;
383  operator_t *operator;
384  lvm_status_t status;
385 
386  p->ip = 0;
387  status = EXECUTION_ERROR;
388  type = get_type(p);
389  switch(type) {
390  case LVM_CMP_OP:
391  operator = get_operator(p);
392  status = eval_logic(p, operator);
393  if(!LVM_ERROR(status)) {
394  PRINTF("The statement is %s\n", status == TRUE ? "true" : "false");
395  } else {
396  PRINTF("Execution error: %d\n", (int)status);
397  }
398  break;
399  default:
400  PRINTF("Error: The code must start with a relational operator\n");
401  }
402 
403  return status;
404 }
405 
406 void
407 lvm_set_op(lvm_instance_t *p, operator_t op)
408 {
409  lvm_set_type(p, LVM_ARITH_OP);
410  memcpy(&p->code[p->end], &op, sizeof(op));
411  p->end += sizeof(op);
412 }
413 
414 void
415 lvm_set_relation(lvm_instance_t *p, operator_t op)
416 {
417  lvm_set_type(p, LVM_CMP_OP);
418  memcpy(&p->code[p->end], &op, sizeof(op));
419  p->end += sizeof(op);
420 }
421 
422 void
423 lvm_set_operand(lvm_instance_t *p, operand_t *op)
424 {
425  lvm_set_type(p, LVM_OPERAND);
426  memcpy(&p->code[p->end], op, sizeof(*op));
427  p->end += sizeof(*op);
428 }
429 
430 void
431 lvm_set_long(lvm_instance_t *p, long l)
432 {
433  operand_t op;
434 
435  op.type = LVM_LONG;
436  op.value.l = l;
437 
438  lvm_set_operand(p, &op);
439 }
440 
441 lvm_status_t
442 lvm_register_variable(char *name, operand_type_t type)
443 {
444  variable_id_t id;
445  variable_t *var;
446 
447  id = lookup(name);
448  if(id == LVM_MAX_VARIABLE_ID) {
449  return VARIABLE_LIMIT_REACHED;
450  }
451 
452  var = &variables[id];
453  if(var->name[0] == '\0') {
454  strncpy(var->name, name, sizeof(var->name) - 1);
455  var->name[sizeof(var->name) - 1] = '\0';
456  var->type = type;
457  }
458 
459  return TRUE;
460 }
461 
462 lvm_status_t
463 lvm_set_variable_value(char *name, operand_value_t value)
464 {
465  variable_id_t id;
466 
467  id = lookup(name);
468  if(id == LVM_MAX_VARIABLE_ID) {
469  return INVALID_IDENTIFIER;
470  }
471  variables[id].value = value;
472  return TRUE;
473 }
474 
475 void
476 lvm_set_variable(lvm_instance_t *p, char *name)
477 {
478  operand_t op;
479  variable_id_t id;
480 
481  id = lookup(name);
482  if(id < LVM_MAX_VARIABLE_ID) {
483  PRINTF("var id = %d\n", id);
484  op.type = LVM_VARIABLE;
485  op.value.id = id;
486  lvm_set_operand(p, &op);
487  }
488 }
489 
490 void
491 lvm_clone(lvm_instance_t *dst, lvm_instance_t *src)
492 {
493  memcpy(dst, src, sizeof(*dst));
494 }
495 
496 static void
497 create_intersection(derivation_t *result, derivation_t *d1, derivation_t *d2)
498 {
499  int i;
500 
501  for(i = 0; i < LVM_MAX_VARIABLE_ID; i++) {
502  if(!d1[i].derived && !d2[i].derived) {
503  continue;
504  } else if(d1[i].derived && !d2[i].derived) {
505  result[i].min.l = d1[i].min.l;
506  result[i].max.l = d1[i].max.l;
507  } else if(!d1[i].derived && d2[i].derived) {
508  result[i].min.l = d2[i].min.l;
509  result[i].max.l = d2[i].max.l;
510  } else {
511  /* Both derivations have been made; create an
512  intersection of the ranges. */
513  if(d1[i].min.l > d2[i].min.l) {
514  result[i].min.l = d1[i].min.l;
515  } else {
516  result[i].min.l = d2[i].min.l;
517  }
518 
519  if(d1[i].max.l < d2[i].max.l) {
520  result[i].max.l = d1[i].max.l;
521  } else {
522  result[i].max.l = d2[i].max.l;
523  }
524  }
525  result[i].derived = 1;
526  }
527 
528 #if DEBUG
529  PRINTF("Created an intersection of D1 and D2\n");
530  PRINTF("D1: \n");
531  print_derivations(d1);
532  PRINTF("D2: \n");
533  print_derivations(d2);
534  PRINTF("Result: \n");
535  print_derivations(result);
536 #endif /* DEBUG */
537 }
538 
539 static void
540 create_union(derivation_t *result, derivation_t *d1, derivation_t *d2)
541 {
542  int i;
543 
544  for(i = 0; i < LVM_MAX_VARIABLE_ID; i++) {
545  if(!d1[i].derived && !d2[i].derived) {
546  continue;
547  } else if(d1[i].derived && !d2[i].derived) {
548  result[i].min.l = d1[i].min.l;
549  result[i].max.l = d1[i].max.l;
550  } else if(!d1[i].derived && d2[i].derived) {
551  result[i].min.l = d2[i].min.l;
552  result[i].max.l = d2[i].max.l;
553  } else {
554  /* Both derivations have been made; create a
555  union of the ranges. */
556  if(d1[i].min.l > d2[i].min.l) {
557  result[i].min.l = d2[i].min.l;
558  } else {
559  result[i].min.l = d1[i].min.l;
560  }
561 
562  if(d1[i].max.l < d2[i].max.l) {
563  result[i].max.l = d2[i].max.l;
564  } else {
565  result[i].max.l = d1[i].max.l;
566  }
567  }
568  result[i].derived = 1;
569  }
570 
571 #if DEBUG
572  PRINTF("Created a union of D1 and D2\n");
573  PRINTF("D1: \n");
574  print_derivations(d1);
575  PRINTF("D2: \n");
576  print_derivations(d2);
577  PRINTF("Result: \n");
578  print_derivations(result);
579 #endif /* DEBUG */
580 }
581 
582 static int
583 derive_relation(lvm_instance_t *p, derivation_t *local_derivations)
584 {
585  operator_t *operator;
586  node_type_t type;
587  operand_t operand[2];
588  int i;
589  int variable_id;
590  operand_value_t *value;
591  derivation_t *derivation;
592 
593  type = get_type(p);
594  operator = get_operator(p);
595 
596  if(IS_CONNECTIVE(*operator)) {
597  derivation_t d1[LVM_MAX_VARIABLE_ID];
598  derivation_t d2[LVM_MAX_VARIABLE_ID];
599 
600  if(*operator != LVM_AND && *operator != LVM_OR) {
601  return DERIVATION_ERROR;
602  }
603 
604  PRINTF("Attempting to infer ranges from a logical connective\n");
605 
606  memset(d1, 0, sizeof(d1));
607  memset(d2, 0, sizeof(d2));
608 
609  if(LVM_ERROR(derive_relation(p, d1)) ||
610  LVM_ERROR(derive_relation(p, d2))) {
611  return DERIVATION_ERROR;
612  }
613 
614  if(*operator == LVM_AND) {
615  create_intersection(local_derivations, d1, d2);
616  } else if(*operator == LVM_OR) {
617  create_union(local_derivations, d1, d2);
618  }
619  return TRUE;
620  }
621 
622  for(i = 0; i < 2; i++) {
623  type = get_type(p);
624  switch(type) {
625  case LVM_OPERAND:
626  get_operand(p, &operand[i]);
627  break;
628  default:
629  return DERIVATION_ERROR;
630  }
631  }
632 
633  if(operand[0].type == LVM_VARIABLE && operand[1].type == LVM_VARIABLE) {
634  return DERIVATION_ERROR;
635  }
636 
637  /* Determine which of the operands that is the variable. */
638  if(operand[0].type == LVM_VARIABLE) {
639  if(operand[1].type == LVM_VARIABLE) {
640  return DERIVATION_ERROR;
641  }
642  variable_id = operand[0].value.id;
643  value = &operand[1].value;
644  } else {
645  variable_id = operand[1].value.id;
646  value = &operand[0].value;
647  }
648 
649  if(variable_id >= LVM_MAX_VARIABLE_ID) {
650  return DERIVATION_ERROR;
651  }
652 
653  PRINTF("variable id %d, value %ld\n", variable_id, *(long *)value);
654 
655  derivation = local_derivations + variable_id;
656  /* Default values. */
657  derivation->max.l = LONG_MAX;
658  derivation->min.l = LONG_MIN;
659 
660  switch(*operator) {
661  case LVM_EQ:
662  derivation->max = *value;
663  derivation->min = *value;
664  break;
665  case LVM_GE:
666  derivation->min.l = value->l + 1;
667  break;
668  case LVM_GEQ:
669  derivation->min.l = value->l;
670  break;
671  case LVM_LE:
672  derivation->max.l = value->l - 1;
673  break;
674  case LVM_LEQ:
675  derivation->max.l = value->l;
676  break;
677  default:
678  return DERIVATION_ERROR;
679  }
680 
681  derivation->derived = 1;
682 
683  return TRUE;
684 }
685 
686 lvm_status_t
687 lvm_derive(lvm_instance_t *p)
688 {
689  return derive_relation(p, derivations);
690 }
691 
692 lvm_status_t
693 lvm_get_derived_range(lvm_instance_t *p, char *name,
694  operand_value_t *min, operand_value_t *max)
695 {
696  int i;
697 
698  for(i = 0; i < LVM_MAX_VARIABLE_ID; i++) {
699  if(strcmp(name, variables[i].name) == 0) {
700  if(derivations[i].derived) {
701  *min = derivations[i].min;
702  *max = derivations[i].max;
703  return TRUE;
704  }
705  return DERIVATION_ERROR;
706  }
707  }
708  return INVALID_IDENTIFIER;
709 }
710 
711 #if DEBUG
712 static lvm_ip_t
713 print_operator(lvm_instance_t *p, lvm_ip_t index)
714 {
715  operator_t operator;
716  struct operator_map {
717  operator_t op;
718  char *representation;
719  };
720  struct operator_map operator_map[] = {
721  {LVM_ADD, "+"},
722  {LVM_SUB, "-"},
723  {LVM_MUL, "*"},
724  {LVM_DIV, "/"},
725  {LVM_GE, ">"},
726  {LVM_GEQ, ">="},
727  {LVM_LE, "<"},
728  {LVM_LEQ, "<="},
729  {LVM_EQ, "="},
730  {LVM_NEQ, "<>"},
731  {LVM_AND, "/\\"},
732  {LVM_OR, "\\/"},
733  {LVM_NOT, "!"}
734  };
735  int i;
736 
737  memcpy(&operator, p->code + index, sizeof(operator));
738 
739  for(i = 0; i < sizeof(operator_map) / sizeof(operator_map[0]); i++) {
740  if(operator_map[i].op == operator) {
741  PRINTF("%s ", operator_map[i].representation);
742  break;
743  }
744  }
745 
746  return index + sizeof(operator_t);
747 }
748 
749 static lvm_ip_t
750 print_operand(lvm_instance_t *p, lvm_ip_t index)
751 {
752  operand_t operand;
753 
754  memcpy(&operand, p->code + index, sizeof(operand));
755 
756  switch(operand.type) {
757  case LVM_VARIABLE:
758  if(operand.value.id >= LVM_MAX_VARIABLE_ID || variables[operand.value.id].name == NULL) {
759  PRINTF("var(id:%d):?? ", operand.value.id);
760  } else {
761  PRINTF("var(%s):%ld ", variables[operand.value.id].name,
762  variables[operand.value.id].value.l);
763  }
764  break;
765  case LVM_LONG:
766  PRINTF("long:%ld ", operand.value.l);
767  break;
768  default:
769  PRINTF("?? ");
770  break;
771  }
772 
773  return index + sizeof(operand_t);
774 }
775 
776 static lvm_ip_t
777 print_relation(lvm_instance_t *p, lvm_ip_t index)
778 {
779  /* Relational operators are stored as ordinary operators. */
780  return print_operator(p, index);
781 }
782 #endif /* DEBUG */
783 
784 void
785 lvm_print_code(lvm_instance_t *p)
786 {
787 #if DEBUG
788  lvm_ip_t ip;
789 
790  PRINTF("Code: ");
791 
792  for(ip = 0; ip < p->end;) {
793  switch(*(node_type_t *)(p->code + ip)) {
794  case LVM_CMP_OP:
795  ip = print_relation(p, ip + sizeof(node_type_t));
796  break;
797  case LVM_ARITH_OP:
798  ip = print_operator(p, ip + sizeof(node_type_t));
799  break;
800  case LVM_OPERAND:
801  ip = print_operand(p, ip + sizeof(node_type_t));
802  break;
803  default:
804  PRINTF("Invalid opcode: 0x%x ", p->code[ip]);
805  ip = p->end;
806  break;
807  }
808  }
809  putchar('\n');
810 #endif
811 }
812 
813 void
814 lvm_print_derivations(lvm_instance_t *p)
815 {
816 #if DEBUG
817  print_derivations(derivations);
818 #endif /* DEBUG */
819 }
820 
821 #ifdef TEST
822 int
823 main(void)
824 {
825  lvm_instance_t p;
826  unsigned char code[256];
827 
828  lvm_reset(&p, code, sizeof(code));
829 
830  lvm_register_variable("z", LVM_LONG);
831  lvm_set_variable_value("z", (operand_value_t)15L);
832 
833  lvm_register_variable("y", LVM_LONG);
834  lvm_set_variable_value("y", (operand_value_t)109L);
835 
836  /* Infix: 109 = y /\ 20 > 70 - (6 + z * 3) => 109 = 109 /\ 20 > 19 => true */
837  lvm_set_relation(&p, LVM_AND);
838  lvm_set_relation(&p, LVM_EQ);
839  lvm_set_long(&p, 109);
840  lvm_set_variable(&p, "y");
841  lvm_set_relation(&p, LVM_GE);
842  lvm_set_long(&p, 20);
843  lvm_set_op(&p, LVM_SUB);
844  lvm_set_long(&p, 70);
845  lvm_set_op(&p, LVM_ADD);
846  lvm_set_long(&p, 6);
847  lvm_set_op(&p, LVM_MUL);
848  lvm_set_variable(&p, "z");
849  lvm_set_long(&p, 3);
850 
851  lvm_print_code(&p);
852 
853  lvm_execute(&p);
854 
855  /* Infix: !(9999 + 1 < -1 + 10001) => !(10000 < 10000) => true */
856  lvm_reset(&p, code, sizeof(code));
857  lvm_set_relation(&p, LVM_NOT);
858  lvm_set_relation(&p, LVM_LE);
859  lvm_set_op(&p, LVM_ADD);
860  lvm_set_long(&p, 9999);
861  lvm_set_long(&p, 1);
862  lvm_set_op(&p, LVM_ADD);
863  lvm_set_long(&p, -1);
864  lvm_set_long(&p, 10001);
865 
866  lvm_print_code(&p);
867 
868  lvm_execute(&p);
869 
870  /* Derivation tests */
871 
872  /* Infix: a = 5 => a:(5,5) */
873  lvm_reset(&p, code, sizeof(code));
874  lvm_register_variable("a", LVM_LONG);
875  lvm_set_relation(&p, LVM_EQ);
876  lvm_set_variable(&p, "a");
877  lvm_set_long(&p, 5);
878 
879  lvm_derive(&p);
880  lvm_print_derivations(&p);
881 
882  /* Infix: a < 10 => a:(-oo,9) */
883  lvm_reset(&p, code, sizeof(code));
884  lvm_register_variable("a", LVM_LONG);
885  lvm_set_relation(&p, LVM_LE);
886  lvm_set_variable(&p, "a");
887  lvm_set_long(&p, 10);
888 
889  lvm_derive(&p);
890  lvm_print_derivations(&p);
891 
892  /* Infix: a < 100 /\ 10 < a => a:(11,99) */
893  lvm_reset(&p, code, sizeof(code));
894  lvm_register_variable("a", LVM_LONG);
895  lvm_set_relation(&p, LVM_AND);
896  lvm_set_relation(&p, LVM_LE);
897  lvm_set_variable(&p, "a");
898  lvm_set_long(&p, 100);
899  lvm_set_relation(&p, LVM_GE);
900  lvm_set_long(&p, 10);
901  lvm_set_variable(&p, "a");
902 
903  lvm_derive(&p);
904  lvm_print_derivations(&p);
905 
906  /* Infix: a < 100 /\ b > 100 => a:(-oo,99), b:(101,oo) */
907  lvm_reset(&p, code, sizeof(code));
908  lvm_register_variable("a", LVM_LONG);
909  lvm_register_variable("b", LVM_LONG);
910  lvm_set_relation(&p, LVM_AND);
911  lvm_set_relation(&p, LVM_LE);
912  lvm_set_variable(&p, "a");
913  lvm_set_long(&p, 100);
914  lvm_set_relation(&p, LVM_GE);
915  lvm_set_variable(&p, "b");
916  lvm_set_long(&p, 100);
917 
918  lvm_derive(&p);
919  lvm_print_derivations(&p);
920 
921  /* Infix: a < 100 \/ a < 1000 \/ a < 1902 => a:(-oo,1901) */
922  lvm_reset(&p, code, sizeof(code));
923  lvm_register_variable("a", LVM_LONG);
924  lvm_set_relation(&p, LVM_OR);
925  lvm_set_relation(&p, LVM_LE);
926  lvm_set_variable(&p, "a");
927  lvm_set_long(&p, 100);
928  lvm_set_relation(&p, LVM_OR);
929  lvm_set_relation(&p, LVM_LE);
930  lvm_set_long(&p, 1000);
931  lvm_set_variable(&p, "a");
932  lvm_set_relation(&p, LVM_LE);
933  lvm_set_variable(&p, "a");
934  lvm_set_long(&p, 1902);
935 
936  lvm_derive(&p);
937  lvm_print_derivations(&p);
938 
939  /* Infix: (a < 100 /\ a < 90 /\ a > 80 /\ a < 105) \/ b > 10000 =>
940  a:(81,89), b:(10001:oo) */
941  lvm_reset(&p, code, sizeof(code));
942  lvm_register_variable("a", LVM_LONG);
943  lvm_register_variable("b", LVM_LONG);
944 
945  lvm_set_relation(&p, LVM_OR);
946  lvm_set_relation(&p, LVM_GE);
947  lvm_set_variable(&p, "b");
948  lvm_set_long(&p, 10000);
949 
950  lvm_set_relation(&p, LVM_AND);
951  lvm_set_relation(&p, LVM_LE);
952  lvm_set_variable(&p, "a");
953  lvm_set_long(&p, 100);
954  lvm_set_relation(&p, LVM_AND);
955  lvm_set_relation(&p, LVM_LE);
956  lvm_set_variable(&p, "a");
957  lvm_set_long(&p, 90);
958  lvm_set_relation(&p, LVM_AND);
959  lvm_set_relation(&p, LVM_GE);
960  lvm_set_variable(&p, "a");
961  lvm_set_long(&p, 80);
962  lvm_set_relation(&p, LVM_LE);
963  lvm_set_variable(&p, "a");
964  lvm_set_long(&p, 105);
965 
966  lvm_derive(&p);
967  lvm_print_derivations(&p);
968 
969  printf("Done\n");
970 
971  return 0;
972 }
973 #endif
Definitions and declarations for AQL, the Antelope Query Language.
#define NULL
The null pointer.
int main(void)
This is main...
Definition: ethconfig.c:49
Definitions and declarations for the Propositional Logic Engine.
#define TRUE
An alias for one, used for clarity.
A set of debugging macros.