Mercurial > audlegacy-plugins
comparison src/paranormal/libcalc/execute.c @ 282:3e160f6c04d2 trunk
[svn] - add libcalc from xvs and link to build
author | nenolod |
---|---|
date | Mon, 20 Nov 2006 13:26:09 -0800 |
parents | |
children | f1b6f1b2cdb3 |
comparison
equal
deleted
inserted
replaced
281:65c4d8591b4a | 282:3e160f6c04d2 |
---|---|
1 /* execute.c -- execute precompiled expression expr | |
2 * | |
3 * Copyright (C) 2001 Janusz Gregorczyk <jgregor@kki.net.pl> | |
4 * | |
5 * This file is part of xvs. | |
6 * | |
7 * This program is free software; you can redistribute it and/or modify | |
8 * it under the terms of the GNU General Public License as published by | |
9 * the Free Software Foundation; either version 2 of the License, or | |
10 * (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 * GNU General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU General Public License | |
18 * along with this program; if not, write to the Free Software | |
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
20 */ | |
21 | |
22 #include <glib.h> | |
23 #include <math.h> | |
24 | |
25 #include "execute.h" | |
26 #include "function.h" | |
27 | |
28 /* Execution stack. */ | |
29 | |
30 gboolean check_stack (ex_stack *stack, int depth) { | |
31 if (stack->sp < depth) { | |
32 g_warning ("Stack error"); | |
33 return FALSE; | |
34 } | |
35 | |
36 return TRUE; | |
37 } | |
38 | |
39 void push (ex_stack *stack, double value) { | |
40 g_assert (stack); | |
41 | |
42 if (stack->sp < STACK_DEPTH) { | |
43 stack->value[stack->sp++] = value; | |
44 } else { | |
45 g_warning ("Stack overflow"); | |
46 } | |
47 } | |
48 | |
49 double pop (ex_stack *stack) { | |
50 g_assert (stack); | |
51 | |
52 if (stack->sp > 0) { | |
53 return stack->value[--stack->sp]; | |
54 } else { | |
55 g_warning ("Stack error (stack empty)"); | |
56 return 0.0; | |
57 } | |
58 } | |
59 | |
60 /* */ | |
61 | |
62 void expr_execute (expression_t *expr, symbol_dict_t *dict) { | |
63 char op, *str = expr->data->str; | |
64 ex_stack stack = { 0, { 0.0 }}; | |
65 | |
66 while ((op = *str++)) { | |
67 switch (op) { | |
68 case 'l': /* Load a variable. */ | |
69 push (&stack, dict->variables[load_int (str)].value); | |
70 str += sizeof (int); | |
71 break; | |
72 | |
73 case 's': /* Store to a variable. */ | |
74 dict->variables[load_int (str)].value = pop (&stack); | |
75 str += sizeof (int); | |
76 break; | |
77 | |
78 case 'f': /* Call a function. */ | |
79 function_call (load_int (str), &stack); | |
80 str += sizeof (int); | |
81 break; | |
82 | |
83 case 'c': /* Load a constant. */ | |
84 push (&stack, load_double (str)); | |
85 str += sizeof (double); | |
86 break; | |
87 | |
88 case 'n': /* Do a negation. */ | |
89 push (&stack, -pop (&stack)); | |
90 break; | |
91 | |
92 case '+': /* Do an addition. */ | |
93 push (&stack, pop (&stack) + pop (&stack)); | |
94 break; | |
95 case '-': /* Do a subtraction. */ | |
96 push (&stack, pop (&stack) - pop (&stack)); | |
97 break; | |
98 case '*': /* Do a multiplication. */ | |
99 push (&stack, pop (&stack) * pop (&stack)); | |
100 break; | |
101 case '/': /* Do a division. */ | |
102 if (check_stack (&stack, 2)) { | |
103 double y = stack.value[stack.sp - 2] / stack.value[stack.sp - 1]; | |
104 stack.sp -= 2; | |
105 push (&stack, y); | |
106 } | |
107 break; | |
108 case '^': /* Do an exponentiation. */ | |
109 if (check_stack (&stack, 2)) { | |
110 double y = pow (stack.value[stack.sp - 2], stack.value[stack.sp - 1]); | |
111 stack.sp -= 2; | |
112 push (&stack, y); | |
113 } | |
114 break; | |
115 | |
116 default: | |
117 g_warning ("Invalid opcode: %c", op); | |
118 return; | |
119 } | |
120 } | |
121 } |