summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--context.cc6
-rw-r--r--expr.cc40
-rw-r--r--func.cc36
-rw-r--r--module.cc69
-rw-r--r--openscad.cc9
-rw-r--r--openscad.h46
-rw-r--r--parser.y17
-rw-r--r--value.cc57
8 files changed, 239 insertions, 41 deletions
diff --git a/context.cc b/context.cc
index 6cfae25..e75592a 100644
--- a/context.cc
+++ b/context.cc
@@ -37,7 +37,7 @@ void Context::args(const QVector<QString> &argnames, const QVector<Expression*>
}
}
-Value Context::lookup_variable(QString name)
+Value Context::lookup_variable(QString name) const
{
if (variables.contains(name))
return variables[name];
@@ -46,7 +46,7 @@ Value Context::lookup_variable(QString name)
return Value();
}
-Value Context::evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues)
+Value Context::evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const
{
if (functions_p->contains(name))
return functions_p->value(name)->evaluate(this, argnames, argvalues);
@@ -55,7 +55,7 @@ Value Context::evaluate_function(QString name, const QVector<QString> &argnames,
return Value();
}
-AbstractNode *Context::evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues)
+AbstractNode *Context::evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const
{
if (modules_p->contains(name))
return modules_p->value(name)->evaluate(this, argnames, argvalues);
diff --git a/expr.cc b/expr.cc
index ddc0135..ce0d462 100644
--- a/expr.cc
+++ b/expr.cc
@@ -31,7 +31,7 @@ Expression::~Expression()
delete children[i];
}
-Value Expression::evaluate(Context *context)
+Value Expression::evaluate(const Context *context) const
{
switch (type)
{
@@ -50,6 +50,8 @@ Value Expression::evaluate(Context *context)
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 'F':
{
@@ -59,7 +61,41 @@ Value Expression::evaluate(Context *context)
return context->evaluate_function(call_funcname, call_argnames, argvalues);
}
default:
- return Value();
+ 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 '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();
+ }
+ }
+ default:
+ abort();
}
}
diff --git a/func.cc b/func.cc
index db8dea9..7bac786 100644
--- a/func.cc
+++ b/func.cc
@@ -19,28 +19,49 @@
*/
#include "openscad.h"
-#include <math.h>
AbstractFunction::~AbstractFunction()
{
}
-Value AbstractFunction::evaluate(Context*, const QVector<QString>&, const QVector<Value>&)
+Value AbstractFunction::evaluate(const Context*, const QVector<QString>&, const QVector<Value>&) const
{
return Value();
}
+QString AbstractFunction::dump(QString indent, QString name) const
+{
+ return QString("%1abstract function %2();\n").arg(indent, name);
+}
+
Function::~Function()
{
for (int i=0; i < argexpr.size(); i++)
delete argexpr[i];
+ delete expr;
}
-Value Function::evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues)
+Value Function::evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const
{
Context c(ctx);
c.args(argnames, argexpr, call_argnames, call_argvalues);
- return expr.evaluate(&c);
+ if (expr)
+ return expr->evaluate(&c);
+ return Value();
+}
+
+QString Function::dump(QString indent, QString name) const
+{
+ QString text = QString("%1function %2(").arg(indent, name);
+ for (int i=0; i < argnames.size(); i++) {
+ if (i > 0)
+ text += QString(", ");
+ text += argnames[i];
+ if (argexpr[i])
+ text += QString(" = ") + argexpr[i]->dump();
+ }
+ text += QString(")\n%1\t%2;\n").arg(indent, expr->dump());
+ return text;
}
QHash<QString, AbstractFunction*> builtin_functions;
@@ -49,11 +70,16 @@ BuiltinFunction::~BuiltinFunction()
{
}
-Value BuiltinFunction::evaluate(Context*, const QVector<QString>&, const QVector<Value> &call_argvalues)
+Value BuiltinFunction::evaluate(const Context*, const QVector<QString>&, const QVector<Value> &call_argvalues) const
{
return eval_func(call_argvalues);
}
+QString BuiltinFunction::dump(QString indent, QString name) const
+{
+ return QString("%1builtin function %2();\n").arg(indent, name);
+}
+
Value builtin_sin(const QVector<Value> &args)
{
if (args[0].is_nan || args[0].is_vector)
diff --git a/module.cc b/module.cc
index 0393d07..522e562 100644
--- a/module.cc
+++ b/module.cc
@@ -24,17 +24,43 @@ AbstractModule::~AbstractModule()
{
}
-AbstractNode *AbstractModule::evaluate(Context*, const QVector<QString>&, const QVector<Value>&)
+AbstractNode *AbstractModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value>&) const
{
return NULL;
}
+QString AbstractModule::dump(QString indent, QString name) const
+{
+ return QString("%1abstract module %2();\n").arg(indent, name);
+}
+
ModuleInstanciation::~ModuleInstanciation()
{
foreach (Expression *v, argexpr)
delete v;
}
+QString ModuleInstanciation::dump(QString indent) const
+{
+ QString text = indent;
+ if (!label.isEmpty())
+ text += label + QString(": ");
+ text += modname + QString("(");
+ for (int i=0; i < argnames.size(); i++) {
+ if (i > 0)
+ text += QString(", ");
+ if (!argnames[i].isEmpty())
+ text += argnames[i] + QString(" = ");
+ text += argexpr[i]->dump();
+ }
+ text += QString(") {\n");
+ for (int i = 0; i < children.size(); i++) {
+ children[i]->dump(indent + QString("\t"));
+ }
+ text += QString("%1}\n").arg(indent);
+ return text;
+}
+
Module::~Module()
{
foreach (Expression *v, assignments)
@@ -45,7 +71,7 @@ Module::~Module()
delete v;
}
-AbstractNode *Module::evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues)
+AbstractNode *Module::evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const
{
Context c(ctx);
c.args(argnames, argexpr, call_argnames, call_argvalues);
@@ -55,6 +81,45 @@ AbstractNode *Module::evaluate(Context *ctx, const QVector<QString> &call_argnam
return NULL;
}
+QString Module::dump(QString indent, QString name) const
+{
+ QString text = QString("%1module %2(").arg(indent, name);
+ for (int i=0; i < argnames.size(); i++) {
+ if (i > 0)
+ text += QString(", ");
+ text += argnames[i];
+ if (argexpr[i])
+ text += QString(" = ") + argexpr[i]->dump();
+ }
+ text += QString(") {\n");
+ {
+ QHashIterator<QString, Expression*> i(assignments);
+ while (i.hasNext()) {
+ i.next();
+ text += QString("%1\t%2 = %3;\n").arg(indent, i.key(), i.value()->dump());
+ }
+ }
+ {
+ QHashIterator<QString, AbstractFunction*> i(functions);
+ while (i.hasNext()) {
+ i.next();
+ text += i.value()->dump(indent + QString("\t"), i.key());
+ }
+ }
+ {
+ QHashIterator<QString, AbstractModule*> i(modules);
+ while (i.hasNext()) {
+ i.next();
+ text += i.value()->dump(indent + QString("\t"), i.key());
+ }
+ }
+ for (int i = 0; i < children.size(); i++) {
+ text += children[i]->dump(indent + QString("\t"));
+ }
+ text += QString("%1}\n").arg(indent);
+ return text;
+}
+
QHash<QString, AbstractModule*> builtin_modules;
void initialize_builtin_modules()
diff --git a/openscad.cc b/openscad.cc
index f824c32..cec520a 100644
--- a/openscad.cc
+++ b/openscad.cc
@@ -20,9 +20,6 @@
#include "openscad.h"
-extern int parserdebug;
-int parserparse(void);
-
int main()
{
int rc = 0;
@@ -34,8 +31,10 @@ int main()
ctx.functions_p = &builtin_functions;
ctx.modules_p = &builtin_modules;
- // parserdebug = 1;
- rc = parserparse();
+ AbstractModule *root_module = parse(stdin, 0);
+ QString text = root_module->dump("", "*");
+ printf("%s", text.toAscii().data());
+ delete root_module;
destroy_builtin_functions();
destroy_builtin_modules();
diff --git a/openscad.h b/openscad.h
index 944c8ce..10f44fe 100644
--- a/openscad.h
+++ b/openscad.h
@@ -23,6 +23,9 @@
#include <QHash>
#include <QVector>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
class Value;
class Expression;
@@ -49,6 +52,7 @@ public:
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(const Value &v1, const Value &v2, const Value &v3);
Value& operator = (const Value &v);
Value operator + (const Value &v) const;
@@ -57,6 +61,8 @@ public:
Value operator / (const Value &v) const;
Value operator % (const Value &v) const;
Value inv() const;
+
+ QString dump() const;
};
class Expression
@@ -73,21 +79,24 @@ public:
// Math operators: * / % + -
// Invert (prefix '-'): I
// Constant value: C
- // Variable: V
+ // Create Vector: V
+ // Lookup Variable: L
// Function call: F
char type;
Expression();
~Expression();
- Value evaluate(Context *context);
+ Value evaluate(const Context *context) const;
+ QString dump() const;
};
class AbstractFunction
{
public:
virtual ~AbstractFunction();
- virtual Value evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues);
+ virtual Value evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const;
+ virtual QString dump(QString indent, QString name) const;
};
class BuiltinFunction : public AbstractFunction
@@ -99,7 +108,8 @@ public:
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);
+ virtual Value evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const;
+ virtual QString dump(QString indent, QString name) const;
};
class Function : public AbstractFunction
@@ -108,12 +118,13 @@ public:
QVector<QString> argnames;
QVector<Expression*> argexpr;
- Expression expr;
+ Expression *expr;
Function() { }
virtual ~Function();
- virtual Value evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues);
+ virtual Value evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const;
+ virtual QString dump(QString indent, QString name) const;
};
extern QHash<QString, AbstractFunction*> builtin_functions;
@@ -124,7 +135,8 @@ class AbstractModule
{
public:
virtual ~AbstractModule();
- virtual AbstractNode *evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues);
+ virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const;
+ virtual QString dump(QString indent, QString name) const;
};
class ModuleInstanciation
@@ -134,9 +146,12 @@ public:
QString modname;
QVector<QString> argnames;
QVector<Expression*> argexpr;
+ QVector<ModuleInstanciation*> children;
ModuleInstanciation() { }
~ModuleInstanciation();
+
+ virtual QString dump(QString indent) const;
};
class Module : public AbstractModule
@@ -149,12 +164,13 @@ public:
QHash<QString, AbstractFunction*> functions;
QHash<QString, AbstractModule*> modules;
- QVector<ModuleInstanciation> children;
+ QVector<ModuleInstanciation*> children;
Module() { }
virtual ~Module();
- virtual AbstractNode *evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues);
+ virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const;
+ virtual QString dump(QString indent, QString name) const;
};
extern QHash<QString, AbstractModule*> builtin_modules;
@@ -164,17 +180,17 @@ extern void destroy_builtin_modules();
class Context
{
public:
- Context *parent;
+ const Context *parent;
QHash<QString, Value> variables;
QHash<QString, AbstractFunction*> *functions_p;
QHash<QString, AbstractModule*> *modules_p;
- Context(Context *parent) : parent(parent) { }
+ Context(const 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);
+ Value lookup_variable(QString name) const;
+ Value evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const;
+ AbstractNode *evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const;
};
class AbstractNode
@@ -183,5 +199,7 @@ public:
QVector<AbstractNode*> children;
};
+extern AbstractModule *parse(FILE *f, int debug);
+
#endif
diff --git a/parser.y b/parser.y
index 241bf17..b23b0d4 100644
--- a/parser.y
+++ b/parser.y
@@ -21,15 +21,16 @@
%{
#include "openscad.h"
-#include <stdio.h>
-extern int parserdebug;
int parserlex(void);
void yyerror(char const *s);
int lexerget_lineno(void);
int lexerlex(void);
+QVector<Module*> module_stack;
+Module *module;
+
%}
%union {
@@ -117,3 +118,15 @@ void yyerror (char const *s)
exit(1);
}
+AbstractModule *parse(FILE *f, int debug)
+{
+ module_stack.clear();
+ module = new Module();
+ module_stack.append(module);
+
+ parserdebug = debug;
+ parserparse();
+
+ return module;
+}
+
diff --git a/value.cc b/value.cc
index d6af1a3..7e562fa 100644
--- a/value.cc
+++ b/value.cc
@@ -19,9 +19,35 @@
*/
#include "openscad.h"
-#include <math.h>
-Value& Value::operator = (const Value &v) {
+Value::Value(const Value &v1, const Value &v2, const Value &v3)
+{
+ if (v1.is_nan || v1.is_vector)
+ goto create_nan;
+ if (v2.is_nan || v2.is_vector)
+ goto create_nan;
+ if (v3.is_nan || v3.is_vector)
+ goto create_nan;
+
+ x = v1.x;
+ y = v1.y;
+ z = v1.z;
+
+ is_vector = true;
+ is_nan = false;
+ return;
+
+create_nan:
+ x = 0;
+ y = 0;
+ z = 0;
+
+ is_vector = false;
+ is_nan = true;
+}
+
+Value& Value::operator = (const Value &v)
+{
x = v.x;
y = v.y;
z = v.z;
@@ -30,7 +56,8 @@ Value& Value::operator = (const Value &v) {
return *this;
}
-Value Value::operator + (const Value &v) const {
+Value Value::operator + (const Value &v) const
+{
if (is_nan || v.is_nan)
return Value();
if (is_vector && v.is_vector)
@@ -40,7 +67,8 @@ Value Value::operator + (const Value &v) const {
return Value();
}
-Value Value::operator - (const Value &v) const {
+Value Value::operator - (const Value &v) const
+{
if (is_nan || v.is_nan)
return Value();
if (is_vector && v.is_vector)
@@ -50,7 +78,8 @@ Value Value::operator - (const Value &v) const {
return Value();
}
-Value Value::operator * (const Value &v) const {
+Value Value::operator * (const Value &v) const
+{
if (is_nan || v.is_nan)
return Value();
if (is_vector && v.is_vector) {
@@ -68,19 +97,22 @@ Value Value::operator * (const Value &v) const {
return Value(x * v.x);
}
-Value Value::operator / (const Value &v) const {
+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 {
+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 {
+Value Value::inv() const
+{
if (is_nan)
return Value();
if (is_vector)
@@ -88,3 +120,12 @@ Value Value::inv() const {
return Value(-x);
}
+QString Value::dump() const
+{
+ if (is_nan)
+ return QString("NaN");
+ if (is_vector)
+ return QString("[%1 %2 %3]").arg(x, y, z);
+ return QString("%1").arg(x);
+}
+
contact: Jan Huwald // Impressum