summaryrefslogtreecommitdiff
path: root/expr.cc
blob: 80d5666357b0066c2c2d756bdba6d7a182a466be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
 *  OpenSCAD (www.openscad.at)
 *  Copyright (C) 2009  Clifford Wolf <clifford@clifford.at>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "openscad.h"

Expression::Expression()
{
	type = 0;
}

Expression::~Expression()
{
	for (int i=0; i < children.size(); i++)
		delete children[i];
}

Value Expression::evaluate(const Context *context) const
{
	switch (type)
	{
	case '*':
		return children[0]->evaluate(context) * children[1]->evaluate(context);
	case '/':
		return children[0]->evaluate(context) / children[1]->evaluate(context);
	case '%':
		return children[0]->evaluate(context) % children[1]->evaluate(context);
	case '+':
		return children[0]->evaluate(context) + children[1]->evaluate(context);
	case '-':
		return children[0]->evaluate(context) - children[1]->evaluate(context);
	case 'I':
		return children[0]->evaluate(context).inv();
	case 'C':
		return const_value;
	case 'V':
		return Value(children[0]->evaluate(context), children[1]->evaluate(context), children[2]->evaluate(context));
	case 'L':
		return context->lookup_variable(var_name);
	case 'M':
		{
			Value v = children[0]->evaluate(context);
			if (v.is_nan || !v.is_vector)
				return Value();
			if (var_name == QString("x"))
				return Value(v.x);
			if (var_name == QString("y"))
				return Value(v.y);
			if (var_name == QString("z"))
				return Value(v.z);
			return Value();
		}
	case 'F':
		{
			QVector<Value> argvalues;
			for (int i=0; i < children.size(); i++)
				argvalues.append(children[i]->evaluate(context));
			return context->evaluate_function(call_funcname, call_argnames, argvalues);
		}
	default:
		abort();
	}
}

QString Expression::dump() const
{
	switch (type)
	{
	case '*':
	case '/':
	case '%':
	case '+':
	case '-':
		return QString("(%1%2%3)").arg(children[0]->dump(), QString(type), children[1]->dump());
	case 'I':
		return QString("(-%1)").arg(children[0]->dump());
	case 'C':
		return const_value.dump();
	case 'V':
		return QString("[%1, %2, %3]").arg(children[0]->dump(), children[1]->dump(), children[2]->dump());
	case 'L':
		return var_name;
	case 'M':
		return QString("(%1.%2)").arg(children[0]->dump(), var_name);
	case 'F':
		{
			QString text = call_funcname + QString("(");
			for (int i=0; i < children.size(); i++) {
				if (i > 0)
					text += QString(", ");
				if (!call_argnames[i].isEmpty())
					text += call_argnames[i] + QString(" = ");
				text += children[i]->dump();
			}
			return text + QString(")");
		}
	default:
		abort();
	}
}

contact: Jan Huwald // Impressum