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