From e416017c5e0ef689e9fbc43b520632cde7927c26 Mon Sep 17 00:00:00 2001 From: clifford Date: Sat, 20 Jun 2009 19:00:19 +0000 Subject: Clifford Wolf: Added fundamential backend data structures (it is all still untested) git-svn-id: http://svn.clifford.at/openscad/trunk@3 b57f626f-c46c-0410-a088-ec61d464b74c diff --git a/context.cc b/context.cc new file mode 100644 index 0000000..6cfae25 --- /dev/null +++ b/context.cc @@ -0,0 +1,66 @@ +/* + * OpenSCAD (www.openscad.at) + * Copyright (C) 2009 Clifford Wolf + * + * 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" + +void Context::args(const QVector &argnames, const QVector &argexpr, + const QVector &call_argnames, const QVector &call_argvalues) +{ + for (int i=0; ievaluate(this->parent) : Value(); + } + + int posarg = 0; + for (int i=0; ilookup_variable(name); + return Value(); +} + +Value Context::evaluate_function(QString name, const QVector &argnames, const QVector &argvalues) +{ + if (functions_p->contains(name)) + return functions_p->value(name)->evaluate(this, argnames, argvalues); + if (parent) + return parent->evaluate_function(name, argnames, argvalues); + return Value(); +} + +AbstractNode *Context::evaluate_module(QString name, const QVector &argnames, const QVector &argvalues) +{ + if (modules_p->contains(name)) + return modules_p->value(name)->evaluate(this, argnames, argvalues); + if (parent) + return parent->evaluate_module(name, argnames, argvalues); + return NULL; +} + diff --git a/expr.cc b/expr.cc new file mode 100644 index 0000000..ddc0135 --- /dev/null +++ b/expr.cc @@ -0,0 +1,65 @@ +/* + * OpenSCAD (www.openscad.at) + * Copyright (C) 2009 Clifford Wolf + * + * 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(Context *context) +{ + 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 context->lookup_variable(var_name); + case 'F': + { + QVector 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: + return Value(); + } +} + diff --git a/func.cc b/func.cc new file mode 100644 index 0000000..db8dea9 --- /dev/null +++ b/func.cc @@ -0,0 +1,123 @@ +/* + * OpenSCAD (www.openscad.at) + * Copyright (C) 2009 Clifford Wolf + * + * 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" +#include + +AbstractFunction::~AbstractFunction() +{ +} + +Value AbstractFunction::evaluate(Context*, const QVector&, const QVector&) +{ + return Value(); +} + +Function::~Function() +{ + for (int i=0; i < argexpr.size(); i++) + delete argexpr[i]; +} + +Value Function::evaluate(Context *ctx, const QVector &call_argnames, const QVector &call_argvalues) +{ + Context c(ctx); + c.args(argnames, argexpr, call_argnames, call_argvalues); + return expr.evaluate(&c); +} + +QHash builtin_functions; + +BuiltinFunction::~BuiltinFunction() +{ +} + +Value BuiltinFunction::evaluate(Context*, const QVector&, const QVector &call_argvalues) +{ + return eval_func(call_argvalues); +} + +Value builtin_sin(const QVector &args) +{ + if (args[0].is_nan || args[0].is_vector) + return Value(); + return Value(sin(args[0].x)); +} + +Value builtin_cos(const QVector &args) +{ + if (args[0].is_nan || args[0].is_vector) + return Value(); + return Value(cos(args[0].x)); +} + +Value builtin_asin(const QVector &args) +{ + if (args[0].is_nan || args[0].is_vector) + return Value(); + return Value(asin(args[0].x)); +} + +Value builtin_acos(const QVector &args) +{ + if (args[0].is_nan || args[0].is_vector) + return Value(); + return Value(acos(args[0].x)); +} + +Value builtin_tan(const QVector &args) +{ + if (args[0].is_nan || args[0].is_vector) + return Value(); + return Value(tan(args[0].x)); +} + +Value builtin_atan(const QVector &args) +{ + if (args[0].is_nan || args[0].is_vector) + return Value(); + return Value(atan(args[0].x)); +} + +Value builtin_atan2(const QVector &args) +{ + if (args[0].is_nan || args[0].is_vector || args[1].is_nan || args[1].is_vector) + return Value(); + return Value(atan2(args[0].x, args[1].x)); +} + +void initialize_builtin_functions() +{ + builtin_functions["sin"] = new BuiltinFunction(&builtin_sin); + builtin_functions["cos"] = new BuiltinFunction(&builtin_cos); + builtin_functions["asin"] = new BuiltinFunction(&builtin_asin); + builtin_functions["acos"] = new BuiltinFunction(&builtin_acos); + builtin_functions["tan"] = new BuiltinFunction(&builtin_tan); + builtin_functions["atan"] = new BuiltinFunction(&builtin_atan); + builtin_functions["atan2"] = new BuiltinFunction(&builtin_atan2); +} + +void destroy_builtin_functions() +{ + foreach (AbstractFunction *v, builtin_functions) + delete v; + builtin_functions.clear(); +} + diff --git a/module.cc b/module.cc new file mode 100644 index 0000000..0393d07 --- /dev/null +++ b/module.cc @@ -0,0 +1,71 @@ +/* + * OpenSCAD (www.openscad.at) + * Copyright (C) 2009 Clifford Wolf + * + * 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" + +AbstractModule::~AbstractModule() +{ +} + +AbstractNode *AbstractModule::evaluate(Context*, const QVector&, const QVector&) +{ + return NULL; +} + +ModuleInstanciation::~ModuleInstanciation() +{ + foreach (Expression *v, argexpr) + delete v; +} + +Module::~Module() +{ + foreach (Expression *v, assignments) + delete v; + foreach (AbstractFunction *v, functions) + delete v; + foreach (AbstractModule *v, modules) + delete v; +} + +AbstractNode *Module::evaluate(Context *ctx, const QVector &call_argnames, const QVector &call_argvalues) +{ + Context c(ctx); + c.args(argnames, argexpr, call_argnames, call_argvalues); + + /* FIXME */ + + return NULL; +} + +QHash builtin_modules; + +void initialize_builtin_modules() +{ + /* FIXME */ +} + +void destroy_builtin_modules() +{ + foreach (AbstractModule *v, builtin_modules) + delete v; + builtin_modules.clear(); +} + diff --git a/openscad.cc b/openscad.cc index f312285..f824c32 100644 --- a/openscad.cc +++ b/openscad.cc @@ -18,12 +18,28 @@ * */ +#include "openscad.h" + extern int parserdebug; int parserparse(void); int main() { + int rc = 0; + + initialize_builtin_functions(); + initialize_builtin_modules(); + + Context ctx(NULL); + ctx.functions_p = &builtin_functions; + ctx.modules_p = &builtin_modules; + // parserdebug = 1; - return parserparse(); + rc = parserparse(); + + destroy_builtin_functions(); + destroy_builtin_modules(); + + return rc; } diff --git a/openscad.h b/openscad.h index 08c5f96..944c8ce 100644 --- a/openscad.h +++ b/openscad.h @@ -21,5 +21,167 @@ #ifndef OPENSCAD_H #define OPENSCAD_H +#include +#include + +class Value; +class Expression; + +class AbstractFunction; +class BuiltinFunction; +class Function; + +class AbstractModule; +class ModuleInstanciation; +class Module; + +class Context; +class AbstractNode; + +class Value +{ +public: + double x, y, z; + bool is_vector; + bool is_nan; + + Value() : x(0), y(0), z(0), is_vector(false), is_nan(true) { } + Value(double v1) : x(v1), y(0), z(0), is_vector(false), is_nan(false) { } + Value(double v1, double v2, double v3) : x(v1), y(v2), z(v3), is_vector(true), is_nan(false) { } + Value(const Value &v) : x(v.x), y(v.y), z(v.z), is_vector(v.is_vector), is_nan(v.is_nan) { } + + Value& operator = (const Value &v); + Value operator + (const Value &v) const; + Value operator - (const Value &v) const; + Value operator * (const Value &v) const; + Value operator / (const Value &v) const; + Value operator % (const Value &v) const; + Value inv() const; +}; + +class Expression +{ +public: + QVector children; + + Value const_value; + QString var_name; + + QString call_funcname; + QVector call_argnames; + + // Math operators: * / % + - + // Invert (prefix '-'): I + // Constant value: C + // Variable: V + // Function call: F + char type; + + Expression(); + ~Expression(); + + Value evaluate(Context *context); +}; + +class AbstractFunction +{ +public: + virtual ~AbstractFunction(); + virtual Value evaluate(Context *ctx, const QVector &call_argnames, const QVector &call_argvalues); +}; + +class BuiltinFunction : public AbstractFunction +{ +public: + typedef Value (*eval_func_t)(const QVector &args); + eval_func_t eval_func; + + BuiltinFunction(eval_func_t f) : eval_func(f) { } + virtual ~BuiltinFunction(); + + virtual Value evaluate(Context *ctx, const QVector &call_argnames, const QVector &call_argvalues); +}; + +class Function : public AbstractFunction +{ +public: + QVector argnames; + QVector argexpr; + + Expression expr; + + Function() { } + virtual ~Function(); + + virtual Value evaluate(Context *ctx, const QVector &call_argnames, const QVector &call_argvalues); +}; + +extern QHash builtin_functions; +extern void initialize_builtin_functions(); +extern void destroy_builtin_functions(); + +class AbstractModule +{ +public: + virtual ~AbstractModule(); + virtual AbstractNode *evaluate(Context *ctx, const QVector &call_argnames, const QVector &call_argvalues); +}; + +class ModuleInstanciation +{ +public: + QString label; + QString modname; + QVector argnames; + QVector argexpr; + + ModuleInstanciation() { } + ~ModuleInstanciation(); +}; + +class Module : public AbstractModule +{ +public: + QVector argnames; + QVector argexpr; + + QHash assignments; + QHash functions; + QHash modules; + + QVector children; + + Module() { } + virtual ~Module(); + + virtual AbstractNode *evaluate(Context *ctx, const QVector &call_argnames, const QVector &call_argvalues); +}; + +extern QHash builtin_modules; +extern void initialize_builtin_modules(); +extern void destroy_builtin_modules(); + +class Context +{ +public: + Context *parent; + QHash variables; + QHash *functions_p; + QHash *modules_p; + + Context(Context *parent) : parent(parent) { } + void args(const QVector &argnames, const QVector &argexpr, const QVector &call_argnames, const QVector &call_argvalues); + + Value lookup_variable(QString name); + Value evaluate_function(QString name, const QVector &argnames, const QVector &argvalues); + AbstractNode *evaluate_module(QString name, const QVector &argnames, const QVector &argvalues); +}; + +class AbstractNode +{ +public: + QVector children; +}; + #endif diff --git a/openscad.pro b/openscad.pro index 73d4e86..e914eeb 100644 --- a/openscad.pro +++ b/openscad.pro @@ -6,5 +6,5 @@ LEXSOURCES = lexer.l YACCSOURCES = parser.y HEADERS = openscad.h -SOURCES = openscad.cc +SOURCES = openscad.cc value.cc expr.cc func.cc module.cc context.cc diff --git a/value.cc b/value.cc new file mode 100644 index 0000000..d6af1a3 --- /dev/null +++ b/value.cc @@ -0,0 +1,90 @@ +/* + * OpenSCAD (www.openscad.at) + * Copyright (C) 2009 Clifford Wolf + * + * 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" +#include + +Value& Value::operator = (const Value &v) { + x = v.x; + y = v.y; + z = v.z; + is_vector = v.is_vector; + is_nan = v.is_nan; + return *this; +} + +Value Value::operator + (const Value &v) const { + if (is_nan || v.is_nan) + return Value(); + if (is_vector && v.is_vector) + return Value(x + v.x, y + v.y, z + v.z); + if (!is_vector && !v.is_vector) + return Value(x + v.x); + return Value(); +} + +Value Value::operator - (const Value &v) const { + if (is_nan || v.is_nan) + return Value(); + if (is_vector && v.is_vector) + return Value(x - v.x, y - v.y, z - v.z); + if (!is_vector && !v.is_vector) + return Value(x - v.x); + return Value(); +} + +Value Value::operator * (const Value &v) const { + if (is_nan || v.is_nan) + return Value(); + if (is_vector && v.is_vector) { + double nx = (y-v.y)*(z-v.z) - (z-v.z)*(y-v.y); + double ny = (z-v.z)*(x-v.x) - (x-v.x)*(z-v.z); + double nz = (x-v.x)*(y-v.y) - (y-v.y)*(x-v.x); + return Value(nx, ny, nz); + } + if (is_vector) { + return Value(x * v.x, y * v.x, z * v.x); + } + if (v.is_vector) { + return Value(x * v.x, x * v.y, x * v.z); + } + return Value(x * v.x); +} + +Value Value::operator / (const Value &v) const { + if (is_nan || v.is_nan || is_vector || v.is_vector) + return Value(); + return Value(x / v.x); +} + +Value Value::operator % (const Value &v) const { + if (is_nan || v.is_nan || is_vector || v.is_vector) + return Value(); + return Value(fmod(x, v.x)); +} + +Value Value::inv() const { + if (is_nan) + return Value(); + if (is_vector) + return Value(-x, -y, -z); + return Value(-x); +} + -- cgit v0.10.1