diff options
author | clifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c> | 2009-06-20 19:00:19 (GMT) |
---|---|---|
committer | clifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c> | 2009-06-20 19:00:19 (GMT) |
commit | e416017c5e0ef689e9fbc43b520632cde7927c26 (patch) | |
tree | ff027e61646404db33fde1a4dc245a870fd56722 | |
parent | e80db13e335ccef3e93016a84b9aab1883828bda (diff) |
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
-rw-r--r-- | context.cc | 66 | ||||
-rw-r--r-- | expr.cc | 65 | ||||
-rw-r--r-- | func.cc | 123 | ||||
-rw-r--r-- | module.cc | 71 | ||||
-rw-r--r-- | openscad.cc | 18 | ||||
-rw-r--r-- | openscad.h | 162 | ||||
-rw-r--r-- | openscad.pro | 2 | ||||
-rw-r--r-- | value.cc | 90 |
8 files changed, 595 insertions, 2 deletions
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 <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" + +void Context::args(const QVector<QString> &argnames, const QVector<Expression*> &argexpr, + const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) +{ + for (int i=0; i<argnames.size(); i++) { + variables[argnames[i]] = argexpr[i] ? argexpr[i]->evaluate(this->parent) : Value(); + } + + int posarg = 0; + for (int i=0; i<call_argnames.size(); i++) { + if (call_argnames[i].isEmpty()) { + variables[argnames[posarg++]] = call_argvalues[i]; + } else { + variables[call_argnames[i]] = call_argvalues[i]; + } + } +} + +Value Context::lookup_variable(QString name) +{ + if (variables.contains(name)) + return variables[name]; + if (parent) + return parent->lookup_variable(name); + return Value(); +} + +Value Context::evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &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<QString> &argnames, const QVector<Value> &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; +} + @@ -0,0 +1,65 @@ +/* + * 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(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<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: + return Value(); + } +} + @@ -0,0 +1,123 @@ +/* + * 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" +#include <math.h> + +AbstractFunction::~AbstractFunction() +{ +} + +Value AbstractFunction::evaluate(Context*, const QVector<QString>&, const QVector<Value>&) +{ + return Value(); +} + +Function::~Function() +{ + for (int i=0; i < argexpr.size(); i++) + delete argexpr[i]; +} + +Value Function::evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) +{ + Context c(ctx); + c.args(argnames, argexpr, call_argnames, call_argvalues); + return expr.evaluate(&c); +} + +QHash<QString, AbstractFunction*> builtin_functions; + +BuiltinFunction::~BuiltinFunction() +{ +} + +Value BuiltinFunction::evaluate(Context*, const QVector<QString>&, const QVector<Value> &call_argvalues) +{ + return eval_func(call_argvalues); +} + +Value builtin_sin(const QVector<Value> &args) +{ + if (args[0].is_nan || args[0].is_vector) + return Value(); + return Value(sin(args[0].x)); +} + +Value builtin_cos(const QVector<Value> &args) +{ + if (args[0].is_nan || args[0].is_vector) + return Value(); + return Value(cos(args[0].x)); +} + +Value builtin_asin(const QVector<Value> &args) +{ + if (args[0].is_nan || args[0].is_vector) + return Value(); + return Value(asin(args[0].x)); +} + +Value builtin_acos(const QVector<Value> &args) +{ + if (args[0].is_nan || args[0].is_vector) + return Value(); + return Value(acos(args[0].x)); +} + +Value builtin_tan(const QVector<Value> &args) +{ + if (args[0].is_nan || args[0].is_vector) + return Value(); + return Value(tan(args[0].x)); +} + +Value builtin_atan(const QVector<Value> &args) +{ + if (args[0].is_nan || args[0].is_vector) + return Value(); + return Value(atan(args[0].x)); +} + +Value builtin_atan2(const QVector<Value> &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 <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" + +AbstractModule::~AbstractModule() +{ +} + +AbstractNode *AbstractModule::evaluate(Context*, const QVector<QString>&, const QVector<Value>&) +{ + 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<QString> &call_argnames, const QVector<Value> &call_argvalues) +{ + Context c(ctx); + c.args(argnames, argexpr, call_argnames, call_argvalues); + + /* FIXME */ + + return NULL; +} + +QHash<QString, AbstractModule*> 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; } @@ -21,5 +21,167 @@ #ifndef OPENSCAD_H #define OPENSCAD_H +#include <QHash> +#include <QVector> + +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<Expression*> children; + + Value const_value; + QString var_name; + + QString call_funcname; + QVector<QString> 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<QString> &call_argnames, const QVector<Value> &call_argvalues); +}; + +class BuiltinFunction : public AbstractFunction +{ +public: + typedef Value (*eval_func_t)(const QVector<Value> &args); + eval_func_t eval_func; + + BuiltinFunction(eval_func_t f) : eval_func(f) { } + virtual ~BuiltinFunction(); + + virtual Value evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); +}; + +class Function : public AbstractFunction +{ +public: + QVector<QString> argnames; + QVector<Expression*> argexpr; + + Expression expr; + + Function() { } + virtual ~Function(); + + virtual Value evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); +}; + +extern QHash<QString, AbstractFunction*> builtin_functions; +extern void initialize_builtin_functions(); +extern void destroy_builtin_functions(); + +class AbstractModule +{ +public: + virtual ~AbstractModule(); + virtual AbstractNode *evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); +}; + +class ModuleInstanciation +{ +public: + QString label; + QString modname; + QVector<QString> argnames; + QVector<Expression*> argexpr; + + ModuleInstanciation() { } + ~ModuleInstanciation(); +}; + +class Module : public AbstractModule +{ +public: + QVector<QString> argnames; + QVector<Expression*> argexpr; + + QHash<QString, Expression*> assignments; + QHash<QString, AbstractFunction*> functions; + QHash<QString, AbstractModule*> modules; + + QVector<ModuleInstanciation> children; + + Module() { } + virtual ~Module(); + + virtual AbstractNode *evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); +}; + +extern QHash<QString, AbstractModule*> builtin_modules; +extern void initialize_builtin_modules(); +extern void destroy_builtin_modules(); + +class Context +{ +public: + Context *parent; + QHash<QString, Value> variables; + QHash<QString, AbstractFunction*> *functions_p; + QHash<QString, AbstractModule*> *modules_p; + + Context(Context *parent) : parent(parent) { } + void args(const QVector<QString> &argnames, const QVector<Expression*> &argexpr, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); + + Value lookup_variable(QString name); + Value evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues); + AbstractNode *evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues); +}; + +class AbstractNode +{ +public: + QVector<AbstractNode*> 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 <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" +#include <math.h> + +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); +} + |